lemma (in field) peval_closed [simp]: "in_carrier xs \ peval xs e \ carrier R" "in_carrier xs \ peval xs (PExpr1 e1) \ carrier R" "in_carrier xs \ peval xs (PExpr2 e2) \ carrier R" by (induct e and e1 and e2) simp_all
definition npepow :: "pexpr \ nat \ pexpr" where"npepow e n =
(if n = 0 then PExpr1 (PCnst 1)
else if n = 1 then e
else
(case e of
PExpr1 (PCnst c) \<Rightarrow> PExpr1 (PCnst (c ^ n))
| _ \<Rightarrow> PExpr2 (PPow e n)))"
lemma (in field) npepow_correct: "in_carrier xs \ peval xs (npepow e n) = peval xs (PExpr2 (PPow e n))" by (cases e rule: pexpr_cases) (simp_all add: npepow_def)
fun npemul :: "pexpr \ pexpr \ pexpr" where"npemul x y =
(case x of
PExpr1 (PCnst c) \<Rightarrow> if c = 0 then x
else if c = 1 then y else
(case y of
PExpr1 (PCnst d) \<Rightarrow> PExpr1 (PCnst (c * d))
| _ \<Rightarrow> PExpr2 (PMul x y))
| PExpr2 (PPow e1 n) \<Rightarrow>
(case y of
PExpr2 (PPow e2 m) \<Rightarrow> if n = m then npepow (npemul e1 e2) n
else PExpr2 (PMul x y)
| PExpr1 (PCnst d) \<Rightarrow> if d = 0 then y
else if d = 1 then x
else PExpr2 (PMul x y)
| _ \<Rightarrow> PExpr2 (PMul x y))
| _ \<Rightarrow>
(case y of
PExpr1 (PCnst d) \<Rightarrow> if d = 0 then y
else if d = 1 then x
else PExpr2 (PMul x y)
| _ \<Rightarrow> PExpr2 (PMul x y)))"
lemma (in field) npemul_correct: "in_carrier xs \ peval xs (npemul e1 e2) = peval xs (PExpr2 (PMul e1 e2))" proof (induct e1 e2 rule: npemul.induct) case (1 x y) thenshow ?case proof (cases x y rule: pexpr_cases2) case (PPow_PPow e n e' m) thenshow ?thesis by (simp del: npemul.simps add: 1 npepow_correct nat_pow_distrib
npemul.simps [of "PExpr2 (PPow e n)""PExpr2 (PPow e' m)"]) qed simp_all qed
declare npemul.simps [simp del]
definition npeadd :: "pexpr \ pexpr \ pexpr" where"npeadd x y =
(case x of
PExpr1 (PCnst c) \<Rightarrow> if c = 0 then y
else
(case y of
PExpr1 (PCnst d) \<Rightarrow> PExpr1 (PCnst (c + d))
| _ \<Rightarrow> PExpr1 (PAdd x y))
| _ \<Rightarrow>
(case y of
PExpr1 (PCnst d) \<Rightarrow> if d = 0 then x
else PExpr1 (PAdd x y)
| _ \<Rightarrow> PExpr1 (PAdd x y)))"
definition npesub :: "pexpr \ pexpr \ pexpr" where"npesub x y =
(case y of
PExpr1 (PCnst d) \<Rightarrow> if d = 0 then x
else
(case x of
PExpr1 (PCnst c) \<Rightarrow> PExpr1 (PCnst (c - d))
| _ \<Rightarrow> PExpr1 (PSub x y))
| _ \<Rightarrow>
(case x of
PExpr1 (PCnst c) \<Rightarrow> if c = 0 then PExpr1 (PNeg y)
else PExpr1 (PSub x y)
| _ \<Rightarrow> PExpr1 (PSub x y)))"
definition npeneg :: "pexpr \ pexpr" where"npeneg e =
(case e of
PExpr1 (PCnst c) \<Rightarrow> PExpr1 (PCnst (- c))
| _ \<Rightarrow> PExpr1 (PNeg e))"
lemma (in field) npeneg_correct: "peval xs (npeneg e) = peval xs (PExpr1 (PNeg e))" by (cases e rule: pexpr_cases) (simp_all add: npeneg_def)
lemma option_pair_cases [case_names None Some]: obtains (None) "x = None" | (Some) p q where"x = Some (p, q)" proof (cases x) case None thenshow ?thesis by (rule that) next case (Some r) thenshow ?thesis by (cases r, simp) (rule that) qed
fun isin :: "pexpr \ nat \ pexpr \ nat \ (nat \ pexpr) option" where "isin e n (PExpr2 (PMul e1 e2)) m =
(case isin e n e1 m of
Some (k, e3) \<Rightarrow> if k = 0 then Some (0, npemul e3 (npepow e2 m))
else
(case isin e k e2 m of
Some (l, e4) \<Rightarrow> Some (l, npemul e3 e4)
| None \<Rightarrow> Some (k, npemul e3 (npepow e2 m)))
| None \<Rightarrow>
(case isin e n e2 m of
Some (k, e3) \<Rightarrow> Some (k, npemul (npepow e1 m) e3)
| None \<Rightarrow> None))"
| "isin e n (PExpr2 (PPow e' k)) m =
(if k = 0 then None else isin e n e' (k * m))"
| "isin (PExpr1 e) n (PExpr1 e') m =
(if e = e' then if n \<ge> m then Some (n - m, PExpr1 (PCnst 1))
else Some (0, npepow (PExpr1 e) (m - n))
else None)"
| "isin (PExpr2 e) n (PExpr1 e') m = None"
lemma (in field) isin_correct: assumes"in_carrier xs" and"isin e n e' m = Some (p, e'')" shows"peval xs (PExpr2 (PPow e' m)) = peval xs (PExpr2 (PMul (PExpr2 (PPow e (n - p))) e''))" and"p \ n" using assms by (induct e n e' m arbitrary: p e'' rule: isin.induct)
(force
simp add:
nat_pow_distrib nat_pow_pow nat_pow_mult m_ac
npemul_correct npepow_correct
split: option.split_asm prod.split_asm if_split_asm)+
lemma (in field) isin_correct': "in_carrier xs \ isin e n e' 1 = Some (p, e'') \
peval xs e' = peval xs e [^] (n - p) \ peval xs e''" "in_carrier xs \ isin e n e' 1 = Some (p, e'') \ p \ n" using isin_correct [where m = 1] by simp_all
fun split_aux :: "pexpr \ nat \ pexpr \ pexpr \ pexpr \ pexpr" where "split_aux (PExpr2 (PMul e1 e2)) n e =
(let
(left1, common1, right1) = split_aux e1 n e;
(left2, common2, right2) = split_aux e2 n right1 in (npemul left1 left2, npemul common1 common2, right2))"
| "split_aux (PExpr2 (PPow e' m)) n e =
(if m = 0 then (PExpr1 (PCnst 1), PExpr1 (PCnst 1), e)
else split_aux e' (m * n) e)"
| "split_aux (PExpr1 e') n e =
(case isin (PExpr1 e') n e 1 of
Some (m, e'') \<Rightarrow>
(if m = 0 then (PExpr1 (PCnst 1), npepow (PExpr1 e') n, e'')
else (npepow (PExpr1 e') m, npepow (PExpr1 e') (n - m), e''))
| None \<Rightarrow> (npepow (PExpr1 e') n, PExpr1 (PCnst 1), e))"
lemma split_aux_induct [case_names 1 2 3]: assumes I1: "\e1 e2 n e. P e1 n e \ P e2 n (snd (snd (split_aux e1 n e))) \
P (PExpr2 (PMul e1 e2)) n e" and I2: "\e' m n e. (m \ 0 \ P e' (m * n) e) \ P (PExpr2 (PPow e' m)) n e" and I3: "\e' n e. P (PExpr1 e') n e" shows"P x y z" proof (induct x y z rule: split_aux.induct) case 1 from 1(1) 1(2) [OF refl prod.collapse prod.collapse] show ?caseby (rule I1) next case 2 thenshow ?caseby (rule I2) next case 3 thenshow ?caseby (rule I3) qed
lemma (in field) feval_eq: assumes"in_carrier xs" and"fnorm (FSub e e') = (n, d, c)" and"nonzero xs c" shows"(feval xs e = feval xs e') = (peval xs n = \)" proof - from assms have"nonzero xs (Cond e)""nonzero xs (Cond e')" by (auto simp add: nonzero_union split: prod.split_asm) with assms fnorm_correct [of xs "FSub e e'"] have"feval xs e \ feval xs e' = peval xs n \ peval xs d" "peval xs d \ \" by simp_all show ?thesis proof assume"feval xs e = feval xs e'" with\<open>feval xs e \<ominus> feval xs e' = peval xs n \<oslash> peval xs d\<close> \<open>in_carrier xs\<close> \<open>nonzero xs (Cond e')\<close> have"peval xs n \ peval xs d = \" by (simp add: fexpr_in_carrier minus_eq r_neg) with\<open>peval xs d \<noteq> \<zero>\<close> \<open>in_carrier xs\<close> show"peval xs n = \" by (simp add: divide_eq_0_iff) next assume"peval xs n = \" with\<open>feval xs e \<ominus> feval xs e' = peval xs n \<oslash> peval xs d\<close> \<open>peval xs d \<noteq> \<zero>\<close> \<open>nonzero xs (Cond e)\<close> \<open>nonzero xs (Cond e')\<close> \<open>in_carrier xs\<close> show"feval xs e = feval xs e'" by (simp add: eq_diff0 fexpr_in_carrier) qed qed
ML \<open>
val term_of_nat = HOLogic.mk_number \<^Type>\<open>nat\<close> o @{code integer_of_nat};
val term_of_int = HOLogic.mk_number \<^Type>\<open>int\<close> o @{code integer_of_int};
fun term_of_pexpr (@{code PExpr1} x) = \<^Const>\<open>PExpr1\<close> $ term_of_pexpr1 x
| term_of_pexpr (@{code PExpr2} x) = \<^Const>\<open>PExpr2\<close> $ term_of_pexpr2 x and term_of_pexpr1 (@{code PCnst} k) = \<^Const>\<open>PCnst\<close> $ term_of_int k
| term_of_pexpr1 (@{code PVar} n) = \<^Const>\<open>PVar\<close> $ term_of_nat n
| term_of_pexpr1 (@{code PAdd} (x, y)) = \<^Const>\<open>PAdd\<close> $ term_of_pexpr x $ term_of_pexpr y
| term_of_pexpr1 (@{code PSub} (x, y)) = \<^Const>\<open>PSub\<close> $ term_of_pexpr x $ term_of_pexpr y
| term_of_pexpr1 (@{code PNeg} x) = \<^Const>\<open>PNeg\<close> $ term_of_pexpr x and term_of_pexpr2 (@{code PMul} (x, y)) = \<^Const>\<open>PMul\<close> $ term_of_pexpr x $ term_of_pexpr y
| term_of_pexpr2 (@{code PPow} (x, n)) = \<^Const>\<open>PPow\<close> $ term_of_pexpr x $ term_of_nat n
fun term_of_result (x, (y, zs)) =
HOLogic.mk_prod (term_of_pexpr x, HOLogic.mk_prod
(term_of_pexpr y, HOLogic.mk_list \<^Type>\<open>pexpr\<close> (map term_of_pexpr zs)));
local
fun fnorm (ctxt, ct, t) = \<^instantiate>\<open>x = ct and y = \<open>Thm.cterm_of ctxt t\<close> in cterm \<open>x \<equiv> y\<close> for x y :: \<open>pexpr \<times> pexpr \<times> pexpr list\<close>\<close>;
val (_, raw_fnorm_oracle) = Theory.setup_result (Thm.add_oracle (\<^binding>\<open>fnorm\<close>, fnorm));
fun fnorm_oracle ctxt ct t = raw_fnorm_oracle (ctxt, ct, t);
ML \<open> signature FIELD_TAC =
sig structure Field_Simps:
sig
type T
val get: Context.generic -> T
val put: T -> Context.generic -> Context.generic
val map: (T -> T) -> Context.generic -> Context.generic end
val eq_field_simps:
(term * (thm list * thm list * thm list * thm * thm)) *
(term * (thm list * thm list * thm list * thm * thm)) -> bool
val field_tac: bool -> Proof.context -> int -> tactic end
structure Field_Tac : FIELD_TAC =
struct
open Ring_Tac;
fun field_struct \<^Const_>\<open>Ring.ring.add _ _ for R _ _\<close> = SOME R
| field_struct \<^Const_>\<open>Ring.a_minus _ _ for R _ _\<close> = SOME R
| field_struct \<^Const_>\<open>Group.monoid.mult _ _ for R _ _\<close> = SOME R
| field_struct \<^Const_>\<open>Ring.a_inv _ _ for R _\<close> = SOME R
| field_struct \<^Const_>\<open>Group.pow _ _ _ for R _ _\<close> = SOME R
| field_struct \<^Const_>\<open>Algebra_Aux.m_div _ _for R _ _\<close> = SOME R
| field_struct \<^Const_>\<open>Ring.ring.zero _ _ for R\<close> = SOME R
| field_struct \<^Const_>\<open>Group.monoid.one _ _ for R\<close> = SOME R
| field_struct \<^Const_>\<open>Algebra_Aux.of_integer _ _ for R _\<close> = SOME R
| field_struct _ = NONE;
fun reif_fexpr vs \<^Const_>\<open>Ring.ring.add _ _ for _ a b\<close> = \<^Const>\<open>FAdd for \<open>reif_fexpr vs a\<close> \<open>reif_fexpr vs b\<close>\<close>
| reif_fexpr vs \<^Const_>\<open>Ring.a_minus _ _ for _ a b\<close> = \<^Const>\<open>FSub for \<open>reif_fexpr vs a\<close> \<open>reif_fexpr vs b\<close>\<close>
| reif_fexpr vs \<^Const_>\<open>Group.monoid.mult _ _ for _ a b\<close> = \<^Const>\<open>FMul for \<open>reif_fexpr vs a\<close> \<open>reif_fexpr vs b\<close>\<close>
| reif_fexpr vs \<^Const_>\<open>Ring.a_inv _ _ for _ a\<close> = \<^Const>\<open>FNeg for \<open>reif_fexpr vs a\<close>\<close>
| reif_fexpr vs \<^Const>\<open>Group.pow _ _ _ for _ a n\<close> = \<^Const>\<open>FPow for \<open>reif_fexpr vs a\<close> n\<close>
| reif_fexpr vs \<^Const_>\<open>Algebra_Aux.m_div _ _ for _ a b\<close> = \<^Const>\<open>FDiv for \<open>reif_fexpr vs a\<close> \<open>reif_fexpr vs b\<close>\<close>
| reif_fexpr vs (Free x) = \<^Const>\<open>FVar for \<open>HOLogic.mk_number HOLogic.natT (find_index (equal x) vs)\<close>\<close>
| reif_fexpr vs \<^Const_>\<open>Ring.ring.zero _ _ for _\<close> = \<^term>\<open>FCnst 0\<close>
| reif_fexpr vs \<^Const_>\<open>Group.monoid.one _ _ for _\<close> = \<^term>\<open>FCnst 1\<close>
| reif_fexpr vs \<^Const_>\<open>Algebra_Aux.of_integer _ _ for _ n\<close> = \<^Const>\<open>FCnst for n\<close>
| reif_fexpr _ _ = error "reif_fexpr: bad expression";
fun reif_fexpr' vs \<^Const_>\plus _ for a b\ = \<^Const>\FAdd for \reif_fexpr' vs a\ \reif_fexpr' vs b\\
| reif_fexpr' vs \<^Const_>\minus _ for a b\ = \<^Const>\FSub for \reif_fexpr' vs a\ \reif_fexpr' vs b\\
| reif_fexpr' vs \<^Const_>\times _ for a b\ = \<^Const>\FMul for \reif_fexpr' vs a\ \reif_fexpr' vs b\\
| reif_fexpr' vs \<^Const_>\uminus _ for a\ = \<^Const>\FNeg for \reif_fexpr' vs a\\
| reif_fexpr' vs \<^Const_>\power _ for a n\ = \<^Const>\FPow for \reif_fexpr' vs a\ n\
| reif_fexpr' vs \<^Const_>\divide _ for a b\ = \<^Const>\FDiv for \reif_fexpr' vs a\ \reif_fexpr' vs b\\
| reif_fexpr' vs (Free x) = \<^Const>\<open>FVar for \<open>HOLogic.mk_number HOLogic.natT (find_index (equal x) vs)\<close>\<close>
| reif_fexpr' vs \<^Const_>\zero_class.zero _\ = \<^term>\FCnst 0\
| reif_fexpr' vs \<^Const_>\one_class.one _\ = \<^term>\FCnst 1\
| reif_fexpr' vs \<^Const_>\numeral _ for b\ = \<^Const>\FCnst for \<^Const>\numeral \<^Type>\int\ for b\\
| reif_fexpr' _ _ = error "reif_fexpr: bad expression";
structure Field_Simps = Generic_Data
(struct
type T = (term * (thm list * thm list * thm list * thm * thm)) Net.net
val empty = Net.empty
val merge = Net.merge eq_field_simps end);
fun get_field_simps ctxt optcT t =
(case get_matching_rules ctxt (Field_Simps.get (Context.Proof ctxt)) t of
SOME (ths1, ths2, ths3, th4, th) => let val tr = Thm.transfer' ctxt #>
(case optcT of NONE => I | SOME cT => inst [cT] [] #> norm) in (map tr ths1, map tr ths2, map tr ths3, tr th4, tr th) end
| NONE => error "get_field_simps: lookup failed");
fun nth_el_conv (_, _, _, nth_el_Cons, _) = let
val a = type_of_eqn nth_el_Cons;
val If_conv_a = If_conv a;
fun conv ys n = (case strip_app ys of
(\<^const_name>\<open>Cons\<close>, [x, xs]) =>
transitive'
(inst [] [x, xs, n] nth_el_Cons)
(If_conv_a (args2 nat_eq_conv) Thm.reflexive
(cong2' conv Thm.reflexive (args2 nat_minus_conv)))) in conv end;
fun feval_conv (rls as
([feval_simps_1, feval_simps_2, feval_simps_3,
feval_simps_4, feval_simps_5, feval_simps_6,
feval_simps_7, feval_simps_8, feval_simps_9,
feval_simps_10, feval_simps_11],
_, _, _, _)) = let
val nth_el_conv' = nth_el_conv rls;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.