Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MatrixUpdate Created #787

Merged
merged 27 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
7d6bd32
refactored input arrays to be input lists
JosephBond Oct 2, 2023
679a8ac
Tidied up
JosephBond Oct 2, 2023
d0ccd87
nextIndices implemented in Fluid
JosephBond Oct 2, 2023
82b5516
let binding structure in cost-matrix.fld
JosephBond Oct 2, 2023
b367935
costMatrixInit in fluid in working yet flawed state. Fails to pass te…
JosephBond Oct 2, 2023
abed919
Cost-matrix almost right, but not quite, fails due to forced test fai…
JosephBond Oct 2, 2023
015b262
Removing forced failing tests
JosephBond Oct 2, 2023
78190e2
Actually fixed the borked output
JosephBond Oct 2, 2023
d21b87d
minimum and previous direction example fixed
JosephBond Oct 2, 2023
2ac1b7f
Tidied previous commit
JosephBond Oct 2, 2023
a0e1762
Added more components of dtw example, need some bug fixes
JosephBond Oct 3, 2023
02b5851
Fixing cost predicate, nearly done
JosephBond Oct 3, 2023
dc5a4ba
Pretty sure I fixed cost-matrix now
JosephBond Oct 3, 2023
cd41424
Fixed cost-matrix function now :)
JosephBond Oct 3, 2023
97eced8
Removed fast-vect dependency
JosephBond Oct 3, 2023
025f31c
Inlined arraydata
JosephBond Oct 4, 2023
5594332
tidy up
JosephBond Oct 4, 2023
b78a2d8
Used MatrixRep where possible
JosephBond Oct 4, 2023
0313ec8
tidied up
JosephBond Oct 4, 2023
ecc9ede
Got both functions typechecking?
JosephBond Oct 4, 2023
60d48f3
tidy up
JosephBond Oct 4, 2023
5605fbd
testable matrix update now?
JosephBond Oct 4, 2023
14b2de2
Another tidy up
JosephBond Oct 4, 2023
cf7acab
MatrixUpdate works if inefficient
JosephBond Oct 4, 2023
751a740
final tidy
JosephBond Oct 4, 2023
701a4ab
All tidied and working, now a test
JosephBond Oct 4, 2023
29d3066
Merge branch 'develop' into example-fluid
JosephBond Oct 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions example/Example.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ module Example.Example where

import Prelude

import Data.Array ((..))
-- import Data.Array ((..))
import Data.List ((:), List(..))
import Effect (Effect)
import Effect.Class.Console (log, logShow)
import Example.Util.DTW (distEuclid, distanceDTWWindow)
import Example.Util.DTW (costMatrixInit, distEuclid, distanceDTWWindow)
import Partial.Unsafe (unsafePartial)
import Util ((×))

Expand All @@ -16,14 +17,11 @@ main = do
n = 5
m = 7
window = 2
nextIndices = do
i <- 1 .. n
j <- (max 1 (i - window)) .. (min m (i + window))
[ (i × j) ]
logShow nextIndices
initMat = costMatrixInit n m window
logShow initMat
let
x = [ 3.0, 1.0, 2.0, 2.0, 1.0 ]
y = [ 2.0, 0.0, 0.0, 3.0, 3.0, 1.0, 0.0 ]
x = (3.0 : 1.0 : 2.0 : 2.0 : 1.0 : Nil)
y = (2.0 : 0.0 : 0.0 : 3.0 : 3.0 : 1.0 : 0.0 : Nil)
m1 × m2 = unsafePartial $ distanceDTWWindow x y 2 distEuclid
log "Finished DTW"
logShow m2
Expand Down
14 changes: 10 additions & 4 deletions example/Util/DTW.purs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
module Example.Util.DTW
( NumInf(..)
, costMatrixInit
, distEuclid
, distanceDTWWindow
) where

import Prelude

import Data.Array (length, modifyAtIndices, range, (!!), (..))
import Data.Array (modifyAtIndices, range, (!!), (..))
import Data.Foldable (foldl)
import Data.List (List(..))
import Data.List (List(..), index, length)
import Data.Maybe (fromJust)
import Data.Ord (abs)
import Partial.Unsafe (unsafePartial)
Expand All @@ -29,7 +30,7 @@ costMatrixInit rows cols window = mapMatrix init indexMat
init (_ × 0) = Infty
init (x × y) = if (abs $ x - y) <= window then FNum 0.0 else Infty

distanceDTWWindow :: Partial => Array Number -> Array Number -> Int -> (Number -> Number -> NumInf) -> Matrix NumInf × List (Int × Int)
distanceDTWWindow :: Partial => List Number -> List Number -> Int -> (Number -> Number -> NumInf) -> Matrix NumInf × List (Int × Int)
distanceDTWWindow seq1 seq2 window cost = result × (extractPath priorcells (n × m))
where
n = length seq1
Expand All @@ -48,7 +49,7 @@ distanceDTWWindow seq1 seq2 window cost = result × (extractPath priorcells (n
ijm1 = dists ! i' ! j' - 1
im1jm1 = dists ! i' - 1 ! j' - 1
minim × prev = costAndPrevD (i' × j') im1j ijm1 im1jm1
costij = cost (seq1 ! i' - 1) (seq2 ! j' - 1) `plus` minim
costij = cost (seq1 ? i' - 1) (seq2 ? j' - 1) `plus` minim
in
updateAt i' j' dists (const costij) × updateAt i' j' inds (const prev)

Expand Down Expand Up @@ -92,6 +93,11 @@ unsafeArrayInd arr ind = unsafePartial $ fromJust (arr !! ind)

infixl 5 unsafeArrayInd as !

unsafeListInd :: forall a. List a -> Int -> a
unsafeListInd list ind = unsafePartial $ fromJust (index list ind)

infixl 5 unsafeListInd as ?

mapMatrix :: forall a b. (a -> b) -> Matrix a -> Matrix b
mapMatrix f m = map (\row -> map f row) m

Expand Down
11 changes: 11 additions & 0 deletions fluid/example/dtw/cost-matrix.fld
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
let abs x y = if x - y < 0 then negate (x - y) else (x - y);
costMatrixInit rows cols window =
let ns = [0 .. rows];
ms = [0 .. cols]
in
[| let initV = if or (and (n == 1) (m == 1)) (and (abs n m <= window) (not (or (n == 1) (m == 1))))
then FNum 0
else Infty
in initV | (n, m) in (rows, cols) |]
in costMatrixInit 5 7 1

5 changes: 5 additions & 0 deletions fluid/example/dtw/cost-predicate.fld
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let abs x y = if x - y < 0 then negate (x - y) else (x - y);
initV n m window = if (or (and (n == 0) (m == 0)) (and ((abs n m) <= window) (not (or (n == 0) (m == 0)))))
then FNum 0
else Infty
in initV 1 0 2
2 changes: 2 additions & 0 deletions fluid/example/dtw/matrix-update.fld
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
let mat = [| (n, m) | (n,m) in (3, 3)|]
in matrixUpdate mat (1,1) 100
10 changes: 10 additions & 0 deletions fluid/example/dtw/min-prev.fld
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
let minAndPrev (i, j) im1 jm1 ijm1 =
let minimal = minimum [im1,jm1,ijm1]
in
if minimal == im1
then (((i - 1), j), minimal)
else if minimal == jm1
then ((i, (j - 1)), minimal)
else
(((i - 1), (j - 1)), ijm1)
in minAndPrev (4,5) 3 4 5
5 changes: 5 additions & 0 deletions fluid/example/dtw/next-indices.fld
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
let nextIndices n m window =
[(i, j) | i <- [1 .. n],
j <- [(max 1 (i - window)) .. (min m (i + window))]]
in
nextIndices 5 7 2
4 changes: 4 additions & 0 deletions src/DataType.purs
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,8 @@ dataTypes = L.fromFoldable
, dataType "Marker"
[ "Arrowhead" × 0
]
, dataType "InfNum"
[ "FNum" × 1
, "Infty" × 0
]
]
49 changes: 39 additions & 10 deletions src/Primitive/Defs.purs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ primitives = D.fromFoldable
, "mod" × binaryZero { i: int, o: int, fwd: mod }
, "quot" × binaryZero { i: int, o: int, fwd: quot }
, "rem" × binaryZero { i: int, o: int, fwd: rem }
, "matrixUpdate" × extern matrixMut
]

error_ :: ForeignOp
Expand Down Expand Up @@ -96,8 +97,6 @@ debugLog = mkExists $ ForeignOp' { arity: 1, op': op', op: fwd, op_bwd: unsafePa
bwd :: OpBwd Unit
bwd _ = error unimplemented

type ArrayData a = Array2 (Val a)

dims :: ForeignOp
dims = mkExists $ ForeignOp' { arity: 1, op': op, op: fwd, op_bwd: unsafePartial bwd }
where
Expand All @@ -108,12 +107,12 @@ dims = mkExists $ ForeignOp' { arity: 1, op': op, op: fwd, op_bwd: unsafePartial
Constr <$> new (singleton α) <@> cPair <@> (v1 : v2 : Nil)
op _ = throw "Matrix expected"

fwd :: OpFwd (Raw ArrayData)
fwd :: OpFwd (Array2 (Raw Val))
fwd (Matrix α (MatrixRep (vss × (i × β1) × (j × β2))) : Nil) =
pure $ (map erase <$> vss) × Constr α cPair (Int β1 i : Int β2 j : Nil)
fwd _ = throw "Matrix expected"

bwd :: Partial => OpBwd (Raw ArrayData)
bwd :: Partial => OpBwd (Array2 (Raw Val))
bwd (vss × Constr α c (Int β1 i : Int β2 j : Nil)) | c == cPair =
Matrix α (MatrixRep (((<$>) botOf <$> vss) × (i × β1) × (j × β2))) : Nil

Expand All @@ -122,22 +121,52 @@ matrixLookup = mkExists $ ForeignOp' { arity: 2, op': op, op: fwd, op_bwd: bwd }
where
op :: OpGraph
op (Matrix _ r : Constr _ c (Int _ i : Int _ j : Nil) : Nil)
| c == cPair = matrixGet i j r
| c == cPair = pure $ matrixGet i j r
op _ = throw "Matrix and pair of integers expected"

fwd :: OpFwd (Raw ArrayData × (Int × Int) × (Int × Int))
fwd :: OpFwd (Raw MatrixRep × (Int × Int))
fwd (Matrix _ r@(MatrixRep (vss × (i' × _) × (j' × _))) : Constr _ c (Int _ i : Int _ j : Nil) : Nil)
| c == cPair = do
v <- matrixGet i j r
pure $ ((map erase <$> vss) × (i' × j') × (i × j)) × v
let v = matrixGet i j r
pure $ (MatrixRep ((map erase <$> vss) × ((i' × unit) × (j' × unit))) × (i × j)) × v
fwd _ = throw "Matrix and pair of integers expected"

bwd :: OpBwd (Raw ArrayData × (Int × Int) × (Int × Int))
bwd ((vss × (i' × j') × (i × j)) × v) =
bwd :: OpBwd (Raw MatrixRep × (Int × Int))
bwd (((MatrixRep (vss × (i' × _) × (j' × _))) × (i × j)) × v) =
Matrix bot (matrixUpdate i j (const v) (MatrixRep (((<$>) botOf <$> vss) × (i' × bot) × (j' × bot))))
: Constr bot cPair (Int bot i : Int bot j : Nil)
: Nil

matrixMut :: ForeignOp
matrixMut = mkExists $ ForeignOp' { arity: 3, op': op, op: fwd, op_bwd: bwd }
where
op :: OpGraph
op (Matrix α r : Constr _ c (Int _ i : Int _ j : Nil) : v : Nil)
| c == cPair = Matrix <$> new (singleton α) <@> (matrixUpdate i j (const v) r)
op _ = throw "Matrix, pair of ints, and new val expected"

fwd :: OpFwd (Raw MatrixRep × (Int × Int) × Raw Val)
fwd (Matrix α r@(MatrixRep (vss × (i' × _) × (j' × _))) : Constr _ c (Int _ i : Int _ j : Nil) : v : Nil)
| c == cPair =
let
oldV = matrixGet i j r
newM = matrixUpdate i j (const v) r
in
pure $ (MatrixRep ((map erase <$> vss) × ((i' × unit) × (j' × unit))) × (i × j) × (erase oldV)) × (Matrix α newM)

fwd _ = throw "Matrix, pair of ints, and new val expected"

bwd :: OpBwd (Raw MatrixRep × (Int × Int) × Raw Val)
bwd ((((MatrixRep (vss × (i' × _) × (j' × _))) × (i × j) × oldV) × (Matrix α r))) =
let
newV = matrixGet i j r
in
Matrix α (matrixUpdate i j (const (map (const bot) oldV)) (MatrixRep (((<$>) botOf <$> vss) × (i' × bot) × (j' × bot))))
: Constr bot cPair (Int bot i : Int bot j : Nil)
: newV
: Nil
bwd _ = error "absurd backwards!"

dict_difference :: ForeignOp
dict_difference = mkExists $ ForeignOp' { arity: 2, op': op, op: fwd, op_bwd: unsafePartial bwd }
where
Expand Down
11 changes: 5 additions & 6 deletions src/Val.purs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import Foreign.Object (keys) as O
import Graph (Vertex(..))
import Graph.GraphWriter (class MonadWithGraphAlloc)
import Lattice (class BoundedJoinSemilattice, class BoundedLattice, class Expandable, class JoinSemilattice, class Neg, Raw, definedJoin, expand, maybeJoin, neg, (∨))
import Util (type (×), Endo, error, orElse, throw, unsafeUpdateAt, (!), (×), (≜), (≞))
import Util (type (×), Endo, definitely, error, orElse, throw, unsafeUpdateAt, (!), (×), (≜), (≞))
import Util.Pretty (Doc, beside, text)

data Val a
Expand Down Expand Up @@ -106,11 +106,10 @@ newtype MatrixRep a = MatrixRep (Array2 (Val a) × (Int × a) × (Int × a))

type Array2 a = Array (Array a)

matrixGet :: forall a m. MonadThrow Error m => Int -> Int -> MatrixRep a -> m (Val a)
matrixGet i j (MatrixRep (vss × _ × _)) =
orElse "Index out of bounds" do
us <- vss !! (i - 1)
us !! (j - 1)
matrixGet :: forall a. Int -> Int -> MatrixRep a -> Val a
matrixGet i j (MatrixRep (vss × _ × _)) = definitely "index out of bounds!" $ do
us <- vss !! (i - 1)
us !! (j - 1)

matrixUpdate :: forall a. Int -> Int -> Endo (Val a) -> Endo (MatrixRep a)
matrixUpdate i j δv (MatrixRep (vss × h × w)) =
Expand Down
16 changes: 14 additions & 2 deletions test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,20 @@ tests = concat
, test_linking
]

-- test_scratchpad :: Array (String × Aff Unit)
-- test_scratchpad = []
-- tests = test_scratchpad

test_scratchpad :: Array (String × Aff Unit)
test_scratchpad = second void <$> many
[ { file: "dtw/matrix-update"
, fwd_expect:
"FNum 0, Infty, Infty, Infty, Infty, Infty, Infty,\n\
\Infty, FNum 0, FNum 0, Infty, Infty, Infty, Infty,\n\
\Infty, FNum 0, FNum 0, FNum 0, Infty, Infty, Infty,\n\
\Infty, Infty, FNum 0, FNum 0, FNum 0, Infty, Infty,\n\
\Infty, Infty, Infty, FNum 0, FNum 0, FNum 0, Infty"
}
]
1

test_desugaring :: Array (String × Aff Unit)
test_desugaring = second void <$> many desugar_cases 1
Expand Down
15 changes: 15 additions & 0 deletions test/Spec/Specs.purs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,21 @@ misc_cases =
, { file: "range", fwd_expect: "((0, 0) : ((0, 1) : ((1, 0) : ((1, 1) : []))))" }
, { file: "records", fwd_expect: "{a : 2, b : 6, c : 7, d : (5 : []), e : 7}" }
, { file: "reverse", fwd_expect: "(2 : (1 : []))" }
, { file: "dtw/next-indices", fwd_expect: "((1, 1) : ((1, 2) : ((1, 3) : ((2, 1) : ((2, 2) : ((2, 3) : ((2, 4) : ((3, 1) : ((3, 2) : ((3, 3) : ((3, 4) : ((3, 5) : ((4, 2) : ((4, 3) : ((4, 4) : ((4, 5) : ((4, 6) : ((5, 3) : ((5, 4) : ((5, 5) : ((5, 6) : ((5, 7) : []))))))))))))))))))))))" }
, { file: "dtw/cost-matrix"
, fwd_expect:
"FNum 0, Infty, Infty, Infty, Infty, Infty, Infty,\n\
\Infty, FNum 0, FNum 0, Infty, Infty, Infty, Infty,\n\
\Infty, FNum 0, FNum 0, FNum 0, Infty, Infty, Infty,\n\
\Infty, Infty, FNum 0, FNum 0, FNum 0, Infty, Infty,\n\
\Infty, Infty, Infty, FNum 0, FNum 0, FNum 0, Infty"
}
, { file: "dtw/matrix-update"
, fwd_expect:
"100, (1, 2), (1, 3),\n\
\(2, 1), (2, 2), (2, 3),\n\
\(3, 1), (3, 2), (3, 3)"
}
]

desugar_cases :: Array TestSpec
Expand Down