open import 1Lab.Reflection.Variables
open import 1Lab.Reflection.Solver
open import 1Lab.Reflection
open import Algebra.Ring.Cat.Initial
open import Algebra.Ring.Commutative
open import Algebra.Group.Ab
open import Algebra.Group
open import Algebra.Ring
open import Cat.Displayed.Total
open import Cat.Prelude hiding (_+_ ; _*_ ; _-_)
open import Data.Fin.Product
open import Data.Fin.Base
open import Data.Int.Base
open import Data.List hiding (lookup ; tabulate)
open import Data.Dec
open import Data.Nat
import Algebra.Ring.Reasoning as Kit
import Data.Int.Base as B
open Total-hom
module Algebra.Ring.Solver where
module Impl {ℓ} {R : Type ℓ} (cring : CRing-on R) where
private
R' : Ring _
R' = record { fst = el _ (CRing-on.has-is-set cring) ; snd = CRing-on.has-ring-on cring }
module R = Kit R'
ℤ↪R-rh = Int-is-initial R' .centre
module ℤ↪R = is-ring-hom (ℤ↪R-rh .preserves)
open CRing-on cring using (*-commutes)
embed-coe : Int → R
embed-coe x = ℤ↪R-rh .hom (lift x)
embed-lemma : {h' : Int → R} → is-ring-hom (Liftℤ {ℓ} .snd) (R' .snd) (h' ⊙ lower) → ∀ x → embed-coe x ≡ h' x
embed-lemma p x = happly (ap Total-hom.hom (Int-is-initial R' .paths (total-hom _ p))) (lift x)
data Poly : Nat → Type ℓ
data Normal : Nat → Type ℓ
data Poly where
∅ : ∀ {n} → Poly n
_*x+_ : ∀ {n} → Poly (suc n) → Normal n → Poly (suc n)
data Normal where
con : Int → Normal 0
poly : ∀ {n} → Poly (suc n) → Normal (suc n)
Ep : ∀ {n} → Poly (suc n) → Vec R (suc n) → R
En : ∀ {n} → Normal n → Vec R n → R
Ep ∅ i = R.0r
Ep (p *x+ c) (x ∷ e) = Ep p (x ∷ e) R.* x R.+ En c e
En (con x) i = embed-coe x
En (poly x) i = Ep x i
0h : ∀ {n} → Poly n
0n : ∀ {n} → Normal n
0h = ∅
0n {zero} = con 0
0n {suc n} = poly 0h
1h : ∀ {n} → Poly (suc n)
1n : ∀ {n} → Normal n
1h {n} = ∅ *x+ 1n {n}
1n {zero} = con 1
1n {suc n} = poly 1h
_==ₕ_ : ∀ {n} (x y : Poly n) → Maybe (x ≡ y)
_==ₙ_ : ∀ {n} (x y : Normal n) → Maybe (x ≡ y)
∅ ==ₕ ∅ = just refl
∅ ==ₕ (_ *x+ _) = nothing
(_ *x+ _) ==ₕ ∅ = nothing
(p *x+ x) ==ₕ (q *x+ y) with p ==ₕ q | x ==ₙ y
... | just p=q | just x=y = just $ ap₂ _*x+_ p=q x=y
... | just _ | nothing = nothing
... | nothing | just _ = nothing
... | nothing | nothing = nothing
con c ==ₙ con d with c ≡? d
... | yes c=d = just (ap con c=d)
... | no ¬c=d = nothing
poly x ==ₙ poly y with x ==ₕ y
... | just x=y = just $ ap poly x=y
... | nothing = nothing
_*x+ₙ_ : ∀ {n} → Poly (suc n) → Normal n → Poly (suc n)
(p *x+ c') *x+ₙ c = (p *x+ c') *x+ c
∅ *x+ₙ c with c ==ₙ 0n
... | just c≈0 = ∅
... | nothing = ∅ *x+ c
_+ₚ_ : ∀ {n} → Poly (suc n) → Poly (suc n) → Poly (suc n)
_+ₙ_ : ∀ {n} → Normal n → Normal n → Normal n
∅ +ₚ y = y
y +ₚ ∅ = y
(p *x+ x) +ₚ (q *x+ y) = (p +ₚ q) *x+ₙ (x +ₙ y)
con x +ₙ con y = con (x +ℤ y)
poly x +ₙ poly y = poly (x +ₚ y)
_*x+ₚ_ : ∀ {n} → Poly (suc n) → Poly (suc n) → Poly (suc n)
p *x+ₚ (q *x+ d) = (p +ₚ q) *x+ₙ d
∅ *x+ₚ ∅ = ∅
(p *x+ c) *x+ₚ ∅ = (p *x+ c) *x+ 0n
_*ₙₚ_ : ∀ {n} → Normal n → Poly (suc n) → Poly (suc n)
_*ₚₙ_ : ∀ {n} → Poly (suc n) → Normal n → Poly (suc n)
_*ₚ_ : ∀ {n} → Poly (suc n) → Poly (suc n) → Poly (suc n)
_*ₙ_ : ∀ {n} → Normal n → Normal n → Normal n
infix 30 _*ₙₚ_ _*ₚₙ_ _*ₚ_ _*ₙ_
c *ₙₚ ∅ = ∅
c *ₙₚ (p *x+ d) with c ==ₙ 0n
... | just _ = ∅
... | nothing = (c *ₙₚ p) *x+ (c *ₙ d)
∅ *ₚₙ y = ∅
(p *x+ c) *ₚₙ d with d ==ₙ 0n
... | just _ = ∅
... | nothing = (p *ₚₙ d) *x+ (c *ₙ d)
con x *ₙ con y = con (x *ℤ y)
poly x *ₙ poly y = poly (x *ₚ y)
∅ *ₚ _ = ∅
(p *x+ c) *ₚ ∅ = ∅
(p *x+ c) *ₚ (q *x+ d) = ((p *ₚ q) *x+ₚ (p *ₚₙ d +ₚ c *ₙₚ q)) *x+ₙ (c *ₙ d)
-ₙ_ : ∀ {n} → Normal n → Normal n
-ₚ_ : ∀ {n} → Poly (suc n) → Poly (suc n)
-ₙ con x = con (negℤ x)
-ₙ poly x = poly (-ₚ x)
-ₚ x = (-ₙ 1n) *ₙₚ x
data Op : Type where
[+] : Op
[*] : Op
data Polynomial (m : Nat) : Type ℓ where
op : (o : Op) (p q : Polynomial m) → Polynomial m
con : (c : Int) → Polynomial m
var : (x : Fin m) → Polynomial m
:-_ : (p : Polynomial m) → Polynomial m
infixl 30 _:-_ _:+_
infixl 40 _:*_
_:+_ : ∀ {n} → Polynomial n → Polynomial n → Polynomial n
_:+_ = op [+]
_:*_ : ∀ {n} → Polynomial n → Polynomial n → Polynomial n
_:*_ = op [*]
_:-_ : ∀ {n} → Polynomial n → Polynomial n → Polynomial n
x :- y = x :+ (:- y)
_:×_ : ∀ {n} → Nat → Polynomial n → Polynomial n
zero :× p = con 0
suc m :× p = p :+ (m :× p)
sem : Op → R → R → R
sem [+] = R._+_
sem [*] = R._*_
eval : ∀ {n} → Polynomial n → Vec R n → R
instance
⟦⟧-Polynomial : ∀ {n} → ⟦⟧-notation (Polynomial n)
⟦⟧-Polynomial = brackets _ eval
Number-Polynomial : ∀ {n} → Number (Polynomial n)
Number-Polynomial .Number.Constraint x = Lift _ ⊤
Number-Polynomial .Number.fromNat n = con (pos n)
eval (op o p₁ p₂) ρ = sem o (⟦ p₁ ⟧ ρ) (⟦ p₂ ⟧ ρ)
eval (con c) ρ = embed-coe c
eval (var x) ρ = lookup ρ x
eval (:- p) ρ = R.- ⟦ p ⟧ ρ
normal-coe : ∀ {n} → Int → Normal n
normal-coe {zero} x = con x
normal-coe {suc n} x = poly (∅ *x+ₙ normal-coe x)
normal-var : ∀ {n} → Fin n → Normal n
normal-var fzero = poly ((∅ *x+ 1n) *x+ 0n)
normal-var (fsuc f) = poly (∅ *x+ₙ normal-var f)
normal : ∀ {n} → Polynomial n → Normal n
normal (op [+] x y) = normal x +ₙ normal y
normal (op [*] x y) = normal x *ₙ normal y
normal (con c) = normal-coe c
normal (var x) = normal-var x
normal (:- x) = -ₙ (normal x)
⟦_⟧ₙ : ∀ {n} → Polynomial n → Vec R n → R
⟦ x ⟧ₙ ρ = En (normal x) ρ
0n-hom : ∀ {n} (ρ : Vec R n) → En 0n ρ ≡ R.0r
0n-hom [] = ℤ↪R.pres-0
0n-hom (x ∷ ρ) = refl
1n-hom : ∀ {n} (ρ : Vec R n) → En 1n ρ ≡ R.1r
1n-hom [] = ℤ↪R.pres-id
1n-hom (x ∷ ρ) =
(R.0r R.* x) R.+ (En 1n ρ) ≡⟨ R.eliml R.*-zerol ⟩
En 1n ρ ≡⟨ 1n-hom ρ ⟩
R.1r ∎
*x+ₙ-sound
: ∀ {n} (p : Poly (suc n)) (c : Normal n) ρ
→ Ep (p *x+ₙ c) ρ ≡ Ep (p *x+ c) ρ
*x+ₙ-sound ∅ c (e ∷ ρ) with c ==ₙ 0n
... | just x = sym $
Ep (∅ *x+ ⌜ c ⌝) (e ∷ ρ) ≡⟨ ap! x ⟩
Ep (∅ *x+ 0n) (e ∷ ρ) ≡⟨⟩
(R.0r R.* e) R.+ En 0n ρ ≡⟨ R.eliml R.*-zerol ⟩
En 0n ρ ≡⟨ 0n-hom ρ ⟩
R.0r ∎
... | nothing = refl
*x+ₙ-sound (p *x+ x) c ρ = refl
∅*x+ₙ-hom
: ∀ {n} (c : Normal n) x ρ
→ Ep (∅ *x+ₙ c) (x ∷ ρ) ≡ En c ρ
∅*x+ₙ-hom c x ρ with c ==ₙ 0n
... | just x = sym (ap (λ c → En c ρ) x ∙ 0n-hom ρ)
... | nothing = R.eliml R.*-zerol
+ₚ-hom
: ∀ {n} (p q : Poly (suc n)) ρ
→ Ep (p +ₚ q) ρ ≡ Ep p ρ R.+ Ep q ρ
+ₙ-hom
: ∀ {n} (p q : Normal n) ρ
→ En (p +ₙ q) ρ ≡ En p ρ R.+ En q ρ
+ₚ-hom ∅ q ρ = sym R.+-idl
+ₚ-hom (p *x+ x) ∅ ρ = sym R.+-idr
+ₚ-hom (p *x+ c) (q *x+ d) (x ∷ ρ) =
Ep ((p +ₚ q) *x+ₙ (c +ₙ d)) (x ∷ ρ) ≡⟨ *x+ₙ-sound (p +ₚ q) (c +ₙ d) (x ∷ ρ) ⟩
Ep ((p +ₚ q) *x+ (c +ₙ d)) (x ∷ ρ) ≡⟨⟩
⌜ Ep (p +ₚ q) (x ∷ ρ) ⌝ R.* x R.+ En (c +ₙ d) ρ ≡⟨ ap! (+ₚ-hom p q (x ∷ ρ)) ⟩
(Ep p (x ∷ ρ) R.+ Ep q (x ∷ ρ)) R.* x R.+ ⌜ En (c +ₙ d) ρ ⌝ ≡⟨ ap! (+ₙ-hom c d ρ) ⟩
⌜ (Ep p (x ∷ ρ) R.+ Ep q (x ∷ ρ)) R.* x ⌝ R.+ (En c ρ R.+ En d ρ) ≡⟨ ap! R.*-distribr ⟩
Ep p (x ∷ ρ) R.* x R.+ Ep q (x ∷ ρ) R.* x R.+ (En c ρ R.+ En d ρ) ≡⟨ R.a.pullr (R.pulll R.+-commutes) ⟩
Ep p (x ∷ ρ) R.* x R.+ (En c ρ R.+ Ep q (x ∷ ρ) R.* x R.+ En d ρ) ≡⟨ R.a.extendl (R.a.pulll refl) ⟩
Ep p (x ∷ ρ) R.* x R.+ En c ρ R.+ (Ep q (x ∷ ρ) R.* x R.+ En d ρ) ∎
+ₙ-hom (con x) (con y) ρ = ℤ↪R.pres-+ (lift x) (lift y)
+ₙ-hom (poly p) (poly q) ρ = +ₚ-hom p q ρ
*x+-hom
: ∀ {n} (p q : Poly (suc n)) x ρ
→ Ep (p *x+ₚ q) (x ∷ ρ)
≡ Ep p (x ∷ ρ) R.* x R.+ Ep q (x ∷ ρ)
*x+-hom ∅ ∅ x ρ = R.introl R.*-zerol
*x+-hom (p *x+ c) ∅ x ρ = ap₂ R._+_ refl (0n-hom ρ)
*x+-hom p (q *x+ d) x ρ =
Ep (p *x+ₚ (q *x+ d)) (x ∷ ρ) ≡⟨⟩
Ep ((p +ₚ q) *x+ₙ d) (x ∷ ρ) ≡⟨ *x+ₙ-sound (p +ₚ q) d (x ∷ ρ) ⟩
⌜ Ep (p +ₚ q) (x ∷ ρ) ⌝ R.* x R.+ En d ρ ≡⟨ ap! (+ₚ-hom p q (x ∷ ρ)) ⟩
⌜ (Ep p (x ∷ ρ) R.+ Ep q (x ∷ ρ)) R.* x ⌝ R.+ En d ρ ≡⟨ ap! R.*-distribr ⟩
Ep p (x ∷ ρ) R.* x R.+ Ep q (x ∷ ρ) R.* x R.+ En d ρ ≡⟨ R.pullr refl ⟩
Ep p (x ∷ ρ) R.* x R.+ (Ep q (x ∷ ρ) R.* x R.+ En d ρ) ∎
*ₙₚ-hom
: ∀ {n} (c : Normal n) (p : Poly (suc n)) x ρ
→ Ep (c *ₙₚ p) (x ∷ ρ) ≡ En c ρ R.* Ep p (x ∷ ρ)
*ₚₙ-hom
: ∀ {n} (c : Normal n) (p : Poly (suc n)) x ρ
→ Ep (p *ₚₙ c) (x ∷ ρ) ≡ Ep p (x ∷ ρ) R.* En c ρ
*ₙ-hom : ∀ {n} (c d : Normal n) ρ → En (c *ₙ d) ρ ≡ En c ρ R.* En d ρ
*ₚ-hom : ∀ {n} (p q : Poly (suc n)) ρ → Ep (p *ₚ q) ρ ≡ Ep p ρ R.* Ep q ρ
*ₚ-hom ∅ q ρ = sym R.*-zerol
*ₚ-hom (p *x+ c) ∅ ρ = sym R.*-zeror
*ₚ-hom (p *x+ c) (q *x+ d) (x ∷ ρ) =
*x+ₙ-sound ((p *ₚ q) *x+ₚ ((p *ₚₙ d) +ₚ (c *ₙₚ q))) _ (x ∷ ρ)
∙ ap₂ R._+_ (ap₂ R._*_ (*x+-hom (p *ₚ q) ((p *ₚₙ d) +ₚ (c *ₙₚ q)) x ρ) refl) refl
∙ ap₂ R._+_ (ap₂ R._*_ (ap₂ R._+_ (ap (R._* x) (*ₚ-hom p q (x ∷ ρ)))
(+ₚ-hom (p *ₚₙ d) (c *ₙₚ q) (x ∷ ρ))) refl
∙ ap₂ R._*_ (ap₂ R._+_ refl (ap₂ R._+_ (*ₚₙ-hom d p x ρ) (*ₙₚ-hom c q x ρ)))
refl) refl
∙ ap₂ R._+_ refl (*ₙ-hom c d ρ) ∙ lemma _ _ _ _ _
where
lemma
: ∀ p q x d c
→ (p R.* q R.* x R.+ ((p R.* d) R.+ (c R.* q))) R.* x R.+ (c R.* d)
≡ (p R.* x R.+ c) R.* (q R.* x R.+ d)
lemma a c x d b =
(a R.* c R.* x R.+ (a R.* d R.+ b R.* c)) R.* x R.+ b R.* d ≡⟨ ap₂ R._+_ R.*-distribr refl ⟩
(a R.* c R.* x R.* x R.+ (a R.* d R.+ b R.* c) R.* x) R.+ b R.* d ≡⟨ sym R.+-associative ⟩
a R.* c R.* x R.* x R.+ ((a R.* d R.+ b R.* c) R.* x R.+ b R.* d) ≡⟨ ap₂ R._+_ lem₁ (ap₂ R._+_ lem₂ refl) ⟩
a R.* x R.* (c R.* x) R.+ (a R.* x R.* d R.+ b R.* (c R.* x) R.+ b R.* d) ≡⟨ ap₂ R._+_ refl (sym R.+-associative) ⟩
a R.* x R.* (c R.* x) R.+ (a R.* x R.* d R.+ (b R.* (c R.* x) R.+ b R.* d)) ≡⟨ R.+-associative ⟩
a R.* x R.* (c R.* x) R.+ a R.* x R.* d R.+ (b R.* (c R.* x) R.+ b R.* d) ≡˘⟨ ap₂ R._+_ R.*-distribl R.*-distribl ⟩
a R.* x R.* (c R.* x R.+ d) R.+ b R.* (c R.* x R.+ d) ≡˘⟨ R.*-distribr ⟩
(a R.* x R.+ b) R.* (c R.* x R.+ d) ∎
where
lem₁' =
a R.* c R.* x ≡˘⟨ R.*-associative ⟩
a R.* ⌜ c R.* x ⌝ ≡⟨ ap! *-commutes ⟩
a R.* (x R.* c) ≡⟨ R.*-associative ⟩
a R.* x R.* c ∎
lem₁ =
a R.* c R.* x R.* x ≡⟨ ap₂ R._*_ lem₁' refl ⟩
a R.* x R.* c R.* x ≡˘⟨ R.*-associative ⟩
a R.* x R.* (c R.* x) ∎
lem₂ =
(a R.* d R.+ b R.* c) R.* x ≡⟨ R.*-distribr ⟩
a R.* d R.* x R.+ b R.* c R.* x ≡˘⟨ ap₂ R._+_ R.*-associative R.*-associative ⟩
a R.* ⌜ d R.* x ⌝ R.+ b R.* (c R.* x) ≡⟨ ap! *-commutes ⟩
a R.* (x R.* d) R.+ b R.* (c R.* x) ≡⟨ ap₂ R._+_ R.*-associative refl ⟩
a R.* x R.* d R.+ b R.* (c R.* x) ∎
*ₙ-hom (con x) (con y) ρ = ℤ↪R.pres-* (lift x) (lift y)
*ₙ-hom (poly p) (poly q) ρ = *ₚ-hom p q ρ
*ₙₚ-hom c ∅ x ρ = sym R.*-zeror
*ₙₚ-hom c (p *x+ d) x ρ with c ==ₙ 0n
... | just c=0 = sym (ap₂ R._*_ (ap (λ e → En e ρ) c=0 ∙ 0n-hom ρ) refl ∙ R.*-zerol)
... | nothing =
ap₂ R._+_ (ap (R._* x) (*ₙₚ-hom c p x ρ) ∙ sym R.*-associative) (*ₙ-hom c d ρ)
∙ sym R.*-distribl
*ₚₙ-hom c ∅ x ρ = sym R.*-zerol
*ₚₙ-hom c (p *x+ d) x ρ with c ==ₙ 0n
... | just c=0 = sym (ap₂ R._*_ refl (ap (λ e → En e ρ) c=0 ∙ 0n-hom ρ) ∙ R.*-zeror)
... | nothing =
ap₂ R._+_ (ap (R._* x) (*ₚₙ-hom c p x ρ) ·· sym R.*-associative ·· ap₂ R._*_ refl *-commutes ∙ R.*-associative)
(*ₙ-hom d c ρ)
∙ sym R.*-distribr
-ₚ-hom : ∀ {n} (p : Poly (suc n)) ρ → Ep (-ₚ p) ρ ≡ R.- Ep p ρ
-ₙ-hom : ∀ {n} (n : Normal n) ρ → En (-ₙ n) ρ ≡ R.- En n ρ
-ₚ-hom p (x ∷ ρ) =
*ₙₚ-hom (-ₙ 1n) p x ρ
∙ ap₂ R._*_ (-ₙ-hom 1n ρ ∙ ap R.-_ (1n-hom ρ)) refl
∙ R.*-negatel ∙ ap R.-_ R.*-idl
-ₙ-hom (con x) ρ = ℤ↪R.pres-neg {x = lift x}
-ₙ-hom (poly x) ρ = -ₚ-hom x ρ
sound-coe
: ∀ {n} (c : Int) (ρ : Vec R n) → En (normal-coe c) ρ ≡ embed-coe c
sound-coe c [] = refl
sound-coe c (x ∷ ρ) = ∅*x+ₙ-hom (normal-coe c) x ρ ∙ sound-coe c ρ
sound-var : ∀ {n} (j : Fin n) ρ → En (normal-var j) ρ ≡ lookup ρ j
sound-var fzero (x ∷ ρ) =
Ep (∅ *x+ 1n) (x ∷ ρ) R.* x R.+ En 0n ρ ≡⟨ R.elimr (0n-hom ρ) ⟩
⌜ Ep (∅ *x+ 1n) (x ∷ ρ) ⌝ R.* x ≡⟨ ap! (R.eliml R.*-zerol ∙ 1n-hom ρ) ⟩
R.1r R.* x ≡⟨ R.*-idl ⟩
x ∎
sound-var (fsuc j) (x ∷ ρ) = ∅*x+ₙ-hom (normal-var j) x ρ ∙ sound-var j ρ
sound : ∀ {n} (p : Polynomial n) ρ → En (normal p) ρ ≡ ⟦ p ⟧ ρ
sound (op [+] p q) ρ = +ₙ-hom (normal p) (normal q) ρ ∙ ap₂ R._+_ (sound p ρ) (sound q ρ)
sound (op [*] p q) ρ = *ₙ-hom (normal p) (normal q) ρ ∙ ap₂ R._*_ (sound p ρ) (sound q ρ)
sound (con c) ρ = sound-coe c ρ
sound (var x) ρ = sound-var x ρ
sound (:- p) ρ = -ₙ-hom (normal p) ρ ∙ ap R.-_ (sound p ρ)
expand : ∀ {n} → Polynomial n → Vec R n → R
expand e ρ = ⟦ e ⟧ ρ
solve
: ∀ {n} (p q : Polynomial n) (r : Vec R n)
→ En (normal p) r ≡ En (normal q) r → ⟦ p ⟧ r ≡ ⟦ q ⟧ r
solve p q r prf = sym (sound p r) ·· prf ·· sound q r
private
test-distrib : ∀ x y z → x R.* (y R.+ z) ≡ y R.* x R.+ z R.* x
test-distrib x y z =
solve (var 0 :* (var 1 :+ var 2)) ((var 1 :* var 0) :+ (var 2 :* var 0)) (x ∷ y ∷ z ∷ []) refl
test-identities : ∀ x → x R.+ (R.0r R.* R.1r) ≡ (R.1r R.+ R.0r) R.* x
test-identities x =
solve (var 0 :+ (con 0 :* con 1)) ((con 1 :+ con 0) :* var 0) (x ∷ []) refl
module Explicit {ℓ} (R : CRing ℓ) where
private module I = Impl (R .snd)
open I renaming (solve to solve-impl)
open I public using (Polynomial ; _:+_ ; _:-_ ; :-_ ; _:*_ ; con ; Number-Polynomial)
_≔_ : ∀ {n} → Polynomial n → Polynomial n → Polynomial n × Polynomial n
x ≔ y = x , y
private
variables : ∀ {n} → Πᶠ {n = n} λ i → Polynomial n
variables = tabulateₚ var
abstract
solve
: (n : Nat) (f : Arrᶠ {n = n} (λ i → Polynomial n) (Polynomial n × Polynomial n))
→ (let (lhs , rhs) = applyᶠ {n = n} f variables)
→ ∀ᶠ n (λ i → ⌞ R ⌟) λ vs
→ (let rs = tabulate (indexₚ vs))
→ En (normal lhs) rs ≡ En (normal rhs) rs
→ ⟦ lhs ⟧ rs ≡ ⟦ rhs ⟧ rs
solve n f = curry-∀ᶠ {n = n} (λ a → solve-impl lhs rhs (tabulate (indexₚ a)))
where open Σ (applyᶠ {n = n} f variables) renaming (fst to lhs ; snd to rhs)
module Reflection where
private
pattern ring-args cring args = (_ hm∷ _ hm∷ cring v∷ args)
pattern is-ring-args is-ring args = (_ hm∷ _ hm∷ _ hm∷ _ hm∷ _ hm∷ is-ring v∷ args)
pattern is-group-args is-group args = (_ hm∷ _ hm∷ _ hm∷ is-group v∷ args)
pattern ring-field field-name cring args =
def field-name (ring-args (def (quote CRing-on.has-ring-on) (ring-args cring [])) args)
pattern group-field field-name cring args =
def field-name
(is-group-args
(def (quote is-ring.+-group)
(is-ring-args (ring-field (quote Ring-on.has-is-ring) cring []) []))
args)
mk-cring-args : Term → List (Arg Term) → List (Arg Term)
mk-cring-args cring args = unknown h∷ unknown h∷ cring v∷ args
pattern “1” cring = ring-field (quote Ring-on.1r) cring []
pattern “*” cring x y = ring-field (quote Ring-on._*_) cring (x v∷ y v∷ [])
pattern “+” cring x y = ring-field (quote Ring-on._+_) cring (x v∷ y v∷ [])
pattern “0” cring = group-field (quote is-abelian-group.1g) cring []
pattern “-” cring x = group-field (quote is-abelian-group.inverse) cring (x v∷ [])
“expand” : Term → Term → Term → Term
“expand” cring p env = def (quote Impl.expand) (mk-cring-args cring (unknown h∷ p v∷ env v∷ []))
“solve” : Term → Term → Term → Term → Term
“solve” cring lhs rhs env =
def (quote Impl.solve) (mk-cring-args cring (unknown h∷ lhs v∷ rhs v∷ env v∷ “refl” v∷ []))
build-expr : ∀ {ℓ} {A : Type ℓ} → Term → Variables A → Term → TC (Term × Variables A)
build-expr cring vs (“0” cring') = do
unify cring cring'
z ← quoteTC (Int.pos 0)
pure $ con (quote Impl.Polynomial.con) (z v∷ []) , vs
build-expr cring vs (“1” cring') = do
unify cring cring'
o ← quoteTC (Int.pos 1)
pure $ con (quote Impl.Polynomial.con) (o v∷ []) , vs
build-expr cring vs (“*” cring' t1 t2) = do
unify cring cring'
e1 , vs ← build-expr cring vs t1
e2 , vs ← build-expr cring vs t2
pure $ def (quote Impl._:*_) (mk-cring-args cring $ e1 v∷ e2 v∷ []) , vs
build-expr cring vs (“+” cring' t1 t2) = do
unify cring cring'
e1 , vs ← build-expr cring vs t1
e2 , vs ← build-expr cring vs t2
pure $ def (quote Impl._:+_) (mk-cring-args cring $ e1 v∷ e2 v∷ []) , vs
build-expr cring vs (“-” cring' tm) = do
unify cring cring'
e , vs ← build-expr cring vs tm
pure $ con (quote Impl.Polynomial.:-_) (e v∷ []) , vs
build-expr cring vs tm = do
(v , vs) ← bind-var vs tm
pure $ con (quote Impl.Polynomial.var) (v v∷ []) , vs
dont-reduce : List Name
dont-reduce =
quote Number.fromNat ∷
quote is-abelian-group.1g ∷
quote Ring-on.1r ∷
quote is-abelian-group.inverse ∷
quote Ring-on._*_ ∷
quote Ring-on._+_ ∷
[]
cring-solver : ∀ {ℓ} {A : Type ℓ} → CRing-on A → TC (VariableSolver A)
cring-solver {A = A} cring = do
cring-tm ← quoteTC cring
pure $ var-solver dont-reduce (build-expr cring-tm) (“solve” cring-tm) (“expand” cring-tm)
repr-macro : ∀ {ℓ} {A : Type ℓ} → CRing-on A → Term → Term → TC ⊤
repr-macro cring tm hole = do
solver ← cring-solver cring
mk-var-repr solver tm
expand-macro : ∀ {ℓ} {A : Type ℓ} → CRing-on A → Term → Term → TC ⊤
expand-macro cring tm hole = do
solver ← cring-solver cring
mk-var-normalise solver tm hole
solve-macro : ∀ {ℓ} {A : Type ℓ} → CRing-on A → Term → TC ⊤
solve-macro cring hole = do
solver ← cring-solver cring
mk-var-solver solver hole
macro
cring-repr! : ∀ {ℓ} → CRing ℓ → Term → Term → TC ⊤
cring-repr! cring tm = Reflection.repr-macro (cring .snd) tm
cring-simpl! : ∀ {ℓ} → CRing ℓ → Term → Term → TC ⊤
cring-simpl! cring tm = Reflection.expand-macro (cring .snd) tm
cring-on! : ∀ {ℓ} {A : Type ℓ} → CRing-on A → Term → TC ⊤
cring-on! cring = Reflection.solve-macro cring
cring! : ∀ {ℓ} → CRing ℓ → Term → TC ⊤
cring! cring = Reflection.solve-macro (cring .snd)
private module TestCRing {ℓ} (R : CRing ℓ) where
module R = CRing-on (R .snd)
test-distrib : ∀ x y z → x R.* (y R.+ z) ≡ (y R.* x) R.+ (z R.* x)
test-distrib x y z = cring! R
test-identities : ∀ x → x R.+ (R.0r R.* R.1r) ≡ (R.1r R.+ R.0r) R.* x
test-identities x = cring! R
test-negation : ∀ x y → x R.* (R.- y) ≡ R.- (x R.* y)
test-negation x y = cring! R
private module TestExplicit where
open Explicit ℤ-comm
_ : ∀ x y u v → (x B.*ℤ y) B.*ℤ (u B.*ℤ v) ≡ (x B.*ℤ u) B.*ℤ (y B.*ℤ v)
_ = λ x y u v → solve 4
(λ x y u v → (x :* y) :* (u :* v) ≔ (x :* u) :* (y :* v))
x y u v refl