{-# OPTIONS --without-K --safe #-} open import Polynomial.Parameters module Polynomial.Homomorphism.Lemmas {r₁ r₂ r₃} (homo : Homomorphism r₁ r₂ r₃) where open import Data.List using (_∷_; []) open import Relation.Nullary using (Dec; yes; no) open import Data.Nat as ℕ using (ℕ; suc; zero; compare) open import Data.Vec as Vec using (Vec; _∷_) open import Level using (lift) open import Data.Fin using (Fin) open import Relation.Binary.PropositionalEquality as ≡ using (_≡_) open import Data.Product using (_,_; proj₁; proj₂; map₁; _×_) open import Data.Empty using (⊥-elim) open import Data.Maybe using (nothing; just) open import Data.Bool using (Bool;true;false) open import Data.Unit using (tt) open import Function import Data.Nat.Properties as ℕ-Prop open Homomorphism homo open import Polynomial.Reasoning ring open import Polynomial.NormalForm homo open import Polynomial.Exponentiation rawRing pow-add′ : ∀ x i j → (x ^ i +1) * (x ^ j +1) ≈ x ^ (j ℕ.+ suc i) +1 pow-add′ x i ℕ.zero = refl pow-add′ x i (suc j) = begin x ^ i +1 * (x ^ j +1 * x) ≈⟨ sym (*-assoc _ _ _) ⟩ x ^ i +1 * x ^ j +1 * x ≈⟨ ≪* pow-add′ x i j ⟩ x ^ (j ℕ.+ suc i) +1 * x ∎ pow-add : ∀ x y i j → y ^ j +1 * x *⟨ y ⟩^ i ≈ x *⟨ y ⟩^ (i ℕ.+ suc j) pow-add x y ℕ.zero j = refl pow-add x y (suc i) j = go x y i j where go : ∀ x y i j → y ^ j +1 * ((y ^ i +1) * x) ≈ y ^ (i ℕ.+ suc j) +1 * x go x y ℕ.zero j = sym (*-assoc _ _ _) go x y (suc i) j = begin y ^ j +1 * (y ^ i +1 * y * x) ≈⟨ *≫ *-assoc _ y x ⟩ y ^ j +1 * (y ^ i +1 * (y * x)) ≈⟨ go (y * x) y i j ⟩ y ^ (i ℕ.+ suc j) +1 * (y * x) ≈⟨ sym (*-assoc _ y x) ⟩ y ^ suc (i ℕ.+ suc j) +1 * x ∎ pow-opt : ∀ x ρ i → x *⟨ ρ ⟩^ i ≈ ρ ^ i * x pow-opt x ρ ℕ.zero = sym (*-identityˡ x) pow-opt x ρ (suc i) = refl pow-hom : ∀ {n} i → (xs : Coeff n +) → ∀ ρ ρs → Σ⟦ xs ⟧ (ρ , ρs) *⟨ ρ ⟩^ i ≈ Σ⟦ xs ⍓+ i ⟧ (ρ , ρs) pow-hom ℕ.zero (x Δ j & xs) ρ ρs rewrite ℕ-Prop.+-identityʳ j = refl pow-hom (suc i) (x ≠0 Δ j & xs) ρ ρs = begin ρ ^ i +1 * (((x , xs) ⟦∷⟧ (ρ , ρs)) *⟨ ρ ⟩^ j) ≈⟨ pow-add _ ρ j i ⟩ (((x , xs) ⟦∷⟧ (ρ , ρs)) *⟨ ρ ⟩^ (j ℕ.+ suc i)) ∎ pow-mul-cong : ∀ {x y} → x ≈ y → ∀ ρ i → x *⟨ ρ ⟩^ i ≈ y *⟨ ρ ⟩^ i pow-mul-cong x≈y ρ ℕ.zero = x≈y pow-mul-cong x≈y ρ (suc i₁) = *≫ x≈y pow-distrib-+1 : ∀ x y i → (x * y) ^ i +1 ≈ x ^ i +1 * y ^ i +1 pow-distrib-+1 x y ℕ.zero = refl pow-distrib-+1 x y (suc i) = begin (x * y) ^ i +1 * (x * y) ≈⟨ ≪* pow-distrib-+1 x y i ⟩ (x ^ i +1 * y ^ i +1) * (x * y) ≈⟨ *-assoc _ _ _ ⟨ trans ⟩ (*≫ (sym (*-assoc _ _ _) ⟨ trans ⟩ (≪* *-comm _ _))) ⟩ x ^ i +1 * (x * y ^ i +1 * y) ≈⟨ (*≫ *-assoc _ _ _) ⟨ trans ⟩ sym (*-assoc _ _ _) ⟩ (x ^ i +1 * x) * (y ^ i +1 * y) ∎ pow-distrib : ∀ x y i → (x * y) ^ i ≈ x ^ i * y ^ i pow-distrib x y ℕ.zero = sym (*-identityˡ _) pow-distrib x y (suc i) = pow-distrib-+1 x y i pow-mult-+1 : ∀ x i j → (x ^ i +1) ^ j +1 ≈ x ^ (i ℕ.+ j ℕ.* suc i) +1 pow-mult-+1 x i ℕ.zero rewrite ℕ-Prop.+-identityʳ i = refl pow-mult-+1 x i (suc j) = begin (x ^ i +1) ^ j +1 * (x ^ i +1) ≈⟨ ≪* pow-mult-+1 x i j ⟩ (x ^ (i ℕ.+ j ℕ.* suc i) +1) * (x ^ i +1) ≈⟨ pow-add′ x _ i ⟩ x ^ (i ℕ.+ suc (i ℕ.+ j ℕ.* suc i)) +1 ∎ pow-cong-+1 : ∀ {x y} i → x ≈ y → x ^ i +1 ≈ y ^ i +1 pow-cong-+1 ℕ.zero x≈y = x≈y pow-cong-+1 (suc i) x≈y = pow-cong-+1 i x≈y ⟨ *-cong ⟩ x≈y pow-cong : ∀ {x y} i → x ≈ y → x ^ i ≈ y ^ i pow-cong ℕ.zero x≈y = refl pow-cong (suc i) x≈y = pow-cong-+1 i x≈y zero-hom : ∀ {n} (p : Poly n) → Zero p → (ρs : Vec Carrier n) → 0# ≈ ⟦ p ⟧ ρs zero-hom (Σ _ Π _) () zero-hom (Κ x Π i≤n) p≡0 ρs = Zero-C⟶Zero-R x p≡0 pow-suc : ∀ x i → x ^ suc i ≈ x * x ^ i pow-suc x ℕ.zero = sym (*-identityʳ _) pow-suc x (suc i) = *-comm _ _ pow-sucʳ : ∀ x i → x ^ suc i ≈ x ^ i * x pow-sucʳ x ℕ.zero = sym (*-identityˡ _) pow-sucʳ x (suc i) = refl Σ?⟦_⟧ : ∀ {n} (xs : Coeff n *) → Carrier × Vec Carrier n → Carrier Σ?⟦ [] ⟧ _ = 0# Σ?⟦ ∹ x ⟧ = Σ⟦ x ⟧ _⟦∷⟧?_ : ∀ {n} (x : Poly n × Coeff n *) → Carrier × Vec Carrier n → Carrier (x , xs) ⟦∷⟧? (ρ , ρs) = ρ * Σ?⟦ xs ⟧ (ρ , ρs) + ⟦ x ⟧ ρs Σ?-hom : ∀ {n} (xs : Coeff n +) → ∀ ρ → Σ?⟦ ∹ xs ⟧ ρ ≈ Σ⟦ xs ⟧ ρ Σ?-hom _ _ = refl ⟦∷⟧?-hom : ∀ {n} (x : Poly n) → ∀ xs ρ ρs → (x , xs) ⟦∷⟧? (ρ , ρs) ≈ (x , xs) ⟦∷⟧ (ρ , ρs) ⟦∷⟧?-hom x (∹ xs) ρ ρs = refl ⟦∷⟧?-hom x [] ρ ρs = (≪+ zeroʳ _) ⟨ trans ⟩ +-identityˡ _ pow′-hom : ∀ {n} i (xs : Coeff n *) → ∀ ρ ρs → ((Σ?⟦ xs ⟧ (ρ , ρs)) *⟨ ρ ⟩^ i) ≈ (Σ?⟦ xs ⍓* i ⟧ (ρ , ρs)) pow′-hom i (∹ xs) ρ ρs = pow-hom i xs ρ ρs pow′-hom zero [] ρ ρs = refl pow′-hom (suc i) [] ρ ρs = zeroʳ _ ∷↓-hom-0 : ∀ {n} (x : Poly n) → ∀ xs ρ ρs → Σ?⟦ x Δ 0 ∷↓ xs ⟧ (ρ , ρs) ≈ (x , xs) ⟦∷⟧ (ρ , ρs) ∷↓-hom-0 x xs ρ ρs with zero? x ∷↓-hom-0 x xs ρ ρs | no ¬p = refl ∷↓-hom-0 x [] ρ ρs | yes p = zero-hom x p ρs ∷↓-hom-0 x (∹ xs) ρ ρs | yes p = begin Σ⟦ xs ⍓+ 1 ⟧ (ρ , ρs) ≈⟨ sym (pow-hom 1 xs ρ ρs) ⟩ ρ * Σ⟦ xs ⟧ (ρ , ρs) ≈⟨ sym (+-identityʳ _) ⟨ trans ⟩ (+≫ zero-hom x p ρs) ⟩ ρ * Σ⟦ xs ⟧ (ρ , ρs) + ⟦ x ⟧ ρs ∎ ∷↓-hom-s : ∀ {n} (x : Poly n) → ∀ i xs ρ ρs → Σ?⟦ x Δ suc i ∷↓ xs ⟧ (ρ , ρs) ≈ (ρ ^ i +1) * (x , xs) ⟦∷⟧ (ρ , ρs) ∷↓-hom-s x i xs ρ ρs with zero? x ∷↓-hom-s x i xs ρ ρs | no ¬p = refl ∷↓-hom-s x i [] ρ ρs | yes p = sym ((*≫ sym (zero-hom x p ρs)) ⟨ trans ⟩ zeroʳ _) ∷↓-hom-s x i (∹ xs) ρ ρs | yes p = begin Σ⟦ xs ⍓+ (suc (suc i)) ⟧ (ρ , ρs) ≈⟨ sym (pow-hom (suc (suc i)) xs ρ ρs) ⟩ (ρ ^ suc i +1) * Σ⟦ xs ⟧ (ρ , ρs) ≈⟨ *-assoc _ _ _ ⟩ (ρ ^ i +1) * (ρ * Σ⟦ xs ⟧ (ρ , ρs)) ≈⟨ *≫ (sym (+-identityʳ _) ⟨ trans ⟩ (+≫ zero-hom x p ρs)) ⟩ ρ ^ i +1 * (ρ * Σ⟦ xs ⟧ (ρ , ρs) + ⟦ x ⟧ ρs) ∎ ∷↓-hom : ∀ {n} → (x : Poly n) → ∀ i xs ρ ρs → Σ?⟦ x Δ i ∷↓ xs ⟧ (ρ , ρs) ≈ ρ ^ i * ((x , xs) ⟦∷⟧ (ρ , ρs)) ∷↓-hom x ℕ.zero xs ρ ρs = ∷↓-hom-0 x xs ρ ρs ⟨ trans ⟩ sym (*-identityˡ _) ∷↓-hom x (suc i) xs ρ ρs = ∷↓-hom-s x i xs ρ ρs ⟦∷⟧-hom : ∀ {n} → (x : Poly n) → (xs : Coeff n *) → ∀ ρ ρs → (x , xs) ⟦∷⟧ (ρ , ρs) ≈ ρ * Σ?⟦ xs ⟧ (ρ , ρs) + ⟦ x ⟧ ρs ⟦∷⟧-hom x [] ρ ρs = sym ((≪+ zeroʳ _) ⟨ trans ⟩ +-identityˡ _) ⟦∷⟧-hom x (∹ xs) ρ ρs = refl Σ-Π↑-hom : ∀ {i n m} → (xs : Coeff i +) → (si≤n : suc i ≤′ n) → (sn≤m : suc n ≤′ m) → ∀ ρ → Σ⟦ xs ⟧ (drop-1 (≤′-step si≤n ⟨ ≤′-trans ⟩ sn≤m) ρ) ≈ Σ⟦ xs ⟧ (drop-1 si≤n (proj₂ (drop-1 sn≤m ρ))) Σ-Π↑-hom xs si≤n ≤′-refl (_ ∷ _) = refl Σ-Π↑-hom xs si≤n (≤′-step sn≤m) (_ ∷ ρ) = Σ-Π↑-hom xs si≤n sn≤m ρ Π↑-hom : ∀ {n m} → (x : Poly n) → (sn≤m : suc n ≤′ m) → ∀ ρ → ⟦ x Π↑ sn≤m ⟧ ρ ≈ ⟦ x ⟧ (proj₂ (drop-1 sn≤m ρ)) Π↑-hom (Κ x Π i≤sn) _ _ = refl Π↑-hom (Σ xs Π i≤sn) = Σ-Π↑-hom xs i≤sn trans-join-coeffs-hom : ∀ {i j-1 n} → (i≤j-1 : suc i ≤′ j-1) → (j≤n : suc j-1 ≤′ n) → (xs : Coeff i +) → ∀ ρ → Σ⟦ xs ⟧ (drop-1 i≤j-1 (proj₂ (drop-1 j≤n ρ))) ≈ Σ⟦ xs ⟧ (drop-1 (≤′-step i≤j-1 ⟨ ≤′-trans ⟩ j≤n) ρ) trans-join-coeffs-hom i<j-1 ≤′-refl xs (_ ∷ _) = refl trans-join-coeffs-hom i<j-1 (≤′-step j<n) xs (_ ∷ ρ) = trans-join-coeffs-hom i<j-1 j<n xs ρ trans-join-hom : ∀ {i j-1 n} → (i≤j-1 : i ≤′ j-1) → (j≤n : suc j-1 ≤′ n) → (x : FlatPoly i) → ∀ ρ → ⟦ x Π i≤j-1 ⟧ (proj₂ (drop-1 j≤n ρ)) ≈ ⟦ x Π (≤′-step i≤j-1 ⟨ ≤′-trans ⟩ j≤n) ⟧ ρ trans-join-hom i≤j-1 j≤n (Κ x) _ = refl trans-join-hom i≤j-1 j≤n (Σ x) = trans-join-coeffs-hom i≤j-1 j≤n x Π↓-hom : ∀ {n m} → (xs : Coeff n *) → (sn≤m : suc n ≤′ m) → ∀ ρ → ⟦ xs Π↓ sn≤m ⟧ ρ ≈ Σ?⟦ xs ⟧ (drop-1 sn≤m ρ) Π↓-hom [] sn≤m _ = 0-homo Π↓-hom (∹ x₁ Δ zero & ∹ xs ) sn≤m _ = refl Π↓-hom (∹ x Δ suc j & xs ) sn≤m _ = refl Π↓-hom (∹ _≠0 x {x≠0} Δ zero & [] ) sn≤m ρs = let (ρ , ρs′) = drop-1 sn≤m ρs in begin ⟦ x Π↑ sn≤m ⟧ ρs ≈⟨ Π↑-hom x sn≤m ρs ⟩ ⟦ x ⟧ ρs′ ∎ drop-1⇒lookup : ∀ {n} → (i : Fin n) → (ρs : Vec Carrier n) → proj₁ (drop-1 (Fin⇒≤ i) ρs) ≡ Vec.lookup ρs i drop-1⇒lookup Fin.zero (ρ ∷ ρs) = ≡.refl drop-1⇒lookup (Fin.suc i) (ρ ∷ ρs) = drop-1⇒lookup i ρs poly-foldR : ∀ {n} ρ ρs → ([f] : Fold n) → (f : Carrier → Carrier) → (∀ {x y} → x ≈ y → f x ≈ f y) → (∀ x y → x * f y ≈ f (x * y)) → (∀ y {ys} zs → Σ?⟦ ys ⟧ (ρ , ρs) ≈ f (Σ?⟦ zs ⟧ (ρ , ρs)) → [f] (y , ys) ⟦∷⟧? (ρ , ρs) ≈ f ((y , zs) ⟦∷⟧? (ρ , ρs)) ) → (f 0# ≈ 0#) → ∀ xs → Σ?⟦ para [f] xs ⟧ (ρ , ρs) ≈ f (Σ⟦ xs ⟧ (ρ , ρs)) poly-foldR ρ ρs f e cng dist step base (x ≠0 Δ suc i & []) = let y,ys = f (x , []) y = proj₁ y,ys ys = proj₂ y,ys in begin Σ?⟦ y Δ suc i ∷↓ ys ⟧ (ρ , ρs) ≈⟨ ∷↓-hom-s y i ys ρ ρs ⟩ (ρ ^ i +1) * ((y , ys) ⟦∷⟧ (ρ , ρs)) ≈˘⟨ *≫ ⟦∷⟧?-hom y ys ρ ρs ⟩ (ρ ^ i +1) * ((y , ys) ⟦∷⟧? (ρ , ρs)) ≈⟨ *≫ step x [] (sym base) ⟩ (ρ ^ i +1) * e ((x , []) ⟦∷⟧? (ρ , ρs)) ≈⟨ *≫ cng (⟦∷⟧?-hom x [] ρ ρs) ⟩ (ρ ^ i +1) * e ((x , []) ⟦∷⟧ (ρ , ρs)) ≈⟨ dist _ _ ⟩ e (ρ ^ i +1 * ((x , []) ⟦∷⟧ (ρ , ρs))) ∎ poly-foldR ρ ρs f e cng dist step base (x ≠0 Δ suc i & ∹ xs) = let ys = para f xs y,zs = f (x , ys) y = proj₁ y,zs zs = proj₂ y,zs in begin Σ?⟦ y Δ suc i ∷↓ zs ⟧ (ρ , ρs) ≈⟨ ∷↓-hom-s y i zs ρ ρs ⟩ (ρ ^ i +1) * ((y , zs) ⟦∷⟧ (ρ , ρs)) ≈˘⟨ *≫ ⟦∷⟧?-hom y zs ρ ρs ⟩ (ρ ^ i +1) * ((y , zs) ⟦∷⟧? (ρ , ρs)) ≈⟨ *≫ step x (∹ xs) (poly-foldR ρ ρs f e cng dist step base xs) ⟩ (ρ ^ i +1) * e ((x , (∹ xs)) ⟦∷⟧? (ρ , ρs)) ≈⟨ *≫ cng (⟦∷⟧?-hom x (∹ xs) ρ ρs) ⟩ (ρ ^ i +1) * e ((x , (∹ xs)) ⟦∷⟧ (ρ , ρs)) ≈⟨ dist _ _ ⟩ e (ρ ^ i +1 * ((x , (∹ xs)) ⟦∷⟧ (ρ , ρs))) ∎ poly-foldR ρ ρs f e cng dist step base (x ≠0 Δ ℕ.zero & []) = let y,zs = f (x , []) y = proj₁ y,zs zs = proj₂ y,zs in begin Σ?⟦ y Δ ℕ.zero ∷↓ zs ⟧ (ρ , ρs) ≈⟨ ∷↓-hom-0 y zs ρ ρs ⟩ ((y , zs) ⟦∷⟧ (ρ , ρs)) ≈˘⟨ ⟦∷⟧?-hom y zs ρ ρs ⟩ ((y , zs) ⟦∷⟧? (ρ , ρs)) ≈⟨ step x [] (sym base) ⟩ e ((x , []) ⟦∷⟧? (ρ , ρs)) ≈⟨ cng (⟦∷⟧?-hom x [] ρ ρs) ⟩ e ((x , []) ⟦∷⟧ (ρ , ρs)) ∎ poly-foldR ρ ρs f e cng dist step base (x ≠0 Δ ℕ.zero & (∹ xs)) = let ys = para f xs y,zs = f (x , ys) y = proj₁ y,zs zs = proj₂ y,zs in begin Σ?⟦ y Δ ℕ.zero ∷↓ zs ⟧ (ρ , ρs) ≈⟨ ∷↓-hom-0 y zs ρ ρs ⟩ ((y , zs) ⟦∷⟧ (ρ , ρs)) ≈˘⟨ ⟦∷⟧?-hom y zs ρ ρs ⟩ ((y , zs) ⟦∷⟧? (ρ , ρs)) ≈⟨ step x (∹ xs) (poly-foldR ρ ρs f e cng dist step base xs) ⟩ e ((x , (∹ xs)) ⟦∷⟧ (ρ , ρs)) ≈⟨ cng (⟦∷⟧?-hom x (∹ xs) ρ ρs) ⟩ e ((x , (∹ xs)) ⟦∷⟧ (ρ , ρs)) ∎ poly-mapR : ∀ {n} ρ ρs → ([f] : Poly n → Poly n) → (f : Carrier → Carrier) → (∀ {x y} → x ≈ y → f x ≈ f y) → (∀ x y → x * f y ≈ f (x * y)) → (∀ x y → f (x + y) ≈ f x + f y) → (∀ y → ⟦ [f] y ⟧ ρs ≈ f (⟦ y ⟧ ρs) ) → (f 0# ≈ 0#) → ∀ xs → Σ?⟦ poly-map [f] xs ⟧ (ρ , ρs) ≈ f (Σ⟦ xs ⟧ (ρ , ρs)) poly-mapR ρ ρs [f] f cng *-dist +-dist step′ base xs = poly-foldR ρ ρs (map₁ [f]) f cng *-dist step base xs where step : ∀ y {ys} zs → Σ?⟦ ys ⟧ (ρ , ρs) ≈ f (Σ?⟦ zs ⟧ (ρ , ρs)) →(map₁ [f] (y , ys) ⟦∷⟧? (ρ , ρs)) ≈ f ((y , zs) ⟦∷⟧? (ρ , ρs)) step y {ys} zs ys≋zs = begin map₁ [f] (y , ys) ⟦∷⟧? (ρ , ρs) ≡⟨⟩ ρ * Σ?⟦ ys ⟧ (ρ , ρs) + ⟦ [f] y ⟧ ρs ≈⟨ ((*≫ ys≋zs) ⟨ trans ⟩ *-dist ρ _) ⟨ +-cong ⟩ step′ y ⟩ f (ρ * Σ?⟦ zs ⟧ (ρ , ρs)) + f (⟦ y ⟧ ρs) ≈⟨ sym (+-dist _ _) ⟩ f ((y , zs) ⟦∷⟧? (ρ , ρs)) ∎