diff --git a/thys/ML_Unification/Examples/E_Unification_Examples.thy b/thys/ML_Unification/Examples/E_Unification_Examples.thy --- a/thys/ML_Unification/Examples/E_Unification_Examples.thy +++ b/thys/ML_Unification/Examples/E_Unification_Examples.thy @@ -1,155 +1,155 @@ \<^marker>\creator "Kevin Kappelmann"\ section \E-Unification Examples\ theory E_Unification_Examples imports Main ML_Unification_HOL_Setup Unify_Fact_Tactic begin paragraph \Summary\ text \Sample applications of e-unifiers, methods, etc. introduced in this session.\ experiment begin - subsection \Using The Simplifier For Unification.\ inductive_set even :: "nat set" where zero: "0 \ even" | step: "n \ even \ Suc (Suc n) \ even" text \Premises of the form @{term "SIMPS_TO_UNIF lhs rhs"} are solved by @{ML_structure Simplifier_Unification}. It first normalises @{term lhs} and then unifies the normalisation with @{term rhs}. See also @{theory ML_Unification.ML_Unification_HOL_Setup}.\ lemma [uhint where prio = Prio.LOW]: "n \ 0 \ PROP SIMPS_TO_UNIF (n - 1) m \ n \ Suc m" unfolding SIMPS_TO_UNIF_eq by linarith text \By default, below unification methods use @{ML Standard_Mixed_Unification.first_higherp_first_comb_higher_unify}, which is a combination of various practical unification algorithms.\ schematic_goal "(\x. x + 4 = n) \ Suc ?x = n" by uassm lemma "6 \ even" apply (urule step) apply (urule step) apply (urule step) apply (urule zero) done lemma "(220 + (80 - 2 * 2)) \ even" apply (urule step) apply (urule step)+ apply (urule zero) done lemma assumes "[a,b,c] = [c,b,a]" shows "[a] @ [b,c] = [c,b,a]" using assms by uassm lemma "x \ ({z, y, x} \ S) \ {x}" by (ufact TrueI) lemma "(x + (y :: nat))^2 \ x^2 + 2*x*y + y^2 + 4 * y + x - y" supply power2_sum[simp] by (ufact TrueI) lemma assumes "\s. P (Suc (Suc 0)) (s(x := (1 :: nat), x := 1 + 1 * 4 - 3))" shows "P 2 (s(x := 2))" by (ufact assms[of s]) subsection \Providing Canonical Solutions With Unification Hints\ -lemma [uhint]: "xs \ [] \ length xs \ 0" by simp +lemma [uhint]: "length [] \ 0" by simp schematic_goal "length ?xs = 0" by (ufact refl) -lemma [uhint]: "(n :: nat) \ m \ n - m \ 0" by simp +lemma sub_self_eq_zero [uhint]: "(n :: nat) - n \ 0" by simp schematic_goal "n - ?m = (0 :: nat)" by (ufact refl) text \The following fails because, by default, @{ML Standard_Unification_Hints.try_hints} uses the higher-order pattern unifier to unify hints against a given disagreement pair, and @{term 0} cannot be higher-order pattern unified with @{term "length []"}. The unification of the hint requires the use of yet another hint, namely @{term "length xs = 0"} (cf. above).\ schematic_goal "n - ?m = length []" \ \by (ufact refl)\ oops text \There are two ways to fix this: -\<^enum> We allow the recursive uses of unification hints when searching for suitable unification hints. -\<^enum> We use a different unification hint that the recursive use of hints explicit.\ +\<^enum> We allow the recursive use of unification hints when unifying @{thm sub_self_eq_zero} and our goal. +\<^enum> We use a different unification hint that makes the recursive use of unification hints explicit.\ -text \Solution 1: recursive usages of hints. Warning: such recursive applications easily loop.\ +text \Solution 1: we can use @{attribute rec_uhint} for recursive usages of hints. +Warning: recursive applications easily loop.\ schematic_goal "n - ?m = length []" - using [[uhint where concl_unifier = Standard_Mixed_Unification.first_higherp_first_comb_higher_unify]] + supply sub_self_eq_zero[rec_uhint] by (ufact refl) text \Solution 2: make the recursion explicit in the hint.\ lemma [uhint]: "k \ 0 \ (n :: nat) \ m \ n - m \ k" by simp schematic_goal "n - ?m = length []" by (ufact refl) subsection \Strenghten Unification With Unification Hints\ lemma assumes [uhint]: "n = m" shows "n - m = (0 :: nat)" by (ufact refl) lemma assumes "x = y" shows "y = x" supply eq_commute[uhint] by (ufact assms) paragraph \Unfolding definitions.\ definition "mysuc n = Suc n" lemma assumes "\m. Suc n > mysuc m" shows "mysuc n > Suc 3" supply mysuc_def[uhint] by (ufact assms) paragraph \Discharging meta impliciations with object-level implications\ lemma [uhint]: "Trueprop A \ A' \ Trueprop B \ B' \ Trueprop (A \ B) \ (PROP A' \ PROP B')" using atomize_imp[symmetric] by simp lemma assumes "A \ (B \ C) \ D" shows "A \ (B \ C) \ D" using assms by ufact subsection \Better Control Over Meta Variable Instantiations\ text \Consider the following type-inference problem.\ schematic_goal assumes app_typeI: "\f x. (\x. ArgT x \ DomT x (f x)) \ ArgT x \ DomT x (f x)" and f_type: "\x. ArgT x \ DomT x (f x)" and x_type: "ArgT x" shows "?T (f x)" apply (urule app_typeI) \\compare with the following application, creating an (unintuitive) higher-order instantiation\ (* apply (rule app_typeI) *) oops end end diff --git a/thys/ML_Unification/Examples/Unification_Hints_Reification_Examples.thy b/thys/ML_Unification/Examples/Unification_Hints_Reification_Examples.thy --- a/thys/ML_Unification/Examples/Unification_Hints_Reification_Examples.thy +++ b/thys/ML_Unification/Examples/Unification_Hints_Reification_Examples.thy @@ -1,212 +1,213 @@ \<^marker>\creator "Kevin Kappelmann"\ \<^marker>\contributor "Paul Bachmann"\ section \Examples: Reification Via Unification Hints\ theory Unification_Hints_Reification_Examples imports HOL.Rat ML_Unification_HOL_Setup Unify_Fact_Tactic begin paragraph \Summary\ text \Reification via unification hints. For an introduction to unification hints refer to \<^cite>\"unif-hints"\. We support a generalisation of unification hints as described in @{theory ML_Unification.ML_Unification_Hints}.\ subsection \Setup\ text \One-time setup to obtain a unifier with unification hints for the purpose of reification. -We could also simply use the standard unification hints @{attribute uhint}, -but having separate instances is a cleaner approach.\ +We could also simply use the standard unification hints @{attribute uhint} and +@{attribute rec_uhint}, but having separate instances is a cleaner approach.\ ML\ @{functor_instance struct_name = Reification_Unification_Hints and functor_name = Term_Index_Unification_Hints and id = \"reify"\ and more_args = \ structure TI = Discrimination_Tree val init_args = { + concl_unifier = NONE, + prems_unifier = NONE, normalisers = SOME Higher_Order_Pattern_Unification.norms_unify, retrieval = SOME (Term_Index_Unification_Hints_Args.mk_sym_retrieval TI.norm_term TI.unifiables), - prems_unifier = NONE, - concl_unifier = NONE, hint_preprocessor = SOME (Standard_Unification_Hints.get_hint_preprocessor (Context.the_generic_context ())) }\} val reify_unify = Unification_Combinator.add_fallback_unifier (fn unif_theory => Higher_Order_Pattern_Unification.e_unify Unification_Util.unify_types unif_theory unif_theory) (Reification_Unification_Hints.try_hints |> Unification_Combinator.norm_unifier (#norm_term Higher_Order_Pattern_Unification.norms_unify)) \ local_setup \Reification_Unification_Hints.setup_attribute NONE\ text \Premises of hints should again be unified by the reification unifier.\ declare [[reify_uhint where prems_unifier = reify_unify]] subsection \Formulas with Quantifiers and Environment\ text \The following example is taken from HOL-Library.Reflection\_Examples. It is recommended to compare the approach presented here with the reflection tactic presented in said theory.\ datatype form = TrueF | FalseF | Less nat nat | And form form | Or form form | Neg form | ExQ form primrec interp :: "form \ ('a::ord) list \ bool" where "interp TrueF vs \ True" | "interp FalseF vs \ False" | "interp (Less i j) vs \ vs ! i < vs ! j" | "interp (And f1 f2) vs \ interp f1 vs \ interp f2 vs" | "interp (Or f1 f2) vs \ interp f1 vs \ interp f2 vs" | "interp (Neg f) vs \ \ interp f vs" | "interp (ExQ f) vs \ (\v. interp f (v # vs))" paragraph \Reification with unification and recursive hint unification for conclusion\ text \The following illustrates how to use the equations @{thm interp.simps} directly as unification hints for reification.\ experiment begin text \Hints for list lookup.\ declare List.nth_Cons_Suc[reify_uhint where prio = Prio.LOW] and List.nth_Cons_0[reify_uhint] text \Hints to reify formulas of type @{type bool} into formulas of type @{type form}.\ declare interp.simps[reify_uhint] text \We have to allow the hint unifier to recursively look for hints during unification of the hint's conclusion.\ declare [[reify_uhint where concl_unifier = reify_unify]] (*uncomment the following to see the hint unification process*) (* declare [[ML_map_context \Logger.set_log_levels Unification_Base.logger Logger.DEBUG\]] *) schematic_goal "interp ?f (?vs :: ('a :: ord) list) = (\(x :: 'a). x < y \ \(\(z :: 'a). v < z \ \False))" by (ufact refl where unifier = reify_unify) text \While this all works nicely if set up correctly, it can be rather difficult to understand and debug the recursive unification process for a hint's conclusion. In the next paragraph, we present an alternative that is closer to the examples presented in the original unification hints paper \<^cite>\"unif-hints"\.\ end paragraph \Reification with matching without recursion for conclusion\ text \We disallow the hint unifier to recursively look for hints while unifying the conclusion; instead, we only allow the hint unifier to match the hint's conclusion against the disagreement terms.\ declare [[reify_uhint where concl_unifier = Higher_Order_Pattern_Unification.match]] text \However, this also means that we now have to write our hints such that the hint's conclusion can successfully be matched against the disagreement terms. In particular, the disagreement terms may still contain meta variables that we want to instantiate with the help of the unification hints. Essentially, a hint then describes a canonical instantiation for these meta variables.\ experiment begin lemma [reify_uhint where prio = Prio.LOW]: "n \ Suc n' \ vs \ v # vs' \ vs' ! n' \ x \ vs ! n \ x" by simp lemma [reify_uhint]: "n \ 0 \ vs \ x # vs' \ vs ! n \ x" by simp lemma [reify_uhint]: "\e \ ExQ f; \v. interp f (v # vs) \ P v\ \ interp e vs \ \v. P v" "\e \ Less i j; x \ vs ! i; y \ vs ! j\ \ interp e vs \ x < y" "\e \ And f1 f2; interp f1 vs \ r1; interp f2 vs \ r2\ \ interp e vs \ r1 \ r2" "\e \ Or f1 f2; interp f1 vs \ r1; interp f2 vs \ r2\ \ interp e vs \ r1 \ r2" "e \ Neg f \ interp f vs \ r \ interp e vs \ \r" "e \ TrueF \ interp e vs \ True" "e \ FalseF \ interp e vs \ False" by simp_all schematic_goal "interp ?f (?vs :: ('a :: ord) list) = (\(x :: 'a). x < y \ \(\(z :: 'a). v < z \ \False))" by (urule refl where unifier = reify_unify) + end text \The next examples are modification from \<^cite>\"unif-hints"\.\ subsection \Simple Arithmetic\ datatype add_expr = Var int | Add add_expr add_expr fun eval_add_expr :: "add_expr \ int" where "eval_add_expr (Var i) = i" | "eval_add_expr (Add ex1 ex2) = eval_add_expr ex1 + eval_add_expr ex2" lemma eval_add_expr_Var [reify_uhint where prio = Prio.LOW]: "e \ Var i \ eval_add_expr e \ i" by simp lemma eval_add_expr_add [reify_uhint]: "e \ Add e1 e2 \ eval_add_expr e1 \ m \ eval_add_expr e2 \ n \ eval_add_expr e \ m + n" by simp ML_command\ val t1 = Proof_Context.read_term_pattern @{context} "eval_add_expr ?e" val t2 = Proof_Context.read_term_pattern @{context} "1 + (2 + 7) :: int" val _ = Unification_Util.log_unif_results @{context} (t1, t2) (reify_unify []) \ schematic_goal "eval_add_expr ?e = (1 + (2 + 7) :: int)" by (urule refl where unifier = reify_unify) subsection \Arithmetic with Environment\ datatype mul_expr = Unit | Var nat | Mul mul_expr mul_expr | Inv mul_expr fun eval_mul_expr :: "mul_expr \ rat list \ rat" where "eval_mul_expr (Unit, \) = 1" | "eval_mul_expr (Var i, \) = \ ! i" | "eval_mul_expr (Mul e1 e2, \) = eval_mul_expr (e1, \) * eval_mul_expr (e2, \)" | "eval_mul_expr (Inv e, \) = inverse (eval_mul_expr (e, \))" text \Split @{term e} into an expression and an environment.\ lemma [reify_uhint where prio = Prio.VERY_LOW]: "e \ (e1, \) \ eval_mul_expr (e1, \) \ n \ eval_mul_expr e \ n" by simp text \Hints for environment lookup.\ lemma [reify_uhint where prio = Prio.LOW]: "e \ Var (Suc p) \ \ \ s # \ \ n \ eval_mul_expr (Var p, \) \ eval_mul_expr (e, \) \ n" by simp lemma [reify_uhint]: "e \ Var 0 \ \ \ n # \ \ eval_mul_expr (e, \) \ n" by simp lemma [reify_uhint]: "e1 \ Inv e2 \ n \ eval_mul_expr (e2, \) \ eval_mul_expr (e1, \) \ inverse n" - "e \ Mul e1 e2 \ m \ eval_mul_expr (e1, \) \ - n \ eval_mul_expr (e2, \) \ eval_mul_expr (e, \) \ m * n" + "e \ Mul e1 e2 \ m \ eval_mul_expr (e1, \) \ n \ eval_mul_expr (e2, \) \ + eval_mul_expr (e, \) \ m * n" "e \ Unit \ eval_mul_expr (e, \) \ 1" by simp_all ML_command\ val t1 = Proof_Context.read_term_pattern @{context} "eval_mul_expr ?e" val t2 = Proof_Context.read_term_pattern @{context} "1 * inverse 3 * 5 :: rat" val _ = Unification_Util.log_unif_results' 1 @{context} (t2, t1) (reify_unify []) \ schematic_goal "eval_mul_expr ?e = (1 * inverse 3 * 5 :: rat)" by (ufact refl where unifier = reify_unify) end diff --git a/thys/ML_Unification/ML_Unification_HOL_Setup.thy b/thys/ML_Unification/ML_Unification_HOL_Setup.thy --- a/thys/ML_Unification/ML_Unification_HOL_Setup.thy +++ b/thys/ML_Unification/ML_Unification_HOL_Setup.thy @@ -1,32 +1,34 @@ \<^marker>\creator "Kevin Kappelmann"\ section \Setup for HOL\ theory ML_Unification_HOL_Setup imports HOL.HOL ML_Unification_Hints begin lemma eq_eq_True: "P \ (P \ Trueprop True)" by standard+ simp_all declare [[uhint where hint_preprocessor = \Unification_Hints_Base.obj_logic_hint_preprocessor @{thm atomize_eq[symmetric]} (Conv.rewr_conv @{thm eq_eq_True})\]] +and [[rec_uhint where hint_preprocessor = \Unification_Hints_Base.obj_logic_hint_preprocessor + @{thm atomize_eq[symmetric]} (Conv.rewr_conv @{thm eq_eq_True})\]] lemma eq_TrueI: "PROP P \ PROP P \ Trueprop True" by (standard) simp declare [[ucombine add = \Standard_Unification_Combine.eunif_data (Simplifier_Unification.SIMPS_TO_unify @{thm eq_TrueI} |> Unification_Combinator.norm_closed_unifier (#norm_term Standard_Mixed_Unification.norms_first_higherp_first_comb_higher_unify) |> Unification_Combinator.unifier_from_closed_unifier |> K) (Standard_Unification_Combine.default_metadata \<^binding>\SIMPS_TO_unif\)\]] declare [[ucombine add = \Standard_Unification_Combine.eunif_data (Simplifier_Unification.SIMPS_TO_UNIF_unify @{thm eq_TrueI} Standard_Mixed_Unification.norms_first_higherp_first_comb_higher_unify (Standard_Mixed_Unification.first_higherp_first_comb_higher_unify |> Unification_Combinator.norm_unifier Envir_Normalisation.beta_norm_term_unif) |> Unification_Combinator.norm_unifier (#norm_term Standard_Mixed_Unification.norms_first_higherp_first_comb_higher_unify) |> K) (Standard_Unification_Combine.default_metadata \<^binding>\SIMPS_TO_UNIF_unif\)\]] end diff --git a/thys/ML_Unification/Unification_Hints/ML_Unification_Hints.thy b/thys/ML_Unification/Unification_Hints/ML_Unification_Hints.thy --- a/thys/ML_Unification/Unification_Hints/ML_Unification_Hints.thy +++ b/thys/ML_Unification/Unification_Hints/ML_Unification_Hints.thy @@ -1,55 +1,87 @@ \<^marker>\creator "Kevin Kappelmann"\ section \Unification Hints\ theory ML_Unification_Hints imports ML_Generic_Data_Utils ML_Term_Index ML_Unifiers ML_Unification_Parsers begin paragraph \Summary\ text \A generalisation of unification hints, originally introduced in \<^cite>\"unif-hints"\. We support a generalisation that \<^enum> allows additional universal variables in premises \<^enum> allows non-atomic left-hand sides for premises \<^enum> allows arbitrary functions to perform the matching/unification of a hint with a disagreement pair. General shape of a hint: \\y1...yn. (\x1...xn1. lhs1 \ rhs1) \ ... \ (\x1...xnk. lhsk \ rhsk) \ lhs \ rhs\ \ ML_file\unification_hints_base.ML\ ML_file\unification_hints.ML\ ML_file\term_index_unification_hints.ML\ ML\ + @{functor_instance struct_name = Standard_Unification_Hints_Rec + and functor_name = Term_Index_Unification_Hints + and id = \"rec"\ + and more_args = \ + structure TI = Discrimination_Tree + val init_args = { + concl_unifier = SOME Standard_Mixed_Unification.first_higherp_first_comb_higher_unify, + prems_unifier = SOME (Standard_Mixed_Unification.first_higherp_first_comb_higher_unify + |> Unification_Combinator.norm_unifier Envir_Normalisation.beta_norm_term_unif), + normalisers = SOME Standard_Mixed_Unification.norms_first_higherp_first_comb_higher_unify, + retrieval = SOME (Term_Index_Unification_Hints_Args.mk_sym_retrieval + TI.norm_term TI.unifiables), + hint_preprocessor = SOME (K I) + }\} +\ +local_setup \Standard_Unification_Hints_Rec.setup_attribute NONE\ + +text\Standard unification hints using +@{ML Standard_Mixed_Unification.first_higherp_first_comb_higher_unify} +when looking for hints are accessible via @{attribute rec_uhint}.\ + +ML\ @{functor_instance struct_name = Standard_Unification_Hints and functor_name = Term_Index_Unification_Hints and id = \""\ and more_args = \ structure TI = Discrimination_Tree val init_args = { concl_unifier = SOME Higher_Ordern_Pattern_First_Decomp_Unification.unify, - normalisers = SOME Standard_Mixed_Unification.norms_first_higherp_first_comb_higher_unify, prems_unifier = SOME (Standard_Mixed_Unification.first_higherp_first_comb_higher_unify |> Unification_Combinator.norm_unifier Envir_Normalisation.beta_norm_term_unif), + normalisers = SOME Standard_Mixed_Unification.norms_first_higherp_first_comb_higher_unify, retrieval = SOME (Term_Index_Unification_Hints_Args.mk_sym_retrieval TI.norm_term TI.unifiables), hint_preprocessor = SOME (K I) }\} \ local_setup \Standard_Unification_Hints.setup_attribute NONE\ -text\Standard unification hints are accessible via @{attribute uhint}.\ +text\Standard unification hints using @{ML Higher_Ordern_Pattern_First_Decomp_Unification.unify} +when looking for hints are accessible via @{attribute uhint}. Note: there will be no recursive +usage of unification hints when searching for potential unification hints in this case. See also +@{file "../Examples/E_Unification_Examples.thy"}\ declare [[ucombine add = \Standard_Unification_Combine.eunif_data + (Standard_Unification_Hints_Rec.try_hints + |> Unification_Combinator.norm_unifier + (#norm_term Standard_Mixed_Unification.norms_first_higherp_first_comb_higher_unify) + |> K) + (Standard_Unification_Combine.default_metadata Standard_Unification_Hints_Rec.binding)\]] +and [[ucombine add = \Standard_Unification_Combine.eunif_data (Standard_Unification_Hints.try_hints |> Unification_Combinator.norm_unifier (#norm_term Standard_Mixed_Unification.norms_first_higherp_first_comb_higher_unify) |> K) (Standard_Unification_Combine.default_metadata Standard_Unification_Hints.binding)\]] + text\Examples see @{dir "../Examples"}.\ end