src/HOL/Tools/Metis/metis_tactics.ML
changeset 43212 050a03afe024
parent 43211 77c432fe28ff
child 43228 2ed2f092e990
equal deleted inserted replaced
43211:77c432fe28ff 43212:050a03afe024
    14   val default_unsound_type_sys : string
    14   val default_unsound_type_sys : string
    15   val default_sound_type_sys : string
    15   val default_sound_type_sys : string
    16   val trace : bool Config.T
    16   val trace : bool Config.T
    17   val verbose : bool Config.T
    17   val verbose : bool Config.T
    18   val new_skolemizer : bool Config.T
    18   val new_skolemizer : bool Config.T
    19   val old_metis_tac : Proof.context -> thm list -> int -> tactic
    19   val metis_tac : string list -> Proof.context -> thm list -> int -> tactic
    20   val old_metisF_tac : Proof.context -> thm list -> int -> tactic
    20   val metisFT_tac : Proof.context -> thm list -> int -> tactic
    21   val old_metisFT_tac : Proof.context -> thm list -> int -> tactic
       
    22   val new_metis_tac : string list -> Proof.context -> thm list -> int -> tactic
       
    23   val new_metisFT_tac : Proof.context -> thm list -> int -> tactic
       
    24   val setup : theory -> theory
    21   val setup : theory -> theory
    25 end
    22 end
    26 
    23 
    27 structure Metis_Tactics : METIS_TACTICS =
    24 structure Metis_Tactics : METIS_TACTICS =
    28 struct
    25 struct
    36 val full_typesN = "full_types"
    33 val full_typesN = "full_types"
    37 
    34 
    38 val default_unsound_type_sys = "poly_args"
    35 val default_unsound_type_sys = "poly_args"
    39 val default_sound_type_sys = "poly_preds_heavy_query"
    36 val default_sound_type_sys = "poly_preds_heavy_query"
    40 
    37 
    41 fun method_call_for_mode HO = (@{binding old_metis}, "")
    38 fun method_call_for_type_sys type_sys =
    42   | method_call_for_mode FO = (@{binding metisF}, "")
    39   if type_sys = default_sound_type_sys then
    43   | method_call_for_mode FT = (@{binding old_metisFT}, "")
    40     (@{binding metisFT}, "")
    44   | method_call_for_mode (Type_Sys type_sys) =
    41   else
    45     if type_sys = default_sound_type_sys then
    42     (@{binding metis},
    46       (@{binding metisFT}, "")
    43      if type_sys = default_unsound_type_sys then "" else type_sys)
    47     else
       
    48       (@{binding metis},
       
    49        if type_sys = default_unsound_type_sys then "" else type_sys)
       
    50 
    44 
    51 val new_skolemizer =
    45 val new_skolemizer =
    52   Attrib.setup_config_bool @{binding metis_new_skolemizer} (K false)
    46   Attrib.setup_config_bool @{binding metis_new_skolemizer} (K false)
    53 
    47 
    54 (* Designed to work also with monomorphic instances of polymorphic theorems. *)
    48 (* Designed to work also with monomorphic instances of polymorphic theorems. *)
    90    literalsWeight = 0.0,
    84    literalsWeight = 0.0,
    91    models = []}
    85    models = []}
    92 val resolution_params = {active = active_params, waiting = waiting_params}
    86 val resolution_params = {active = active_params, waiting = waiting_params}
    93 
    87 
    94 (* Main function to start Metis proof and reconstruction *)
    88 (* Main function to start Metis proof and reconstruction *)
    95 fun FOL_SOLVE (mode :: fallback_modes) ctxt cls ths0 =
    89 fun FOL_SOLVE (type_sys :: fallback_type_syss) ctxt cls ths0 =
    96   let val thy = Proof_Context.theory_of ctxt
    90   let val thy = Proof_Context.theory_of ctxt
    97       val _ =
       
    98         if mode = FO then
       
    99           legacy_feature "Old 'metisF' command -- use 'metis' instead"
       
   100         else
       
   101           ()
       
   102       val new_skolemizer =
    91       val new_skolemizer =
   103         Config.get ctxt new_skolemizer orelse null (Meson.choice_theorems thy)
    92         Config.get ctxt new_skolemizer orelse null (Meson.choice_theorems thy)
   104       val th_cls_pairs =
    93       val th_cls_pairs =
   105         map2 (fn j => fn th =>
    94         map2 (fn j => fn th =>
   106                 (Thm.get_name_hint th,
    95                 (Thm.get_name_hint th,
   110       val dischargers = map (fst o snd) th_cls_pairs
    99       val dischargers = map (fst o snd) th_cls_pairs
   111       val _ = trace_msg ctxt (fn () => "FOL_SOLVE: CONJECTURE CLAUSES")
   100       val _ = trace_msg ctxt (fn () => "FOL_SOLVE: CONJECTURE CLAUSES")
   112       val _ = app (fn th => trace_msg ctxt (fn () => Display.string_of_thm ctxt th)) cls
   101       val _ = app (fn th => trace_msg ctxt (fn () => Display.string_of_thm ctxt th)) cls
   113       val _ = trace_msg ctxt (fn () => "THEOREM CLAUSES")
   102       val _ = trace_msg ctxt (fn () => "THEOREM CLAUSES")
   114       val _ = app (fn th => trace_msg ctxt (fn () => Display.string_of_thm ctxt th)) ths
   103       val _ = app (fn th => trace_msg ctxt (fn () => Display.string_of_thm ctxt th)) ths
   115       val (mode, sym_tab, {axioms, old_skolems, ...}) =
   104       val (sym_tab, axioms, old_skolems) =
   116         prepare_metis_problem ctxt mode cls ths
   105         prepare_metis_problem ctxt type_sys cls ths
   117       fun get_isa_thm mth Isa_Reflexive_or_Trivial =
   106       fun get_isa_thm mth Isa_Reflexive_or_Trivial =
   118           reflexive_or_trivial_from_metis ctxt sym_tab old_skolems mth
   107           reflexive_or_trivial_from_metis ctxt sym_tab old_skolems mth
   119         | get_isa_thm _ (Isa_Raw ith) = ith
   108         | get_isa_thm _ (Isa_Raw ith) = ith
   120       val axioms = axioms |> map (fn (mth, ith) => (mth, get_isa_thm mth ith))
   109       val axioms = axioms |> map (fn (mth, ith) => (mth, get_isa_thm mth ith))
   121       val _ = trace_msg ctxt (fn () => "CLAUSES GIVEN TO METIS")
   110       val _ = trace_msg ctxt (fn () => "CLAUSES GIVEN TO METIS")
   122       val thms = axioms |> map fst
   111       val thms = axioms |> map fst
   123       val _ = app (fn th => trace_msg ctxt (fn () => Metis_Thm.toString th)) thms
   112       val _ = app (fn th => trace_msg ctxt (fn () => Metis_Thm.toString th)) thms
   124       val _ = trace_msg ctxt (fn () => "mode = " ^ string_of_mode mode)
   113       val _ = trace_msg ctxt (fn () => "type_sys = " ^ type_sys)
   125       val _ = trace_msg ctxt (fn () => "START METIS PROVE PROCESS")
   114       val _ = trace_msg ctxt (fn () => "START METIS PROVE PROCESS")
   126   in
   115   in
   127       case filter (fn t => prop_of t aconv @{prop False}) cls of
   116       case filter (fn t => prop_of t aconv @{prop False}) cls of
   128           false_th :: _ => [false_th RS @{thm FalseE}]
   117           false_th :: _ => [false_th RS @{thm FalseE}]
   129         | [] =>
   118         | [] =>
   134                           Metis_Thm.toString mth)
   123                           Metis_Thm.toString mth)
   135                 val ctxt' = fold Variable.declare_constraints (map prop_of cls) ctxt
   124                 val ctxt' = fold Variable.declare_constraints (map prop_of cls) ctxt
   136                              (*add constraints arising from converting goal to clause form*)
   125                              (*add constraints arising from converting goal to clause form*)
   137                 val proof = Metis_Proof.proof mth
   126                 val proof = Metis_Proof.proof mth
   138                 val result =
   127                 val result =
   139                   fold (replay_one_inference ctxt' mode old_skolems sym_tab)
   128                   axioms
   140                        proof axioms
   129                   |> fold (replay_one_inference ctxt' old_skolems sym_tab) proof
   141                 val used = map_filter (used_axioms axioms) proof
   130                 val used = map_filter (used_axioms axioms) proof
   142                 val _ = trace_msg ctxt (fn () => "METIS COMPLETED...clauses actually used:")
   131                 val _ = trace_msg ctxt (fn () => "METIS COMPLETED...clauses actually used:")
   143                 val _ = app (fn th => trace_msg ctxt (fn () => Display.string_of_thm ctxt th)) used
   132                 val _ = app (fn th => trace_msg ctxt (fn () => Display.string_of_thm ctxt th)) used
   144                 val names = th_cls_pairs |> map fst
   133                 val names = th_cls_pairs |> map fst
   145                 val used_names =
   134                 val used_names =
   164                          [discharge_skolem_premises ctxt dischargers ith])
   153                          [discharge_skolem_premises ctxt dischargers ith])
   165                   | _ => (trace_msg ctxt (fn () => "Metis: No result"); [])
   154                   | _ => (trace_msg ctxt (fn () => "Metis: No result"); [])
   166             end
   155             end
   167         | Metis_Resolution.Satisfiable _ =>
   156         | Metis_Resolution.Satisfiable _ =>
   168             (trace_msg ctxt (fn () => "Metis: No first-order proof with the lemmas supplied");
   157             (trace_msg ctxt (fn () => "Metis: No first-order proof with the lemmas supplied");
   169              if null fallback_modes then
   158              if null fallback_type_syss then
   170                ()
   159                ()
   171              else
   160              else
   172                raise METIS ("FOL_SOLVE",
   161                raise METIS ("FOL_SOLVE",
   173                             "No first-order proof with the lemmas supplied");
   162                             "No first-order proof with the lemmas supplied");
   174              [])
   163              [])
   175   end
   164   end
   176   handle METIS (loc, msg) =>
   165   handle METIS (loc, msg) =>
   177          case fallback_modes of
   166          case fallback_type_syss of
   178            [] => error ("Failed to replay Metis proof in Isabelle." ^
   167            [] => error ("Failed to replay Metis proof in Isabelle." ^
   179                         (if Config.get ctxt verbose then "\n" ^ loc ^ ": " ^ msg
   168                         (if Config.get ctxt verbose then "\n" ^ loc ^ ": " ^ msg
   180                          else ""))
   169                          else ""))
   181          | mode :: _ =>
   170          | type_sys :: _ =>
   182            let val (binding, arg) = method_call_for_mode mode in
   171            let val (binding, arg) = method_call_for_type_sys type_sys in
   183              (verbose_warning ctxt
   172              (verbose_warning ctxt
   184                   ("Falling back on " ^
   173                   ("Falling back on " ^
   185                    quote (Binding.qualified_name_of binding ^
   174                    quote (Binding.qualified_name_of binding ^
   186                           (arg |> arg <> "" ? enclose " (" ")")) ^ "...");
   175                           (arg |> arg <> "" ? enclose " (" ")")) ^ "...");
   187               FOL_SOLVE fallback_modes ctxt cls ths0)
   176               FOL_SOLVE fallback_type_syss ctxt cls ths0)
   188             end
   177             end
   189 
   178 
   190 val neg_clausify =
   179 val neg_clausify =
   191   single
   180   single
   192   #> Meson.make_clauses_unsorted
   181   #> Meson.make_clauses_unsorted
   202      all_tac) st0
   191      all_tac) st0
   203 
   192 
   204 val type_has_top_sort =
   193 val type_has_top_sort =
   205   exists_subtype (fn TFree (_, []) => true | TVar (_, []) => true | _ => false)
   194   exists_subtype (fn TFree (_, []) => true | TVar (_, []) => true | _ => false)
   206 
   195 
   207 fun generic_metis_tac modes ctxt ths i st0 =
   196 fun generic_metis_tac type_syss ctxt ths i st0 =
   208   let
   197   let
   209     val _ = trace_msg ctxt (fn () =>
   198     val _ = trace_msg ctxt (fn () =>
   210         "Metis called with theorems\n" ^
   199         "Metis called with theorems\n" ^
   211         cat_lines (map (Display.string_of_thm ctxt) ths))
   200         cat_lines (map (Display.string_of_thm ctxt) ths))
   212     fun tac clause = resolve_tac (FOL_SOLVE modes ctxt clause ths) 1
   201     fun tac clause = resolve_tac (FOL_SOLVE type_syss ctxt clause ths) 1
   213   in
   202   in
   214     if exists_type type_has_top_sort (prop_of st0) then
   203     if exists_type type_has_top_sort (prop_of st0) then
   215       (verbose_warning ctxt "Proof state contains the universal sort {}";
   204       (verbose_warning ctxt "Proof state contains the universal sort {}";
   216        Seq.empty)
   205        Seq.empty)
   217     else
   206     else
   218       Meson.MESON (preskolem_tac ctxt) (maps neg_clausify) tac ctxt i st0
   207       Meson.MESON (preskolem_tac ctxt) (maps neg_clausify) tac ctxt i st0
   219   end
   208   end
   220 
   209 
   221 val old_metis_modes = [HO, FT]
   210 val metis_default_type_syss = [default_unsound_type_sys, default_sound_type_sys]
   222 val old_metisF_modes = [FO, FT]
   211 val metisFT_type_syss = [default_sound_type_sys]
   223 val old_metisFT_modes = [FT]
   212 
   224 val new_metis_default_modes =
   213 fun metis_tac [] = generic_metis_tac metis_default_type_syss
   225   map Type_Sys [default_unsound_type_sys, default_sound_type_sys]
   214   | metis_tac type_syss = generic_metis_tac type_syss
   226 val new_metisFT_modes = [Type_Sys default_sound_type_sys]
   215 val metisFT_tac = generic_metis_tac metisFT_type_syss
   227 
       
   228 val old_metis_tac = generic_metis_tac old_metis_modes
       
   229 val old_metisF_tac = generic_metis_tac old_metisF_modes
       
   230 val old_metisFT_tac = generic_metis_tac old_metisFT_modes
       
   231 fun new_metis_tac [] = generic_metis_tac new_metis_default_modes
       
   232   | new_metis_tac type_syss = generic_metis_tac (map Type_Sys type_syss)
       
   233 val new_metisFT_tac = generic_metis_tac new_metisFT_modes
       
   234 
   216 
   235 (* Whenever "X" has schematic type variables, we treat "using X by metis" as
   217 (* Whenever "X" has schematic type variables, we treat "using X by metis" as
   236    "by (metis X)" to prevent "Subgoal.FOCUS" from freezing the type variables.
   218    "by (metis X)" to prevent "Subgoal.FOCUS" from freezing the type variables.
   237    We don't do it for nonschematic facts "X" because this breaks a few proofs
   219    We don't do it for nonschematic facts "X" because this breaks a few proofs
   238    (in the rare and subtle case where a proof relied on extensionality not being
   220    (in the rare and subtle case where a proof relied on extensionality not being
   239    applied) and brings few benefits. *)
   221    applied) and brings few benefits. *)
   240 val has_tvar =
   222 val has_tvar =
   241   exists_type (exists_subtype (fn TVar _ => true | _ => false)) o prop_of
   223   exists_type (exists_subtype (fn TVar _ => true | _ => false)) o prop_of
   242 
   224 
   243 fun method modes (type_sys, ths) ctxt facts =
   225 fun method type_syss (type_sys, ths) ctxt facts =
   244   let
   226   let
   245     val (schem_facts, nonschem_facts) = List.partition has_tvar facts
   227     val (schem_facts, nonschem_facts) = List.partition has_tvar facts
   246     val modes = type_sys |> Option.map (single o Type_Sys) |> the_default modes
   228     val type_syss = type_sys |> Option.map single |> the_default type_syss
   247   in
   229   in
   248     HEADGOAL (Method.insert_tac nonschem_facts THEN'
   230     HEADGOAL (Method.insert_tac nonschem_facts THEN'
   249               CHANGED_PROP o generic_metis_tac modes ctxt (schem_facts @ ths))
   231               CHANGED_PROP
   250   end
   232               o generic_metis_tac type_syss ctxt (schem_facts @ ths))
   251 
   233   end
   252 fun setup_method (modes as mode :: _) =
   234 
   253   (if modes = new_metis_default_modes then
   235 fun setup_method (type_syss as type_sys :: _) =
       
   236   (if type_syss = metis_default_type_syss then
   254      (Args.parens Parse.short_ident
   237      (Args.parens Parse.short_ident
   255       >> (fn s => if s = full_typesN then default_sound_type_sys else s))
   238       >> (fn s => if s = full_typesN then default_sound_type_sys else s))
   256      |> Scan.option |> Scan.lift
   239      |> Scan.option |> Scan.lift
   257    else
   240    else
   258      Scan.succeed NONE)
   241      Scan.succeed NONE)
   259   -- Attrib.thms >> (METHOD oo method modes)
   242   -- Attrib.thms >> (METHOD oo method type_syss)
   260   |> Method.setup (fst (method_call_for_mode mode))
   243   |> Method.setup (fst (method_call_for_type_sys type_sys))
   261 
   244 
   262 val setup =
   245 val setup =
   263   [(old_metis_modes, "Metis for FOL and HOL problems"),
   246   [(metis_default_type_syss, "Metis for FOL and HOL problems"),
   264    (old_metisF_modes, "Metis for FOL problems (legacy)"),
   247    (metisFT_type_syss,
   265    (old_metisFT_modes,
   248     "Metis for FOL/HOL problems with fully-typed translation")]
   266     "Metis for FOL/HOL problems with fully-typed translation"),
       
   267    (new_metis_default_modes, "Metis for FOL and HOL problems (experimental)"),
       
   268    (new_metisFT_modes,
       
   269     "Metis for FOL/HOL problems with fully-typed translation (experimental)")]
       
   270   |> fold (uncurry setup_method)
   249   |> fold (uncurry setup_method)
   271 
   250 
   272 end;
   251 end;