0 | module Data.Tensor.Utils
5 | import Control.Monad.State
7 | import Data.Tensor.Tensor
8 | import Data.Container.Additive
9 | import Data.Container.SubTerm
30 | namespace CommonNames
32 | Scalar : (a : Type) -> Type
33 | Scalar a = Tensor [] a
36 | Vector : (c : Axis) -> (a : Type) -> Type
37 | Vector c a = Tensor [c] a
40 | Matrix : (row, col : Axis) -> ConsistentWith row [col] =>
42 | Matrix row col a = Tensor [row, col] a
44 | namespace FillZerosOnes
48 | fillAt : {shape : TensorShape rank} ->
49 | (tensorCont shape).Shp -> (x : a) -> Tensor shape a
50 | fillAt = tensorReplicateAt
53 | fill : {shape : TensorShape rank} ->
54 | AllC TensorMonoid shape =>
56 | fill = tensorReplicate
59 | zerosAt : Num a => {shape : TensorShape rank} ->
60 | (tensorCont shape).Shp ->
62 | zerosAt s = fillAt s (fromInteger 0)
65 | zeros : Num a => {shape : TensorShape rank} ->
66 | AllC TensorMonoid shape =>
68 | zeros = zerosAt tensorUnitShape
71 | onesAt : Num a => {shape : TensorShape rank} ->
72 | (tensorCont shape).Shp ->
74 | onesAt s = fillAt s (fromInteger 1)
77 | ones : Num a => {shape : TensorShape rank} ->
78 | AllC TensorMonoid shape =>
80 | ones = onesAt tensorUnitShape
84 | identityBool : {0 c : Axis} -> IsCubical c =>
86 | identityBool @{MkIsCubical _ n}
87 | = outerWith (==) (positions {sh=()}) (positions {sh=()})
92 | identity : {0 c : Axis} -> IsCubical c =>
93 | Num a => Tensor [c, c] a
94 | identity @{MkIsCubical _ n} = fromBool <$> identityBool
109 | arange : {0 stop : Axis} -> IsCubical stop =>
110 | Cast Nat a => Tensor [stop] a
111 | arange @{MkIsCubical _ n} = cast . finToNat <$> positions {sh=()}
116 | arangeFromTo : {default (TTInternalName ~~> 0) start : Axis} ->
118 | (cStart : IsCubical start) => (cStop : IsCubical stop) =>
119 | Cast Nat a => Tensor [stop.name ~~> minus (stop.dim) (start.dim)] a
120 | arangeFromTo {cStart=(MkIsCubical _ n)} {cStop=(MkIsCubical _ m)}
121 | = cast . (+n) . finToNat <$> positions {sh=()}
126 | flip : {shape : TensorShape rank} ->
127 | (axis : Fin rank) ->
128 | IsCubical (index axis (toVect shape)) =>
129 | Tensor shape a -> Tensor shape a
132 | namespace Concatenate
136 | concat : {shape : TensorShape rank} -> {l : AxisName} ->
137 | {x, y : Axis} -> IsCubical x => IsCubical y =>
138 | ConsistentWith (l ~~> x.dim + y.dim) shape =>
139 | ConsistentWith x shape =>
140 | ConsistentWith y shape =>
141 | Tensor (x :: shape) a ->
142 | Tensor (y :: shape) a ->
143 | Tensor ((l ~~> x.dim + y.dim) :: shape) a
144 | concat @{MkIsCubical _ n} @{MkIsCubical _ m} t t'
145 | = embedTopExt $
extractTopExt t ++ extractTopExt t'
154 | size : {shape : TensorShape rank} ->
155 | Tensor shape a -> Nat
160 | size : {shape : TensorShape rank} ->
161 | All IsCubical (toVect shape) =>
162 | (0 _ : Tensor shape a) -> Nat
163 | size {shape} _ = size (toVect shape)
170 | flatten : {0 shape : TensorShape rank} ->
171 | Foldable (Tensor shape) =>
172 | Tensor shape a -> List a
179 | flatten : {shape : TensorShape rank} ->
180 | All IsCubical (conts shape) =>
181 | Tensor shape a -> Vect (size shape) a
182 | flatten = toVect . extMap (flattenCubical DefaultLayoutOrder) . GetT
188 | max : {0 shape : TensorShape rank} ->
189 | Foldable (Tensor shape) => Ord a =>
190 | Tensor shape a -> Maybe a
191 | max = max . flatten
193 | namespace ArgMinMax
195 | argmax : {i : Axis} -> Ord a => IsFoldable i.cont => IsNonEmpty i.cont =>
196 | (t : Tensor [i] a) -> i.cont.Pos t.extractShapeRank1
197 | argmax t = argmax (rank1ToExt t)
202 | argmin : {i : Axis} -> Ord a => IsFoldable i.cont => IsNonEmpty i.cont =>
203 | (t : Tensor [i] a) -> i.cont.Pos t.extractShapeRank1
204 | argmin = argmax @{Reverse}
210 | isClose : {default 1.0e-8 atol : Double} -> {default 1.0e-5 rtol : Double} ->
211 | Double -> Double -> Bool
212 | isClose x y = abs (x - y) <= atol + rtol * abs y
216 | allClose : {0 shape : TensorShape rank} ->
217 | Applicative (Tensor shape) => Foldable (Tensor shape) =>
218 | {default 1.0e-8 atol : Double} -> {default 1.0e-5 rtol : Double} ->
219 | Tensor shape Double -> Tensor shape Double -> Bool
220 | allClose t t' = all id [| isClose {atol} {rtol} t t' |]
224 | oneHot : {0 c : Axis} -> IsCubical c =>
225 | (i : Fin (c.dim)) ->
226 | Num a => Tensor [c] a
227 | oneHot @{MkIsCubical _ n} i = set zeros [i] 1
229 | namespace Triangular
232 | cTriBool : {c : Axis} ->
233 | (ip : InterfaceOnPositions c.cont MOrd) =>
234 | TensorMonoid c.cont =>
235 | (sh : c.cont.Shp) -> Tensor [c, c] Bool
237 | = let cPositions = positions {sh=sh}
238 | pp : MOrd (c.cont.Pos sh) := GetInterface ip sh
239 | in outerWith (flip isSubTerm) cPositions cPositions
242 | triBool : {0 c : Axis} -> IsCubical c =>
244 | triBool @{MkIsCubical _ n} = cTriBool ()
250 | tri : {0 c : Axis} -> IsCubical c =>
251 | Num a => Tensor [c, c] a
252 | tri @{MkIsCubical _ n} = fromBool <$> triBool
257 | lowerTriangular : {0 c : Axis} -> IsCubical c =>
258 | Num a => Tensor [c, c] a -> Tensor [c, c] a
259 | lowerTriangular @{MkIsCubical _ n} = (* tri)
264 | upperTriangular : {0 c : Axis} -> IsCubical c =>
265 | Num a => Tensor [c, c] a -> Tensor [c, c] a
266 | upperTriangular @{MkIsCubical _ n} = (* ((fromBool . not) <$> triBool))
270 | maskedFill : {shape : TensorShape rank} ->
271 | Num a => AllC TensorMonoid shape =>
272 | (t : Tensor shape a) ->
273 | (mask : Tensor shape Bool) ->
276 | maskedFill t mask fill = liftA2Tensor mask t <&>
277 | (\(maskVal, tVal) => if maskVal then fill else tVal)
280 | sum : {shape : TensorShape rank} ->
281 | Algebra (Tensor shape) a =>
282 | Tensor shape a -> a
286 | mean : {shape : TensorShape rank} ->
287 | All IsCubical (toVect shape) =>
290 | Algebra (Tensor shape) a =>
291 | Tensor shape a -> a
292 | mean t = sum t / cast (Cubical.size t)
295 | variance : {c : Axis} -> IsCubical c =>
296 | Neg a => Fractional a => Cast Nat a =>
298 | variance @{MkIsCubical _ n} t =
299 | let inputMinusMean = t - pure (mean t)
300 | in mean (inputMinusMean * inputMinusMean)
304 | cumulativeSum : {c : Axis} -> Num a =>
305 | Traversable (Ext c.cont) =>
306 | Tensor [c] a -> Tensor [c] a
307 | cumulativeSum = extToRank1 . cumulativeSum . rank1ToExt
312 | namespace TensorComMonoid
316 | tensorComMonoid : {shape : TensorShape rank} -> AllC TensorMonoid shape =>
317 | ComMonoid a -> ComMonoid (Tensor shape a)
318 | tensorComMonoid (MkComMonoid p z) = MkComMonoid
319 | (\t, t' => [| p t t' |])
322 | namespace Traversals
324 | inorder : Tensor [b ~> BinTreeNode] a -> Tensor [l ~> List] a
325 | inorder = extToRank1 . extMap BinTreeNode.inorder . rank1ToExt
331 | {shape : TensorShape rank} ->
333 | AllC TensorMonoid shape =>
334 | Traversable (Tensor shape) =>
335 | Random (Tensor shape a) where
336 | randomIO = sequence (pure randomIO)
337 | randomRIO (lo, hi) = traverse randomRIO [| MkPair lo hi |]
340 | tta : Applicative (Tensor ["a" ~~> 1])
343 | ttt : Traversable (Tensor ["b" ~~> 1])
346 | ttd : Random Double
349 | randTensorShape : Random (Tensor ["a" ~~> 2, "b" ~~> 3] Double)
350 | randTensorShape = %search
354 | random : Num a => Random a => HasIO io =>
355 | (shape : TensorShape rank) ->
356 | All IsCubical (toVect shape) =>
357 | Applicative (Tensor shape) =>
358 | Traversable (Tensor shape) =>
359 | io (Tensor shape a)
360 | random shape = sequence $
pure $
randomRIO (0, 1)