diff options
author | Greg Brown <greg.brown@cl.cam.ac.uk> | 2022-04-07 17:58:39 +0100 |
---|---|---|
committer | Greg Brown <greg.brown@cl.cam.ac.uk> | 2022-04-07 17:58:39 +0100 |
commit | 662ca19ed7dabecdf17cdd555132f106bb768e58 (patch) | |
tree | f13341097e3caf02869f4951619f842d60bd20f2 | |
parent | e2b91853b58c57b8ad616e728bc55e3570490343 (diff) |
Add a new ring solver tactic.
-rw-r--r-- | Everything.agda | 3 | ||||
-rw-r--r-- | src/Helium/Tactic/CommutativeRing/NonReflective.agda | 283 |
2 files changed, 286 insertions, 0 deletions
diff --git a/Everything.agda b/Everything.agda index 039338b..cd0f148 100644 --- a/Everything.agda +++ b/Everything.agda @@ -125,3 +125,6 @@ import Helium.Semantics.Axiomatic.Triple -- Base definitions for the denotational semantics. import Helium.Semantics.Denotational.Core + +-- Ring solver tactic using integers as coefficients +import Helium.Tactic.CommutativeRing.NonReflective diff --git a/src/Helium/Tactic/CommutativeRing/NonReflective.agda b/src/Helium/Tactic/CommutativeRing/NonReflective.agda new file mode 100644 index 0000000..12029a5 --- /dev/null +++ b/src/Helium/Tactic/CommutativeRing/NonReflective.agda @@ -0,0 +1,283 @@ +-------------------------------------------------------------------------------- +-- Agda Helium +-- +-- Ring solver tactic using integers as coefficients +-------------------------------------------------------------------------------- + +{-# OPTIONS --without-K --safe #-} + +open import Helium.Algebra.Ordered.StrictTotal.Bundles using (CommutativeRing) +import Helium.Algebra.Ordered.StrictTotal.Properties.CommutativeRing as Ringₚ +open import Relation.Nullary + +module Helium.Tactic.CommutativeRing.NonReflective + {ℓ₁ ℓ₂ ℓ₃} + (R : CommutativeRing ℓ₁ ℓ₂ ℓ₃) + (1≉0 : let module R = CommutativeRing R in ¬ R.1# R.≈ R.0#) + where + +open import Data.Bool.Base +open import Data.Sign using (Sign) renaming (_*_ to _S*_) +open import Level using (0ℓ; _⊔_) + +open import Relation.Binary.Reasoning.StrictPartialOrder (CommutativeRing.strictPartialOrder R) + +module R where + open CommutativeRing R public + renaming + ( trans to <-trans + ; irrefl to <-irrefl + ; asym to <-asym + ; 0<a+0<b⇒0<ab to x>0∧y>0⇒xy>0 + ) + + open Ringₚ R public + + infixr 2 _,_ + + record Positive : Set (ℓ₁ ⊔ ℓ₂ ⊔ ℓ₃) where + constructor _,_ + field + val : Carrier + proof : val ≥ 0# + + open Positive + + infixl 6 _*⁺_ _*′_ + infix 5 _◃_ + + _*⁺_ : Positive → Positive → Positive + +x *⁺ +y = +x .val * +y .val , x≥0∧y≥0⇒x*y≥0 (+x .proof) (+y .proof) + + _◃_ : Sign → Positive → Carrier + Sign.- ◃ +x = - (+x .val) + Sign.+ ◃ +x = +x .val + + sign : Carrier → Sign + sign x with does (x <? 0#) + ... | true = Sign.- + ... | false = Sign.+ + + ∣_∣ : Carrier → Positive + ∣ x ∣ with x <? 0# + ... | yes x<0 = - x , <⇒≤ (x<0⇒-x>0 x<0) + ... | no x≮0 = x , ≮⇒≥ x≮0 + + ◃-congˡ : ∀ s +x +y → +x .val ≈ +y .val → s ◃ +x ≈ s ◃ +y + ◃-congˡ Sign.- +x +y x≈y = -‿cong x≈y + ◃-congˡ Sign.+ +x +y x≈y = x≈y + + _*′_ : Carrier → Carrier → Carrier + x *′ y = sign x S* sign y ◃ ∣ x ∣ *⁺ ∣ y ∣ + + *′≈* : ∀ x y → x *′ y ≈ x * y + *′≈* x y with x <? 0# | y <? 0# + ... | yes x<0 | yes y<0 = -x*-y≈x*y x y + ... | yes x<0 | no y≮0 = begin-equality + - (- x * y) ≈⟨ -‿cong (-‿*-distribˡ x y) ⟩ + - - (x * y) ≈⟨ -‿involutive (x * y) ⟩ + x * y ∎ + ... | no x≮0 | yes y<0 = begin-equality + - (x * - y) ≈⟨ -‿cong (-‿*-distribʳ x y) ⟩ + - - (x * y) ≈⟨ -‿involutive (x * y) ⟩ + x * y ∎ + ... | no x≮0 | no y≮0 = Eq.refl + +open import Algebra.Bundles using (Ring) +open import Algebra.Morphism +import Data.Bool.Properties as Boolₚ +open import Data.Empty using (⊥-elim) +open import Data.Integer as ℤ hiding (suc) +open import Data.Integer.Properties as ℤₚ +open import Data.Maybe.Base +open import Data.Nat.Base as ℕ using (ℕ; suc; z≤n; s≤s) +import Data.Nat.Properties as ℕₚ +open import Data.Product +import Data.Unit +open import Data.Vec hiding (_⊛_) +open import Data.Vec.N-ary +open import Function + +open import Relation.Binary.PropositionalEquality + +open import Tactic.RingSolver.Core.AlmostCommutativeRing +open import Tactic.RingSolver.Core.Expression public +open import Tactic.RingSolver.Core.Polynomial.Parameters + +private + T-≡ : ∀ {x} → T x ⇔ x ≡ true + T-≡ {false} = mk⇔ (λ ()) (λ ()) + T-≡ {true} = mk⇔ (λ _ → refl) (λ _ → _) + + T-≡′ : ∀ {x} → T (not x) ⇔ x ≡ false + T-≡′ {false} = mk⇔ (λ _ → refl) (λ _ → _) + T-≡′ {true} = mk⇔ (λ ()) λ () + + T-¬ : ∀ {x} → T (not x) ⇔ (¬ T x) + T-¬ {false} = mk⇔ (λ _ ⊥ → ⊥) (λ ¬⊥ → _) + T-¬ {true} = mk⇔ (λ ⊥ _ → ⊥) (λ ¬⊤ → ¬⊤ _) + +module Ops where + ℤ-coeff : RawCoeff 0ℓ 0ℓ + ℤ-coeff = record + { rawRing = Ring.rawRing ℤₚ.+-*-ring + ; isZero = does ∘ (0ℤ ℤ.≟_) + } + + ring : AlmostCommutativeRing ℓ₁ ℓ₂ + ring = fromCommutativeRing R.Unordered.commutativeRing (decToMaybe ∘ (R.0# R.≟_)) + + ℤ⟶R : RawCoeff.rawRing ℤ-coeff -Raw-AlmostCommutative⟶ ring + ℤ⟶R = record + { ⟦_⟧ = ⟦_⟧ + ; +-homo = +-homo + ; *-homo = *-homo + ; -‿homo = -‿homo + ; 0-homo = R.Eq.refl + ; 1-homo = R.Eq.refl + } + where + ⟦_⟧ : ℤ → R.Carrier + ⟦ + n ⟧ = n R.× R.1# + ⟦ -[1+ n ] ⟧ = R.- (suc n R.× R.1#) + + ∸-homo : ∀ {m n} → m ℕ.≤ n → ⟦ + (n ℕ.∸ m) ⟧ R.≈ ⟦ + n ⟧ R.- ⟦ + m ⟧ + ∸-homo {.0} {n} z≤n = begin-equality + n R.× R.1# ≈˘⟨ R.+-identityʳ _ ⟩ + n R.× R.1# R.+ R.0# ≈˘⟨ R.+-congˡ R.-0≈0 ⟩ + n R.× R.1# R.- R.0# ∎ + ∸-homo {.suc m} {.suc n} (s≤s m≤n) = begin-equality + (n ℕ.∸ m) R.× R.1# ≈⟨ ∸-homo m≤n ⟩ + n R.× R.1# R.- m R.× R.1# ≈˘⟨ R.+-congʳ (R.+-identityʳ _) ⟩ + n R.× R.1# R.+ R.0# R.- m R.× R.1# ≈˘⟨ R.+-congʳ (R.+-congˡ (R.-‿inverseʳ R.1#)) ⟩ + n R.× R.1# R.+ (R.1# R.- R.1#) R.- m R.× R.1# ≈˘⟨ R.+-congʳ (R.+-assoc _ _ _) ⟩ + n R.× R.1# R.+ R.1# R.- R.1# R.- m R.× R.1# ≈⟨ R.+-assoc _ _ _ ⟩ + n R.× R.1# R.+ R.1# R.+ (R.- R.1# R.- m R.× R.1#) ≈⟨ R.+-cong (R.+-comm _ R.1#) (R.-‿+-comm R.1# _) ⟩ + R.1# R.+ n R.× R.1# R.- (R.1# R.+ m R.× R.1#) ≈˘⟨ R.+-cong (R.1+× n R.1#) (R.-‿cong (R.1+× m R.1#)) ⟩ + suc n R.× R.1# R.- suc m R.× R.1# ∎ + + -‿homo : ∀ n → ⟦ - n ⟧ R.≈ R.- ⟦ n ⟧ + -‿homo -[1+ n ] = R.Eq.sym (R.-‿involutive _) + -‿homo +0 = R.Eq.sym R.-0≈0 + -‿homo +[1+ n ] = R.Eq.refl + + ⊖-homo : ∀ m n → ⟦ m ⊖ n ⟧ R.≈ ⟦ + m ⟧ R.- ⟦ + n ⟧ + ⊖-homo m n with m ℕ.<ᵇ n in eq + ... | true = begin-equality + ⟦ - (+ (n ℕ.∸ m)) ⟧ ≈⟨ -‿homo (+ (n ℕ.∸ m)) ⟩ + R.- ⟦ + (n ℕ.∸ m) ⟧ ≈⟨ R.-‿cong (∸-homo (ℕₚ.<⇒≤ (ℕₚ.<ᵇ⇒< m n (Equivalence.g T-≡ eq)))) ⟩ + R.- (⟦ + n ⟧ R.- ⟦ + m ⟧) ≈˘⟨ R.-‿+-comm ⟦ + n ⟧ (R.- ⟦ + m ⟧) ⟩ + R.- ⟦ + n ⟧ R.- R.- ⟦ + m ⟧ ≈⟨ R.+-congˡ (R.-‿involutive ⟦ + m ⟧) ⟩ + R.- ⟦ + n ⟧ R.+ ⟦ + m ⟧ ≈⟨ R.+-comm (R.- ⟦ + n ⟧) ⟦ + m ⟧ ⟩ + ⟦ + m ⟧ R.- ⟦ + n ⟧ ∎ + ... | false = ∸-homo (ℕₚ.≮⇒≥ {m} {n} (Equivalence.f T-¬ (Equivalence.g T-≡′ eq) ∘ ℕₚ.<⇒<ᵇ)) + + +-homo : ∀ m n → ⟦ m + n ⟧ R.≈ ⟦ m ⟧ R.+ ⟦ n ⟧ + +-homo -[1+ m ] -[1+ n ] = begin-equality + R.- (suc (suc (m ℕ.+ n)) R.× R.1#) ≡˘⟨ cong (λ x → R.- (x R.× R.1#)) (ℕₚ.+-suc (suc m) n) ⟩ + R.- ((suc m ℕ.+ suc n) R.× R.1#) ≈⟨ R.-‿cong (R.×-homo-+ R.1# (suc m) (suc n)) ⟩ + R.- (suc m R.× R.1# R.+ suc n R.× R.1#) ≈˘⟨ R.-‿+-comm _ _ ⟩ + R.- (suc m R.× R.1#) R.- (suc n R.× R.1#) ∎ + +-homo -[1+ m ] (+ n) = begin-equality + ⟦ n ⊖ suc m ⟧ ≈⟨ ⊖-homo n (suc m) ⟩ + ⟦ + n ⟧ R.+ ⟦ -[1+ m ] ⟧ ≈⟨ R.+-comm ⟦ + n ⟧ ⟦ -[1+ m ] ⟧ ⟩ + ⟦ -[1+ m ] ⟧ R.+ ⟦ + n ⟧ ∎ + +-homo (+ m) -[1+ n ] = ⊖-homo m (suc n) + +-homo (+ m) (+ n) = R.×-homo-+ R.1# m n + + ∣∙∣-homo : ∀ n → ⟦ + ∣ n ∣ ⟧ R.≈ R.Positive.val R.∣ ⟦ n ⟧ ∣ + ∣∙∣-homo n with ⟦ n ⟧ R.<? R.0# + ∣∙∣-homo (+ n) | yes n<0 = ⊥-elim (R.<⇒≱ n<0 (R.x≥0⇒n×x≥0 n R.0≤1)) + ∣∙∣-homo (+ n) | no n≮0 = R.Eq.refl + ∣∙∣-homo -[1+ n ] | yes n<0 = R.Eq.sym (R.-‿involutive _) + ∣∙∣-homo -[1+ n ] | no n≮0 = ⊥-elim (n≮0 (R.x>0⇒-x<0 (R.n≢0∧x>0⇒n×x>0 (suc n) (R.x≉y⇒0<1 1≉0)))) + + sign-homo : ∀ n → sign n ≡ R.sign ⟦ n ⟧ + sign-homo n with ⟦ n ⟧ R.<? R.0# + sign-homo (+ n) | yes n<0 = ⊥-elim (R.<⇒≱ n<0 (R.x≥0⇒n×x≥0 n R.0≤1)) + sign-homo (+ n) | no n≮0 = refl + sign-homo -[1+ n ] | yes n<0 = refl + sign-homo -[1+ n ] | no n≮0 = ⊥-elim (n≮0 (R.x>0⇒-x<0 (R.n≢0∧x>0⇒n×x>0 (suc n) (R.x≉y⇒0<1 1≉0)))) + + ◃-homo : ∀ s n → ⟦ s ◃ n ⟧ R.≈ s R.◃ (⟦ + n ⟧ R., R.x≥0⇒n×x≥0 n R.0≤1) + ◃-homo Sign.- 0 = R.Eq.sym R.-0≈0 + ◃-homo Sign.- (suc n) = R.Eq.refl + ◃-homo Sign.+ 0 = R.Eq.refl + ◃-homo Sign.+ (suc n) = R.Eq.refl + + *ⁿ-homo : ∀ m n → ⟦ + (m ℕ.* n) ⟧ R.≈ ⟦ + m ⟧ R.* ⟦ + n ⟧ + *ⁿ-homo 0 n = R.Eq.sym (R.zeroˡ ⟦ + n ⟧) + *ⁿ-homo (suc m) n = begin-equality + (n ℕ.+ m ℕ.* n) R.× R.1# ≈⟨ R.×-homo-+ R.1# n (m ℕ.* n) ⟩ + n R.× R.1# R.+ (m ℕ.* n) R.× R.1# ≈⟨ R.+-congˡ (*ⁿ-homo m n) ⟩ + n R.× R.1# R.+ m R.× R.1# R.* n R.× R.1# ≈˘⟨ R.+-congʳ (R.*-identityˡ _) ⟩ + R.1# R.* n R.× R.1# R.+ m R.× R.1# R.* n R.× R.1# ≈˘⟨ R.distribʳ _ R.1# _ ⟩ + (R.1# R.+ m R.× R.1#) R.* n R.× R.1# ≈˘⟨ R.*-congʳ (R.1+× m R.1#) ⟩ + suc m R.× R.1# R.* n R.× R.1# ∎ + + *-homo : ∀ m n → ⟦ m * n ⟧ R.≈ ⟦ m ⟧ R.* ⟦ n ⟧ + *-homo m n = begin-equality + ⟦ m * n ⟧ ≡⟨⟩ + ⟦ sm*sn ◃ ∣ m ∣ ℕ.* ∣ n ∣ ⟧ ≈⟨ ◃-homo sm*sn (∣ m ∣ ℕ.* ∣ n ∣) ⟩ + sm*sn R.◃ (⟦ + (∣ m ∣ ℕ.* ∣ n ∣) ⟧ R., ∣m∣∣n∣≥0) ≈⟨ R.◃-congˡ sm*sn _ _ (*ⁿ-homo ∣ m ∣ ∣ n ∣) ⟩ + sm*sn R.◃ (⟦ + ∣ m ∣ ⟧ R.* ⟦ + ∣ n ∣ ⟧ R., ∣mn∣≥0) ≈⟨ R.◃-congˡ sm*sn _ _ (R.*-cong (∣∙∣-homo m) (∣∙∣-homo n)) ⟩ + sm*sn R.◃ R.∣ ⟦ m ⟧ ∣ R.*⁺ R.∣ ⟦ n ⟧ ∣ ≡⟨ cong₂ (λ x y → x S* y R.◃ R.∣ ⟦ m ⟧ ∣ R.*⁺ R.∣ ⟦ n ⟧ ∣) (sign-homo m) (sign-homo n) ⟩ + Rsm*Rsn R.◃ R.∣ ⟦ m ⟧ ∣ R.*⁺ R.∣ ⟦ n ⟧ ∣ ≡⟨⟩ + ⟦ m ⟧ R.*′ ⟦ n ⟧ ≈⟨ R.*′≈* ⟦ m ⟧ ⟦ n ⟧ ⟩ + ⟦ m ⟧ R.* ⟦ n ⟧ ∎ + where + ∣m∣∣n∣≥0 = R.x≥0⇒n×x≥0 (∣ m ∣ ℕ.* ∣ n ∣) R.0≤1 + ∣mn∣≥0 = R.x≥0∧y≥0⇒x*y≥0 (R.x≥0⇒n×x≥0 ∣ m ∣ R.0≤1) (R.x≥0⇒n×x≥0 ∣ n ∣ R.0≤1) + sm*sn = sign m S* sign n + Rsm*Rsn = R.sign ⟦ m ⟧ S* R.sign ⟦ n ⟧ + + homo : Homomorphism 0ℓ 0ℓ ℓ₁ ℓ₂ + homo = record + { from = ℤ-coeff + ; to = ring + ; morphism = ℤ⟶R + ; Zero-C⟶Zero-R = λ { +0 _ → R.Eq.refl } + } + + open Eval R.Unordered.rawRing (_-Raw-AlmostCommutative⟶_.⟦_⟧ ℤ⟶R) public + + open import Tactic.RingSolver.Core.Polynomial.Base (Homomorphism.from homo) + + norm : ∀ {n} → Expr ℤ n → Poly n + norm (Κ x) = κ x + norm (Ι x) = ι x + norm (x ⊕ y) = norm x ⊞ norm y + norm (x ⊗ y) = norm x ⊠ norm y + norm (x ⊛ i) = norm x ⊡ i + norm (⊝ x) = ⊟ norm x + + ⟦_⇓⟧ : ∀ {n} → Expr ℤ n → Vec R.Carrier n → R.Carrier + ⟦ expr ⇓⟧ = ⟦ norm expr ⟧ₚ + where open import Tactic.RingSolver.Core.Polynomial.Semantics homo renaming (⟦_⟧ to ⟦_⟧ₚ) + + correct : ∀ {n} (expr : Expr ℤ n) ρ → ⟦ expr ⇓⟧ ρ R.≈ ⟦ expr ⟧ ρ + correct {n = n} = go + where + open import Tactic.RingSolver.Core.Polynomial.Homomorphism homo + + go : ∀ (expr : Expr ℤ n) ρ → ⟦ expr ⇓⟧ ρ R.≈ ⟦ expr ⟧ ρ + go (Κ x) ρ = κ-hom x ρ + go (Ι x) ρ = ι-hom x ρ + go (x ⊕ y) ρ = ⊞-hom (norm x) (norm y) ρ ⟨ R.Eq.trans ⟩ (go x ρ ⟨ R.+-cong ⟩ go y ρ) + go (x ⊗ y) ρ = ⊠-hom (norm x) (norm y) ρ ⟨ R.Eq.trans ⟩ (go x ρ ⟨ R.*-cong ⟩ go y ρ) + go (x ⊛ i) ρ = ⊡-hom (norm x) i ρ ⟨ R.Eq.trans ⟩ R.^-congˡ i (go x ρ) + go (⊝ x) ρ = ⊟-hom (norm x) ρ ⟨ R.Eq.trans ⟩ R.-‿cong (go x ρ) + + open import Relation.Binary.Reflection R.strictTotalOrder.Eq.setoid Ι ⟦_⟧ ⟦_⇓⟧ correct public + +solve : ∀ (n : ℕ) → + (f : N-ary n (Expr ℤ n) (Expr ℤ n × Expr ℤ n)) → + Eqʰ n R._≈_ (curryⁿ (Ops.⟦_⇓⟧ (proj₁ (Ops.close n f)))) (curryⁿ (Ops.⟦_⇓⟧ (proj₂ (Ops.close n f)))) → + Eq n R._≈_ (curryⁿ (Ops.⟦_⟧ (proj₁ (Ops.close n f)))) (curryⁿ (Ops.⟦_⟧ (proj₂ (Ops.close n f)))) +solve = Ops.solve +{-# INLINE solve #-} + +infixl 6 _⊜_ +_⊜_ : ∀ {n} → Expr ℤ n → Expr ℤ n → Expr ℤ n × Expr ℤ n +_⊜_ = _,_ +{-# INLINE _⊜_ #-} |