\import Algebra.Monoid \import Algebra.Monoid.GCD \import Algebra.Pointed \import Arith.Nat \import Data.Or \import Logic \import Paths \open Monoid(Inv,LDiv) \class Irr {M : CMonoid} (\coerce e : M) (notInv : Not (Inv e)) { | isIrr {x y : M} : e = x * y -> Inv x || Inv y | isCancelable-left {x y : M} : e * x = e * y -> x = y \lemma decide (x y : M) (e=x*y : e = x * y) : Inv x `Or` Inv y => ||.rec (Or.levelProp (\lam (i : Inv x) (j : Inv y) => notInv (transport (Inv __) (inv e=x*y) (Inv.product i j)))) inl inr (isIrr e=x*y) \lemma notIdemp (p : e = e * e) : Empty => notInv (\case isIrr p \with { | byLeft r => r | byRight r => r }) } \where { \lemma cancelative {M : CancelCMonoid} (p : M) (notInv : Not (Inv p)) (irr : \Pi {x y : M} -> p = x * y -> Inv x || Inv y) : Irr p notInv \cowith | isIrr => irr | isCancelable-left => cancel_*-left p } \class Prime \extends Irr | isPrime {x y : M} : LDiv e (x * y) -> LDiv e x || LDiv e y | isIrr {x} {y} e=x*y => \case isPrime (\new LDiv e (x * y) ide (ide-right *> e=x*y)) \with { | byLeft (e|x : LDiv e x) => byRight (Inv.lmake e|x.inv (isCancelable-left (inv (ide-right *> e=x*y *> pmap (`* y) (inv e|x.inv-right) *> *-assoc)))) | byRight (e|y : LDiv e y) => byLeft (Inv.lmake e|y.inv (isCancelable-left (inv (ide-right *> e=x*y *> *-comm *> pmap (`* x) (inv e|y.inv-right) *> *-assoc)))) } \lemma irr-isPrime {M : GCDMonoid} (p : Irr {M}) : Prime p p.notInv \cowith | isCancelable-left => p.isCancelable-left | isPrime {x} {y} p|x*y => \case irr-cmp x \with { | byLeft p|x => byLeft p|x | byRight p_x => \case M.coprime_*_div p|x*y p_x \with { | inP r => byRight r } } \where \lemma irr-cmp (a : M) : LDiv p a || IsCoprime p a => \let | (inP (gc : GCD p a)) => isGCD p a | g => gc.gcd | g|p : LDiv g p => gc.gcd|val1 | g|a : LDiv g a => gc.gcd|val2 | x => g|p.inv \in \case p.isIrr (inv g|p.inv-right) \with { | byLeft (gi : Inv g) => byRight (\lam z z|p z|a => \have z|g : LDiv z g => gc.gcd-univ z z|p z|a \in Inv.rmake (gi.inv * z|g.inv) ( z * (gi.inv * z|g.inv) ==< pmap (z *) *-comm >== z * (z|g.inv * gi.inv) ==< inv *-assoc >== (z * z|g.inv) * gi.inv ==< pmap (`* gi.inv) z|g.inv-right >== g * gi.inv ==< gi.inv-right >== ide `qed)) | byRight (xi : Inv x) => byLeft (\new LDiv p a (xi.inv * g|a.inv) ( p * (xi.inv * g|a.inv) ==< inv *-assoc >== (p * xi.inv) * g|a.inv ==< pmap ((__ * xi.inv) * g|a.inv) (inv g|p.inv-right) >== ((g * x) * xi.inv) * g|a.inv ==< pmap (`* g|a.inv) *-assoc >== (g * (x * xi.inv)) * g|a.inv ==< pmap ((g * __) * g|a.inv) xi.inv-right >== (g * ide) * g|a.inv ==< pmap (`* g|a.inv) ide-right >== g * g|a.inv ==< g|a.inv-right >== a `qed)) } \lemma nat_irr {n : Nat} (p : Irr {NatSemiring}) (n|p : LDiv n p) : (n = 1) || (n = p) => \case p.isIrr (inv n|p.inv-right) \with { | byLeft (j : Inv n) => byLeft (natUnit j.inv-left) | byRight (j : Inv n|p.inv) => byRight (pmap (n *) (inv (natUnit j.inv-left)) *> n|p.inv-right) }