forked from bollu/discrete-differential-geometry
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMain.hs
395 lines (292 loc) · 12.1 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
module Main where
import qualified GHC.TypeNats as TN
import Control.Monad(ap, join)
import qualified Data.Map as M
import qualified Data.List as L
import qualified Prob as P
import qualified Arr as A
import qualified ChainGraded as CG
import qualified ChainUngraded as CUG
import qualified ChainFromFreeAb as CAB
import qualified Simplex as Simplex
import Data.Proxy
-- TODO: use http://penrose.ink/ to generate diagrams!
-- | reals
type R = Float
-- | integers
type Z = Int
data Nat = NZ | NS Nat
-- | finite maps from a to b
type (#>) a b = M.Map a b
-- | evaluate a finite map
(#$) :: Ord a => (a #> b) -> a -> b
(#$) = (M.!)
-- | homology provides a boundary operator over a graded type a
class HomologyN (a :: Nat -> *) where
boundaryn :: a (NS n) -> (a n)
class CohomologyN (a :: Nat -> *) where
coboundaryn :: a n -> a (NS n)
-- d^2 = 0
class Homology a where
boundary :: a -> a
class Cohomology where
coboundary :: a -> a
-- | free abelian group over 'a'
data FreeAb (a :: Nat -> *) (n:: Nat) where
FreeAb :: [(a n, Z)] -> FreeAb a n
singletonFreeAb :: a n -> Z -> FreeAb a n
singletonFreeAb a i = FreeAb [(a, i)]
unFreeAb :: FreeAb a n -> [(a n, Z)]
unFreeAb (FreeAb coeffs) = coeffs
instance Show (a NZ) => Show (FreeAb a NZ) where
show (FreeAb a) = show a
instance Show (a (NS n)) => Show (FreeAb a (NS n)) where
show (FreeAb a) = show a
instance Ord (a NZ) => Ord (FreeAb a NZ) where
compare = undefined
instance Ord (a (NS n)) => Ord (FreeAb a (NS n)) where
compare = undefined
deriving instance (Eq (a n)) => Eq (FreeAb a n)
-- deriving instance (Ord (a n)) => Ord (FreeAb a n)
-- | simplify, by removing zero elements
simplifyFreeAb :: (Ord (a n)) => FreeAb a n -> FreeAb a n
simplifyFreeAb (FreeAb coeffs) =
let coeffs' = M.toList $ M.fromListWith (+) coeffs
in FreeAb $ [(a, c) | (a, c) <- coeffs', c /= 0]
-- | evaluate a function on a free abelian group
-- nice. (a -> r) -> r. TODO: can we think of this as continuation?
evalFreeAb :: Num r => FreeAb a n -> (a n -> r) -> r
evalFreeAb (FreeAb coeffs) f = sum $ [(fromIntegral c) * (f a) | (a, c) <- coeffs ]
class GradedFunctor (f :: (Nat -> *) -> Nat -> *) where
gfmap :: (a n -> b m) -> f a n -> f b m
-- | should return be allowd to inject into any level?
class GradedMonad (f :: (Nat -> *) -> Nat -> *) where
greturn :: a n -> f a n
gbind :: f a n -> (a n -> f m b) -> f m b
instance GradedFunctor FreeAb where
gfmap f (FreeAb coeffs) = FreeAb $ [(f a, c) | (a, c) <- coeffs]
instance GradedMonad FreeAb where
greturn a = FreeAb [(a, 1)]
gbind (FreeAb fa) (a2fb) = FreeAb $ do
(a, c) <- fa
(b, c') <- unFreeAb $ a2fb a
return $ (b, c * c')
gjoin :: FreeAb (FreeAb a) n -> FreeAb a n
gjoin ffa = gbind ffa id
-- instance Monad (FreeAb n) where
-- return a = FreeAb $ [(a, 1)]
-- -- FreeAb a -> (a -> FreeAb b) -> FreeAb b
-- (FreeAb fa) >>= a2fb = simplifyFreeAb $ FreeAb $ do
-- (a, c) <- fa
-- (b, c') <- unFreeAb $ a2fb a
-- return $ (b, c * c')
--
-- instance Applicative FreeAb where
-- (<*>) = ap
-- pure = return
--
-- instance Functor FreeAb where
-- fmap f (FreeAb ab) = FreeAb ([(f a, c) | (a, c) <- ab])
--
--
-- instance Show a => Show (FreeAb a) where
-- show (FreeAb coeffs) =
-- let
-- in if null coeffs
-- then "0"
-- else "(" <> L.intercalate " + " [show z <> show a | (a, z) <- coeffs] <> ")"
instance Ord (a n) => Num (FreeAb a n) where
fromInteger 0 = FreeAb $ []
fromInteger x = error "unimplemented fromInteger"
(FreeAb f) + (FreeAb g) = simplifyFreeAb $ FreeAb $ f ++ g
negate (FreeAb coeffs) = FreeAb $ [(a, -z) | (a, z) <- coeffs]
-- | uninhabited
data Void
-- | discrete n-dimensional manifold on abstract points b
data DiscreteManifold (b :: *) (n :: Nat) where
Point :: b -> DiscreteManifold b NZ
Boundary :: FreeAb (DiscreteManifold b) n -> DiscreteManifold b (NS n)
-- | find the image of a discrete manifold under a mapping of points.
mapDiscreteManifold :: (a -> b) -> DiscreteManifold a n -> DiscreteManifold b n
mapDiscreteManifold f (Point a) = Point (f a)
mapDiscreteManifold f (Boundary ab) = Boundary $ gfmap (mapDiscreteManifold f) ab
getManifoldBoundary :: DiscreteManifold b (NS n) -> FreeAb (DiscreteManifold b) n
getManifoldBoundary (Boundary chain) = chain
-- ACHIEVEMENT 1: HAVE A THEORY OF CHAINS
getChainBoundary :: FreeAb (DiscreteManifold b) (NS n) -> FreeAb (DiscreteManifold b) n
getChainBoundary chain = chain `gbind` getManifoldBoundary
(-.) :: Ord (DiscreteManifold b n) => DiscreteManifold b n -> DiscreteManifold b n -> DiscreteManifold b (NS n)
(-.) a b = Boundary $ FreeAb $ [(b, -1), (a, 1)]
-- | Create a higher dimensional manifold given the boundary
fromBoundary :: Ord (DiscreteManifold b n) => [DiscreteManifold b n] -> DiscreteManifold b (NS n)
fromBoundary ms = Boundary $ FreeAb $ [(m, 1) | m <- ms]
-- deriving instance (Eq b, Ord b, Eq (DiscreteManifold b n), Ord (DiscreteManifold b n)) => Ord (DiscreteManifold b (NS n))
instance Eq b => Eq (DiscreteManifold b NZ) where
Point b == Point b' = b == b'
instance (Eq b, Ord b) => Ord (DiscreteManifold b NZ) where
Point b `compare` Point b' = b `compare` b'
instance (Eq (DiscreteManifold b n)) => Eq (DiscreteManifold b (NS n)) where
Boundary b == Boundary b' = b == b'
instance (Eq (DiscreteManifold b n), Ord (FreeAb (DiscreteManifold b) n)) => Ord (DiscreteManifold b (NS n)) where
Boundary b `compare` Boundary b' = b `compare` b'
instance Show b => Show (DiscreteManifold b NZ) where
show (Point p) = show p
instance (Show (FreeAb (DiscreteManifold b) n), Show b) => Show (DiscreteManifold b (NS n)) where
show (Boundary b) = show b
-- | differential forms on an n-dimensional manifold over points b
data Form (b :: *) (n :: Nat) where
Function :: (DiscreteManifold b n -> R) -> Form b n
Differential :: Form b n -> Form b (NS n)
-- S = dim (n + 1) | boundary(S) = dimension n
-- df = dim (n + 1) | f = dimension n
-- | integral_{S} domega = integral_dS omega
-- ACHIEVEMENT 2: HAVE A THEORY OF COCHAINS AND INTEGRATION
integrateForm :: Form b n -> FreeAb (DiscreteManifold b) n -> R
integrateForm (Function f) m = evalFreeAb m f
integrateForm (Differential f) m = integrateForm f (getChainBoundary m)
pullbackForm :: (DiscreteManifold a n -> DiscreteManifold b m) -> Form b m -> Form a n
pullbackForm fwd (Function f) = Function (f . fwd)
pullbackForm fwd (Differential f) = undefined
instance CohomologyN (Form b) where
-- | automatic optimisation: boundary of boundary is zero
-- coboundaryn (Differential (Differential _)) = Function (\_ -> 0)
coboundaryn x = Differential x
-- Integral(omega) (dS) = integral (dOmega) s
class (HomologyN a, CohomologyN b) => PairingN a b | a -> b, b -> a where
integrate :: a n -> b n -> R
a, b, c :: DiscreteManifold Char NZ
a = Point 'a'
b = Point 'b'
c = Point 'c'
ab, bc, ca :: DiscreteManifold Char (NS NZ)
ab = b -. a
bc = c -. b
ca = a -. c
loop :: DiscreteManifold Char (NS (NS NZ))
loop = fromBoundary [ab, bc, ca]
-- | Simplifying using loops is monadic!
loopBoundary :: FreeAb (DiscreteManifold Char) NZ
loopBoundary = simplifyFreeAb $ getManifoldBoundary loop `gbind` getManifoldBoundary
f :: Form Char NZ
f = Function $
\d -> if d == a then 1 else if d == b then 2 else if d == c then 4 else error "unknown"
mainForms :: IO ()
mainForms = do
print $ integrateForm (Differential f) (getManifoldBoundary loop) -- 0
print $ integrateForm (Differential (Differential f)) (singletonFreeAb loop 1)-- 0
print $ integrateForm f (singletonFreeAb a 1)
print $ integrateForm f (singletonFreeAb b 1)
print $ integrateForm f (singletonFreeAb c 1)
print $ integrateForm f (getManifoldBoundary ab)
-- Step 2: Build probability theory
-- ================================
-- Discrete mapping, takes points to ponts. Can we determine everything else
-- from this?
-- | A distribution is a 0-form on the space
type Distribution a = Form a NZ
data RandomVariable a where
Return :: a -> RandomVariable a
Sample01 :: (Bool -> RandomVariable a) -> RandomVariable a
deriving(Functor)
instance Monad RandomVariable where
return = Return
(Return a) >>= a2mb = a2mb a
(Sample01 maproducer) >>= a2mb =
Sample01 $ \b -> (maproducer b) >>= a2mb
instance Applicative RandomVariable where
pure = return
(<*>) = ap
-- | bilinear function between points
type Metric a = DiscreteManifold a NZ -> DiscreteManifold a NZ -> R
-- | Given a random variable, approximate the distribution
-- | Can we _create_ an over-approximation of the domain where we sample
-- from, and then use that as a manifold???
calculateDistribution :: Eq a => RandomVariable a -> Distribution a
calculateDistribution (Return a) = undefined
-- | Sample from a given distribution
sampleDistribution :: Eq a => Distribution a -> IO [a]
sampleDistribution = undefined
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- ================================================================
-- TRYING TO DEFINE CHAIN
data Chain (n :: Nat) a where
C0 :: a -> Chain NZ a
CS :: [(Chain n a, Z)] -> Chain (NS n) a
deriving instance Show a => Show (Chain n a)
-- | Re-weigh the outermost elements of the chain by weight w
chainWeigh :: Z -> Chain n a -> Chain n a
chainWeigh _ (C0 a) = C0 a
chainWeigh w (CS acs) = CS [(a, w*c) | (a, c) <- acs]
instance Functor (Chain n) where
fmap f (C0 a) = C0 (f a)
fmap f (CS coeffs) = CS [(fmap f chain, c) | (chain, c) <- coeffs]
type family PrevN a where
PrevN NZ = NZ
PrevN (NS n) = n
type family PlusN a b where
PlusN NZ NZ = NZ
PlusN NZ a = a
PlusN a NZ = a
PlusN (NS n) m = NS (PlusN n m)
class GradedMonad2 (f :: Nat -> * -> *) where
greturn2 :: a -> f NZ a
gbind2 :: f (NS (NS n)) a -> (f (NS n) a -> f (PrevN m) b) -> f m b
instance GradedMonad2 Chain where
greturn2 = C0
chainNormalize :: Ord (Chain (PrevN n) a) => Chain n a -> Chain n a
chainNormalize (C0 a) = C0 a
chainNormalize (CS coeffs) = CS $ M.toList $ M.fromListWith (+) coeffs
chainBoundary :: Chain (NS (NS n)) a -> Chain (NS n) a
chainBoundary (CS coeffs_n_plus_1) = CS $ do
(CS chain_n_plus_1, c) <- coeffs_n_plus_1
(chain_n, c') <- chain_n_plus_1
return (chain_n, c * c')
a', b', c' :: Chain NZ Char
a' = C0 'a'
b' = C0 'b'
c' = C0 'c'
ab', bc', ca' :: Chain (NS NZ) Char
ab' = CS [(b', 1), (a', -1)]
bc' = CS [(c', 1), (b', -1)]
ca' = CS [(c', 1), (a', -1)]
abc' :: Chain (NS (NS NZ)) Char
abc' = CS [(ab', 1), (bc', 1), (ca', 1)]
main :: IO ()
main = do
mainForms
A.main
CG.main
CUG.main
CAB.main
Simplex.main