Theory Linear_Polynomial_Impl
subsection ‹An Implementation of Linear Polynomials as Ordered Association Lists›
theory Linear_Polynomial_Impl
imports
"HOL-Library.AList"
Linear_Polynomial
begin
typedef (overloaded) ('a :: zero,'v :: linorder) lpoly_impl =
"{ (c :: 'a, vcs :: ('v × 'a) list).
sorted (map fst vcs) ∧
distinct (map fst vcs) ∧
Ball (snd ` set vcs) ((≠) 0)}"
by (intro exI[of _ "(0,[])"], auto)
setup_lifting type_definition_lpoly_impl
definition lookup_0 :: "('a × 'b :: zero)list ⇒ 'a ⇒ 'b" where
"lookup_0 xs x = (case map_of xs x of None ⇒ 0 | Some y ⇒ y)"
lemma lookup_0_empty[simp]: "lookup_0 [] = (λ x. 0)"
by (intro ext, auto simp: lookup_0_def)
lemma lookup_0_single[simp]: "lookup_0 [(x,c)] = (λ y. 0)(x := c)"
by (intro ext, auto simp: lookup_0_def)
lemma finite_lookup_0[simp, intro]: "finite {x . lookup_0 xs x ≠ 0}"
unfolding lookup_0_def
by (rule finite_subset[OF _ finite_set, of _ "map fst xs"],
force split: option.splits dest!: map_of_SomeD)
lift_definition lpoly_of :: "('a :: zero, 'v :: linorder) lpoly_impl ⇒ ('a,'v)lpoly" is
"λ (c, vcs) cx. case cx of None ⇒ c | Some x ⇒ lookup_0 vcs x"
apply clarsimp
subgoal for c vcs
apply (rule finite_subset[of _ "insert None (Some ` {x. lookup_0 vcs x ≠ 0})"])
subgoal apply (clarsimp split: option.splits)
subgoal for x by (cases x, auto)
done
subgoal by simp
done
done
code_datatype lpoly_of
lift_definition zero_lpoly_impl :: "('a :: zero, 'v :: linorder) lpoly_impl" is
"(0,[])" by auto
lemma zero_lpoly_impl[code]: "0 = lpoly_of zero_lpoly_impl"
by (transfer, auto split: option.splits)
lift_definition const_lpoly_impl :: "'a ⇒ ('a :: zero, 'v :: linorder) lpoly_impl" is
"λ c. (c,[])" by auto
lemma const_lpoly_impl[code]: "const_l c = lpoly_of (const_lpoly_impl c)"
by (transfer, auto split: option.splits)
lift_definition constant_lpoly_impl :: "('a :: zero, 'v :: linorder) lpoly_impl ⇒ 'a" is fst .
lemma constant_lpoly_impl[code]: "constant_l (lpoly_of p) = constant_lpoly_impl p"
by (transfer, auto)
lift_definition var_lpoly_impl :: "'v :: linorder ⇒ ('a :: {comm_monoid_mult,zero_neq_one}, 'v) lpoly_impl" is
"λ x. (0, [(x,1)])" by auto
lemma var_lpoly_impl[code]: "var_l x = lpoly_of (var_lpoly_impl x)"
by transfer (auto split: option.splits)
lift_definition uminus_lpoly_impl :: "('a :: ab_group_add, 'v :: linorder) lpoly_impl ⇒ ('a,'v) lpoly_impl" is
"λ (c, vcs). (uminus c, map (map_prod id uminus) vcs)"
by force
lemma uminus_lpoly_impl[code]: "- lpoly_of p = lpoly_of (uminus_lpoly_impl p)"
by transfer (force split: option.split simp: map_of_eq_None_iff lookup_0_def eq_key_imp_eq_value)
fun merge_coeffs_main :: "('a :: zero ⇒ 'a ⇒ 'a) ⇒ ('v :: linorder × 'a) list ⇒ ('v × 'a)list ⇒ ('v × 'a)list" where
"merge_coeffs_main f ((x,c) # xs) ((y,d) # ys) = (
if x = y then (x,f c d) # merge_coeffs_main f xs ys
else if x < y then (x,f c 0) # merge_coeffs_main f xs ((y,d) # ys)
else (y,f 0 d) # merge_coeffs_main f ((x,c) # xs) ys)"
| "merge_coeffs_main f [] ys = map (map_prod id (f 0)) ys"
| "merge_coeffs_main f xs [] = map (map_prod id (λ x. f x 0)) xs"
lemma merge_coeffs_main: assumes "sorted (map fst vxs)" "distinct (map fst vxs)"
"sorted (map fst vys)" "distinct (map fst vys)"
and "f 0 0 = 0"
shows "sorted (map fst (merge_coeffs_main f vxs vys))
∧ distinct (map fst (merge_coeffs_main f vxs vys))
∧ fst ` set (merge_coeffs_main f vxs vys) = fst ` set vxs ∪ fst ` set vys
∧ lookup_0 (merge_coeffs_main f vxs vys) x = f (lookup_0 vxs x) (lookup_0 vys x)"
using assms
proof (induction f vxs vys rule: merge_coeffs_main.induct)
case (1 f x c xs y d ys)
let ?lhs = "merge_coeffs_main f ((x, c) # xs) ((y, d) # ys)"
consider (eq) "x = y" | (lt) "x ≠ y" "x < y" | (gt) "x ≠ y" "¬ x < y" by linarith
thus ?case
proof cases
case eq
from eq "1.prems" have "sorted (map fst xs)" "distinct (map fst xs)"
"sorted (map fst ys)" "distinct (map fst ys)" "f 0 0 = 0" by auto
note IH = "1.IH"(1)[OF eq this]
from eq have res: "?lhs = (x, f c d) # merge_coeffs_main f xs ys" by auto
from eq "1.prems" IH show ?thesis unfolding res using IH
apply (intro conjI)
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by (force simp: lookup_0_def map_of_eq_None_iff split: option.split dest: eq_key_imp_eq_value)
done
next
case lt
from lt "1.prems" have "sorted (map fst xs)" "distinct (map fst xs)"
"sorted (map fst ((y, d) # ys))" "distinct (map fst ((y, d) # ys))" "f 0 0 = 0" by auto
note IH = "1.IH"(2)[OF lt this]
from lt have res: "?lhs = (x, f c 0) # merge_coeffs_main f xs ((y, d) # ys)" by auto
from lt "1.prems" IH show ?thesis unfolding res using IH
apply (intro conjI)
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by (force simp: lookup_0_def map_of_eq_None_iff split: option.split dest: eq_key_imp_eq_value)
done
next
case gt
from gt "1.prems" have "sorted (map fst ((x, c) # xs))" "distinct (map fst ((x, c) # xs))"
"sorted (map fst ys)" "distinct (map fst ys)" "f 0 0 = 0" by auto
note IH = "1.IH"(3)[OF gt this]
from gt have res: "?lhs = (y, f 0 d) # merge_coeffs_main f ((x, c) # xs) ys" by auto
from gt "1.prems" IH show ?thesis unfolding res using IH
apply (intro conjI)
subgoal by auto
subgoal by auto
subgoal by auto
subgoal by (force simp: lookup_0_def map_of_eq_None_iff split: option.split dest: eq_key_imp_eq_value)
done
qed
next
case (2 f ys)
then show ?case
apply (intro conjI)
subgoal by force
subgoal by force
subgoal by force
by (force simp: map_of_eq_None_iff lookup_0_def split: option.split dest: eq_key_imp_eq_value)
next
case (3 f v va)
then show ?case
apply (intro conjI)
subgoal by force
subgoal by force
subgoal by force
by (force simp: map_of_eq_None_iff lookup_0_def split: option.split dest: eq_key_imp_eq_value)
qed
definition filter_0 where "filter_0 = filter (λ p. snd p ≠ 0)"
lemma filter_0: assumes "distinct (map fst xs)" "sorted (map fst xs)"
shows "lookup_0 (filter_0 xs) = lookup_0 xs"
"distinct (map fst (filter_0 xs))"
"sorted (map fst (filter_0 xs))"
"Ball (snd ` set (filter_0 xs)) ((≠) 0)"
subgoal
apply (intro ext)
apply (clarsimp simp: lookup_0_def filter_0_def split: option.split)
apply (intro conjI impI allI)
subgoal for x
by (smt (verit, ccfv_SIG) eq_snd_iff map_of_SomeD mem_Collect_eq not_None_eq set_filter weak_map_of_SomeI)
subgoal for x y by (force dest: map_of_SomeD simp: map_of_eq_None_iff)
subgoal for x y z using assms
by (metis (no_types, lifting) eq_key_imp_eq_value map_of_SomeD mem_Collect_eq set_filter)
done
subgoal using assms(1) unfolding filter_0_def by (rule distinct_map_filter)
subgoal using assms(2) unfolding filter_0_def by (rule sorted_filter)
subgoal unfolding filter_0_def by auto
done
definition merge_coeffs :: "('a :: zero ⇒ 'a ⇒ 'a) ⇒ ('v :: linorder × 'a) list ⇒ ('v × 'a)list ⇒ ('v × 'a)list" where
"merge_coeffs f xs ys = filter_0 (merge_coeffs_main f xs ys)"
lemma merge_coeffs: assumes "sorted (map fst vxs)" "distinct (map fst vxs)"
"sorted (map fst vys)" "distinct (map fst vys)"
and "f 0 0 = 0"
shows "sorted (map fst (merge_coeffs f vxs vys))" (is ?A)
"distinct (map fst (merge_coeffs f vxs vys))" (is ?B)
"Ball (snd ` set (merge_coeffs f vxs vys)) ((≠) 0)" (is ?C)
"lookup_0 (merge_coeffs f vxs vys) x = f (lookup_0 vxs x) (lookup_0 vys x)" (is ?D)
proof -
let ?m = "merge_coeffs_main f vxs vys"
from merge_coeffs_main[OF assms(1-4), of f, OF assms(5)]
have "distinct (map fst ?m)" "sorted (map fst ?m)" "lookup_0 ?m x = f (lookup_0 vxs x) (lookup_0 vys x)"
by auto
from filter_0[OF this(1-2)] this(3)
show ?A ?B ?C ?D
unfolding merge_coeffs_def[symmetric] by auto
qed
lift_definition minus_lpoly_impl :: "('a :: ab_group_add, 'v :: linorder) lpoly_impl ⇒ ('a,'v) lpoly_impl ⇒ ('a,'v) lpoly_impl" is
"λ (c, vxs) (d, vys). (c - d, merge_coeffs minus vxs vys)"
apply clarsimp
subgoal for vxs vys
using merge_coeffs[of vxs vys minus] by auto
done
lemma minus_lpoly_impl[code]: "lpoly_of p - lpoly_of q = lpoly_of (minus_lpoly_impl p q)"
apply transfer
apply clarsimp
apply (intro ext)
subgoal for a vxs b vys x
using merge_coeffs[of vxs vys minus]
by (cases x, auto)
done
lift_definition plus_lpoly_impl :: "('a :: ab_group_add, 'v :: linorder) lpoly_impl ⇒ ('a,'v) lpoly_impl ⇒ ('a,'v) lpoly_impl" is
"λ (c, vxs) (d, vys). (c + d, merge_coeffs plus vxs vys)"
apply clarsimp
subgoal for vxs vys
using merge_coeffs[of vxs vys plus] by auto
done
lemma plus_lpoly_impl[code]: "lpoly_of p + lpoly_of q = lpoly_of (plus_lpoly_impl p q)"
apply transfer
apply clarsimp
apply (intro ext)
subgoal for a vxs b vys x
using merge_coeffs[of vxs vys plus]
by (cases x, auto)
done
lift_definition map_lpoly_impl :: "('a :: zero ⇒ 'a) ⇒ ('a,'v :: linorder)lpoly_impl ⇒ ('a,'v)lpoly_impl" is
"λ f (c,vcs). (f c, filter_0 (map (map_prod id f) vcs))"
by clarsimp (intro conjI filter_0, auto simp: filter_0_def)
lemma map_lpoly_impl: "f 0 = 0 ⟹ fun_of_lpoly (lpoly_of (map_lpoly_impl f p)) = (λ x. f (fun_of_lpoly (lpoly_of p) x))"
apply (intro ext)
apply transfer
apply clarsimp
subgoal for x f c vcs
apply (cases x)
subgoal by simp
subgoal for y
apply (simp add: filter_0)
by (force simp: lookup_0_def map_of_eq_None_iff dest: eq_key_imp_eq_value split: option.split)
done
done
definition "sdiv_lpoly_impl p x = map_lpoly_impl (λ y. y div x) p"
lemma sdiv_lpoly_impl[code]: "sdiv_l (lpoly_of p) x = lpoly_of (sdiv_lpoly_impl p x)"
apply (intro lpoly_fun_of_eqI)
apply (unfold sdiv_lpoly_impl_def, subst map_lpoly_impl, force)
by transfer auto
definition "smult_lpoly_impl x p = map_lpoly_impl ((*) x) p"
lemma smult_lpoly_impl[code]: "smult_l x (lpoly_of p) = lpoly_of (smult_lpoly_impl x p)"
apply (intro lpoly_fun_of_eqI)
apply (unfold smult_lpoly_impl_def, subst map_lpoly_impl, force)
by transfer auto
instantiation lpoly :: (type,type)equal begin
definition equal_lpoly :: "('a, 'b) lpoly ⇒ ('a, 'b) lpoly ⇒ bool" where "equal_lpoly = (=)"
instance
by (intro_classes, auto simp: equal_lpoly_def)
end
instantiation lpoly_impl :: (zero,linorder)equal begin
lift_definition equal_lpoly_impl :: "('a, 'b) lpoly_impl ⇒ ('a, 'b) lpoly_impl ⇒ bool"
is "λ (c,xs) (d,ys). c = d ∧ xs = ys" .
instance
by (intro_classes, transfer, auto)
end
lift_definition vars_coeffs_impl :: "('a :: zero, 'v :: linorder) lpoly_impl ⇒ ('v × 'a) list" is snd .
lemma vars_coeffs_impl:
"set (vars_coeffs_impl p) = (λ v. (v, coeff_l (lpoly_of p) v)) ` vars_l (lpoly_of p)" (is ?A)
"distinct (map fst (vars_coeffs_impl p))" (is ?B)
"sorted (map fst (vars_coeffs_impl p))" (is ?C)
"vars_l_list (lpoly_of p) = map fst (vars_coeffs_impl p)" (is ?D)
"vars_coeffs_impl p = map (λ v. (v, coeff_l (lpoly_of p) v)) (vars_l_list (lpoly_of p))" (is ?E)
proof -
show ?A ?B ?C
proof (atomize(full), transfer, goal_cases)
case (1 p)
define vcs where "vcs = snd p"
with 1 have sort: "sorted (map fst vcs)" and
dist: "distinct (map fst vcs)" and
non0: "∀y∈set vcs. snd y ≠ 0" by auto
let ?set = "(λx. (x, lookup_0 vcs x)) ` {x. lookup_0 vcs x ≠ 0}"
{
fix x c
{
assume x: "(x,c) ∈ set vcs"
with non0 have c: "c ≠ 0" by auto
with dist x have "lookup_0 vcs x = c" unfolding lookup_0_def by simp
hence "(x,c) ∈ ?set" using c by auto
}
moreover
{
assume "(x,c) ∈ ?set"
hence look: "lookup_0 vcs x = c" and c: "c ≠ 0" by auto
hence "(x,c) ∈ set vcs" unfolding lookup_0_def
by (cases "map_of vcs x"; force dest: map_of_SomeD)
}
ultimately have "(x,c) ∈ set vcs ⟷ (x,c) ∈ ?set" by auto
}
with 1 show ?case unfolding vcs_def by auto
qed
show ?D unfolding vars_l_list_def using ‹?A› ‹?B› ‹?C›
by (metis (no_types, lifting) fst_eqD image_set list.map_comp list.map_ident_strong o_def sorted_distinct_set_unique sorted_list_of_set.distinct_sorted_key_list_of_set sorted_list_of_set.sorted_sorted_key_list_of_set vars_l_list vars_l_list_def)
show ?E using ‹?A› ‹?B› ‹?C› ‹?D›
by (smt (verit, ccfv_SIG) fst_conv image_iff list.map_comp list.map_ident_strong o_def)
qed
declare vars_coeffs_impl(4)[code]
declare eval_l_def[code del]
lemma eval_lpoly_impl[code]: "eval_l α (lpoly_of p) =
constant_lpoly_impl p + (∑(x, c) ← vars_coeffs_impl p. c * α x)"
unfolding eval_l_def constant_lpoly_impl
unfolding vars_coeffs_impl(5)
unfolding vars_l_list[symmetric]
apply (subst sum.distinct_set_conv_list)
subgoal unfolding vars_l_list_def by simp
subgoal unfolding map_map o_def split ..
done
declare substitute_all_l_def[code del]
lemma substitute_all_impl[code]: "substitute_all_l σ (lpoly_of p) =
const_l (constant_lpoly_impl p) + (∑(x, c) ← vars_coeffs_impl p. smult_l c (σ x))"
unfolding substitute_all_l_def constant_lpoly_impl
unfolding vars_coeffs_impl(5)
unfolding vars_l_list[symmetric]
apply (subst sum.distinct_set_conv_list)
subgoal unfolding vars_l_list_def by simp
subgoal unfolding map_map o_def split ..
done
lemma equal_lpoly_impl[code]: "HOL.equal (lpoly_of p) (lpoly_of q) = (p = q)"
proof (unfold equal_lpoly_def, standard)
assume *: "lpoly_of p = lpoly_of q"
hence "vars_coeffs_impl p = vars_coeffs_impl q"
unfolding vars_coeffs_impl(5) by simp
moreover from * have "constant_l (lpoly_of p) = constant_l (lpoly_of q)" by simp
from this[unfolded constant_lpoly_impl]
have "constant_lpoly_impl p = constant_lpoly_impl q" .
ultimately show "p = q" by transfer auto
qed auto
fun update_main :: "'v :: linorder ⇒ 'a :: zero ⇒ ('v × 'a) list ⇒ ('v × 'a) list" where
"update_main x a ((y,b) # zs) = (if x > y then (y,b) # update_main x a zs
else if x = y then (y, a) # zs else (x,a) # (y, b) # zs)"
| "update_main x a [] = [(x,a)]"
lemma update_main: assumes "sorted (map fst vcs)" "distinct (map fst vcs)" "Ball (snd ` set vcs) ((≠) 0)"
and "vcs' = update_main x a vcs"
and a: "a ≠ 0"
shows "sorted (map fst vcs')" "distinct (map fst vcs')" "Ball (snd ` set vcs') ((≠) 0)"
"fst ` set vcs' = insert x (fst ` set vcs)"
"lookup_0 vcs' z = ((lookup_0 vcs)(x := a)) z"
using assms(1-4)
proof (atomize(full), induct vcs arbitrary: vcs')
case Nil
thus ?case using a by auto
next
case (Cons p vcs vcs1)
obtain y b where p: "p = (y,b)" by force
note Cons = Cons[unfolded p list.simps fst_conv]
consider (gt) "x > y" | (lt) "x < y" | (eq) "x = y" by fastforce
thus ?case
proof cases
case gt
define vcs2 where "vcs2 = update_main x a vcs"
from gt Cons have vcs1: "vcs1 = (y, b) # vcs2" unfolding vcs2_def by auto
from Cons(2-) have *:
"sorted (map fst vcs)"
"distinct (map fst vcs)"
"∀y∈snd ` set vcs. 0 ≠ y" by auto
from Cons(1)[OF * vcs2_def] Cons(2-4) a gt
show ?thesis unfolding p vcs1 by (auto simp: lookup_0_def)
next
case lt
with Cons have vcs1: "vcs1 = (x,a) # (y,b) # vcs" by auto
from Cons(2-4) a lt
show ?thesis unfolding p vcs1 by (auto simp: lookup_0_def)
next
case eq
with Cons have vcs1: "vcs1 = (x,a) # vcs" by auto
from Cons(2-4) a eq
show ?thesis unfolding p vcs1 by (auto simp: lookup_0_def)
qed
qed
fun update_main_0 :: "'v :: linorder ⇒ ('v × 'a) list ⇒ ('v × 'a) list" where
"update_main_0 x ((y,b) # zs) = (if x > y then (y,b) # update_main_0 x zs
else if x = y then zs else (y, b) # zs)"
| "update_main_0 x [] = []"
lemma update_main_0: assumes "sorted (map fst vcs)" "distinct (map fst vcs)" "Ball (snd ` set vcs) ((≠) 0)"
and "vcs' = update_main_0 x vcs"
shows "sorted (map fst vcs')" "distinct (map fst vcs')" "Ball (snd ` set vcs') ((≠) 0)"
"fst ` set vcs' = fst ` set vcs - {x}"
"lookup_0 vcs' z = ((lookup_0 vcs)(x := 0)) z"
using assms(1-4)
proof (atomize(full), induct vcs arbitrary: vcs')
case Nil
hence vcs': "vcs' = []" by auto
show ?case unfolding vcs' by auto
next
case (Cons p vcs vcs1)
obtain y b where p: "p = (y,b)" by force
note Cons = Cons[unfolded p list.simps fst_conv]
consider (gt) "x > y" | (lt) "x < y" | (eq) "x = y" by fastforce
thus ?case
proof cases
case gt
define vcs2 where "vcs2 = update_main_0 x vcs"
from gt Cons have vcs1: "vcs1 = (y, b) # vcs2" unfolding vcs2_def by auto
from Cons(2-) have *:
"sorted (map fst vcs)"
"distinct (map fst vcs)"
"∀y∈snd ` set vcs. 0 ≠ y" by auto
from Cons(1)[OF * vcs2_def] Cons(2-4) gt
show ?thesis unfolding p vcs1 by (auto simp: lookup_0_def)
next
case lt
with Cons have vcs1: "vcs1 = (y,b) # vcs" by auto
from Cons(2-4) lt
show ?thesis unfolding p vcs1 by (auto simp: lookup_0_def split: option.split)
next
case eq
with Cons have vcs1: "vcs1 = vcs" by auto
from Cons(2-4) eq
show ?thesis unfolding p vcs1 by (force simp: lookup_0_def split: option.split)
qed
qed
lift_definition update_lpoly_impl :: "'v :: linorder ⇒ 'a :: zero ⇒ ('a,'v)lpoly_impl ⇒ ('a,'v)lpoly_impl" is
"λ x a (c, vs). if a = 0 then (c, update_main_0 x vs) else (c, update_main x a vs)"
apply clarsimp
subgoal for x a c vs d vcs
proof goal_cases
case 1
show ?case
proof (cases "a = 0")
case True
hence vcs: "vcs = update_main_0 x vs" and c: "c = d" using 1 by auto
from update_main_0[OF 1(2) 1(3) _ vcs] 1(4)
show ?thesis using c by auto
next
case False
hence vcs: "vcs = update_main x a vs" and c: "c = d" using 1 by auto
from update_main[OF 1(2) 1(3) _ vcs False] 1(4)
show ?thesis using c by auto
qed
qed
done
lemma update_lpoly_impl: "fun_of_lpoly (lpoly_of (update_lpoly_impl x a p)) = (fun_of_lpoly (lpoly_of p))(Some x := a)"
apply (transfer, clarsimp, intro conjI ext impI)
subgoal for x a z vs p
using update_main_0(5)[of vs _ x, OF _ _ _ refl]
by (cases p, auto)
subgoal for x a z vs p
using update_main(5)[of vs _ x a, OF _ _ _ refl]
by (cases p, auto)
done
lift_definition coeff_lpoly_impl :: "('a :: zero, 'v :: linorder)lpoly_impl ⇒ 'v ⇒ 'a" is
"λ (c,p) x. lookup_0 p x" .
lemma coeff_lpoly_impl[code]: "coeff_l (lpoly_of p) x = coeff_lpoly_impl p x"
by (transfer, auto)
definition substitute_l_impl where
"substitute_l_impl x p q = (let c = coeff_lpoly_impl q x in
plus_lpoly_impl (update_lpoly_impl x 0 q) (smult_lpoly_impl c p))"
lemma substitute_l_impl[code]:
"substitute_l x (lpoly_of p) (lpoly_of q) = lpoly_of (substitute_l_impl x p q)"
unfolding substitute_l_impl_def Let_def
unfolding plus_lpoly_impl[symmetric] smult_lpoly_impl[symmetric] coeff_lpoly_impl[symmetric]
proof (intro lpoly_fun_of_eqI, goal_cases)
case (1 y)
show ?case using update_lpoly_impl[of x 0 q]
by transfer auto
qed
definition reorder_nontriv_var_impl where
"reorder_nontriv_var_impl x p y = (let c = coeff_lpoly_impl p x
in update_lpoly_impl y (-1) (update_lpoly_impl x 1 (sdiv_lpoly_impl p c)))"
lemma reorder_nontriv_var_impl[code]:
"reorder_nontriv_var x (lpoly_of p) y = lpoly_of (reorder_nontriv_var_impl x p y)"
unfolding reorder_nontriv_var_impl_def Let_def sdiv_lpoly_impl_def coeff_lpoly_impl[symmetric]
proof (intro lpoly_fun_of_eqI, goal_cases)
case (1 z)
show ?case unfolding update_lpoly_impl
apply (subst map_lpoly_impl, force)
by transfer auto
qed
declare min_var_def[code del]
lemmas min_var_impl = min_var_def[of "lpoly_of p" for p,
folded vars_coeffs_impl(5)]
declare min_var_impl[code]
declare gcd_coeffs_l_def[code del]
lemma Gcd_set: "Gcd (set (xs :: 'a :: semiring_Gcd list)) = gcd_list xs"
unfolding Gcd_set_eq_fold Gcd_fin.set_eq_fold[of xs] ..
lemma gcd_coeffs_impl[code]:
"gcd_coeffs_l (lpoly_of (p :: ('a :: semiring_Gcd,_)lpoly_impl)) = fold gcd (map snd (vars_coeffs_impl p)) 0"
unfolding gcd_coeffs_l_def vars_coeffs_impl(5) map_map o_def snd_conv
unfolding vars_l_list[symmetric] image_set Gcd_set Gcd_fin.set_eq_fold ..
lift_definition change_const_impl :: "'a ⇒ ('a :: zero, 'v :: linorder)lpoly_impl ⇒ ('a, 'v)lpoly_impl"
is "λ c (d,vs). (c,vs)" by auto
lemma change_const_impl[code]: "change_const c (lpoly_of p) = lpoly_of (change_const_impl c p)"
by (intro lpoly_fun_of_eqI, transfer, auto)
end