module Algebra.Group.Ab.Tensor where
Bilinear mapsð
A function where all types involved are equipped with abelian group structures, is called bilinear when it satisfies and it is a group homomorphism in each of its arguments.
record Bilinear (A : Abelian-group â) (B : Abelian-group â') (C : Abelian-group â'') : Type (â â â' â â'') where private module A = Abelian-group-on (A .snd) module B = Abelian-group-on (B .snd) module C = Abelian-group-on (C .snd) field map : â A â â â B â â â C â pres-*l : â x y z â map (x A.* y) z â¡ map x z C.* map y z pres-*r : â x y z â map x (y B.* z) â¡ map x y C.* map x z
fixl-is-group-hom : â a â is-group-hom B.AbelianâGroup-on C.AbelianâGroup-on (map a) fixl-is-group-hom a .is-group-hom.pres-â x y = pres-*r a x y fixr-is-group-hom : â b â is-group-hom A.AbelianâGroup-on C.AbelianâGroup-on (λ a â map a b) fixr-is-group-hom b .is-group-hom.pres-â x y = pres-*l x y b module fixl {a} = is-group-hom (fixl-is-group-hom a) module fixr {a} = is-group-hom (fixr-is-group-hom a) open fixl renaming ( pres-id to pres-idr ; pres-inv to pres-invr ; pres-diff to pres-diffr ) hiding ( pres-â ) public open fixr renaming ( pres-id to pres-idl ; pres-inv to pres-invl ; pres-diff to pres-diffl ) hiding ( pres-â ) public module _ {A : Abelian-group â} {B : Abelian-group â'} {C : Abelian-group â''} where private module A = Abelian-group-on (A .snd) module B = Abelian-group-on (B .snd) module C = Abelian-group-on (C .snd) Bilinear-path : {ba bb : Bilinear A B C} â (â x y â Bilinear.map ba x y â¡ Bilinear.map bb x y) â ba â¡ bb Bilinear-path {ba = ba} {bb} p = q where open Bilinear q : ba â¡ bb q i .map x y = p x y i q i .pres-*l x y z = is-propâpathp (λ i â C.has-is-set (p (x A.* y) z i) (p x z i C.* p y z i)) (ba .pres-*l x y z) (bb .pres-*l x y z) i q i .pres-*r x y z = is-propâpathp (λ i â C.has-is-set (p x (y B.* z) i) (p x y i C.* p x z i)) (ba .pres-*r x y z) (bb .pres-*r x y z) i instance Extensional-bilinear : â {âr} ⊠ef : Extensional (â A â â â B â â â C â) âr ⊠â Extensional (Bilinear A B C) âr Extensional-bilinear ⊠ef ⊠= injectionâextensional! (λ h â Bilinear-path (λ x y â h # x # y)) ef module _ {â} (A B C : Abelian-group â) where
We have already noted that the set of group homomorphisms between a pair of abelian groups is an abelian group, under pointwise multiplication. The type of bilinear maps is equivalent to the type of group homomorphisms
curry-bilinear : Bilinear A B C â Ab.Hom A Ab[ B , C ] curry-bilinear f .hom a .hom = f .Bilinear.map a curry-bilinear f .hom a .preserves = Bilinear.fixl-is-group-hom f a curry-bilinear f .preserves .is-group-hom.pres-â x y = ext λ z â f .Bilinear.pres-*l _ _ _ curry-bilinear-is-equiv : is-equiv curry-bilinear curry-bilinear-is-equiv = is-isoâis-equiv morp where morp : is-iso curry-bilinear morp .is-iso.inv uc .Bilinear.map x y = uc # x # y morp .is-iso.inv uc .Bilinear.pres-*l x y z = ap (_# _) (uc .preserves .is-group-hom.pres-â _ _) morp .is-iso.inv uc .Bilinear.pres-*r x y z = (uc # _) .preserves .is-group-hom.pres-â _ _ morp .is-iso.rinv uc = trivial! morp .is-iso.linv uc = trivial!
The tensor productð
Thinking about the currying isomorphism
we set out to search for an abelian group which lets us âassociateâ
Bilinear
in the other direction:
Bilinear maps
are equivalent to group homomorphisms
but is there a construction
ââ,
playing the role of product type, such that
is also the type of bilinear maps
module _ {â â'} (A : Abelian-group â) (B : Abelian-group â') where private module A = Abelian-group-on (A .snd) module B = Abelian-group-on (B .snd)
The answer is yes: rather than we write this infix as and refer to it as the tensor product of abelian groups. Since is determined by the maps out of it, we can construct it directly as a higher inductive type. We add a constructor for every operation we want, and for the equations these should satisfy: should be an Abelian group, and it should admit a bilinear map
data Tensor : Type (â â â') where :1 : Tensor _:*_ : Tensor â Tensor â Tensor :inv : Tensor â Tensor squash : is-set Tensor t-invl : â {x} â :inv x :* x â¡ :1 t-idl : â {x} â :1 :* x â¡ x t-assoc : â {x y z} â x :* (y :* z) â¡ (x :* y) :* z t-comm : â {x y} â x :* y â¡ y :* x _,_ : â A â â â B â â Tensor t-pres-*r : â {x y z} â (x , y B.* z) â¡ (x , y) :* (x , z) t-pres-*l : â {x y z} â (x A.* y , z) â¡ (x , z) :* (y , z)
The first 8 constructors are, by definition, exactly what we need to
make Tensor
into an abelian group.
The latter three are the bilinear map
Since this is an inductive type, itâs the initial object equipped with
these data.
open make-abelian-group make-abelian-tensor : make-abelian-group Tensor make-abelian-tensor .ab-is-set = squash make-abelian-tensor .mul = _:*_ make-abelian-tensor .inv = :inv make-abelian-tensor .1g = :1 make-abelian-tensor .idl x = t-idl make-abelian-tensor .assoc x y z = t-assoc make-abelian-tensor .invl x = t-invl make-abelian-tensor .comm x y = t-comm _â_ : Abelian-group (â â â') _â_ = to-ab make-abelian-tensor to-tensor : Bilinear A B _â_ to-tensor .Bilinear.map = _,_ to-tensor .Bilinear.pres-*l x y z = t-pres-*l to-tensor .Bilinear.pres-*r x y z = t-pres-*r
Tensor-elim-prop : â {â'} {P : Tensor â Type â'} â (â x â is-prop (P x)) â (â x y â P (x , y)) â (â {x y} â P x â P y â P (x :* y)) â (â {x} â P x â P (:inv x)) â P :1 â â x â P x Tensor-elim-prop {P = P} pprop ppair padd pinv pz = go where go : â x â P x go (x , y) = ppair x y go :1 = pz go (x :* y) = padd (go x) (go y) go (:inv x) = pinv (go x) go (squash x y p q i j) = is-propâsquarep (λ i j â pprop (squash x y p q i j)) (λ i â go x) (λ i â go (p i)) (λ i â go (q i)) (λ i â go y) i j go (t-invl {x} i) = is-propâpathp (λ i â pprop (t-invl i)) (padd (pinv (go x)) (go x)) pz i go (t-idl {x} i) = is-propâpathp (λ i â pprop (t-idl i)) (padd pz (go x)) (go x) i go (t-assoc {x} {y} {z} i) = is-propâpathp (λ i â pprop (t-assoc i)) (padd (go x) (padd (go y) (go z))) (padd (padd (go x) (go y)) (go z)) i go (t-comm {x} {y} i) = is-propâpathp (λ i â pprop (t-comm i)) (padd (go x) (go y)) (padd (go y) (go x)) i go (t-pres-*r {x} {y} {z} i) = is-propâpathp (λ i â pprop (t-pres-*r i)) (ppair x (y B.* z)) (padd (ppair x y) (ppair x z)) i go (t-pres-*l {x} {y} {z} i) = is-propâpathp (λ i â pprop (t-pres-*l i)) (ppair (x A.* y) z) (padd (ppair x z) (ppair y z)) i module _ {â â' â''} (A : Abelian-group â) (B : Abelian-group â') (C : Abelian-group â'') where private module A = Abelian-group-on (A .snd) module B = Abelian-group-on (B .snd) module C = Abelian-group-on (C .snd)
If we have any bilinear map we can first extend it to a function of sets by recursion, then prove that this is a group homomorphism. It turns out that this extension is definitionally a group homomorphism.
bilinear-mapâfunction : Bilinear A B C â Tensor A B â â C â bilinear-mapâfunction bilin = go module bilinear-mapâfunction where go : Tensor A B â â C â go :1 = C.1g go (x :* y) = go x C.* go y go (:inv x) = go x C.â»Â¹ go (x , y) = Bilinear.map bilin x y go (squash x y p q i j) = C.has-is-set (go x) (go y) (λ i â go (p i)) (λ i â go (q i)) i j go (t-invl {x} i) = C.inversel {x = go x} i go (t-idl {x} i) = C.idl {x = go x} i go (t-assoc {x} {y} {z} i) = C.associative {x = go x} {go y} {go z} i go (t-comm {x} {y} i) = C.commutes {x = go x} {y = go y} i go (t-pres-*r {a} {b} {c} i) = Bilinear.pres-*r bilin a b c i go (t-pres-*l {a} {b} {c} i) = Bilinear.pres-*l bilin a b c i {-# DISPLAY bilinear-mapâfunction.go b = bilinear-mapâfunction b #-}
module _ {â} (A B C : Abelian-group â) where private module A = Abelian-group-on (A .snd) module B = Abelian-group-on (B .snd) module C = Abelian-group-on (C .snd)
from-bilinear-map : Bilinear A B C â Ab.Hom (A â B) C from-bilinear-map bilin .hom = bilinear-mapâfunction A B C bilin from-bilinear-map bilin .preserves .is-group-hom.pres-â x y = refl
Itâs also easy to construct a function in the opposite direction,
turning group homomorphisms into bilinear maps, but proving that this is
an equivalence requires appealing to an induction principle of Tensor
which handles the
equational fields: Tensor-elim-prop
.
to-bilinear-map : Ab.Hom (A â B) C â Bilinear A B C to-bilinear-map gh .Bilinear.map x y = gh # (x , y) to-bilinear-map gh .Bilinear.pres-*l x y z = ap (apply gh) t-pres-*l â gh .preserves .is-group-hom.pres-â _ _ to-bilinear-map gh .Bilinear.pres-*r x y z = ap (apply gh) t-pres-*r â gh .preserves .is-group-hom.pres-â _ _ from-bilinear-map-is-equiv : is-equiv from-bilinear-map from-bilinear-map-is-equiv = is-isoâis-equiv morp where morp : is-iso from-bilinear-map morp .is-iso.inv = to-bilinear-map morp .is-iso.rinv hom = ext $ Tensor-elim-prop A B (λ x â C.has-is-set _ _) (λ x y â refl) (λ x y â apâ C._*_ x y â sym (hom .preserves .is-group-hom.pres-â _ _)) (λ x â ap C._â»Â¹ x â sym (is-group-hom.pres-inv (hom .preserves))) (sym (is-group-hom.pres-id (hom .preserves))) morp .is-iso.linv x = trivial!
BilinearâHom : Bilinear A B C â Ab.Hom (A â B) C BilinearâHom = from-bilinear-map , from-bilinear-map-is-equiv HomâBilinear : Ab.Hom (A â B) C â Bilinear A B C HomâBilinear = BilinearâHom eâ»Â¹ module BilinearâHom = Equiv BilinearâHom module HomâBilinear = Equiv HomâBilinear module _ {â} {A B C : Abelian-group â} where instance Extensional-tensor-hom : â {âr} ⊠ef : Extensional (â A â â â B â â â C â) âr ⊠â Extensional (Ab.Hom (A â B) C) âr Extensional-tensor-hom ⊠ef ⊠= injectionâextensional! {f = λ f x y â f .hom (x , y)} (λ {x} p â HomâBilinear.injective _ _ _ (ext (subst (ef .Patháµ _) p (ef .refláµ _)))) auto {-# OVERLAPS Extensional-tensor-hom #-}
The tensor-hom adjunctionð
Since we have a construction satisfying weâre driven, being category theorists, to question its naturality: Is the tensor product a functor, and is this equivalence of Hom-sets an adjunction?
The answer is yes, and the proofs are essentially plugging together existing definitions, other than the construction of the functorial action of
Ab-tensor-functor : Functor (Ab â ÃᶠAb â) (Ab â) Ab-tensor-functor .Fâ (A , B) = A â B Ab-tensor-functor .Fâ (f , g) = from-bilinear-map _ _ _ bilin where bilin : Bilinear _ _ _ bilin .Bilinear.map x y = f # x , g # y bilin .Bilinear.pres-*l x y z = ap (_, g # z) (f .preserves .is-group-hom.pres-â _ _) â t-pres-*l bilin .Bilinear.pres-*r x y z = ap (f # x ,_) (g .preserves .is-group-hom.pres-â _ _) â t-pres-*r Ab-tensor-functor .F-id = trivial! Ab-tensor-functor .F-â f g = trivial! Tensorâ£Hom : (A : Abelian-group â) â Bifunctor.Left Ab-tensor-functor A ⣠Bifunctor.Right Ab-hom-functor A Tensorâ£Hom A = hom-isoâadjoints to to-eqv nat where to : â {x y} â Ab.Hom (x â A) y â Ab.Hom x Ab[ A , y ] to f = curry-bilinear _ _ _ (to-bilinear-map _ _ _ f) to-eqv : â {x y} â is-equiv (to {x} {y}) to-eqv = â-is-equiv (HomâBilinear _ _ _ .snd) (curry-bilinear-is-equiv _ _ _) nat : hom-iso-natural {L = Bifunctor.Left Ab-tensor-functor A} {R = Bifunctor.Right Ab-hom-functor A} to nat f g h = trivial!