{-# OPTIONS --safe --warning=error --without-K #-} open import LogicalFormulae open import Groups.Groups open import Groups.Homomorphisms.Definition open import Groups.Definition open import Numbers.Naturals.Definition open import Setoids.Orders open import Setoids.Setoids open import Functions open import Sets.EquivalenceRelations open import Vectors open import Lists.Lists open import Maybe open import Agda.Primitive using (Level; lzero; lsuc; _⊔_) module Groups.Polynomials.Definition {a b : _} {A : Set a} {S : Setoid {a} {b} A} {_+_ : A → A → A} (G : Group S _+_) where open Setoid S open Equivalence eq open Group G NaivePoly : Set a NaivePoly = List A 0P : NaivePoly 0P = [] polysEqual : NaivePoly → NaivePoly → Set (a ⊔ b) polysEqual [] [] = True' polysEqual [] (x :: b) = (x ∼ 0G) && polysEqual [] b polysEqual (x :: a) [] = (x ∼ 0G) && polysEqual a [] polysEqual (x :: a) (y :: b) = (x ∼ y) && polysEqual a b polysReflexive : {x : NaivePoly} → polysEqual x x polysReflexive {[]} = record {} polysReflexive {x :: y} = reflexive ,, polysReflexive polysSymmetricZero : {x : NaivePoly} → polysEqual [] x → polysEqual x [] polysSymmetricZero {[]} 0=x = record {} polysSymmetricZero {x :: y} (fst ,, snd) = fst ,, polysSymmetricZero snd polysSymmetricZero' : {x : NaivePoly} → polysEqual x [] → polysEqual [] x polysSymmetricZero' {[]} 0=x = record {} polysSymmetricZero' {x :: y} (fst ,, snd) = fst ,, polysSymmetricZero' snd polysSymmetric : {x y : NaivePoly} → polysEqual x y → polysEqual y x polysSymmetric {[]} {y} x=y = polysSymmetricZero x=y polysSymmetric {x :: xs} {[]} x=y = polysSymmetricZero' {x :: xs} x=y polysSymmetric {x :: xs} {y :: ys} (fst ,, snd) = symmetric fst ,, polysSymmetric {xs} {ys} snd polysTransitive : {x y z : NaivePoly} → polysEqual x y → polysEqual y z → polysEqual x z polysTransitive {[]} {[]} {[]} x=y y=z = record {} polysTransitive {[]} {[]} {x :: z} x=y y=z = y=z polysTransitive {[]} {x :: y} {[]} (fst ,, snd) y=z = record {} polysTransitive {[]} {x :: y} {x₁ :: z} (fst ,, snd) (fst2 ,, snd2) = transitive (symmetric fst2) fst ,, polysTransitive snd snd2 polysTransitive {x :: xs} {[]} {[]} x=y y=z = x=y polysTransitive {x :: xs} {[]} {z :: zs} (fst ,, snd) (fst2 ,, snd2) = transitive fst (symmetric fst2) ,, polysTransitive snd snd2 polysTransitive {x :: xs} {y :: ys} {[]} (fst ,, snd) (fst2 ,, snd2) = transitive fst fst2 ,, polysTransitive snd snd2 polysTransitive {x :: xs} {y :: ys} {z :: zs} (fst ,, snd) (fst2 ,, snd2) = transitive fst fst2 ,, polysTransitive snd snd2 naivePolySetoid : Setoid NaivePoly Setoid._∼_ naivePolySetoid = polysEqual Equivalence.reflexive (Setoid.eq naivePolySetoid) = polysReflexive Equivalence.symmetric (Setoid.eq naivePolySetoid) = polysSymmetric Equivalence.transitive (Setoid.eq naivePolySetoid) = polysTransitive polyInjection : A → NaivePoly polyInjection a = a :: [] polyInjectionIsInj : SetoidInjection S naivePolySetoid polyInjection SetoidInjection.wellDefined polyInjectionIsInj x=y = x=y ,, record {} SetoidInjection.injective polyInjectionIsInj {x} {y} (fst ,, snd) = fst -- the zero polynomial has no degree -- all other polynomials have a degree degree : ((x : A) → (x ∼ 0G) || ((x ∼ 0G) → False)) → NaivePoly → Maybe ℕ degree decide [] = no degree decide (x :: poly) with decide x degree decide (x :: poly) | inl x=0 with degree decide poly degree decide (x :: poly) | inl x=0 | no = no degree decide (x :: poly) | inl x=0 | yes deg = yes (succ deg) degree decide (x :: poly) | inr x!=0 with degree decide poly degree decide (x :: poly) | inr x!=0 | no = yes 0 degree decide (x :: poly) | inr x!=0 | yes n = yes (succ n) degreeWellDefined : (decide : ((x : A) → (x ∼ 0G) || ((x ∼ 0G) → False))) {x y : NaivePoly} → polysEqual x y → degree decide x ≡ degree decide y degreeWellDefined decide {[]} {[]} x=y = refl degreeWellDefined decide {[]} {x :: y} (fst ,, snd) with decide x degreeWellDefined decide {[]} {x :: y} (fst ,, snd) | inl x=0 with inspect (degree decide y) degreeWellDefined decide {[]} {x :: y} (fst ,, snd) | inl x=0 | no with≡ pr rewrite pr = refl degreeWellDefined decide {[]} {x :: y} (fst ,, snd) | inl x=0 | yes bad with≡ pr rewrite pr = exFalso (noNotYes (transitivity (degreeWellDefined decide {[]} {y} snd) pr)) degreeWellDefined decide {[]} {x :: y} (fst ,, snd) | inr x!=0 with inspect (degree decide y) degreeWellDefined decide {[]} {x :: y} (fst ,, snd) | inr x!=0 | no with≡ pr rewrite pr = exFalso (x!=0 fst) degreeWellDefined decide {[]} {x :: y} (fst ,, snd) | inr x!=0 | yes deg with≡ pr rewrite pr = exFalso (x!=0 fst) degreeWellDefined decide {x :: xs} {[]} x=y with decide x degreeWellDefined decide {x :: xs} {[]} (fst ,, snd) | inl x=0 with inspect (degree decide xs) degreeWellDefined decide {x :: xs} {[]} (fst ,, snd) | inl x=0 | no with≡ pr rewrite pr = refl degreeWellDefined decide {x :: xs} {[]} (fst ,, snd) | inl x=0 | yes bad with≡ pr rewrite pr = exFalso (noNotYes (transitivity (equalityCommutative (degreeWellDefined decide snd)) pr)) degreeWellDefined decide {x :: xs} {[]} (fst ,, snd) | inr x!=0 = exFalso (x!=0 fst) degreeWellDefined decide {x :: xs} {y :: ys} (fst ,, snd) with decide x degreeWellDefined decide {x :: xs} {y :: ys} (fst ,, snd) | inl x=0 with decide y degreeWellDefined decide {x :: xs} {y :: ys} (fst ,, snd) | inl x=0 | inl y=0 with inspect (degree decide ys) degreeWellDefined decide {x :: xs} {y :: ys} (fst ,, snd) | inl x=0 | inl y=0 | no with≡ pr rewrite degreeWellDefined decide {xs} {ys} snd | pr = refl degreeWellDefined decide {x :: xs} {y :: ys} (fst ,, snd) | inl x=0 | inl y=0 | (yes th) with≡ pr rewrite degreeWellDefined decide {xs} {ys} snd | pr = refl degreeWellDefined decide {x :: xs} {y :: ys} (fst ,, snd) | inl x=0 | inr y!=0 = exFalso (y!=0 (transitive (symmetric fst) x=0)) degreeWellDefined decide {x :: xs} {y :: ys} (fst ,, snd) | inr x!=0 with decide y degreeWellDefined decide {x :: xs} {y :: ys} (fst ,, snd) | inr x!=0 | inl y=0 = exFalso (x!=0 (transitive fst y=0)) degreeWellDefined decide {x :: xs} {y :: ys} (fst ,, snd) | inr x!=0 | inr y!=0 with inspect (degree decide ys) degreeWellDefined decide {x :: xs} {y :: ys} (fst ,, snd) | inr x!=0 | inr y!=0 | no with≡ pr rewrite degreeWellDefined decide {xs} {ys} snd | pr = refl degreeWellDefined decide {x :: xs} {y :: ys} (fst ,, snd) | inr x!=0 | inr y!=0 | yes x₁ with≡ pr rewrite degreeWellDefined decide {xs} {ys} snd | pr = refl degreeNoImpliesZero : (decide : ((x : A) → (x ∼ 0G) || ((x ∼ 0G) → False))) → (a : NaivePoly) → degree decide a ≡ no → polysEqual a [] degreeNoImpliesZero decide [] not = record {} degreeNoImpliesZero decide (x :: a) not with decide x degreeNoImpliesZero decide (x :: a) not | inl x=0 with inspect (degree decide a) degreeNoImpliesZero decide (x :: a) not | inl x=0 | no with≡ pr rewrite pr = x=0 ,, degreeNoImpliesZero decide a pr degreeNoImpliesZero decide (x :: a) not | inl x=0 | (yes deg) with≡ pr rewrite pr = exFalso (noNotYes (equalityCommutative not)) degreeNoImpliesZero decide (x :: a) not | inr x!=0 with degree decide a degreeNoImpliesZero decide (x :: a) () | inr x!=0 | no degreeNoImpliesZero decide (x :: a) () | inr x!=0 | yes x₁ emptyImpliesDegreeZero : (decide : ((x : A) → (x ∼ 0G) || ((x ∼ 0G) → False))) → (a : NaivePoly) → polysEqual a [] → degree decide a ≡ no emptyImpliesDegreeZero decide [] a=[] = refl emptyImpliesDegreeZero decide (x :: a) (fst ,, snd) with decide x emptyImpliesDegreeZero decide (x :: a) (fst ,, snd) | inl x=0 with inspect (degree decide a) emptyImpliesDegreeZero decide (x :: a) (fst ,, snd) | inl x=0 | no with≡ pr rewrite pr = refl emptyImpliesDegreeZero decide (x :: a) (fst ,, snd) | inl x=0 | (yes deg) with≡ pr rewrite pr = exFalso (noNotYes (transitivity (equalityCommutative (emptyImpliesDegreeZero decide a snd)) pr)) emptyImpliesDegreeZero decide (x :: a) (fst ,, snd) | inr x!=0 = exFalso (x!=0 fst)