{-# 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))