packages feed

linear-smc-2.2.2: Control/Category/Tensors.hs

{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE LinearTypes #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UnicodeSyntax #-}
module Control.Category.Tensors (R,
                                 constant, zeroTensor, delta, contract, deriv, juggleDown, juggleUp, plus, (⋆),
                                 tensorEval, tensorEval1, tensorEmbed, tensorEmbed1,
                                 affinity, derivUsingAffinity,

                                 TensorCategory(..), CoordinateCategory(..), AutonomousObj(..),
                                 Group(..), VectorSpace(..), Dual(..)) where

import Data.Kind
import Control.Category.Constrained
import Control.Category.StructuredObject
import Control.Category.Linear.Internal
import qualified Control.Category.FreeCartesian as FC
import Control.Category.FreeCartesian ((▴))
import Prelude hiding (id, (.), Num(..), uncurry)

class Group v where
  (+)     :: v -> v -> v
  zero    :: v
  negate  :: v -> v

class Group v => VectorSpace scalar v where
  (*^)  ::  scalar -> v -> v

type DualClosed (con :: Type -> Constraint) =
  forall x. (con x) => con (Dual x) :: Constraint


class Autonomous cat => TensorCategory v cat where
  metric          :: {-<-}(O2 cat v Unit) =>{->-} (v ⊗ v) `cat` Unit
  cometric        :: {-<-}(O2 cat v Unit) =>{->-} Unit `cat` (v ⊗ v)
  derivSemantics  :: {-<-}O3 cat a b v =>{->-} (a `cat` b) -> ((v ⊗ a) `cat` b)
  default derivSemantics  :: {-<-}(O3 cat a b v, Obj cat ~ con, TensorClosed con, GroupCat cat, v ~ Atom s, OO s a, OO s b, CoordinateCategory v cat, con ()) =>{->-} (a `cat` b) -> ((v ⊗ a) `cat` b)
  derivSemantics = derivUsingAffinity


juggleDown :: (con ~ Obj cat, TensorClosed con, DualClosed con, AutonomousObj con, TensorCategory v cat, con v, con ())
  => Dual v `cat` v
juggleDown = compactHelper2 cometric

juggleUp :: (con ~ Obj cat, TensorClosed con, DualClosed con, AutonomousObj con, TensorCategory v cat, con v, con ())
  => v `cat` Dual v
juggleUp = compactHelper1 metric

compactHelper1 :: (Autonomous k, Obj k ~ con, DualClosed con, TensorClosed con, con a, con b, con ()) => k (a ⊗ b) () -> k a (Dual b)
compactHelper1 f = unitor' ∘ (id × f) ∘ assoc . (swap × id) . assoc' . (id × turn) ∘ unitor

compactHelper2 :: (Autonomous k, Obj k ~ con, DualClosed con, TensorClosed con, con a, con b, con ()) => k () (a ⊗ b) -> k (Dual a) b
compactHelper2 f = unitor' ∘ swap ∘ ((turn' ∘ swap) × id) ∘ assoc' ∘ (id × f) ∘ unitor


shuf ::
  ( Monoidal k
  , con ~ Obj k
  , TensorClosed con
  , con a, con s, con b
  ) => (a ⊗ (s ⊗ b)) `k` (s ⊗ (a ⊗ b))
shuf = assoc ∘ (swap × id) ∘ assoc'



class TensorCategory v cat => CoordinateCategory v cat  where
  partialDerivative :: O3 cat a b v => (a `cat` b) -> ((v ⊗ a) `cat` b)
  christoffel     :: {-<-}(Obj cat v)=>{->-} (v ⊗ v) `cat` v


derivUsingAffinity :: forall a b v s k con.
  (AutonomousObj con, TensorClosed con, OO s a, OO s b, v ~ Atom s,
   con a, con b, con v, con (),
   GroupCat k, CoordinateCategory v k, Obj k ~ con )
  => k a b -> k (v ⊗ a) b
derivUsingAffinity t = partialDerivative t + negate (t ∘ affinity) + (affinity ∘ (id × t))


type AdditiveCat scalar (cat :: Type -> Type -> Type) = forall a b. VectorSpace scalar (a `cat` b)
type GroupCat (cat :: Type -> Type -> Type) = forall a b. Group (a `cat` b)

data S cat r where
  Compose  :: {-<-}Obj cat x => {->-} (x `cat` Unit) -> FC.Cat cat {-<-}(Obj cat){->-} r x -> S cat r
  Plus   :: (Bool -> S cat r) ⊸ S cat r
type R cat r = P cat r Unit ⊸ S cat r



constant      :: (Monoidal cat, AdditiveCat scalar cat {-<-},con r, con a, Autonomous cat, Obj cat ~ con, DualClosed con, TensorClosed con, con (){->-})
  => scalar -> R cat r
constant s (Y u) = Compose (s *^ id) u




zeroTensor = tensorEmbed1 zero

plus f u = Plus (\b -> f b u) 

Compose t1 q1  ⋆- Compose t2 q2  = Compose (unitor' ∘ (t1 × t2)) (q1 ▴ q2)
Plus f         ⋆- t              = Plus (\c -> f c ⋆- t)
t              ⋆- Plus f         = Plus (\c -> t ⋆- f c)

deriv'         :: {-<-} forall v cat con r. (con v, TensorClosed con, con ~ Obj cat, con r, con (), Monoidal cat, ProdObj con) =>{->-} (TensorCategory v cat) => P cat r v ⊸ S cat r ⊸ S cat r
deriv'  (Y i)  (Compose t q)  = Compose (derivSemantics t) (i ▴ q)
deriv'  p      (Plus f )      = Plus (\c -> deriv' p (f c) )


deriv i r u = deriv' i (r u)

cartesianToMonoidal  :: {-<-}(Obj cat~con,Monoidal cat, ProdObj con, TensorClosed con, con (), con a, con b) => {->-} FC.Cat cat {-<-}con{->-} a b -> a `cat` b
cartesianToMonoidal = FC.toSMC

tensorEval0'   :: ({-<-}Obj cat ~ con, con a, TensorClosed con, ProdObj con, con (), {->-}Monoidal cat, GroupCat  cat) => S cat a -> a `cat` Unit
tensorEval0' u = case u of
  (Compose t q)  -> t ∘ cartesianToMonoidal q
  Plus f         -> tensorEval0' (f True) + tensorEval0' (f False)

tensorEval1 f          = tensorEval0' (uncurry f (Y (FC.embed unitor)))
tensorEval f         = unitor' . swap . (tensorEval1 (uncurry f) × id) . assoc' . (id × turn) . unitor
tensorEmbed1 f (Y q) (Y u) = Compose (f ∘ unitor') (q ▴ u)
tensorEmbed t i j     = tensorEmbed1 (turn' ∘ (t × id)) (merge (i,j))


delta'         :: {-<-}(Autonomous cat, TensorClosed obj, DualClosed obj, Obj cat ~ obj, obj a, obj (), obj r) => {->-}P cat r a ⊸ P cat r (Dual a) ⊸ S cat r
delta' (Y i) (Y j) = Compose turn' (i ▴ j)

delta i j u = eatU u (delta' i j)

type U cat r = P cat r Unit

eatU :: (con ~ Obj cat, TensorClosed con, ProdObj con, con r, con (), Monoidal cat) => U cat r ⊸ S cat r ⊸ S cat r
eatU (Y f) (Compose φ g) = Compose (φ ∘ unitor') (g ▴ f)
eatU p (Plus f) = Plus (\b -> eatU p (f b))


tensorEmbed   :: ({-<-}Obj cat ~ con, con a, con b, TensorClosed con, DualClosed con, ProdObj con, con (), {->-}Autonomous cat) => (a `cat` b) -> (forall r. {-<-} con r => {->-} P cat r a ⊸ P cat r (Dual b) ⊸ R cat r)
tensorEmbed1  :: ({-<-}Obj cat ~ con, con a, TensorClosed con, ProdObj con, con (), {->-}Monoidal cat) => (a `cat` Unit) -> (forall r. {-<-}  con r => {->-} P cat r a ⊸ R cat r)

tensorEval    :: ({-<-}Obj cat ~ con, con a, con b, DualClosed con, TensorClosed con, ProdObj con, con (), {->-}Autonomous cat, GroupCat  cat) => (forall r. {-<-} con r => {->-} P cat r a ⊸ P cat r (Dual b) ⊸ R cat r) -> a `cat` b
tensorEval1    :: ({-<-}Obj cat ~ con, con a, TensorClosed con, ProdObj con, con (), {->-}Monoidal cat, GroupCat cat) => (forall r. {-<-} con r => {->-} P cat r a ⊸ R cat r) -> a `cat` Unit

zeroTensor    :: (GroupCat cat, Autonomous cat{-<-}, Obj cat ~ con, con r, con a,  DualClosed con, TensorClosed con, con (){->-}) => P cat r a ⊸ R cat r

plus          :: (Bool -> R cat r) ⊸ R cat r
(⋆)           :: (Monoidal cat {-<-}, O2 cat r (), TensorClosed con, con ~ Obj cat {->-}) => R cat r ⊸ R cat r ⊸ R cat r
(⋆-)      :: (Monoidal cat, {-<-} O2 cat r (), TensorClosed con, con ~ Obj cat {->-}) => S cat r ⊸ S cat r ⊸ S cat r
(f ⋆ g) u = dupU u & \(u1,u2) -> f u1 ⋆- g u2

dupU :: (Monoidal cat,con ~ Obj cat, TensorClosed con, ProdObj con, con r, con Unit) => U cat r ⊸ (U cat r,U cat r)
dupU = split ∘ (encode unitor)

delta         :: {-<-}(Autonomous cat, TensorClosed obj, DualClosed obj, Obj cat ~ obj, obj a, obj (), obj r) => {->-}P cat r a ⊸ P cat r (Dual a) ⊸ R cat r
contract :: {-<-}(Autonomous cat, con ~ Obj cat, con a, con r, con (), con (Dual a), TensorClosed con, DualClosed con) => {->-}(P cat r (Dual a) ⊸ P cat r a ⊸ R cat r) ⊸ R cat r
contract f u = uncurry (uncurry f) (encode ((turn × id) . unitor) u) 

deriv         :: {-<-}forall v cat con r.  (con v, TensorClosed con, con ~ Obj cat, con r, con (), Monoidal cat, ProdObj con) =>{->-} (TensorCategory v cat) => P cat r v ⊸ R cat r ⊸ R cat r

uncurry   :: (Monoidal cat {-<-} , O3 cat r a b, con (), TensorClosed con, con ~ Obj cat{->-})  =>  (P cat r a ⊸ P cat r b ⊸ k) ⊸ (P cat r (a⊗b) ⊸ k)
uncurry f p = split p & \case (a,b) -> f a b

(&) ::  a ⊸ (a ⊸ b) ⊸ b
x & f = f x


affinity :: forall v a s k con.
            (con ~ Obj k, OO s a, con a, con v, con (), v ~ Atom s,
             TensorClosed con, AutonomousObj con, GroupCat k,
             TensorCategory (Atom s) k,CoordinateCategory (Atom s) k)
         => k (Atom s ⊗ a) a
affinity = aff getRepr

aff :: forall s k con a.
       (con ~ Obj k, con a, con (Atom s), con (),
        TensorClosed con, AutonomousObj con, TensorCategory (Atom s) k,
        GroupCat k, CoordinateCategory (Atom s) k)
    => Repr s a -> k (Atom s ⊗ a) a
aff = \case
  RAtom -> christoffel
  RUnit -> zero
  RPair p q ->
    objprod @con @a //
    ((aff p × id) ∘ assoc') + ((id × aff q) ∘ shuf)
  RDual q ->
    dualObj @con @a //
    negate (unitor' . swap .
           (turn' × id) .
           assoc' . (id × swap) . assoc .
           ((( aff q × id) . assoc' . (id × (swap . turn) ) . unitor) × id))