\import Algebra.Domain(Domain,IntegralDomain) \import Algebra.Group \import Algebra.Meta \import Algebra.Monoid \import Algebra.Monoid.Category(MonoidHom, func-+) \import Algebra.Monoid.Sub \import Algebra.Pointed \import Algebra.Pointed.Sub \import Algebra.Ring \import Algebra.Ring.Category \import Algebra.Ring.RingHom \import Algebra.Semiring \import Arith.Nat \import Category \import Function (isInj, isSurj) \import Function.Meta \import HLevel \import Logic \import Meta \import Order.PartialOrder \import Paths \import Paths.Meta \import Relation.Equivalence \import Set \hiding (#) \import Set.Category \open Monoid(Inv) \open Precat(>>) \instance SubsetPoset {M : Monoid} : Poset (SubSet M) | <= (S S' : SubSet M) => \Pi (x : M) -> S x -> S' x | <=-refl x p => p | <=-transitive S1<=S2 S2<=S3 x p => S2<=S3 x (S1<=S2 x p) | <=-antisymmetric S1<=S2 S2<=S1 => path (\lam i => \new SubSet M (\lam x => propExt (S1<=S2 x) (S2<=S1 x) @ i)) \class Localization (R : CRing) (S : SubSet R) (R' : CRing) { | inL : RingHom R R' | local (x : R) : S x -> Inv (inL x) | local-univ {R'' : CRing} (f : RingHom R R'') (l : \Pi (x : R) -> S x -> Inv (f x)) : Contr (\Sigma (g : RingHom R' R'') (\Pi (x : R) -> g (inL x) = f x)) \func lift {R'' : CRing} (f : RingHom R R'') (l : \Pi (x : R) -> S x -> Inv (f x)) : RingHom R' R'' => (Contr.center {local-univ f l}).1 \lemma lift-prop {R'' : CRing} (f : RingHom R R'') (l : \Pi (x : R) -> S x -> Inv (f x)) : inL >> lift f l = f => RingHom.equals {R} {R''} {inL >> lift f l} (Contr.center {local-univ f l}).2 \lemma lift-prop-func {R'' : CRing} (f : RingHom R R'') (l : \Pi (x : R) -> S x -> Inv (f x)) (x : R) : func {lift f l} (inL x) = f x => path (\lam i => func {lift-prop f l @ i} x) \lemma remove_inL {R'' : CRing} (f g : RingHom R' R'') (p : \Pi (x : R) -> f (inL x) = g (inL x)) : f = g => pmap __.1 (isContr=>isProp (local-univ {\this} {R''} (inL >> g) (\lam x sx => MonoidHom.presInv g (local x sx))) (f,p) (g, \lam _ => idp)) } \where { \use \level levelProp (R : CRing) {S : SubSet R} (l1 l2 : Localization R S) : l1 = l2 => \have e => lift-iso S S l1 l2 l1.local l2.local \in ext (Cat.isotoid e, Cat.transport_Hom_iso-right e l1.inL (l1.lift-prop l2.inL l2.local)) \lemma lift-iso {R : CRing} (S1 S2 : SubSet R) (l1 : Localization R S1) (l2 : Localization R S2) (p1 : \Pi (x : R) -> S2 x -> Inv (l1.inL x)) (p2 : \Pi (x : R) -> S1 x -> Inv (l2.inL x)) : Iso (l1.lift l2.inL p2) \cowith | hinv => l2.lift l1.inL p1 | hinv_f => l1.remove_inL {l1.R'} (l1.lift l2.inL p2 >> l2.lift l1.inL p1) (id l1.R') \lam x => pmap (func {l2.lift l1.inL p1}) (l1.lift-prop-func l2.inL p2 x) *> l2.lift-prop-func l1.inL p1 x | f_hinv => l2.remove_inL {l2.R'} (l2.lift l1.inL p1 >> l1.lift l2.inL p2) (id l2.R') \lam x => pmap (func {l1.lift l2.inL p2}) (l2.lift-prop-func l1.inL p1 x) *> l1.lift-prop-func l2.inL p2 x } \instance LocRing {R : CRing} (S : SubMonoid R) : CRing \cowith | E => Type | zro => in~ (zro, ide, contains_ide) | + => ++ | zro-left {in~ _} => path (~-equiv _ _ equation) | +-assoc {in~ _} {in~ _} {in~ _} => path (~-equiv _ _ (pmap2 (*) equation (inv *-assoc))) | +-comm {in~ _} {in~ _} => path (~-equiv _ _ equation) | ide => in~ (ide, ide, contains_ide) | * => ** | ide-left {in~ _} => path (~-equiv _ _ equation) | *-assoc {in~ _} {in~ _} {in~ _} => path (~-equiv _ _ equation) | ldistr {in~ _} {in~ _} {in~ _} => path (~-equiv _ _ equation) | negative => neg | negative-left {in~ _} => path (~-equiv _ _ equation) | *-comm {in~ _} {in~ _} => path (~-equiv _ _ (pmap2 (*) *-comm *-comm)) | natCoef n => in~ (natCoef n, 1, contains_ide) | natCoefZero => path (\lam i => in~ (natCoefZero i, 1, contains_ide)) | natCoefSuc n => pmap in~ $ ext (natCoefSuc n *> equation, inv ide-left) \where { \func SType (S : SubMonoid R) => \Sigma (x y : R) (S y) \func Type => Quotient {SType S} (\lam a b => a.1 * b.2 = b.1 * a.2) \lemma inl-surj : isSurj (inl~ {R} {S}) => Quotient.in-surj \lemma equals-lem {a b : SType S} (c : R) (s : S c) (p : a.1 * b.2 * c = b.1 * a.2 * c) : inl~ a = inl~ b => \let a' : SType S => (a.1 * c, a.2 * c, contains_* a.3 s) \in path (~-equiv a a' equation) *> path (~-equiv a' b equation) \lemma equals1 {a b : SType S} (p : a.1 * b.2 = b.1 * a.2) : inl~ a = inl~ b => equals-lem 1 S.contains_ide (simplify p) \lemma unequals {a b : SType S} (p : inl~ a = inl~ b) : TruncP (\Sigma (c : R) (S c) (a.1 * b.2 * c = b.1 * a.2 * c)) => Equivalence.Closure.univ (\new Equivalence (SType S) { | ~ x y => TruncP (\Sigma (z : R) (S z) (x.1 * y.2 * z = y.1 * x.2 * z)) | ~-reflexive => inP (ide, contains_ide, idp) | ~-symmetric (inP (z,c,p)) => inP (z, c, inv p) | ~-transitive {x} {y} (inP (t,ct,pt)) (inP (s,cs,ps)) => inP (y.2 * (t * s), contains_* y.3 (contains_* ct cs), equation) }) (\lam x~y => inP (ide, contains_ide, simplify x~y)) (Quotient.equality p) \lemma equality {a b : SType S} : (inl~ a = inl~ b) = TruncP (\Sigma (c : R) (S c) (a.1 * b.2 * c = b.1 * a.2 * c)) => propExt unequals (\lam (inP (c,s,p)) => equals-lem c s p) \lemma swap {R : CMonoid} {r1 r2 s1 s2 : R} : (r1 * r2) * (s1 * s2) = (r1 * s1) * (r2 * s2) => equation \func neg (a : Type) : Type \elim a | in~ (r,s,p) => in~ (negative r, s, p) | ~-equiv (r,s,p) (r',s',p') rs~rs' i => ~-equiv (negative r, s, p) (negative r', s', p') equation i \func ++ (a b : Type) : Type \elim a, b | in~ (r1,s1,p1), in~ (r2,s2,p2) => in~ (r1 * s2 + r2 * s1, s1 * s2, contains_* p1 p2) | ~-equiv (r1,s1,p1) (r1',s1',p1') rs1~rs1' i, in~ (r2,s2,p2) => ~-equiv (r1 * s2 + r2 * s1, s1 * s2, contains_* p1 p2) (r1' * s2 + r2 * s1', s1' * s2, contains_* p1' p2) equation i | in~ (r1,s1,p1), ~-equiv (r2,s2,p2) (r2',s2',p2') rs2~rs2' i => ~-equiv (r1 * s2 + r2 * s1, s1 * s2, contains_* p1 p2) (r1 * s2' + r2' * s1, s1 * s2', contains_* p1 p2') equation i \func ** (a b : Type) : Type \elim a, b | in~ (r1,s1,p1), in~ (r2,s2,p2) => in~ (r1 * r2, s1 * s2, contains_* p1 p2) | ~-equiv (r1,s1,p1) (r1',s1',p1') rs1~rs1' i, in~ (r2,s2,p2) => ~-equiv (r1 * r2, s1 * s2, contains_* p1 p2) (r1' * r2, s1' * s2, contains_* p1' p2) equation i | in~ (r1,s1,p1), ~-equiv (r2,s2,p2) (r2',s2',p2') rs2~rs2' i => ~-equiv (r1 * r2, s1 * s2, contains_* p1 p2) (r1 * r2', s1 * s2', contains_* p1 p2') equation i \lemma trivial {x : R} (n : R.IsNilpotent x) (s : S x) : Contr (LocRing S) \elim n | inP (n,p) => \new Contr { | center => in~ (zro, ide, contains_ide) | contraction => \case \elim __ \with { | in~ a => equals-lem 0 (transport S p $ S.contains_pow s) simplify } } \lemma closure-equiv {R : CRing} (S : SubSet R) (l1 : Localization R S) (l2 : Localization R (closure S)) : Iso (l1.lift l2.inL (\lam x x<-S => l2.local x (closure.ext S x x<-S))) => Localization.lift-iso S (closure S) l1 l2 (inv-closure l1) (\lam x x<-S => l2.local x (closure.ext S x x<-S)) \where { \open SubMonoid \lemma inv-closure (l : Localization R S) (x : R) (p : closure S x) : Inv (l.inL x) \elim p | inP (0, p) => l.local x p | inP (suc n, byLeft x<-C) => inv-closure l x (inP (n, x<-C)) | inP (suc n, byRight (byLeft x=1)) => rewrite (pmap l.inL x=1 *> l.inL.func-ide) (\new Inv ide ide ide-left ide-left) | inP (suc n, byRight (byRight (y, z, y<-C, z<-C, x=y*z))) => rewrite (pmap l.inL x=y*z *> l.inL.func-*) (Inv.product (inv-closure l y (inP (n, y<-C))) (inv-closure l z (inP (n, z<-C)))) } \lemma nilpotent-contr (b : R) (Sb : S b) (n : Nat) (p : R.pow b n = 0) : Contr (LocRing S) => isProp=>isContr (\case \elim __, \elim __ \with { | in~ x, in~ y => equals-lem 0 (rewriteI p $ S.contains_pow Sb) simplify }) $ inl~ (0,b,Sb) } \func inl~ {R : CRing} {S : SubMonoid R} (x : LocRing.SType S) : LocRing.Type => in~ x \lemma loc_unequals_domain {D : IntegralDomain} (S : SubMonoid D) (nz : \Pi (x : D) -> S x -> x /= 0) {a b : LocRing.SType S} (p : inl~ a = inl~ b) : a.1 * b.2 = b.1 * a.2 => \case LocRing.unequals p \with { | inP (c,c1,p) => Domain.nonZero-cancel-right (nz c c1) p } \func locMap {R : CRing} {S : SubMonoid R} : RingHom R (LocRing S) \cowith | func x => in~ (x, ide, contains_ide) | func-ide => idp | func-+ => path (~-equiv _ _ (path (\lam i => ((inv ide-right @ i) + (inv ide-right @ i)) * (ide-right @ i)))) | func-* => path (~-equiv _ _ simplify) \lemma locMap-inj {R : CRing} {S : SubMonoid R} (p : \Pi {a : R} -> S a -> \Pi {x y : R} -> x * a = y * a -> x = y) : isInj (locMap {R} {S}) => \lam {a} {b} q => \case LocRing.unequals q \with { | inP (c,Sc,d) => p Sc $ rewrite (ide-right,ide-right) in d } \func localization {R : CRing} (S : SubMonoid R) : Localization R S \cowith | R' => LocRing S | inL => locMap | local => elem-inv | local-univ {R''} (f : RingHom R R'') l => Contr.make (later (liftHom f l, liftHom-loc f l)) \lam q => ext $ locMap-epi {_} {_} {_} {liftHom f l} $ RingHom.equals \lam x => liftHom-loc f l x *> inv (q.2 x) \where { \open LocRing \func elem-inv (s : R) (p : S s) => \new Inv {LocRing S} { | val => in~ (s, ide, contains_ide) | inv => in~ (ide, s, p) | inv-left => equals1 (*-comm *> pmap (ide *) *-comm) | inv-right => equals1 (*-comm *> pmap (ide *) *-comm) } \lemma locMap-epi : isEpi locMap => \lam {Q} {g h : RingHom} q => RingHom.equals \lam (in~ (r,s,p)) => \have | j => path (~-equiv {SType S} (r,s,p) (r * ide, ide * s, contains_* contains_ide p) (inv *-assoc)) | d r' => pmap (\lam (t : RingHom R Q) => t r') q | m1 => transport (Inv {Q} __ (g (in~ (ide, s, p)))) (d s) (MonoidHom.presInv g (elem-inv s p)) | m2 => MonoidHom.presInv h (elem-inv s p) \in g (in~ (r,s,p)) ==< pmap g j >== g (in~ (r * ide, ide * s, contains_* contains_ide p)) ==< g.func-* >== g (in~ (r, ide, contains_ide)) * g (in~ (ide, s, p)) ==< pmap2 (\lam t1 (t2 : Inv (h (in~ (s, ide, contains_ide)))) => t1 * t2.inv) (d r) (Inv.levelProp m1 m2) >== h (in~ (r, ide, contains_ide)) * h (in~ (ide, s, p)) ==< inv h.func-* >== h (in~ (r * ide, ide * s, contains_* contains_ide p)) ==< inv (pmap h j) >== h (in~ (r,s,p)) `qed \func lift {R' : CRing} (f : RingHom R R') (l : \Pi (x : R) -> S x -> Inv (f x)) (a : Type {R} {S}) : R' \elim a | in~ (r,s,p) => f r * Inv.inv {l s p} | ~-equiv (r,s,p) (r',s',p') rs~rs' => f r * Inv.inv {l s p} ==< pmap (`* Inv.inv {l s p}) (inv ide-right) >== (f r * ide) * Inv.inv {l s p} ==< pmap ((f r * __) * Inv.inv {l s p}) (inv (Inv.inv-right {l s' p'})) >== (f r * (f s' * Inv.inv {l s' p'})) * Inv.inv {l s p} ==< pmap (`* Inv.inv {l s p}) (inv *-assoc) >== ((f r * f s') * Inv.inv {l s' p'}) * Inv.inv {l s p} ==< pmap ((__ * Inv.inv {l s' p'}) * Inv.inv {l s p}) (inv f.func-*) >== (f (r * s') * Inv.inv {l s' p'}) * Inv.inv {l s p} ==< *-assoc >== f (r * s') * (Inv.inv {l s' p'} * Inv.inv {l s p}) ==< pmap (f __ * (Inv.inv {l s' p'} * Inv.inv {l s p})) rs~rs' >== f (r' * s) * (Inv.inv {l s' p'} * Inv.inv {l s p}) ==< pmap (`* (Inv.inv {l s' p'} * Inv.inv {l s p})) f.func-* >== (f r' * f s) * (Inv.inv {l s' p'} * Inv.inv {l s p}) ==< swap >== (f r' * Inv.inv {l s' p'}) * (f s * Inv.inv {l s p}) ==< pmap ((f r' * Inv.inv {l s' p'}) *) (Inv.inv-right {l s p}) >== (f r' * Inv.inv {l s' p'}) * ide ==< ide-right >== f r' * Inv.inv {l s' p'} `qed \func liftHom {R' : CRing} (f : RingHom R R') (l : \Pi (x : R) -> S x -> Inv (f x)) : RingHom (LocRing S) R' \cowith | func => lift f l | func-ide => pmap (f ide *) ( Inv.inv {l ide contains_ide} ==< inv ide-right >== Inv.inv {l ide contains_ide} * ide ==< pmap (Inv.inv {l ide contains_ide} *) (inv f.func-ide) >== Inv.inv {l ide contains_ide} * f ide ==< Inv.inv-left {l ide contains_ide} >== ide `qed) *> ide-right *> f.func-ide | func-+ {in~ (r1,s1,p1)} {in~ (r2,s2,p2)} => f (r1 * s2 + r2 * s1) * Inv.inv {l (s1 * s2) (contains_* p1 p2)} ==< pmap2 (*) f.func-+ (func-inv f s1 s2 p1 p2 l) >== (f (r1 * s2) + f (r2 * s1)) * (Inv.inv {l s2 p2} * Inv.inv {l s1 p1}) ==< pmap2 ((__ + __) * (Inv.inv {l s2 p2} * Inv.inv {l s1 p1})) f.func-* f.func-* >== (f r1 * f s2 + f r2 * f s1) * (Inv.inv {l s2 p2} * Inv.inv {l s1 p1}) ==< rdistr >== (f r1 * f s2) * (Inv.inv {l s2 p2} * Inv.inv {l s1 p1}) + (f r2 * f s1) * (Inv.inv {l s2 p2} * Inv.inv {l s1 p1}) ==< pmap ((f r1 * f s2) * __ + (f r2 * f s1) * (Inv.inv {l s2 p2} * Inv.inv {l s1 p1})) *-comm >== (f r1 * f s2) * (Inv.inv {l s1 p1} * Inv.inv {l s2 p2}) + (f r2 * f s1) * (Inv.inv {l s2 p2} * Inv.inv {l s1 p1}) ==< pmap2 (+) swap swap >== (f r1 * Inv.inv {l s1 p1}) * (f s2 * Inv.inv {l s2 p2}) + (f r2 * Inv.inv {l s2 p2}) * (f s1 * Inv.inv {l s1 p1}) ==< pmap2 ((f r1 * Inv.inv {l s1 p1}) * __ + (f r2 * Inv.inv {l s2 p2}) * __) (Inv.inv-right {l s2 p2}) (Inv.inv-right {l s1 p1}) >== (f r1 * Inv.inv {l s1 p1}) * ide + (f r2 * Inv.inv {l s2 p2}) * ide ==< pmap2 (+) ide-right ide-right >== f r1 * Inv.inv {l s1 p1} + f r2 * Inv.inv {l s2 p2} `qed | func-* {in~ (r1,s1,p1)} {in~ (r2,s2,p2)} => f (r1 * r2) * Inv.inv {l (s1 * s2) (contains_* p1 p2)} ==< pmap2 (*) f.func-* (func-inv f s1 s2 p1 p2 l) >== (f r1 * f r2) * (Inv.inv {l s2 p2} * Inv.inv {l s1 p1}) ==< pmap ((f r1 * f r2) *) *-comm >== (f r1 * f r2) * (Inv.inv {l s1 p1} * Inv.inv {l s2 p2}) ==< swap >== (f r1 * Inv.inv {l s1 p1}) * (f r2 * Inv.inv {l s2 p2}) `qed \where \lemma func-inv {R' : CRing} (f : RingHom R R') (s1 s2 : R) (p1 : S s1) (p2 : S s2) (l : \Pi (x : R) -> S x -> Inv (f x)) : Inv.inv {l (s1 * s2) (contains_* p1 p2)} = Inv.inv {l s2 p2} * Inv.inv {l s1 p1} => \have e => \new Inv (f s1 * f s2) { | inv => Inv.inv {l (s1 * s2) (contains_* p1 p2)} | inv-left => pmap (Inv.inv {l (s1 * s2) (contains_* p1 p2)} *) (inv f.func-*) *> Inv.inv-left {l (s1 * s2) (contains_* p1 p2)} | inv-right => pmap (`* Inv.inv {l (s1 * s2) (contains_* p1 p2)}) (inv f.func-*) *> Inv.inv-right {l (s1 * s2) (contains_* p1 p2)} } \in pmap (\lam (t : Inv (f s1 * f s2)) => t.inv) (Inv.levelProp e Inv.product.func) \lemma liftHom-loc {R' : CRing} (f : RingHom R R') (l : \Pi (x : R) -> S x -> Inv (f x)) (x : R) : liftHom f l (locMap x) = f x => pmap (f x *) (inv ide-right *> pmap (Inv.inv {l ide contains_ide} *) (inv f.func-ide) *> Inv.inv-left {l ide contains_ide}) *> ide-right \open SubMonoid(powers) \open Monoid \hiding (equals) \func pow-map (b : R) (n : Nat) : RingHom (LocRing (powers (pow b n))) (LocRing (powers b)) \cowith | func => \case __ \with { | in~ (x,y,c) => in~ (x, y, TruncP.map c (\lam p => (n * p.1, rewrite pow_* p.2))) | ~-equiv x y r i => ~-equiv _ _ (later r) i } | func-+ {in~ x} {in~ y} => path (~-equiv _ _ idp) | func-ide => path (~-equiv _ _ idp) | func-* {in~ x} {in~ y} => path (~-equiv _ _ idp) \lemma pow-map_loc (b : R) (n : Nat) : pow-map b n ∘ locMap = locMap => exts \lam x => path (~-equiv _ _ idp) \lemma div-map_loc {a b : R} (a|b : LDiv a b) : div-map a|b ∘ locMap = locMap => exts \lam x => \case (div-map.aux a|b (x, ide, contains_ide {powers a})).2 \with { | inP ((n,a^n=1),p) => inv p *> path (~-equiv _ _ equation) } \func div-map {a b : R} (a|b : LDiv a b) : RingHom (LocRing (powers a)) (LocRing (powers b)) \cowith | func => aux-func a|b | func-+ {in~ x} {in~ y} => \case (aux a|b x).2, (aux a|b y).2, (aux a|b _).2 \with { | inP ((n,a^n=x2),p1), inP ((m,a^m=y2),p2), inP ((k,a^k=x2y2),p3) => inv p3 *> path (~-equiv _ _ equation) *> pmap2 (+) p1 p2 } | func-ide => \case (aux a|b _).2 \with { | inP ((n,a^n=1),p) => inv p *> path (~-equiv _ _ equation) } | func-* {in~ x} {in~ y} => \case (aux a|b x).2, (aux a|b y).2, (aux a|b _).2 \with { | inP ((n,a^n=x2),p1), inP ((m,a^m=y2),p2), inP ((k,a^k=x2y2),p3) => inv p3 *> path (~-equiv _ _ equation) *> pmap2 (*) p1 p2 } \where { \lemma aux {a b : R} (a|b : LDiv a b) (x : SType (powers a)) => TruncP.rec-set {_} {LocRing (powers b)} x.3 (\lam (n,a^n=y) => in~ $ later (x.1 * pow a|b.inv n, pow a|b.inv n * pow a n, inP (n, rewriteI a|b.inv-right $ R.pow_*-comm *> *-comm))) (\lam (n,a^n=x2) (m,a^m=x2) => later $ path (~-equiv _ _ $ later $ rewrite (a^n=x2,a^m=x2) swap)) \func aux-func {a b : R} (a|b : LDiv a b) (x : LocRing (powers a)) : LocRing (powers b) => \case \elim x \with { | in~ x => (aux a|b x).1 | ~-equiv x y r => \case (aux a|b x).2, (aux a|b y).2 \with { | inP ((n,a^n=x2),p), inP ((m,a^m=y2),q) => inv p *> path (~-equiv _ _ equation) *> q } } } \lemma map-lemma {R S : CRing} {M : SubMonoid R} (f : RingHom (LocRing M) S) {x : LocRing.SType M} (i : Inv (f (inl~ (x.2, 1, contains_ide)))) : f (inl~ x) = f (inl~ (x.1, 1, contains_ide)) * i.inv => \have t : inl~ x = inl~ (x.1, 1, contains_ide) * inl~ (1, x.2, x.3) => path $ ~-equiv _ _ (inv *-assoc) \in pmap f t *> f.func-* *> pmap (_ *) (Inv.inv-isUnique (Inv.lmake (f $ inl~ (1, x.2, x.3)) $ inv f.func-* *> pmap f (path $ ~-equiv _ _ *-assoc) *> f.func-ide) i idp) \lemma powers-inv {R S : CRing} (f : RingHom R S) {a : R} (p : Inv (f a)) (x : R) (c : powers a x) : Inv (f x) \elim c | inP (0, idp) => \new Inv { | inv => 1 | inv-left => ide-left *> f.func-ide | inv-right => ide-right *> f.func-ide } | inP (suc n, idp) => rewrite f.func-* $ Inv.product (powers-inv f p (pow a n) (inP (n, idp))) p } \lemma div_loc {R : CRing} {S : SubMonoid R} {a b : R} {Sb : S b} (a|b : Monoid.LDiv b a) : inl~ (a,b,Sb) = locMap a|b.inv => LocRing.equals1 $ ide-right *> inv a|b.inv-right *> *-comm \open localization \func loc_change-of-base1 {R S : CRing} (f : RingHom R S) {a : R} : RingHom (LocRing (SubMonoid.powers a)) (LocRing (SubMonoid.powers (f a))) => liftHom (locMap ∘ f) $ powers-inv (locMap ∘ f) $ elem-inv {_} {SubMonoid.powers (f a)} (f a) (inP (1, ide-left)) \lemma loc_change-of-base1-loc {R S : CRing} (f : RingHom R S) {a : R} : loc_change-of-base1 f {a} ∘ locMap = locMap ∘ f => exts (liftHom-loc (locMap ∘ f) (powers-inv _ _))