src/HOL/Tools/Sledgehammer/sledgehammer_reconstruct.ML
changeset 51178 06689dbfe072
parent 51165 58f8716b04ee
child 51179 0d5f8812856f
equal deleted inserted replaced
51177:e8c9755fd14e 51178:06689dbfe072
   454        Inference_Step (name, role, t, rule, deps) :: lines  (* keep line *)
   454        Inference_Step (name, role, t, rule, deps) :: lines  (* keep line *)
   455      else
   455      else
   456        map (replace_dependencies_in_line (name, deps)) lines)  (* drop line *)
   456        map (replace_dependencies_in_line (name, deps)) lines)  (* drop line *)
   457 
   457 
   458 val indent_size = 2
   458 val indent_size = 2
   459 val no_label = ("", ~1)
       
   460 
   459 
   461 fun string_for_proof ctxt type_enc lam_trans i n =
   460 fun string_for_proof ctxt type_enc lam_trans i n =
   462   let
   461   let
       
   462     fun maybe_show qs = if member (op =) qs Show then "show" else "have"
   463     fun of_indent ind = replicate_string (ind * indent_size) " "
   463     fun of_indent ind = replicate_string (ind * indent_size) " "
   464     fun of_free (s, T) =
   464     fun of_free (s, T) =
   465       maybe_quote s ^ " :: " ^
   465       maybe_quote s ^ " :: " ^
   466       maybe_quote (simplify_spaces (with_vanilla_print_mode
   466       maybe_quote (simplify_spaces (with_vanilla_print_mode
   467         (Syntax.string_of_typ ctxt) T))
   467         (Syntax.string_of_typ ctxt) T))
   468     val of_frees = space_implode " and " o map of_free
   468     val of_frees = space_implode " and " o map of_free
       
   469     fun maybe_moreover ind qs nr_subproofs =
       
   470         if member (op =) qs Then andalso nr_subproofs > 0
       
   471           then of_indent ind ^ "moreover\n"
       
   472           else ""
   469     fun of_label l = if l = no_label then "" else string_for_label l ^ ": "
   473     fun of_label l = if l = no_label then "" else string_for_label l ^ ": "
   470     fun of_have qs =
   474     fun of_have qs nr_subproofs =
   471       (if member (op =) qs Ultimately then "ultimately " else "") ^
   475       if (member (op =) qs Then andalso nr_subproofs>0) orelse (nr_subproofs>1)
   472       (if member (op =) qs Then then
   476         then "ultimately " ^ maybe_show qs
   473          if member (op =) qs Show then "thus" else "hence"
   477         else
   474        else
   478           (if member (op =) qs Then orelse nr_subproofs>0 then
   475          if member (op =) qs Show then "show" else "have")
   479              if member (op =) qs Show then "thus" else "hence"
       
   480            else
       
   481              maybe_show qs)
   476     fun of_obtain qs xs =
   482     fun of_obtain qs xs =
   477       (if member (op =) qs Then then "then " else "") ^ "obtain " ^
   483       (if member (op =) qs Then then "then " else "") ^ "obtain " ^
   478       of_frees xs ^ " where"
   484       of_frees xs ^ " where"
   479     val of_term =
   485     val of_term =
   480       annotate_types ctxt
   486       annotate_types ctxt
   490     and of_step ind (Fix xs) = of_indent ind ^ "fix " ^ of_frees xs ^ "\n"
   496     and of_step ind (Fix xs) = of_indent ind ^ "fix " ^ of_frees xs ^ "\n"
   491       | of_step ind (Let (t1, t2)) =
   497       | of_step ind (Let (t1, t2)) =
   492         of_indent ind ^ "let " ^ of_term t1 ^ " = " ^ of_term t2 ^ "\n"
   498         of_indent ind ^ "let " ^ of_term t1 ^ " = " ^ of_term t2 ^ "\n"
   493       | of_step ind (Assume (l, t)) =
   499       | of_step ind (Assume (l, t)) =
   494         of_indent ind ^ "assume " ^ of_label l ^ of_term t ^ "\n"
   500         of_indent ind ^ "assume " ^ of_label l ^ of_term t ^ "\n"
   495       | of_step ind (Obtain (qs, xs, l, t, By_Metis facts)) =
   501       | of_step ind (Obtain (qs, xs, l, t, By_Metis (subproofs, facts))) =      (* FIXME *)
       
   502         maybe_moreover ind qs (length subproofs) ^
       
   503         of_subproofs ind subproofs ^
   496         of_indent ind ^ of_obtain qs xs ^ " " ^
   504         of_indent ind ^ of_obtain qs xs ^ " " ^
   497         of_label l ^ of_term t ^
   505         of_label l ^ of_term t ^
   498         (* The new skolemizer puts the arguments in the same order as the ATPs
   506         (* The new skolemizer puts the arguments in the same order as the ATPs
   499            (E and Vampire -- but see also "atp_proof_reconstruct.ML" regarding
   507            (E and Vampire -- but see also "atp_proof_reconstruct.ML" regarding
   500            Vampire). *)
   508            Vampire). *)
   501         of_metis ind "using [[metis_new_skolem]] " facts ^ "\n"
   509         of_metis ind "using [[metis_new_skolem]] " facts ^ "\n"
   502       | of_step ind (Prove (qs, l, t, By_Metis facts)) =
   510       | of_step ind (Prove (qs, l, t, By_Metis (subproofs, facts))) =
   503         of_prove ind qs l t facts
   511         maybe_moreover ind qs (length subproofs) ^
   504       | of_step ind (Prove (qs, l, t, Case_Split proofs)) =
   512         of_subproofs ind subproofs ^
   505         implode (map (prefix (of_indent ind ^ "moreover\n") o of_block ind)
   513         of_prove ind qs (length subproofs) l t facts
   506                      proofs) ^
       
   507         of_prove ind qs l t ([], [])
       
   508       | of_step ind (Prove (qs, l, t, Subblock proof)) =
       
   509         of_block ind proof ^ of_prove ind qs l t ([], [])
       
   510     and of_steps prefix suffix ind steps =
   514     and of_steps prefix suffix ind steps =
   511       let val s = implode (map (of_step ind) steps) in
   515       let val s = implode (map (of_step ind) steps) in
   512         replicate_string (ind * indent_size - size prefix) " " ^ prefix ^
   516         replicate_string (ind * indent_size - size prefix) " " ^ prefix ^
   513         String.extract (s, ind * indent_size,
   517         String.extract (s, ind * indent_size,
   514                         SOME (size s - ind * indent_size - 1)) ^
   518                         SOME (size s - ind * indent_size - 1)) ^
   515         suffix ^ "\n"
   519         suffix ^ "\n"
   516       end
   520       end
   517     and of_block ind proof = of_steps "{ " " }" (ind + 1) proof
   521     and of_block ind proof = of_steps "{ " " }" (ind + 1) proof
   518     and of_prove ind qs l t facts =
   522     and of_subproofs ind subproofs =
   519       of_indent ind ^ of_have qs ^ " " ^ of_label l ^ of_term t ^
   523         subproofs
       
   524           |> map (of_block ind)
       
   525           |> space_implode (of_indent ind ^ "moreover\n")
       
   526     and of_prove ind qs nr_subproofs l t facts =
       
   527       of_indent ind ^ of_have qs nr_subproofs ^ " " ^ of_label l ^ of_term t ^
   520       of_metis ind "" facts ^ "\n"
   528       of_metis ind "" facts ^ "\n"
   521     (* One-step proofs are pointless; better use the Metis one-liner
   529     (* One-step proofs are pointless; better use the Metis one-liner
   522        directly. *)
   530        directly. *)
   523     and of_proof [Prove (_, _, _, By_Metis _)] = ""
   531     and of_proof [Prove (_, _, _, By_Metis ([], _))] = ""
   524       | of_proof proof =
   532       | of_proof proof =
   525         (if i <> 1 then "prefer " ^ string_of_int i ^ "\n" else "") ^
   533         (if i <> 1 then "prefer " ^ string_of_int i ^ "\n" else "") ^
   526         of_indent 0 ^ "proof -\n" ^ of_steps "" "" 1 proof ^ of_indent 0 ^
   534         of_indent 0 ^ "proof -\n" ^ of_steps "" "" 1 proof ^ of_indent 0 ^
   527         (if n <> 1 then "next" else "qed")
   535         (if n <> 1 then "next" else "qed")
   528   in of_proof end
   536   in of_proof end
   529 
   537 
   530 fun used_labels_of_step (Obtain (_, _, _, _, By_Metis (ls, _))) = ls
   538 fun add_labels_of_step (Obtain (_, _, _, _, By_Metis (subproofs, (ls, _)))) =
   531   | used_labels_of_step (Prove (_, _, _, by)) =
   539       union (op =) (add_labels_of_proofs subproofs ls)
   532     (case by of
   540   | add_labels_of_step (Prove (_, _, _, By_Metis (subproofs, (ls, _)))) =
   533        By_Metis (ls, _) => ls
   541       union (op =) (add_labels_of_proofs subproofs ls)
   534      | Case_Split proofs => fold (union (op =) o used_labels_of) proofs []
   542   | add_labels_of_step _ = I
   535      | Subblock proof => used_labels_of proof)
   543 and add_labels_of_proof proof = fold add_labels_of_step proof
   536   | used_labels_of_step _ = []
   544 and add_labels_of_proofs proofs = fold add_labels_of_proof proofs
   537 and used_labels_of proof = fold (union (op =) o used_labels_of_step) proof []
       
   538 
   545 
   539 fun kill_useless_labels_in_proof proof =
   546 fun kill_useless_labels_in_proof proof =
   540   let
   547   let
   541     val used_ls = used_labels_of proof
   548     val used_ls = add_labels_of_proof proof []
   542     fun do_label l = if member (op =) used_ls l then l else no_label
   549     fun do_label l = if member (op =) used_ls l then l else no_label
   543     fun do_step (Assume (l, t)) = Assume (do_label l, t)
   550     fun do_step (Assume (l, t)) = Assume (do_label l, t)
   544       | do_step (Obtain (qs, xs, l, t, by)) = Obtain (qs, xs, do_label l, t, by)
   551       | do_step (Obtain (qs, xs, l, t, By_Metis (subproofs, facts))) =
   545       | do_step (Prove (qs, l, t, by)) =
   552           Obtain (qs, xs, do_label l, t, By_Metis (map do_proof subproofs, facts))
   546         Prove (qs, do_label l, t,
   553       | do_step (Prove (qs, l, t, By_Metis (subproofs, facts))) =
   547                case by of
   554           Prove (qs, do_label l, t, By_Metis (map do_proof subproofs, facts))
   548                  Case_Split proofs => Case_Split (map do_proof proofs)
       
   549                | Subblock proof => Subblock (do_proof proof)
       
   550                | _ => by)
       
   551       | do_step step = step
   555       | do_step step = step
   552     and do_proof proof = map do_step proof
   556     and do_proof proof = map do_step proof
   553   in do_proof proof end
   557   in do_proof proof end
   554 
   558 
   555 fun prefix_for_depth n = replicate_string (n + 1)
   559 fun prefix_for_depth n = replicate_string (n + 1)
   563         let val l' = (prefix_for_depth depth have_prefix, next_have) in
   567         let val l' = (prefix_for_depth depth have_prefix, next_have) in
   564           (l', (l, l') :: subst, next_have + 1)
   568           (l', (l, l') :: subst, next_have + 1)
   565         end
   569         end
   566     fun do_facts subst =
   570     fun do_facts subst =
   567       apfst (maps (the_list o AList.lookup (op =) subst))
   571       apfst (maps (the_list o AList.lookup (op =) subst))
   568     fun do_byline subst depth nexts by =
   572     fun do_byline subst depth nexts (By_Metis (subproofs, facts)) =
   569       case by of
   573       By_Metis
   570         By_Metis facts => By_Metis (do_facts subst facts)
   574         (map (do_proof subst (depth + 1) (1, 1)) subproofs, do_facts subst facts)
   571       | Case_Split proofs =>
       
   572         Case_Split (map (do_proof subst (depth + 1) (1, 1)) proofs)
       
   573       | Subblock proof => Subblock (do_proof subst depth nexts proof)
       
   574     and do_proof _ _ _ [] = []
   575     and do_proof _ _ _ [] = []
   575       | do_proof subst depth (next_assum, next_have) (Assume (l, t) :: proof) =
   576       | do_proof subst depth (next_assum, next_have) (Assume (l, t) :: proof) =
   576         if l = no_label then
   577         if l = no_label then
   577           Assume (l, t) :: do_proof subst depth (next_assum, next_have) proof
   578           Assume (l, t) :: do_proof subst depth (next_assum, next_have) proof
   578         else
   579         else
   606   let
   607   let
   607     fun label_of (Assume (l, _)) = SOME l
   608     fun label_of (Assume (l, _)) = SOME l
   608       | label_of (Obtain (_, _, l, _, _)) = SOME l
   609       | label_of (Obtain (_, _, l, _, _)) = SOME l
   609       | label_of (Prove (_, l, _, _)) = SOME l
   610       | label_of (Prove (_, l, _, _)) = SOME l
   610       | label_of _ = NONE
   611       | label_of _ = NONE
   611     fun chain_step (SOME l0)
   612     fun do_qs_lfs NONE lfs = ([], lfs)
   612                    (step as Obtain (qs, xs, l, t, By_Metis (lfs, gfs))) =
   613       | do_qs_lfs (SOME l0) lfs =
   613         if member (op =) lfs l0 then
   614         if member (op =) lfs l0 then ([Then], lfs |> remove (op =) l0)
   614           Obtain (Then :: qs, xs, l, t, By_Metis (lfs |> remove (op =) l0, gfs))
   615         else ([], lfs)
   615         else
   616     fun chain_step lbl (Obtain (qs, xs, l, t,
   616           step
   617                                         By_Metis (subproofs, (lfs, gfs)))) =
   617       | chain_step (SOME l0)
   618         let val (qs', lfs) = do_qs_lfs lbl lfs in
   618                    (step as Prove (qs, l, t, By_Metis (lfs, gfs))) =
   619           Obtain (qs' @ qs, xs, l, t,
   619         if member (op =) lfs l0 then
   620             By_Metis (chain_proofs subproofs, (lfs, gfs)))
   620           Prove (Then :: qs, l, t, By_Metis (lfs |> remove (op =) l0, gfs))
   621         end
   621         else
   622       | chain_step lbl (Prove (qs, l, t, By_Metis (subproofs, (lfs, gfs)))) =
   622           step
   623         let val (qs', lfs) = do_qs_lfs lbl lfs in
   623       | chain_step _ (Prove (qs, l, t, Case_Split proofs)) =
   624           Prove (qs' @ qs, l, t,
   624         Prove (qs, l, t, Case_Split (map (chain_proof NONE) proofs))
   625             By_Metis (chain_proofs subproofs, (lfs, gfs)))
   625       | chain_step _ (Prove (qs, l, t, Subblock proof)) =
   626         end
   626         Prove (qs, l, t, Subblock (chain_proof NONE proof))
       
   627       | chain_step _ step = step
   627       | chain_step _ step = step
   628     and chain_proof _ [] = []
   628     and chain_proof _ [] = []
   629       | chain_proof (prev as SOME _) (i :: is) =
   629       | chain_proof (prev as SOME _) (i :: is) =
   630         chain_step prev i :: chain_proof (label_of i) is
   630         chain_step prev i :: chain_proof (label_of i) is
   631       | chain_proof _ (i :: is) = i :: chain_proof (label_of i) is
   631       | chain_proof _ (i :: is) = i :: chain_proof (label_of i) is
       
   632     and chain_proofs proofs = map (chain_proof NONE) proofs
   632   in chain_proof NONE end
   633   in chain_proof NONE end
   633 
   634 
   634 type isar_params =
   635 type isar_params =
   635   bool * bool * Time.time option * real * string Symtab.table
   636   bool * bool * Time.time option * real * string Symtab.table
   636   * (string * stature) list vector * int Symtab.table * string proof * thm
   637   * (string * stature) list vector * int Symtab.table * string proof * thm
   719                   (Library.foldr1 s_conj (map HOLogic.dest_not negs),
   720                   (Library.foldr1 s_conj (map HOLogic.dest_not negs),
   720                    Library.foldr1 s_disj pos)
   721                    Library.foldr1 s_disj pos)
   721               | _ => fold (curry s_disj) lits @{term False}
   722               | _ => fold (curry s_disj) lits @{term False}
   722             end
   723             end
   723             |> HOLogic.mk_Trueprop |> close_form
   724             |> HOLogic.mk_Trueprop |> close_form
   724         fun isar_proof_of_direct_proof outer accum [] =
   725         fun isar_proof_of_direct_proof outer predecessor accum [] =
   725             rev accum |> outer ? (append assms
   726             rev accum |> outer ? (append assms
   726                                   #> not (null params) ? cons (Fix params))
   727                                   #> not (null params) ? cons (Fix params))
   727           | isar_proof_of_direct_proof outer accum (inf :: infs) =
   728           | isar_proof_of_direct_proof outer predecessor accum (inf :: infs) =
   728             let
   729             let
   729               fun maybe_show outer c =
   730               fun maybe_show outer c =
   730                 (outer andalso length c = 1 andalso subset (op =) (c, conjs))
   731                 (outer andalso length c = 1 andalso subset (op =) (c, conjs))
   731                 ? cons Show
   732                 ? cons Show
   732               fun do_rest step =
   733               fun do_rest lbl step =
   733                 isar_proof_of_direct_proof outer (step :: accum) infs
   734                 isar_proof_of_direct_proof outer lbl (step :: accum) infs
   734               val is_fixed = Variable.is_declared ctxt orf can Name.dest_skolem
   735               val is_fixed = Variable.is_declared ctxt orf can Name.dest_skolem
   735               fun skolems_of t =
   736               fun skolems_of t =
   736                 Term.add_frees t [] |> filter_out (is_fixed o fst) |> rev
   737                 Term.add_frees t [] |> filter_out (is_fixed o fst) |> rev
   737             in
   738             in
   738               case inf of
   739               case inf of
   739                 Have (gamma, c) =>
   740                 Have (gamma, c) =>
   740                 let
   741                 let
   741                   val l = label_of_clause c
   742                   val l = label_of_clause c
   742                   val t = prop_of_clause c
   743                   val t = prop_of_clause c
   743                   val by =
   744                   val by =
   744                     By_Metis (fold (add_fact_from_dependencies fact_names) gamma
   745                     By_Metis ([],
   745                                    ([], []))
   746                       (fold (add_fact_from_dependencies fact_names)
       
   747                             gamma no_facts))
   746                   fun prove outer = Prove (maybe_show outer c [], l, t, by)
   748                   fun prove outer = Prove (maybe_show outer c [], l, t, by)
   747                 in
   749                 in
   748                   if is_clause_tainted c then
   750                   if is_clause_tainted c then
   749                     case gamma of
   751                     case gamma of
   750                       [g] =>
   752                       [g] =>
   751                       if is_clause_skolemize_rule g andalso
   753                       if is_clause_skolemize_rule g andalso
   752                          is_clause_tainted g then
   754                          is_clause_tainted g then
   753                         let
   755                         let
   754                           val proof =
   756                           val subproof =
   755                             Fix (skolems_of (prop_of_clause g)) :: rev accum
   757                             Fix (skolems_of (prop_of_clause g)) :: rev accum
   756                         in
   758                         in
   757                           isar_proof_of_direct_proof outer
   759                           isar_proof_of_direct_proof outer l
   758                               [Prove (maybe_show outer c [Then],
   760                               [Prove (maybe_show outer c [],
   759                                       label_of_clause c, prop_of_clause c,
   761                                       label_of_clause c, prop_of_clause c,
   760                                       Subblock proof)] []
   762                                       By_Metis ([subproof], no_facts))] []
   761                         end
   763                         end
   762                       else
   764                       else
   763                         do_rest (prove outer)
   765                         do_rest l (prove outer)
   764                     | _ => do_rest (prove outer)
   766                     | _ => do_rest l (prove outer)
   765                   else
   767                   else
   766                     if is_clause_skolemize_rule c then
   768                     if is_clause_skolemize_rule c then
   767                       do_rest (Obtain ([], skolems_of t, l, t, by))
   769                       do_rest l (Obtain ([], skolems_of t, l, t, by))
   768                     else
   770                     else
   769                       do_rest (prove outer)
   771                       do_rest l (prove outer)
   770                 end
   772                 end
   771               | Cases cases =>
   773               | Cases cases =>
   772                 let
   774                 let
   773                   fun do_case (c, infs) =
   775                   fun do_case (c, infs) =
   774                     Assume (label_of_clause c, prop_of_clause c) ::
   776                     Assume (label_of_clause c, prop_of_clause c) ::
   775                     isar_proof_of_direct_proof false [] infs
   777                     isar_proof_of_direct_proof false no_label [] infs
   776                   val c = succedent_of_cases cases
   778                   val c = succedent_of_cases cases
       
   779                   val l = label_of_clause c
   777                 in
   780                 in
   778                   do_rest (Prove (maybe_show outer c [Ultimately],
   781                   do_rest l
   779                                   label_of_clause c, prop_of_clause c,
   782                     (Prove (maybe_show outer c [],
   780                                   Case_Split (map do_case cases)))
   783                             l, prop_of_clause c,
       
   784                             By_Metis (map do_case cases, ([predecessor], []))))
   781                 end
   785                 end
   782             end
   786             end
   783         val cleanup_labels_in_proof =
   787         val cleanup_labels_in_proof =
   784           chain_direct_proof
   788           chain_direct_proof
   785           #> kill_useless_labels_in_proof
   789           #> kill_useless_labels_in_proof
   786           #> relabel_proof
   790           #> relabel_proof
   787         val (isar_proof, (preplay_fail, preplay_time)) =
   791         val (isar_proof, (preplay_fail, preplay_time)) =
   788           refute_graph
   792           refute_graph
   789           |> redirect_graph axioms tainted bot
   793           |> redirect_graph axioms tainted bot
   790           |> isar_proof_of_direct_proof true []
   794           |> isar_proof_of_direct_proof true no_label []
   791           |> (if not preplay andalso isar_compress <= 1.0 then
   795           |> (if not preplay andalso isar_compress <= 1.0 then
   792                 rpair (false, (true, seconds 0.0))
   796                 rpair (false, (true, seconds 0.0))
   793               else
   797               else
   794                 compress_proof debug ctxt type_enc lam_trans preplay
   798                 compress_proof debug ctxt type_enc lam_trans preplay
   795                   preplay_timeout
   799                   preplay_timeout