on master help sign in
laop/README.md
276 lines 9.4 kB history raw
1# laop - Linear Algebra of Programming library
3[![GitHub CI](https://github.com/bolt12/laop/workflows/CI/badge.svg)](https://github.com/bolt12/laop/actions)
4[![Build status](https://img.shields.io/travis/bolt12/laop.svg?logo=travis)](https://travis-ci.org/bolt12/laop)
5[![Hackage](https://img.shields.io/hackage/v/laop.svg?logo=haskell)](https://hackage.haskell.org/package/laop)
6[![Stackage Lts](http://stackage.org/package/laop/badge/lts)](http://stackage.org/lts/package/laop)
7[![Stackage Nightly](http://stackage.org/package/laop/badge/nightly)](http://stackage.org/nightly/package/laop)
9The LAoP discipline generalises relations and functions treating them as
10Boolean matrices and in turn consider these as arrows.
12__LAoP__ is a library for algebraic (inductive) construction and manipulation of matrices
13in Haskell. See [my Msc Thesis](https://github.com/bolt12/master-thesis) for the
14motivation behind the library, the underlying theory, and implementation details.
16This module offers many of the combinators mentioned in the work of
17[Macedo (2012)](https://repositorium.sdum.uminho.pt/handle/1822/22894) and [Oliveira (2012)](https://pdfs.semanticscholar.org/ccf5/27fa9179081223bffe8067edd81948644fc0.pdf).
19See the package in hackage [here](https://hackage.haskell.org/package/laop-0.1.1.0)
21A Functional Pearl has been written and can be regarded as the [reference document](https://github.com/bolt12/tymfgg-pearl) for this library.
23## Features
25This library offers 3 main matrix programming modules:
27- One in which matrices are typed with type level natural numbers;
28- One in which matrices are typed with arbitrary generic data types;
29- One in which matrices are regarded as relations, i.e. boolean matrices;
31There's also an experimental module that uses matrices to represent probability
32distributions.
34The most interesting feature is that matrices are represented as an inductive data type.
35Given this formulation, matrix algorithms can be expressed in a much more elegant and
36calculational style than the traditional vector of vectors representation. This data type
37guarantees that a matrix will always have valid dimensions. It can also express block matrix
38computations naturally, which leads to total, efficient and statically typed manipulation
39and transformation functions.
41Like matrix multiplication, other common operations, such as matrix transposition, benefit from a block-oriented structure that leads to a simple and natural divide-and-conquer algorithmic solution. Performance wise, this means that without much effort we can obtain optimal cache-oblivious algorithms.
43Given this, this new matrix formulation compared to other libraries:
45- Is more compositional and polymorphic and does not have partial matrix manipulation functions (hence less chances for usage errors);
46- Our implementation of matrices enables simple manipulation of submatrices, making it particularly suitable for formal verification and equation reasoning, using the mathematical framework defined by the linear algebra of programming. Furthermore, the data type constructors ensure that the matrices of this kind are sound, i.e. malformed matrices with incorrect dimensions of the sort, can not be constructed.
48## Known issues
50Unfortunately, due to the use of type-level programming features, this approach sometimes requires type dimensions to be constrainted, in some way, impossible to write idiomatic Arrow instances, for example. Type inference isn't perfect, when it comes to infer the types of matrices which dimensions are computed using type level naturals multiplication, the compiler needs type annotations in order to succeed. And not all kinds of programs can be modeled using matrices, namely programs that deal with arbitrary infinite data types such as lists or integers (although there are some workarounds).
52## Notes
54This is still a work in progress, any feedback is welcome!
56## Example
58```Haskell
59{-# LANGUAGE DeriveGeneric #-}
60{-# LANGUAGE FlexibleContexts #-}
61{-# LANGUAGE TypeOperators #-}
62{-# LANGUAGE TypeApplications #-}
63{-# LANGUAGE DataKinds #-}
65module Main where
67import Matrix.Type
68import Utils
69import Dist
70import GHC.TypeLits
71import Data.Coerce
72import GHC.Generics
73import Control.Category hiding (id)
74import Prelude hiding ((.))
76-- Monty Hall Problem
77data Outcome = Win | Lose
78 deriving (Bounded, Enum, Eq, Show, Generic)
80switch :: Outcome -> Outcome
81switch Win = Lose
82switch Lose = Win
84firstChoice :: Matrix Double () Outcome
85firstChoice = col [1/3, 2/3]
87secondChoice :: Matrix Double Outcome Outcome
88secondChoice = fromF' switch
90-- Dice sum
92type SS = Natural 1 6 -- Sample Space
94sumSS :: SS -> SS -> Natural 2 12
95sumSS = coerceNat (+)
97sumSSM = fromF' (uncurry sumSS)
99condition :: (Int, Int) -> Int -> Int
100condition (fst, snd) thrd = if fst == snd
101 then fst * 3
102 else fst + snd + thrd
104conditionSS :: (SS, SS) -> SS -> Natural 3 18
105conditionSS = coerceNat2 condition
107conditionalThrows = fromF' (uncurry conditionSS) . khatri (khatri die die) die
109die :: Matrix Double () SS
110die = col $ map (const (1/6)) [nat @1 @6 1 .. nat 6]
112-- Sprinkler
114rain :: Matrix Double () Bool
115rain = col [0.8, 0.2]
117sprinkler :: Matrix Double Bool Bool
118sprinkler = fromLists [[0.6, 0.99], [0.4, 0.01]]
120grass :: Matrix Double (Bool, Bool) Bool
121grass = fromLists [[1, 0.2, 0.1, 0.01], [0, 0.8, 0.9, 0.99]]
123state :: Matrix Double () (Bool, (Bool, Bool))
124state = khatri grass identity . khatri sprinkler identity . rain
126grass_wet :: Matrix Double (Bool, (Bool, Bool)) One
127grass_wet = row [0,1] . kp1
129rainning :: Matrix Double (Bool, (Bool, Bool)) One
130rainning = row [0,1] . kp2 . kp2
132-- Alcuin Puzzle
134data Being = Farmer | Fox | Goose | Beans
135 deriving (Bounded, Enum, Eq, Show, Generic)
137data Bank = LeftB | RightB
138 deriving (Bounded, Enum, Eq, Show, Generic)
140eats :: Being -> Being -> Bool
141eats Fox Goose = True
142eats Goose Beans = True
143eats _ _ = False
145eatsR :: R.Relation Being Being
146eatsR = R.toRel eats
148cross :: Bank -> Bank
149cross LeftB = RightB
150cross RightB = LeftB
152crossR :: R.Relation Bank Bank
153crossR = R.fromF' cross
155-- | Initial state, everyone in the left bank
156locationLeft :: Being -> Bank
157locationLeft _ = LeftB
159locationLeftR :: R.Relation Being Bank
160locationLeftR = R.fromF' locationLeft
162-- | Initial state, everyone in the right bank
163locationRight :: Being -> Bank
164locationRight _ = RightB
166locationRightR :: R.Relation Being Bank
167locationRightR = R.fromF' locationRight
169-- Properties
171-- Being at the same bank
172sameBank :: R.Relation Being Bank -> R.Relation Being Being
173sameBank = R.ker
175-- Risk of somebody eating somebody else
176canEat :: R.Relation Being Bank -> R.Relation Being Being
177canEat w = sameBank w `R.intersection` eatsR
179-- "Starvation" property.
180inv :: R.Relation Being Bank -> Bool
181inv w = (w `R.comp` canEat w) `R.sse` (w `R.comp` farmer)
182 where
183 farmer :: R.Relation Being Being
184 farmer = R.fromF' (const Farmer)
186-- Arbitrary state
187bankState :: Being -> Bank -> Bool
188bankState Farmer LeftB = True
189bankState Fox LeftB = True
190bankState Goose RightB = True
191bankState Beans RightB = True
192bankState _ _ = False
194bankStateR :: R.Relation Being Bank
195bankStateR = R.toRel bankState
197-- Main
199main :: IO ()
200main = do
201 putStrLn "Monty Hall Problem solution:"
202 prettyPrint (secondChoice . firstChoice)
203 putStrLn "\n Sum of dices probability:"
204 prettyPrint (sumSSM `comp` khatri die die)
205 putStrLn "\n Conditional dice throw:"
206 prettyPrint conditionalThrows
207 putStrLn "\n Checking that the last result is indeed a distribution: "
208 prettyPrint (bang . sumSSM . khatri die die)
209 putStrLn "\n Probability of grass being wet:"
210 prettyPrint (grass_wet . state)
211 putStrLn "\n Probability of rain:"
212 prettyPrint (rainning . state)
213 putStrLn "\n Is the arbitrary state a valid state? (Alcuin Puzzle)"
214 print (inv bankStateR)
215```
217```Shell
218Monty Hall Problem solution:
219┌ ┐
220│ 0.6666666666666666 │
221│ 0.3333333333333333 │
222└ ┘
224 Sum of dices probability:
225┌ ┐
226│ 2.7777777777777776e-2 │
227│ 5.555555555555555e-2 │
228│ 8.333333333333333e-2 │
229│ 0.1111111111111111 │
230│ 0.1388888888888889 │
231│ 0.16666666666666666 │
232│ 0.1388888888888889 │
233│ 0.1111111111111111 │
234│ 8.333333333333333e-2 │
235│ 5.555555555555555e-2 │
236│ 2.7777777777777776e-2 │
237└ ┘
239 Conditional dice throw:
240┌ ┐
241│ 2.7777777777777776e-2 │
242│ 9.259259259259259e-3 │
243│ 1.8518518518518517e-2 │
244│ 6.481481481481481e-2 │
245│ 5.555555555555555e-2 │
246│ 8.333333333333333e-2 │
247│ 0.12962962962962962 │
248│ 0.1111111111111111 │
249│ 0.1111111111111111 │
250│ 0.12962962962962962 │
251│ 8.333333333333333e-2 │
252│ 5.555555555555555e-2 │
253│ 6.481481481481481e-2 │
254│ 1.8518518518518517e-2 │
255│ 9.259259259259259e-3 │
256│ 2.7777777777777776e-2 │
257└ ┘
259 Checking that the last result is indeed a distribution:
260┌ ┐
261│ 1.0 │
262└ ┘
264 Probability of grass being wet:
265┌ ┐
266│ 0.4483800000000001 │
267└ ┘
269 Probability of rain:
270┌ ┐
271│ 0.2 │
272└ ┘
274Is the arbitrary state a valid state? (Alcuin Puzzle)
275False
276```