signature NAT_SUB = sig val fheads: term list val norm_plus1: wfconv val norm_plus: wfconv val norm_minus': wfconv val move_outmost: term -> wfconv val cancel_terms: wfconv val norm_minus: wfconv type monomial = cterm list * int val reduce_monomial_list: monomial list -> monomial list val add_polynomial_list: monomial list * monomial list -> monomial list val norm_minus_ct: cterm -> monomial list val norm_ring_term: cterm -> term
val get_sub_head_equiv:
Proof.context -> box_id * cterm -> (box_id * (wfterm * thm)) list val nat_sub_expand_once:
Proof.context -> box_id * wfterm -> (box_id * (wfterm * thm)) list val nat_sub_expand:
Proof.context -> box_id * cterm -> (box_id * (wfterm * thm)) list
val nat_sub_expand_equiv: proofstep val nat_sub_expand_unit: proofstep
val plus_info = Nat_Util.plus_ac_on_typ @{theory} natT val is_numc = UtilArith.is_numc val dest_numc = UtilArith.dest_numc val is_plus = UtilArith.is_plus val is_minus = UtilArith.is_minus val is_times = UtilArith.is_times val is_zero = UtilArith.is_zero val is_one = UtilArith.is_one val wf_rewr_obj_eq = WfTerm.rewr_obj_eq fheads val nat0 = Nat_Util.nat0
val mult_1 = @{thm mult_1} (* 1 * a = a *) val mult_1_right = @{thm mult_1_right} (* a * 1 = a *) val mult_0 = @{thm mult_0} (* 0 * a = 0 *) val mult_0_right = @{thm mult_0_right} (* a * 0 = 0 *) val add_0 = @{thm add_0} (* 0 + a = a *) val add_0_right = @{thm add_0_right} (* a + 0 = a *)
val add_assoc = wf_rewr_obj_eq @{thm add_ac(1)} val add_assoc_sym = wf_rewr_obj_eq (obj_sym @{thm add_ac(1)}) val add_comm = wf_rewr_obj_eq @{thm add_ac(2)} val swap_add = WfTerm.every_conv [add_assoc, WfTerm.arg_conv add_comm,
add_assoc_sym] val times_assoc = wf_rewr_obj_eq @{thm mult_ac(1)} val times_assoc_sym = wf_rewr_obj_eq (obj_sym @{thm mult_ac(1)}) val times_comm = wf_rewr_obj_eq @{thm mult_ac(2)} val swap_times = WfTerm.every_conv [times_assoc, WfTerm.arg_conv times_comm,
times_assoc_sym]
val distrib_r_th = @{thm nat_distrib(1)} val distrib_l_th = @{thm nat_distrib(2)}
val nat_fold_wfconv = WfTerm.conv_of Nat_Util.nat_fold_conv val cancel_0_left = WfTerm.try_conv (wf_rewr_obj_eq @{thm add_0_left}) val append_0_left = wf_rewr_obj_eq (obj_sym @{thm add_0_left})
(* When comparing atoms, constants are greater than non-constants. *) fun compare_atom (t1, t2) = if is_numc t1 andalso is_numc t2 then EQUAL elseif is_numc t1 then GREATER elseif is_numc t2 then LESS else Term_Ord.term_ord (t1, t2)
(* Multiply a monomial with an atom. *) fun norm_mult_atom wft = let val t = WfTerm.term_of wft val (arg1, arg2) = Util.dest_binop_args t in if is_one arg1 then wf_rewr_obj_eq mult_1 wft elseif is_one arg2 then wf_rewr_obj_eq mult_1_right wft elseif is_zero arg1 then wf_rewr_obj_eq mult_0 wft elseif is_zero arg2 then wf_rewr_obj_eq mult_0_right wft elseif is_times arg1 then case compare_atom (dest_arg arg1, arg2) of
GREATER =>
WfTerm.every_conv [swap_times,
WfTerm.arg1_conv norm_mult_atom] wft
| EQUAL => if is_numc (dest_arg arg1) andalso is_numc arg2 then
WfTerm.every_conv [times_assoc,
WfTerm.arg_conv nat_fold_wfconv] wft else
WfTerm.all_conv wft
| _ => WfTerm.all_conv wft else case compare_atom (arg1, arg2) of
GREATER => times_comm wft
| EQUAL => if is_numc arg1 andalso is_numc arg2 then
nat_fold_wfconv wft else
WfTerm.all_conv wft
| _ => WfTerm.all_conv wft end
(* Multiply two monomials. *) fun norm_mult_monomial wft = let val t = WfTerm.term_of wft val (_, arg2) = Util.dest_binop_args t in if is_times arg2 then
WfTerm.every_conv [times_assoc_sym,
WfTerm.arg1_conv norm_mult_monomial,
norm_mult_atom] wft else
norm_mult_atom wft end
(* Destruct t into the form arg * coeff, where coeff is a constant. *) fun dest_monomial t = if is_times t andalso is_numc (dest_arg t) then
(dest_arg1 t, UtilArith.dest_numc (dest_arg t)) elseif is_numc t then
(Nat_Util.mk_nat 1, UtilArith.dest_numc t) else
(t, 1)
(* Normalize ct into the form arg * coeff.
Example:a*4==a*4,a==a*1,4==1*4.
*) fun norm_monomial wft = let val t = WfTerm.term_of wft in if is_times t andalso is_numc (dest_arg t) then
WfTerm.all_conv wft elseif is_numc t then
wf_rewr_obj_eq (obj_sym @{thm mult_1}) wft else
wf_rewr_obj_eq (obj_sym @{thm mult_1_right}) wft end
(* Compare two monomials by removing coefficient. *) fun compare_monomial (t1, t2) = let val (arg1, _) = dest_monomial t1 val (arg2, _) = dest_monomial t2 in if is_one arg1 andalso is_one arg2 then EQUAL elseif is_one arg1 then GREATER elseif is_one arg2 then LESS else Term_Ord.term_ord (arg1, arg2) end
(* Combine two monomials. *) fun combine_monomial wft =
WfTerm.every_conv [WfTerm.binop_conv norm_monomial,
wf_rewr_obj_eq (obj_sym distrib_l_th),
WfTerm.arg_conv nat_fold_wfconv] wft
(* Normalize a + b, where a is a sum and b is an atom. If b is a constant,addittotheendofa.Otherwise,insertbintosorted position.
*) fun norm_plus1 wft = let val (a, b) = wft |> WfTerm.term_of |> Util.dest_binop_args in if is_zero a then wf_rewr_obj_eq add_0 wft elseif is_zero b then wf_rewr_obj_eq add_0_right wft elseif is_plus a then case compare_monomial (dest_arg a, b) of
LESS => WfTerm.all_conv wft
| EQUAL => if is_numc (dest_arg a) andalso is_numc b then
WfTerm.every_conv [add_assoc,
WfTerm.arg_conv nat_fold_wfconv] wft else
WfTerm.every_conv [add_assoc,
WfTerm.arg_conv combine_monomial] wft
| GREATER =>
WfTerm.every_conv [swap_add, WfTerm.arg1_conv norm_plus1] wft else case compare_monomial (a, b) of
LESS => WfTerm.all_conv wft
| EQUAL => if is_numc a andalso is_numc b then
nat_fold_wfconv wft else
combine_monomial wft
| GREATER => wf_rewr_obj_eq @{thm add_ac(2)} wft end
(* Normalize a + b, where a and b are both sums. *) fun norm_plus wft = let val (_, b) = wft |> WfTerm.term_of |> Util.dest_binop_args in if is_plus b then
WfTerm.every_conv [
add_assoc_sym, WfTerm.arg1_conv norm_plus, norm_plus1] wft else
norm_plus1 wft end
(* Assume wft is a sum containing u. Move u into the outermost position. *) fun move_outmost u wft = if u aconv (WfTerm.term_of wft) then WfTerm.all_conv wft elseifnot (is_plus (WfTerm.term_of wft)) then raise Fail "move_outmost: u not found in wft." elselet val (a, b) = wft |> WfTerm.term_of |> Util.dest_binop_args in if u aconv b then WfTerm.all_conv wft elseif is_plus a then
WfTerm.every_conv [WfTerm.arg1_conv (move_outmost u), swap_add] wft elseif u aconv a then
add_comm wft else raise Fail "move_outmost: u not found in wft." end
(* Cancel terms with the same argument from the two sides. *) fun cancel_terms wft = let val (a, b) = wft |> WfTerm.term_of |> Util.dest_binop_args val (ts1, ts2) = apply2 (Auto2_HOL_Extra_Setup.ACUtil.dest_ac plus_info) (a, b)
fun find_same_arg (t1, t2) = case compare_monomial (t1, t2) of
EQUAL => if t1 aconv nat0 orelse t2 aconv nat0 then NONE else SOME (t1, t2)
| _ => NONE
fun prepare_left t1 = if length ts1 = 1then WfTerm.arg1_conv append_0_left else WfTerm.arg1_conv (move_outmost t1)
fun prepare_right t2 = if length ts2 = 1then WfTerm.arg_conv append_0_left else WfTerm.arg_conv (move_outmost t2)
fun apply_th (t1, t2) wft = let val (_, n1) = dest_monomial t1 val (_, n2) = dest_monomial t2 val fold_cv =
WfTerm.every_conv [
WfTerm.arg_conv nat_fold_wfconv,
WfTerm.try_conv (wf_rewr_obj_eq mult_1),
WfTerm.try_conv (wf_rewr_obj_eq mult_1_right)] val le_th = if n1 >= n2 then Nat_Util.nat_le_th n2 n1 else Nat_Util.nat_le_th n1 n2 in if n1 = n2 then
wf_rewr_obj_eq @{thm nat_sub_combine} wft elseif n1 > n2 then
WfTerm.every_conv [
WfTerm.binop_conv (WfTerm.arg_conv norm_monomial),
wf_rewr_obj_eq (le_th RS @{thm nat_sub_combine2}),
WfTerm.arg1_conv (WfTerm.arg_conv fold_cv),
WfTerm.arg1_conv norm_plus] wft else
WfTerm.every_conv [
WfTerm.binop_conv (WfTerm.arg_conv norm_monomial),
wf_rewr_obj_eq (le_th RS @{thm nat_sub_combine3}),
WfTerm.arg_conv (WfTerm.arg_conv fold_cv),
WfTerm.arg_conv norm_plus] wft end in case get_first find_same_arg (Util.all_pairs (ts1, ts2)) of
NONE => WfTerm.all_conv wft
| SOME (t1, t2) =>
WfTerm.every_conv [prepare_left t1, prepare_right t2,
apply_th (t1, t2),
WfTerm.arg1_conv cancel_0_left,
WfTerm.arg_conv cancel_0_left,
cancel_terms] wft end
fun norm_mult_poly_monomial wft = let val t = WfTerm.term_of wft val (arg1, _) = Util.dest_binop_args t in if is_plus arg1 then
WfTerm.every_conv [wf_rewr_obj_eq distrib_r_th,
WfTerm.arg1_conv norm_mult_poly_monomial,
WfTerm.arg_conv norm_mult_monomial,
norm_plus] wft else
norm_mult_monomial wft end
fun norm_mult_polynomials wft = let val t = WfTerm.term_of wft val (_, arg2) = Util.dest_binop_args t in if is_plus arg2 then
WfTerm.every_conv [wf_rewr_obj_eq distrib_l_th,
WfTerm.arg1_conv norm_mult_polynomials,
WfTerm.arg_conv norm_mult_poly_monomial,
norm_plus] wft else
norm_mult_poly_monomial wft end
(* First step, put wft into the form a - b, where a and b are normalizedsums.
*) fun norm_minus' wft = let val t = WfTerm.term_of wft in if is_plus t then (* (a - b) + (c - d) = (a + c) - (b + d) *)
WfTerm.every_conv [WfTerm.binop_conv norm_minus',
wf_rewr_obj_eq @{thm nat_sub1},
WfTerm.binop_conv norm_plus,
cancel_terms] wft elseif is_minus t then (* (a - b) - (c - d) = (a + d) - (b + c) *)
WfTerm.every_conv [WfTerm.binop_conv norm_minus',
wf_rewr_obj_eq @{thm nat_sub2},
WfTerm.binop_conv norm_plus,
cancel_terms] wft elseif is_times t then (* (a - b) * (c - d) = (ac + bd) - (ad + bc) *)
WfTerm.every_conv [
WfTerm.binop_conv norm_minus',
wf_rewr_obj_eq @{thm nat_sub3},
WfTerm.binop_conv (WfTerm.binop_conv norm_mult_polynomials),
WfTerm.binop_conv norm_plus,
cancel_terms] wft else (* Normalize a into a - 0. *)
wf_rewr_obj_eq @{thm nat_sub_norm} wft end
fun list_plus ts = let fun list_rev ts = case ts of
[] => Nat_Util.mk_nat 0
| [t] => t
| t :: ts' => mk_plus (list_rev ts', t) in
list_rev (rev ts) end
fun list_times ts = let fun list_rev ts = case ts of
[] => Nat_Util.mk_nat 1
| [t] => t
| t :: ts' => mk_times (list_rev ts', t) in
list_rev (rev ts) end
(* Compare two monomials *) fun compare_monomial_list ((l1, _), (l2, _)) = if null l1 andalso null l2 then EQUAL elseif null l1 then GREATER elseif null l2 then LESS else Term_Ord.term_ord (list_times (map Thm.term_of l1),
list_times (map Thm.term_of l2))
(* Reduce a list of monomials: combine monomials of the same body. *) fun reduce_monomial_list ls = if null ls then [] elselet val ((l1, c1), rest) = (hd ls, reduce_monomial_list (tl ls)) in case rest of
[] => [(l1, c1)]
| [(_, 0)] => [(l1, c1)]
| (l2, c2) :: rest' => if eq_list (op aconvc) (l1, l2) then if c1 + c2 = 0then rest' else (l1, c1 + c2) :: rest' else (l1, c1) :: (l2, c2) :: rest' end
(* Multiply two monomials. *) fun mult_monomial ((l1, c1), (l2, c2)) =
((l1 @ l2) |> sort (compare_atom o apply2 Thm.term_of), c1 * c2)
(* Multiply two such lists: take the pairwise product, sort within eachmonomial,thensortthelistofmonomials.
*) fun mult_polynomial_term (ls1, ls2) =
(Util.all_pairs (ls1, ls2))
|> map mult_monomial
|> sort compare_monomial_list
|> reduce_monomial_list
fun negate_polynomial_list ls = map (fn (ls, n) => (ls, ~n)) ls
fun norm_minus_ct ct = let val t = Thm.term_of ct in if is_plus t then
add_polynomial_list (norm_minus_ct (Thm.dest_arg1 ct),
norm_minus_ct (Thm.dest_arg ct)) elseif is_minus t then
add_polynomial_list (
norm_minus_ct (Thm.dest_arg1 ct),
negate_polynomial_list (norm_minus_ct (Thm.dest_arg ct))) elseif is_times t then
mult_polynomial_term (norm_minus_ct (Thm.dest_arg1 ct),
norm_minus_ct (Thm.dest_arg ct)) elseif is_numc t then
[([], dest_numc t)] else
[([ct], 1)] end
fun to_monomial (l, c) = if null l then mk_nat c elseif c = 1then list_times (map Thm.term_of l) else mk_times (list_times (map Thm.term_of l), mk_nat c)
fun norm_ring_term ct = let val dest_ring = norm_minus_ct ct val (ps, ms) = filter_split (fn (_, n) => n >= 0) dest_ring in if length ms > 0then Const (@{const_name minus}, natT --> natT --> natT) $
list_plus (map to_monomial ps) $
list_plus (map to_monomial (negate_polynomial_list ms)) else
list_plus (map to_monomial ps) end
(* Obtain head equivalences of cu, normalized to a - b form, and where eachtermissimplified.
*) fun get_sub_head_equiv ctxt (id, ct) = let fun process_wf_head_equiv (id', (wft, eq_th)) = let val cts = subterms_of (Thm.rhs_of eq_th) val simps = Auto2_Setup.WellformData.simplify ctxt fheads cts (id', wft)
fun process_simp (id'', (wft', eq_th')) =
(BoxID.merge_boxes ctxt (id', id''),
(wft', Util.transitive_list [eq_th, eq_th'])) in map process_simp simps end in
(id, ct) |> Auto2_Setup.WellformData.get_head_equiv ctxt fheads
|> maps process_wf_head_equiv
|> filter_out (Thm.is_reflexive o snd o snd) end
(* Given wft in normalized form a - b, expand one of the subterms once.Callsthecorrespondingfunctioninac_stepsonaandb,then combinetheresults.
*) fun nat_sub_expand_once ctxt (id, wft) = let val ct = WfTerm.cterm_of wft val subt = subterms_of ct fun get_equiv cu = get_sub_head_equiv ctxt (id, cu)
fun process_info (id', wf_eq) =
(id', WfTerm.rewrite_on_eqs fheads [wf_eq] wft) in map process_info (maps get_equiv subt) end
(* Find all ways to write ct, up to a certain limit. *) fun nat_sub_expand ctxt (id, ct) = let val max_ac = Config.get ctxt Auto2_HOL_Extra_Setup.AC_ProofSteps.max_ac
fun ac_equiv_eq_better (id, (_, th)) (id', (_, th')) = let val seq1 = subterms_of (Thm.rhs_of th) val seq2 = subterms_of (Thm.rhs_of th') in
Util.is_subseq (op aconvc) (seq1, seq2) andalso
BoxID.is_eq_ancestor ctxt id id' end
fun has_ac_equiv_eq_better infos info' = exists (fn info => ac_equiv_eq_better info info') infos
fun helper (old, new) = case new of
[] => old
| (id', (wft, eq_th)) :: rest => if length old + length new > max_ac then
old @ take (max_ac - length old) new elselet val old' = ((id', (wft, eq_th)) :: old)
fun nat_sub_expand_unit_fn ctxt item = let val {id, tname, ...} = item val ct = the_single tname val t = Thm.term_of ct in ifnot (is_nat_sub_form t) then [] elselet val expand = nat_sub_expand ctxt (id, ct)
fun process_expand (id', (wft, eq_th)) = let val ct = Thm.rhs_of eq_th val ts = norm_minus_ct ct in if length ts = 0 orelse
(length ts = 1 andalso snd (the_single ts) = 1) then let val (_, eq') = norm_minus wft val eq = Util.transitive_list [eq_th, eq'] in
[(id', to_obj_eq eq)] end else [] end in
(maps process_expand expand)
|> filter (BoxID.has_incr_id o fst)
|> map (fn (id, th) => Auto2_Setup.Update.thm_update_sc 1 (id, th)) end end
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 und die Messung sind noch experimentell.