ring2
An experimental variant on the ring
tactic that uses computational
reflection instead of proof generation. Useful for kernel benchmarking.
Returns an element indexed by n
, or zero if n
isn't a valid index.
See tree.get
.
Equations
- t.get_or_zero n = tree.get_or_else n t 0
- atom : pos_num → tactic.ring2.csring_expr
- const : num → tactic.ring2.csring_expr
- add : tactic.ring2.csring_expr → tactic.ring2.csring_expr → tactic.ring2.csring_expr
- mul : tactic.ring2.csring_expr → tactic.ring2.csring_expr → tactic.ring2.csring_expr
- pow : tactic.ring2.csring_expr → num → tactic.ring2.csring_expr
A reflected/meta representation of an expression in a commutative
semiring. This representation is a direct translation of such
expressions - see horner_expr
for a normal form.
Equations
Evaluates a reflected csring_expr
into an element of the
original comm_semiring
type α
, retrieving opaque elements
(atoms) from the tree t
.
Equations
- tactic.ring2.csring_expr.eval t (x.pow n) = tactic.ring2.csring_expr.eval t x ^ ↑n
- tactic.ring2.csring_expr.eval t (x.mul y) = tactic.ring2.csring_expr.eval t x * tactic.ring2.csring_expr.eval t y
- tactic.ring2.csring_expr.eval t (x.add y) = tactic.ring2.csring_expr.eval t x + tactic.ring2.csring_expr.eval t y
- tactic.ring2.csring_expr.eval t (tactic.ring2.csring_expr.const n) = ↑n
- tactic.ring2.csring_expr.eval t (tactic.ring2.csring_expr.atom n) = t.get_or_zero n
- const : znum → tactic.ring2.horner_expr
- horner : tactic.ring2.horner_expr → pos_num → num → tactic.ring2.horner_expr → tactic.ring2.horner_expr
An efficient representation of expressions in a commutative
semiring using the sparse Horner normal form. This type admits
non-optimal instantiations (e.g. P
can be represented as P+0+0
),
so to get good performance out of it, care must be taken to maintain
an optimal, canonical form.
True iff the horner_expr
argument is a valid csring_expr
.
For that to be the case, all its constants must be non-negative.
Equations
Equations
Equations
Represent a csring_expr.atom
in Horner form.
Equations
- tactic.ring2.horner_expr.atom n = 1.horner n 1 0
Alternative constructor for (horner a x n b) which maintains canonical
form by simplifying special cases of a
.
Equations
- a.horner' x n b = tactic.ring2.horner_expr.horner'._match_1 a x n b a
- tactic.ring2.horner_expr.horner'._match_1 a x n b (a₁.horner x₁ n₁ b₁) = ite (x₁ = x ∧ b₁ = 0) (a₁.horner x (n₁ + n) b) (a.horner x n b)
- tactic.ring2.horner_expr.horner'._match_1 a x n b (tactic.ring2.horner_expr.const q) = ite (q = 0) b (a.horner x n b)
Equations
- tactic.ring2.horner_expr.add_const k e = ite (k = 0) e (tactic.ring2.horner_expr.rec (λ (n : znum), tactic.ring2.horner_expr.const (k + n)) (λ (a : tactic.ring2.horner_expr) (x : pos_num) (n : num) (b A B : tactic.ring2.horner_expr), a.horner x n B) e)
Equations
- a₁.add_aux A₁ x₁ (a₂.horner x₂ n₂ b₂) n₁ b₁ B₁ = let e₂ : tactic.ring2.horner_expr := a₂.horner x₂ n₂ b₂ in tactic.ring2.horner_expr.add_aux._match_1 a₁ A₁ x₁ a₂ x₂ n₂ b₂ n₁ B₁ e₂ (a₁.add_aux A₁ x₁ b₂ n₁ b₁ B₁) (λ (k : pos_num), a₁.add_aux A₁ x₁ a₂ ↑k 0 id) (x₁.cmp x₂)
- a₁.add_aux A₁ x₁ (tactic.ring2.horner_expr.const n₂) n₁ b₁ B₁ = tactic.ring2.horner_expr.add_const n₂ (a₁.horner x₁ n₁ b₁)
- tactic.ring2.horner_expr.add_aux._match_1 a₁ A₁ x₁ a₂ x₂ n₂ b₂ n₁ B₁ e₂ _f_1 _f_2 ordering.gt = a₂.horner x₂ n₂ _f_1
- tactic.ring2.horner_expr.add_aux._match_1 a₁ A₁ x₁ a₂ x₂ n₂ b₂ n₁ B₁ e₂ _f_1 _f_2 ordering.eq = tactic.ring2.horner_expr.add_aux._match_2 A₁ x₁ a₂ n₂ b₂ n₁ B₁ (λ (k : pos_num), _f_2 k) (n₁.sub' n₂)
- tactic.ring2.horner_expr.add_aux._match_1 a₁ A₁ x₁ a₂ x₂ n₂ b₂ n₁ B₁ e₂ _f_1 _f_2 ordering.lt = a₁.horner x₁ n₁ (B₁ e₂)
- tactic.ring2.horner_expr.add_aux._match_2 A₁ x₁ a₂ n₂ b₂ n₁ B₁ _f_1 (znum.neg k) = (A₁ (a₂.horner x₁ ↑k 0)).horner x₁ n₁ (B₁ b₂)
- tactic.ring2.horner_expr.add_aux._match_2 A₁ x₁ a₂ n₂ b₂ n₁ B₁ _f_1 (znum.pos k) = (_f_1 k).horner x₁ n₂ (B₁ b₂)
- tactic.ring2.horner_expr.add_aux._match_2 A₁ x₁ a₂ n₂ b₂ n₁ B₁ _f_1 znum.zero = (A₁ a₂).horner' x₁ n₁ (B₁ b₂)
Equations
- (a₁.horner x₁ n₁ b₁).add e₂ = a₁.add_aux a₁.add x₁ e₂ n₁ b₁ b₁.add
- (tactic.ring2.horner_expr.const n₁).add e₂ = tactic.ring2.horner_expr.add_const n₁ e₂
Equations
- e.neg = tactic.ring2.horner_expr.rec (λ (n : znum), tactic.ring2.horner_expr.const (-n)) (λ (a : tactic.ring2.horner_expr) (x : pos_num) (n : num) (b A B : tactic.ring2.horner_expr), A.horner x n B) e
Equations
- tactic.ring2.horner_expr.mul_const k e = ite (k = 0) 0 (ite (k = 1) e (tactic.ring2.horner_expr.rec (λ (n : znum), tactic.ring2.horner_expr.const (n * k)) (λ (a : tactic.ring2.horner_expr) (x : pos_num) (n : num) (b A B : tactic.ring2.horner_expr), A.horner x n B) e))
Equations
- a₁.mul_aux x₁ n₁ b₁ A₁ B₁ (a₂.horner x₂ n₂ b₂) = tactic.ring2.horner_expr.mul_aux._match_1 x₁ n₁ A₁ B₁ a₂ x₂ n₂ b₂ (a₁.mul_aux x₁ n₁ b₁ A₁ B₁ a₂) (a₁.mul_aux x₁ n₁ b₁ A₁ B₁ b₂) (a₁.mul_aux x₁ n₁ b₁ A₁ B₁ a₂) (x₁.cmp x₂)
- a₁.mul_aux x₁ n₁ b₁ A₁ B₁ (tactic.ring2.horner_expr.const n₂) = tactic.ring2.horner_expr.mul_const n₂ (a₁.horner x₁ n₁ b₁)
- tactic.ring2.horner_expr.mul_aux._match_1 x₁ n₁ A₁ B₁ a₂ x₂ n₂ b₂ _f_1 _f_2 _f_3 ordering.gt = _f_1.horner x₂ n₂ _f_2
- tactic.ring2.horner_expr.mul_aux._match_1 x₁ n₁ A₁ B₁ a₂ x₂ n₂ b₂ _f_1 _f_2 _f_3 ordering.eq = let haa : tactic.ring2.horner_expr := _f_3.horner' x₁ n₂ 0 in ite (b₂ = 0) haa (haa.add ((A₁ b₂).horner x₁ n₁ (B₁ b₂)))
- tactic.ring2.horner_expr.mul_aux._match_1 x₁ n₁ A₁ B₁ a₂ x₂ n₂ b₂ _f_1 _f_2 _f_3 ordering.lt = (A₁ (a₂.horner x₂ n₂ b₂)).horner x₁ n₁ (B₁ (a₂.horner x₂ n₂ b₂))
Equations
- (a₁.horner x₁ n₁ b₁).mul = a₁.mul_aux x₁ n₁ b₁ a₁.mul b₁.mul
- (tactic.ring2.horner_expr.const n₁).mul = tactic.ring2.horner_expr.mul_const n₁
Equations
Equations
Equations
Brings expressions into Horner normal form.
Equations
- tactic.ring2.horner_expr.of_csexpr (x.pow n) = (tactic.ring2.horner_expr.of_csexpr x).pow n
- tactic.ring2.horner_expr.of_csexpr (x.mul y) = (tactic.ring2.horner_expr.of_csexpr x).mul (tactic.ring2.horner_expr.of_csexpr y)
- tactic.ring2.horner_expr.of_csexpr (x.add y) = (tactic.ring2.horner_expr.of_csexpr x).add (tactic.ring2.horner_expr.of_csexpr y)
- tactic.ring2.horner_expr.of_csexpr (tactic.ring2.csring_expr.const n) = tactic.ring2.horner_expr.const n.to_znum
- tactic.ring2.horner_expr.of_csexpr (tactic.ring2.csring_expr.atom n) = tactic.ring2.horner_expr.atom n
Evaluates a reflected horner_expr
- see csring_expr.eval
.
Equations
- tactic.ring2.horner_expr.cseval t (a.horner x n b) = tactic.ring.horner (tactic.ring2.horner_expr.cseval t a) (t.get_or_zero x) ↑n (tactic.ring2.horner_expr.cseval t b)
- tactic.ring2.horner_expr.cseval t (tactic.ring2.horner_expr.const n) = ↑(n.abs)
For any given tree t
of atoms and any reflected expression r
,
the Horner form of r
is a valid csring expression, and under t
,
the Horner form evaluates to the same thing as r
.
The main proof-by-reflection theorem. Given reflected csring expressions
r₁
and r₂
plus a storage t
of atoms, if both expressions go to the
same Horner normal form, then the original non-reflected expressions are
equal. H
follows from kernel reduction and is therefore rfl
.
Reflects a csring expression into a csring_expr
, together
with a dlist of atoms, i.e. opaque variables over which the
expression is a polynomial.
In the output of reflect_expr
, atom
s are initialized with incorrect indices.
The indices cannot be computed until the whole tree is built, so another pass over
the expressions is needed - this is what replace
does. The computation (expressed
in the state monad) fixes up atom
s to match their positions in the atom tree.
The initial state is a list of all atom occurrences in the goal, left-to-right.