src/HOL/Tools/Metis/metis_tactic.ML
changeset 70489 12d1e6e2c1d0
parent 70488 c7ef6685c943
child 70513 dc749e0dc6b2
equal deleted inserted replaced
70488:c7ef6685c943 70489:12d1e6e2c1d0
    47    In Isabelle, type tags are stripped away, so we are left with "t = t" or
    47    In Isabelle, type tags are stripped away, so we are left with "t = t" or
    48    "t => t". Type tag idempotence is also handled this way. *)
    48    "t => t". Type tag idempotence is also handled this way. *)
    49 fun reflexive_or_trivial_of_metis ctxt type_enc sym_tab concealed mth =
    49 fun reflexive_or_trivial_of_metis ctxt type_enc sym_tab concealed mth =
    50   (case hol_clause_of_metis ctxt type_enc sym_tab concealed mth of
    50   (case hol_clause_of_metis ctxt type_enc sym_tab concealed mth of
    51     Const (\<^const_name>\<open>HOL.eq\<close>, _) $ _ $ t =>
    51     Const (\<^const_name>\<open>HOL.eq\<close>, _) $ _ $ t =>
    52     let
    52       let
    53       val ct = Thm.cterm_of ctxt t
    53         val ct = Thm.cterm_of ctxt t
    54       val cT = Thm.ctyp_of_cterm ct
    54         val cT = Thm.ctyp_of_cterm ct
    55     in refl |> Thm.instantiate' [SOME cT] [SOME ct] end
    55       in refl |> Thm.instantiate' [SOME cT] [SOME ct] end
    56   | Const (\<^const_name>\<open>disj\<close>, _) $ t1 $ t2 =>
    56   | Const (\<^const_name>\<open>disj\<close>, _) $ t1 $ t2 =>
    57     (if can HOLogic.dest_not t1 then t2 else t1)
    57       (if can HOLogic.dest_not t1 then t2 else t1)
    58     |> HOLogic.mk_Trueprop |> Thm.cterm_of ctxt |> Thm.trivial
    58       |> HOLogic.mk_Trueprop |> Thm.cterm_of ctxt |> Thm.trivial
    59   | _ => raise Fail "expected reflexive or trivial clause")
    59   | _ => raise Fail "expected reflexive or trivial clause")
    60   |> Meson.make_meta_clause ctxt
    60   |> Meson.make_meta_clause ctxt
    61 
    61 
    62 fun lam_lifted_of_metis ctxt type_enc sym_tab concealed mth =
    62 fun lam_lifted_of_metis ctxt type_enc sym_tab concealed mth =
    63   let
    63   let
    64     val tac = rewrite_goals_tac ctxt @{thms lambda_def [abs_def]} THEN resolve_tac ctxt [refl] 1
    64     val tac = rewrite_goals_tac ctxt @{thms lambda_def [abs_def]} THEN resolve_tac ctxt [refl] 1
    65     val t = hol_clause_of_metis ctxt type_enc sym_tab concealed mth
    65     val t = hol_clause_of_metis ctxt type_enc sym_tab concealed mth
    66     val ct = Thm.cterm_of ctxt (HOLogic.mk_Trueprop t)
    66     val ct = Thm.cterm_of ctxt (HOLogic.mk_Trueprop t)
    67   in Goal.prove_internal ctxt [] ct (K tac) |> Meson.make_meta_clause ctxt end
    67   in
       
    68     Goal.prove_internal ctxt [] ct (K tac)
       
    69     |> Meson.make_meta_clause ctxt
       
    70   end
    68 
    71 
    69 fun add_vars_and_frees (t $ u) = fold (add_vars_and_frees) [t, u]
    72 fun add_vars_and_frees (t $ u) = fold (add_vars_and_frees) [t, u]
    70   | add_vars_and_frees (Abs (_, _, t)) = add_vars_and_frees t
    73   | add_vars_and_frees (Abs (_, _, t)) = add_vars_and_frees t
    71   | add_vars_and_frees (t as Var _) = insert (op =) t
    74   | add_vars_and_frees (t as Var _) = insert (op =) t
    72   | add_vars_and_frees (t as Free _) = insert (op =) t
    75   | add_vars_and_frees (t as Free _) = insert (op =) t
    73   | add_vars_and_frees _ = I
    76   | add_vars_and_frees _ = I
    74 
    77 
    75 fun introduce_lam_wrappers ctxt th =
    78 fun introduce_lam_wrappers ctxt th =
    76   if Meson_Clausify.is_quasi_lambda_free (Thm.prop_of th) then
    79   if Meson_Clausify.is_quasi_lambda_free (Thm.prop_of th) then th
    77     th
       
    78   else
    80   else
    79     let
    81     let
    80       fun conv first ctxt ct =
    82       fun conv first ctxt ct =
    81         if Meson_Clausify.is_quasi_lambda_free (Thm.term_of ct) then
    83         if Meson_Clausify.is_quasi_lambda_free (Thm.term_of ct) then Thm.reflexive ct
    82           Thm.reflexive ct
       
    83         else
    84         else
    84           (case Thm.term_of ct of
    85           (case Thm.term_of ct of
    85             Abs (_, _, u) =>
    86             Abs (_, _, u) =>
    86             if first then
    87               if first then
    87               (case add_vars_and_frees u [] of
    88                 (case add_vars_and_frees u [] of
    88                 [] =>
    89                   [] =>
    89                 Conv.abs_conv (conv false o snd) ctxt ct
    90                   Conv.abs_conv (conv false o snd) ctxt ct
    90                 |> (fn th => Meson.first_order_resolve ctxt th @{thm Metis.eq_lambdaI})
    91                   |> (fn th => Meson.first_order_resolve ctxt th @{thm Metis.eq_lambdaI})
    91               | v :: _ =>
    92                 | v :: _ =>
    92                 Abs (Name.uu, fastype_of v, abstract_over (v, Thm.term_of ct)) $ v
    93                     Abs (Name.uu, fastype_of v, abstract_over (v, Thm.term_of ct)) $ v
    93                 |> Thm.cterm_of ctxt
    94                     |> Thm.cterm_of ctxt
    94                 |> Conv.comb_conv (conv true ctxt))
    95                     |> Conv.comb_conv (conv true ctxt))
    95             else
    96               else Conv.abs_conv (conv false o snd) ctxt ct
    96               Conv.abs_conv (conv false o snd) ctxt ct
       
    97           | Const (\<^const_name>\<open>Meson.skolem\<close>, _) $ _ => Thm.reflexive ct
    97           | Const (\<^const_name>\<open>Meson.skolem\<close>, _) $ _ => Thm.reflexive ct
    98           | _ => Conv.comb_conv (conv true ctxt) ct)
    98           | _ => Conv.comb_conv (conv true ctxt) ct)
    99       val eq_th = conv true ctxt (Thm.cprop_of th)
    99       val eq_th = conv true ctxt (Thm.cprop_of th)
   100       (* We replace the equation's left-hand side with a beta-equivalent term
   100       (* We replace the equation's left-hand side with a beta-equivalent term
   101          so that "Thm.equal_elim" works below. *)
   101          so that "Thm.equal_elim" works below. *)
   143 
   143 
   144 exception METIS_UNPROVABLE of unit
   144 exception METIS_UNPROVABLE of unit
   145 
   145 
   146 (* Main function to start Metis proof and reconstruction *)
   146 (* Main function to start Metis proof and reconstruction *)
   147 fun FOL_SOLVE unused type_encs lam_trans ctxt cls ths0 =
   147 fun FOL_SOLVE unused type_encs lam_trans ctxt cls ths0 =
   148   let val thy = Proof_Context.theory_of ctxt
   148   let
   149       val type_enc :: fallback_type_encs = type_encs
   149     val thy = Proof_Context.theory_of ctxt
   150       val new_skolem =
   150 
   151         Config.get ctxt new_skolem orelse null (Meson.choice_theorems thy)
   151     val new_skolem = Config.get ctxt new_skolem orelse null (Meson.choice_theorems thy)
   152       val do_lams =
   152     val do_lams =
   153         (lam_trans = liftingN orelse lam_trans = lam_liftingN)
   153       (lam_trans = liftingN orelse lam_trans = lam_liftingN) ? introduce_lam_wrappers ctxt
   154         ? introduce_lam_wrappers ctxt
   154     val th_cls_pairs =
   155       val th_cls_pairs =
   155       map2 (fn j => fn th =>
   156         map2 (fn j => fn th =>
   156         (Thm.get_name_hint th,
   157                 (Thm.get_name_hint th,
   157           th
   158                  th |> Drule.eta_contraction_rule
   158           |> Drule.eta_contraction_rule
   159                     |> Meson_Clausify.cnf_axiom ctxt new_skolem (lam_trans = combsN) j
   159           |> Meson_Clausify.cnf_axiom ctxt new_skolem (lam_trans = combsN) j
   160                     ||> map do_lams))
   160           ||> map do_lams))
   161              (0 upto length ths0 - 1) ths0
   161         (0 upto length ths0 - 1) ths0
   162       val ths = maps (snd o snd) th_cls_pairs
   162     val ths = maps (snd o snd) th_cls_pairs
   163       val dischargers = map (fst o snd) th_cls_pairs
   163     val dischargers = map (fst o snd) th_cls_pairs
   164       val cls = cls |> map (Drule.eta_contraction_rule #> do_lams)
   164     val cls = cls |> map (Drule.eta_contraction_rule #> do_lams)
   165       val _ = trace_msg ctxt (K "FOL_SOLVE: CONJECTURE CLAUSES")
   165     val _ = trace_msg ctxt (K "FOL_SOLVE: CONJECTURE CLAUSES")
   166       val _ = List.app (fn th => trace_msg ctxt (fn () => Thm.string_of_thm ctxt th)) cls
   166     val _ = List.app (fn th => trace_msg ctxt (fn () => Thm.string_of_thm ctxt th)) cls
   167       val _ = trace_msg ctxt (fn () => "type_enc = " ^ type_enc)
   167 
   168       val type_enc = type_enc_of_string Strict type_enc
   168     val type_enc :: fallback_type_encs = type_encs
   169       val (sym_tab, axioms, ord_info, concealed) =
   169     val _ = trace_msg ctxt (fn () => "type_enc = " ^ type_enc)
   170         generate_metis_problem ctxt type_enc lam_trans cls ths
   170     val type_enc = type_enc_of_string Strict type_enc
   171       fun get_isa_thm mth Isa_Reflexive_or_Trivial =
   171 
       
   172     val (sym_tab, axioms, ord_info, concealed) =
       
   173       generate_metis_problem ctxt type_enc lam_trans cls ths
       
   174     fun get_isa_thm mth Isa_Reflexive_or_Trivial =
   172           reflexive_or_trivial_of_metis ctxt type_enc sym_tab concealed mth
   175           reflexive_or_trivial_of_metis ctxt type_enc sym_tab concealed mth
   173         | get_isa_thm mth Isa_Lambda_Lifted =
   176       | get_isa_thm mth Isa_Lambda_Lifted =
   174           lam_lifted_of_metis ctxt type_enc sym_tab concealed mth
   177           lam_lifted_of_metis ctxt type_enc sym_tab concealed mth
   175         | get_isa_thm _ (Isa_Raw ith) = ith
   178       | get_isa_thm _ (Isa_Raw ith) = ith
   176       val axioms = axioms |> map (fn (mth, ith) => (mth, get_isa_thm mth ith))
   179     val axioms = axioms |> map (fn (mth, ith) => (mth, get_isa_thm mth ith))
   177       val _ = trace_msg ctxt (K "ISABELLE CLAUSES")
   180     val _ = trace_msg ctxt (K "ISABELLE CLAUSES")
   178       val _ = List.app (fn (_, ith) => trace_msg ctxt (fn () => Thm.string_of_thm ctxt ith)) axioms
   181     val _ = List.app (fn (_, ith) => trace_msg ctxt (fn () => Thm.string_of_thm ctxt ith)) axioms
   179       val _ = trace_msg ctxt (K "METIS CLAUSES")
   182     val _ = trace_msg ctxt (K "METIS CLAUSES")
   180       val _ = List.app (fn (mth, _) => trace_msg ctxt (fn () => Metis_Thm.toString mth)) axioms
   183     val _ = List.app (fn (mth, _) => trace_msg ctxt (fn () => Metis_Thm.toString mth)) axioms
   181       val _ = trace_msg ctxt (K "START METIS PROVE PROCESS")
   184 
   182       val ordering =
   185     val _ = trace_msg ctxt (K "START METIS PROVE PROCESS")
   183         if Config.get ctxt advisory_simp then
   186     val ordering =
   184           kbo_advisory_simp_ordering (ord_info ())
   187       if Config.get ctxt advisory_simp
   185         else
   188       then kbo_advisory_simp_ordering (ord_info ())
   186           Metis_KnuthBendixOrder.default
   189       else Metis_KnuthBendixOrder.default
       
   190 
   187     fun fall_back () =
   191     fun fall_back () =
   188       (verbose_warning ctxt
   192       (verbose_warning ctxt
   189            ("Falling back on " ^ quote (metis_call (hd fallback_type_encs) lam_trans) ^ "...");
   193         ("Falling back on " ^ quote (metis_call (hd fallback_type_encs) lam_trans) ^ "...");
   190        FOL_SOLVE unused fallback_type_encs lam_trans ctxt cls ths0)
   194        FOL_SOLVE unused fallback_type_encs lam_trans ctxt cls ths0)
   191   in
   195   in
   192     (case filter (fn t => Thm.prop_of t aconv \<^prop>\<open>False\<close>) cls of
   196     (case filter (fn t => Thm.prop_of t aconv \<^prop>\<open>False\<close>) cls of
   193        false_th :: _ => [false_th RS @{thm FalseE}]
   197       false_th :: _ => [false_th RS @{thm FalseE}]
   194      | [] =>
   198     | [] =>
   195      (case Metis_Resolution.loop (Metis_Resolution.new (resolution_params ordering)
   199         (case Metis_Resolution.loop (Metis_Resolution.new (resolution_params ordering)
   196          {axioms = axioms |> map fst, conjecture = []}) of
   200             {axioms = axioms |> map fst, conjecture = []}) of
   197        Metis_Resolution.Contradiction mth =>
   201           Metis_Resolution.Contradiction mth =>
   198        let
   202           let
   199          val _ = trace_msg ctxt (fn () => "METIS RECONSTRUCTION START: " ^ Metis_Thm.toString mth)
   203             val _ = trace_msg ctxt (fn () => "METIS RECONSTRUCTION START: " ^ Metis_Thm.toString mth)
   200          val ctxt' = fold Variable.declare_constraints (map Thm.prop_of cls) ctxt
   204             val ctxt' = fold Variable.declare_constraints (map Thm.prop_of cls) ctxt
   201                       (*add constraints arising from converting goal to clause form*)
   205               (*add constraints arising from converting goal to clause form*)
   202          val proof = Metis_Proof.proof mth
   206             val proof = Metis_Proof.proof mth
   203          val result = fold (replay_one_inference ctxt' type_enc concealed sym_tab) proof axioms
   207             val result = fold (replay_one_inference ctxt' type_enc concealed sym_tab) proof axioms
   204          val used = map_filter (used_axioms axioms) proof
   208             val used = map_filter (used_axioms axioms) proof
   205          val _ = trace_msg ctxt (K "METIS COMPLETED; clauses actually used:")
   209             val _ = trace_msg ctxt (K "METIS COMPLETED; clauses actually used:")
   206          val _ = List.app (fn th => trace_msg ctxt (fn () => Thm.string_of_thm ctxt th)) used
   210             val _ = List.app (fn th => trace_msg ctxt (fn () => Thm.string_of_thm ctxt th)) used
   207          val (used_th_cls_pairs, unused_th_cls_pairs) =
   211             val (used_th_cls_pairs, unused_th_cls_pairs) =
   208            List.partition (have_common_thm ctxt used o snd o snd) th_cls_pairs
   212               List.partition (have_common_thm ctxt used o snd o snd) th_cls_pairs
   209          val unused_ths = maps (snd o snd) unused_th_cls_pairs
   213             val unused_ths = maps (snd o snd) unused_th_cls_pairs
   210          val unused_names = map fst unused_th_cls_pairs
   214             val unused_names = map fst unused_th_cls_pairs
   211        in
   215 
   212          unused := unused_ths;
   216             val _ = unused := unused_ths;
   213          if not (null unused_names) then
   217             val _ =
   214            verbose_warning ctxt ("Unused theorems: " ^ commas_quote unused_names)
   218               if not (null unused_names) then
   215          else
   219                 verbose_warning ctxt ("Unused theorems: " ^ commas_quote unused_names)
   216            ();
   220               else ();
   217          if not (null cls) andalso not (have_common_thm ctxt used cls) then
   221             val _ =
   218            verbose_warning ctxt "The assumptions are inconsistent"
   222               if not (null cls) andalso not (have_common_thm ctxt used cls) then
   219          else
   223                 verbose_warning ctxt "The assumptions are inconsistent"
   220            ();
   224               else ();
   221          (case result of
   225           in
   222            (_, ith) :: _ =>
   226             (case result of
   223            (trace_msg ctxt (fn () => "Success: " ^ Thm.string_of_thm ctxt ith);
   227               (_, ith) :: _ =>
   224             [discharge_skolem_premises ctxt dischargers ith])
   228                 (trace_msg ctxt (fn () => "Success: " ^ Thm.string_of_thm ctxt ith);
   225          | _ => (trace_msg ctxt (K "Metis: No result"); []))
   229                   [discharge_skolem_premises ctxt dischargers ith])
   226        end
   230             | _ => (trace_msg ctxt (K "Metis: No result"); []))
   227      | Metis_Resolution.Satisfiable _ =>
   231           end
   228        (trace_msg ctxt (K "Metis: No first-order proof with the supplied lemmas");
   232         | Metis_Resolution.Satisfiable _ =>
   229         raise METIS_UNPROVABLE ()))
   233             (trace_msg ctxt (K "Metis: No first-order proof with the supplied lemmas");
   230     handle METIS_UNPROVABLE () => if null fallback_type_encs then [] else fall_back ()
   234               raise METIS_UNPROVABLE ()))
   231          | METIS_RECONSTRUCT (loc, msg) =>
   235         handle METIS_UNPROVABLE () => if null fallback_type_encs then [] else fall_back ()
   232            if null fallback_type_encs then
   236           | METIS_RECONSTRUCT (loc, msg) =>
   233              (verbose_warning ctxt ("Failed to replay Metis proof\n" ^ loc ^ ": " ^ msg); [])
   237               if null fallback_type_encs then
   234            else
   238                 (verbose_warning ctxt ("Failed to replay Metis proof\n" ^ loc ^ ": " ^ msg); [])
   235              fall_back ())
   239               else fall_back ())
   236   end
   240   end
   237 
   241 
   238 fun neg_clausify ctxt combinators =
   242 fun neg_clausify ctxt combinators =
   239   single
   243   single
   240   #> Meson.make_clauses_unsorted ctxt
   244   #> Meson.make_clauses_unsorted ctxt