\import Algebra.Domain.Euclidean \import Algebra.Domain.GCD \import Algebra.Group \import Algebra.Meta \import Algebra.Monoid \import Algebra.Monoid.Category \import Algebra.Monoid.GCD \import Algebra.Ring \import Algebra.Ring.RingHom \import Algebra.Ring.Local \import Data.Or \import Equiv \import Function.Meta ($) \import Logic \import Meta \import Paths \import Paths.Meta \import Set \open Monoid(Inv) -- | A field is a commutative local ring such that non-invertible elements equal to {zro}. \class Field \extends LocalCRing, GCDDomain | #0 x => Inv x | #0-+ => LocalRing.sumInv=>eitherInv | #0-zro (j : Inv zro) => zro/=ide (inv zro_*-right *> j.inv-left) | #0-*-left => Inv.cfactor-left | zro#ide => Inv.lmake ide ide-left | #0-* xj yj => Inv.product xj yj | isGCDDomain x y x#0 y#0 => inP \new GCD { | gcd => 1 | gcd|val1 => \new Monoid.LDiv { | inv => x | inv-right => ide-left } | gcd|val2 => \new Monoid.LDiv { | inv => y | inv-right => ide-left } | gcd-univ g g|x g|y => \new Monoid.LDiv { | inv => Monoid.LDiv.inv {g|x} * Inv.inv {x#0} | inv-right => inv *-assoc *> pmap (`* _) Monoid.LDiv.inv-right *> Inv.inv-right } } -- | A discrete field is a commutative ring such that every element is either {zro} or invertible. \class DiscreteField \extends Field, EuclideanDomain { | finv : E -> E | finv_zro : finv 0 = 0 | finv-right {x : E} (x/=0 : x /= 0) : x * finv x = 1 \field eitherZeroOrInv (x : E) : (x = 0) || Inv x | isEuclidean => inP \new EuclideanRingData { | euclideanMap x => 0 | divMod x y => \case decideEq y 0 \with { | yes _ => (0, x) | no _ => (finv y * x, 0) } | isDivMod x y => mcases \with { | yes _ => equation | no q => zro-right *> inv *-assoc *> rewrite (finv-right q) ide-left } | isEuclideanMap x y y/=0 => mcases {1} \with { | yes y=0 => absurd (y/=0 y=0) | no _ => \lam p => absurd (p idp) } } \default finv \as finv-impl x => \case aux zro/=ide x (eitherZeroOrInv x) \with { | inl _ => 0 | inr (j : Inv) => j.inv } \default finv_zro \as finv_zroImpl : finv-impl 0 = 0 => unfold finv-impl (mcases \with { | inl _ => idp | inr (j : Inv) => absurd (zro/=ide (inv zro_*-left *> j.inv-right)) }) \default finv-right \as id_finvImpl {x} x/=0 : x * finv-impl x = 1 => unfold finv-impl (mcases \with { | inl x=0 => absurd (x/=0 x=0) | inr (j : Inv) => j.inv-right }) \default eitherZeroOrInv x => \case decideEq x 0 \with { | yes x=0 => byLeft x=0 | no x/=0 => byRight (Inv.rmake (finv x) (finv-right x/=0)) } | locality x => \case eitherZeroOrInv x \with { | byLeft x=0 => byRight (Inv.lmake ide equation) | byRight xInv => byLeft xInv } \default decideEq x y => \case eitherZeroOrInv (x - y) \with { | byLeft x-y=0 => yes (fromZero x-y=0) | byRight x-y-isInv => no \lam x=y => #-irreflexive (rewrite x=y in x-y-isInv) } | nonZeroApart {x} x/=0 => \case eitherZeroOrInv x \with { | byLeft x=0 => absurd (x/=0 x=0) | byRight x#0 => x#0 } \lemma finv-left {x : E} (x/=0 : x /= 0) : finv x * x = 1 => *-comm *> finv-right x/=0 \lemma finv-Inv {x : E} (x/=0 : x /= 0) : Inv (finv x) x => Inv.lmake x (finv-right x/=0) \lemma nonZero-Inv {x : E} (x/=0 : x /= 0) : Inv x (finv x) => Inv.rmake (finv x) (finv-right x/=0) \lemma finv/=0 {x : E} (x/=0 : x /= 0) : finv x /= 0 => inv-nonZero (finv-Inv x/=0) \lemma finv_* {x y : E} : finv (x * y) = finv y * finv x => \case decideEq x 0, decideEq y 0 \with { | yes x=0, _ => rewrite (x=0,zro_*-left,finv_zro) (inv zro_*-right) | _, yes y=0 => rewrite (y=0,zro_*-right,finv_zro) (inv zro_*-left) | no x/=0, no y/=0 => Inv.inv-isUnique (nonZero-Inv (nonZero_* x/=0 y/=0)) (Inv.lmake (finv y * finv x) (equation {usingOnly (finv-left x/=0, finv-left y/=0)})) idp } \lemma finv_finv {x : E} : finv (finv x) = x => \case decideEq x 0 \with { | yes x=0 => rewrite (x=0,finv_zro) finv_zro | no x/=0 => Inv.inv-isUnique (nonZero-Inv (finv/=0 x/=0)) (Inv.lmake x (finv-right x/=0)) idp } \lemma zeroDimensional : IsZeroDimensional => \lam a => \case eitherZeroOrInv a \with { | byLeft a=0 => inP (0, 1, rewrite a=0 simplify) | byRight (r : Inv) => inP (r.inv, 0, simplify $ inv r.inv-right) } \lemma decideZeroOrInv (x : E) : (x = 0) `Or` Inv x => aux zro/=ide x (eitherZeroOrInv x) \lemma finv-diff {x : E} (xi : x /= 0) (x+1i : x + 1 /= 0) : finv x - finv (x + 1) = finv (x * (x + 1)) => equation {usingOnly (finv-right xi, finv-right x+1i, finv-right $ nonZero_* xi x+1i)} } \where { \private \lemma aux {R : CRing} (p : zro /= {R} ide) (x : R) (q : (x = 0) || Inv x) : (x = 0) `Or` Inv x \level Or.levelProp (\lam x=0 (j : Inv x) => p $ inv zro_*-left *> pmap (`* _) (inv x=0) *> j.inv-right) => \case q \with { | byLeft r => inl r | byRight r => inr r } \func backwards (f : RingHom) (e : Equiv f) (D : DiscreteField { | Ring => f.Cod }) : DiscreteField { | Ring => f.Dom } \cowith | *-comm => e.isInj $ f.func-* *> *-comm *> inv f.func-* | zro/=ide q => D.zro/=ide $ inv f.func-zro *> pmap f q *> f.func-ide | eitherZeroOrInv a => ||.map (\lam q => e.isInj $ q *> inv f.func-zro) (\lam (fai : Inv (f a)) => \new Inv a { | inv => e.ret fai.inv | inv-left => e.isInj $ f.func-* *> pmap (`* _) (e.f_ret _) *> fai.inv-left *> inv f.func-ide | inv-right => e.isInj $ f.func-* *> pmap (_ *) (e.f_ret _) *> fai.inv-right *> inv f.func-ide }) (D.eitherZeroOrInv (f a)) \func forward {f : RingHom} (e : Equiv f) (D : DiscreteField { | Ring => f.Dom }) : DiscreteField { | Ring => f.Cod } => backwards (\new RingHom f.Cod f.Dom e.ret { | func-+ => e.isInj $ e.f_ret _ *> inv (f.func-+ *> pmap2 (+) (e.f_ret _) (e.f_ret _)) | func-ide => e.isInj $ e.f_ret _ *> inv f.func-ide | func-* => e.isInj $ e.f_ret _ *> inv (f.func-* *> pmap2 (*) (e.f_ret _) (e.f_ret _)) }) (symQEquiv e) D }