0 | module Data.Container.Additive.Morphism.Instances
  1 |
  2 | import Data.Vect
  3 | import Data.List.Quantifiers
  4 | import Data.Vect.Quantifiers
  5 |
  6 | import Data.Container.Base
  7 | import Data.Container.Base.Morphism.Instances as Base
  8 | import Data.ComMonoid
  9 | import Data.Num
 10 | import Data.Container.Additive.Object.Definition
 11 | import Data.Container.Additive.Object.Instances
 12 | import Data.Container.Additive.Extension.Definition
 13 | import Data.Container.Additive.Morphism.Definition
 14 | import Data.Container.Additive.Product.Definitions
 15 | import Data.Container.Additive.Properties.Definitions
 16 |
 17 | import Data.Container.Additive.Quantifiers
 18 |
 19 | import Control.Monad.Distribution
 20 | import Control.Monad.Sample.Definition
 21 |
 22 | import Misc
 23 |
 24 | %hide Base.Object.Instances.Const
 25 | %hide Data.Vect.Quantifiers.All.index
 26 | %hide Base.Morphism.Instances.State.State
 27 | %hide Base.Morphism.Instances.Costate.Costate
 28 |
 29 | -- Not sure if we'll need these?
 30 | -- public export
 31 | -- pushIntoContinuationBag : {p : AddCont} -> {0 d, l : AddCont} ->
 32 | --   d >< p =%+> l ->
 33 | --   p =%+> (pushDown d) >+@ (Bag l)
 34 | -- pushIntoContinuationBag f = !%+ \param => (() <|
 35 | --   map (\dShp => f.fwd (dShp, param)) **
 36 | --     \ll => sum @{UMon p param} $ ll >>=
 37 | --       \(ds ** grads) => extractPGradsBag param ds grads)
 38 | --   where
 39 | --     extractPGrads : (param : p.Shp) ->
 40 | --       (ds : List d.Shp) ->
 41 | --       All l.Pos ((\dShp => f.fwd (dShp, param)) <$> ds) ->
 42 | --       List (p.Pos param)
 43 | --     extractPGrads param [] [] = []
 44 | --     extractPGrads param (dShp :: ds) (grad :: grads) =
 45 | --       snd (f.bwd (dShp, param) grad) :: extractPGrads param ds grads
 46 | -- 
 47 | --     extractPGradsBag : (param : p.Shp) ->
 48 | --       (ds : Bag d.Shp) ->
 49 | --       All l.Pos ((\dShp => f.fwd (dShp, param)) <$> ds) ->
 50 | --       Bag (p.Pos param)
 51 | --     extractPGradsBag param (MkBag dsl) grads
 52 | --       = MkBag $ extractPGrads param dsl grads
 53 | -- 
 54 | -- 
 55 |
 56 | public export
 57 | pushIntoContinuation : {p : AddCont} ->
 58 |   (f : d >*< p =%+> l) ->
 59 |   (p =%+> (pushDown d.Shp) >-+@ l)
 60 | pushIntoContinuation f = !%+ \param => (() <| \dShp => f.fwd (dShp, param) **
 61 |     fromGenerators @{UMon p param}
 62 |       (\(dShp ** grad=> snd (f.bwd (dShp, param) grad)))
 63 |
 64 | ||| Categorical product of additive containers
 65 | ||| On underlying containers computed as the hancock tensor product
 66 | namespace CategoricalProduct
 67 |   public export
 68 |   leftUnit : UnitCont >*< c =%+> c
 69 |   leftUnit = !% leftUnit
 70 |   
 71 |   public export
 72 |   rightUnit : c >*< UnitCont =%+> c
 73 |   rightUnit = !% rightUnit
 74 |
 75 |   public export
 76 |   leftUnitInv : c =%+> UnitCont >*< c
 77 |   leftUnitInv = !% leftUnitInv
 78 |   
 79 |   public export
 80 |   rightUnitInv : c =%+> c >*< UnitCont
 81 |   rightUnitInv = !% rightUnitInv
 82 |
 83 |   public export
 84 |   assocL : (a >*< b) >*< c =%+> a >*< (b >*< c)
 85 |   assocL = !% assocL
 86 |
 87 |   public export
 88 |   assocR : a >*< (b >*< c) =%+> (a >*< b) >*< c
 89 |   assocR = !% assocR
 90 |
 91 |   public export
 92 |   swap : a >*< b =%+> b >*< a
 93 |   swap = !% swap
 94 |
 95 |   public export
 96 |   swapMiddle : (c1 >*< c2) >*< (c3 >*< c4) =%+> (c1 >*< c3) >*< (c2 >*< c4)
 97 |   swapMiddle = !% swapMiddle
 98 |
 99 |   ||| These do not exist for ordinary containers!
100 |   ||| Here we need `c` not to be erased since we're using its monoid structure
101 |   public export
102 |   copy : {c : AddCont} -> c =%+> c >*< c
103 |   copy = !%+ \x => ((x, x) ** uncurry (c.Plus x))
104 |   
105 |   public export
106 |   pairMaps : {c : AddCont} ->
107 |     c =%+> d ->
108 |     c =%+> e ->
109 |     c =%+> d >*< e
110 |   pairMaps f g = copy %+>> (f >*< g)
111 |   
112 |   public export
113 |   projLeft : {d : AddCont} -> c >*< d =%+> c
114 |   projLeft = !%+ \(x, y) => (x ** \x' => (x', d.Zero y))
115 |   
116 |   public export
117 |   projRight : {c : AddCont} -> c >*< d =%+> d
118 |   projRight = !%+ \(x, y) => (y ** \y' => (c.Zero x, y'))
119 |
120 | ||| Structure maps of the left action `>-+@` of `(Cont, >@, Scalar)` on AddCont
121 | ||| They generally use the following components:
122 | ||| * `pureBw` : a position becomes the singleton bag containing it
123 | ||| * `sumBw` : a bag of positions is added up using their monoid structure
124 | ||| * `joinBwComp` : nested bags of positions are flattened
125 | namespace CompositionProductAction
126 |   ||| Backwards pass is ComMon-homomorphism on the nose
127 |   public export
128 |   unitor : {c : AddCont} -> c =%+> Scalar >-+@ c
129 |   unitor = !% (sumBw @{mon c} %>> (Bag <!> leftUnitInv))
130 |
131 |   ||| Backwards map is a ComMon-homomorphism only through the quotient
132 |   public export
133 |   unitorInv : Scalar >-+@ c =%+> c
134 |   unitorInv = !% ((Bag <!> leftUnit) %>> pureBw)
135 |
136 |   public export
137 |   multiplicator : (m >-+@ (n >-+@ c)) =%+> ((m >@ n) >-+@ c)
138 |   multiplicator = !% (Bag <!> ((id >@ pureBw {c = n >@ UC c}) %>> assocR))
139 |
140 |   public export
141 |   multiplicatorInv : ((m >@ n) >-+@ c) =%+> (m >-+@ (n >-+@ c))
142 |   multiplicatorInv = !% ((Bag <!> assocL) %>> joinBwComp {d = n >@ UC c})
143 |
144 | ||| `!*` and `- >-+@ Scalar` are isomorphic: they're both right adjoint to 
145 | ||| `UC`.  They are two presentations of the same free commutative monoid on
146 | ||| positions: `!*` stores a bag of positions directly, while `- >-+@ Scalar` 
147 | ||| stores generators tagged with `Nat` multiplicities.
148 | namespace CompositionActionBang
149 |   ||| Read each position as the generator it is, with multiplicity one
150 |   public export
151 |   actionToFree : {0 e : Cont} -> e >-+@ Scalar =%+> !* e
152 |   actionToFree = !%+ \ex => (shapeExt ex ** map (\mp => (mp ** 1)))
153 |
154 |   ||| Expand each generator into as many copies as its multiplicity says
155 |   public export
156 |   freeToAction : {0 e : Cont} -> !* e =%+> e >-+@ Scalar
157 |   freeToAction = !%+ \x => (x <| \_ => () ** fromGenerators @{bagIsMonoid}
158 |     (\(mp ** n=> scale @{bagIsMonoid} n (pure mp)))
159 |
160 | ||| Structure maps of the left-skew monoidal product `>+@` on AddCont
161 | ||| These definitions follow Theorem 3.1 in https://arxiv.org/abs/2506.06847
162 | namespace SkewCompositionProduct
163 |   ||| Hom-set isomorphism of the adjunction, which is the general purpose
164 |   ||| `addContTranspose` read through the isomorphism above
165 |   public export
166 |   adjR : {c : AddCont} -> UC c =%> m -> c =%+> m >-+@ Scalar
167 |   adjR f = addContTranspose f %+>> freeToAction
168 |
169 |   ||| Inverse of the hom-set isomorphism of the adjunction
170 |   public export
171 |   adjL : c =%+> m >-+@ Scalar -> UC c =%> m
172 |   adjL g = addContTransposeInv (g %+>> actionToFree)
173 |
174 |   public export
175 |   epsilon : UC Scalar =%> Scalar
176 |   epsilon = adjL (unitor {c = Scalar})
177 |
178 |   public export
179 |   leftUnit : {c : AddCont} -> Scalar >+@ c =%+> c
180 |   leftUnit = (epsilon >-+@ id) %+>> unitorInv
181 |
182 |   public export
183 |   rightUnit : {c : AddCont} -> c =%+> c >+@ Scalar
184 |   rightUnit = adjR id
185 |
186 |   public export
187 |   associator : {b : AddCont} -> (a >+@ b) >+@ c =%+> a >+@ (b >+@ c)
188 |   associator = (adjL ((id >-+@ SkewCompositionProduct.rightUnit {c = b})
189 |     %+>> multiplicator {c = Scalar}) >-+@ id) %+>> multiplicatorInv 
190 |
191 |   {-
192 |   Beyond skew structure, only `leftUnitInv` exists, rightUnitInv and assocR do not.
193 |
194 |   leftUnitInv is also not inverse to leftUnit. We only have
195 |   `leftUnitInv %+>> leftUnit = id`, but not the other way around.
196 |
197 |   The right associator is not definable because the forward  part involves the
198 |   the function `g : List (aPos ** bPos) -> c.Shp` which would have to collapse
199 |   a whole list of of positions into a single shape
200 |   -}
201 |   public export
202 |   leftUnitInv : {c : AddCont} -> c =%+> Scalar >+@ c
203 |   leftUnitInv = unitor %+>> (toState () >-+@ id)
204 |
205 |
206 | namespace Coproduct
207 |   public export
208 |   elim : c >+< c =%+> c
209 |   elim = !% elim
210 |
211 | -- public export
212 | -- duoidal : (c >+@ d) >< (e >+@ f) =%+> (c >< e) >+@ (d >< f)
213 | -- duoidal = !%+ \((sc <| idxC), (se <| idxE)) =>
214 | --   ((sc, se) <| \(cp, ep) => (idxC cp, idxE ep) **
215 | --     \ll => ((\((cp, ep) ** (dp, fp)) => (cp ** dp)) <$> ll,
216 | --             (\((cp, ep) ** (dp, fp)) => (ep ** fp)) <$> ll))
217 |
218 | public export
219 | coprodDistrOverTensor : {q, p : AddCont} ->
220 |   (a >+< b) >*< (p >*< q) =%+> (a >*< p) >+< (b >*< q)
221 | coprodDistrOverTensor = !%+ \case
222 |   (Left a, (p, _)) => (Left (a, p) ** \(a', p') => (a', (p', q.Zero _)))
223 |   (Right b, (_, q)) => (Right (b, q) ** \(b', q') => (b', (p.Zero _, q')))
224 |
225 | {-
226 | ||| Not an isomorphism, arising from duoidal structure between >@ and ><
227 | public export
228 | rebracketcomptensor: {y : AddCont} -> (e >+@ y) >< y =%+> e >+@ (y >< y)
229 | rebracketcomptensor = (id {c=e >+@ y} >< leftUnitInv {c=y})
230 |                       %+>> duoidal {c=e} {d=y} {e=Scalar} {f=y}
231 |                       %+>> (rightUnit {c=e} >+@ id {c=(y><y)})
232 |
233 |
234 | public export
235 | distribute : {c : AddCont} ->
236 |   c >< e =%+> s ->
237 |   c >< (e >+@ g) =%+> s >+@ g
238 | distribute f = (rightUnitInv >< id {c=e >+@ g})
239 |              %+>> duoidal {d = Scalar}
240 |              %+>> (f >+@ leftUnit)
241 |
242 | public export
243 | extractEffect : {d : AddCont} ->
244 |   d >< (e >+@ f) =%+> e >+@ (d >< f)
245 | extractEffect = (leftUnitInv >< (id {c=e >+@ f}))
246 |             %+>> duoidal {c=Scalar}
247 |             %+>> (leftUnit >+@ (id {c=d><f}))
248 |
249 | -}
250 |
251 | ||| References for State
252 | ||| Bruno's PhD thesis: https://arxiv.org/abs/2403.13001
253 | ||| Towards Foundations of Cat. Cybernetics: https://arxiv.org/abs/2105.06332
254 | namespace State
255 |   ||| State here differers for the one in `Cont`, because `Scalar` is different
256 |   |||
257 |   |||       ┌─────────────┐
258 |   |||       │             ├──► (x : c.Shp)
259 |   |||       │    State    │
260 |   |||       │             ├◄── c.Pos x
261 |   |||       └─────────────┘
262 |   public export
263 |   State : AddCont -> Type
264 |   State c = Scalar =%+> c
265 |
266 |   public export
267 |   toState : (x : c.Shp) -> State c
268 |   toState x = ?somethingInterestingHmm
269 |   
270 |   -- public export
271 |   -- fromState : State c -> c.Shp
272 |   -- fromState f = f.fwd ()
273 |
274 | ||| References for Costate
275 | ||| Bruno's PhD thesis: https://arxiv.org/abs/2403.13001
276 | ||| Towards Foundations of Cat. Cybernetics: https://arxiv.org/abs/2105.06332
277 | namespace Costate
278 |   ||| Costate here differs from the one in `Cont`, because `Scalar` is different
279 |   |||                  ┌─────────────┐
280 |   |||  (x : c.Shp)  ──►┤             │
281 |   |||                  │   Costate   │
282 |   |||     c.Pos x   ◄──┤             │
283 |   |||                  └─────────────┘
284 |   public export
285 |   Costate : AddCont -> Type
286 |   Costate c = c =%+> Scalar
287 |   
288 |   public export
289 |   toCostate : {c : AddCont} ->
290 |     ((x : c.Shp) -> c.Pos x) -> Costate c
291 |   toCostate s = !%+ \x => (() ** \n => scale @{UMon c x} n (s x))
292 |
293 |   -- public export
294 |   -- fromCostate : Costate c -> (x : c.Shp) -> c.Pos x
295 |   -- fromCostate f x = f.bwd x ()
296 |
297 |   public export
298 |   constantOne : {c : AddCont} ->
299 |     InterfaceOnPositions c Num => Costate c
300 |   constantOne @{MkI p} = toCostate (\x => let numPos = p x in 1)
301 |
302 |   public export
303 |   Delete : {c : AddCont} -> Costate c 
304 |   Delete = toCostate c.Zero
305 |   
306 |
307 | public export
308 | sum : Num a =>
309 |   (Const a >*< Const a) =%+> Const a
310 | sum = !%+ \(x1, x2) => (x1 + x2 ** \x' => (x', x'))
311 |
312 | public export
313 | bwSumBag : {l : Type} ->
314 |   (xs : List l) ->
315 |   (d' : l) ->
316 |   All (const l) xs
317 | bwSumBag [] d' = []
318 | bwSumBag (x :: xs) d' = d' :: bwSumBag xs d'
319 |
320 | public export
321 | sumBag : {l : Type} -> ComMonoid l =>
322 |   BagAll (Const l) =%+> Const l
323 | sumBag = !%+ \(MkBag xs) => (sum (MkBag xs) ** \d' => bwSumBag xs d')
324 |
325 | public export
326 | negate : Num a => Neg a =>
327 |   Const a =%+> Const a
328 | negate = !%+ \x => (-x ** \x' => -x')
329 |
330 | public export
331 | zero : {c : AddCont} -> Num a =>
332 |   c =%+> Const a
333 | zero = !%+ \_ => (0 ** \_ => c.Zero _)
334 |
335 | public export
336 | mul : Num a =>
337 |   (Const a >*< Const a) =%+> Const a
338 | mul = !%+ \(x1, x2) => (x1 * x2 ** \x' => (x' * x2, x' * x1))
339 |
340 | ||| Mean squared error
341 | public export
342 | SquaredDifference : {a : Type} -> Num a => Neg a =>
343 |   (Const a >*< Const a) =%+> (Const a)
344 | SquaredDifference = ((id {c=Const a}) >*< negate) %+>> sum %+>> copy %+>> mul
345 |
346 | namespace Sample
347 |   ||| Select a shape from All to produce an Any at the given index
348 |   ||| Same as `index i (allAnies shapes)` but reduces better
349 |   public export
350 |   selectShape : {cs : Vect k AddCont} ->
351 |     (shapes : All (.Shp) cs) -> (i : Fin k) -> Any (.Shp) cs
352 |   selectShape (s :: ss) FZ = Here s
353 |   selectShape (s :: ss) (FS j) = There (selectShape ss j)
354 |
355 |   ||| Extract the position from an AnyPos at a given index
356 |   public export
357 |   extractPos : {n : Nat} -> {xs : Vect n AddCont} -> {shapes : All (.Shp) xs} ->
358 |     (i : Fin n) ->
359 |     AnyShpPos (selectShape shapes i) ->
360 |     (index i xs).Pos (index i shapes)
361 |   extractPos {shapes = (_ :: _)} FZ (Here x') = x'
362 |   extractPos {shapes = (_ :: _)} (FS j) (There rest) = extractPos j rest
363 |
364 | -- parameters (f : Type -> Type)
365 | --   ||| These are all of the morphisms in the cokleisli category of (f <!> -)  
366 | --   public export
367 | --   MonLens : Cont -> Cont -> Type
368 | --   MonLens c d = (f <!> c) =%> d
369 | -- 
370 | --   public export
371 | --   counit : Monad f => f <!> c =%> c
372 | --   counit = !% \x => (x ** pure)
373 | -- 
374 | --   public export
375 | --   cojoin : Monad f => (f <!> c) =%> (f <!> (f <!> c))
376 | --   cojoin = !% \x => (x ** join)
377 |
378 |   
379 | -- public export
380 | -- record FCoAlgCont (f : Type -> Type) where
381 | --   constructor MkFCoAlgCont
382 | --   carrier : Cont
383 | --   coalg : (a : carrier.Shp) -> f (carrier.Pos a) -> carrier.Pos a
384 |
385 | -- public export
386 | -- coAlgMorphism : (c, d : FCoAlgCont f) -> Type
387 | -- coAlgMorphism c d = c.carrier =%> d.carrier
388 | -- 
389 | -- convert : FCoAlgCont List -> AddCont
390 | -- convert (MkFCoAlgCont carrier coalg) = MkAddCont
391 | --   carrier
392 | --   {mon=(MkI $ \s => MkComMonoid
393 | --     (\l, r => coalg s [l, r])
394 | --     (coalg s []))}