0 | module Data.Tensor.Shape.Shape
2 | import public Decidable.Equality
3 | import Data.Vect.Elem
4 | import Data.Vect.Quantifiers
5 | import Data.List.Quantifiers
7 | import Data.Container.Base
8 | import Data.Tensor.Shape.Axis
75 | data TensorShape : (rank : Nat) ->Type where
77 | (::) : (a : Axis) -> (as : TensorShape k) ->
78 | (axisConsistent : a `ConsistentWith` as) =>
85 | data ConsistentWith : Axis -> TensorShape k -> Type where
86 | NewAxis : {0 a : Axis} -> {0 as : TensorShape k} ->
87 | NotElem a.name as ->
88 | a `ConsistentWith` as
89 | ExistingAxis : {0 a : Axis} -> {0 as : TensorShape k} ->
90 | (e : Elem a.name as) ->
91 | index as a.name = a.cont ->
92 | a `ConsistentWith` as
99 | data Elem : (axisName : AxisName) -> (as : TensorShape rank) -> Type where
100 | Here : {0 as : TensorShape rank} ->
101 | a `ConsistentWith` as =>
102 | axisName = a.name =>
103 | Elem axisName (a :: as)
104 | There : {0 a : Axis} -> {0 as : TensorShape rank} ->
105 | a `ConsistentWith` as =>
106 | (elem : Elem axisName as) =>
107 | Elem axisName (a :: as)
111 | data NotElem : (axisElem : AxisName) -> (as : TensorShape rank) -> Type where
112 | NotInEmpty : NotElem axisElem []
113 | NotInNonEmpty : {0 axisElem : AxisName} -> {0 a : Axis} ->
114 | {0 as : TensorShape rank} ->
115 | (neq : IsNo (decEq axisElem a.name)) ->
116 | (notElem : NotElem axisElem as) =>
117 | (a `ConsistentWith` as) ->
118 | NotElem axisElem (a :: as)
124 | index : (shape : TensorShape rank) ->
125 | (axisName : AxisName) ->
126 | (isElem : Elem axisName shape) =>
128 | index (a :: _) axisName @{Here} = a.cont
129 | index (_ :: as) axisName @{There} = index as axisName
133 | rename : (shape : TensorShape rank) ->
134 | (axisName : AxisName) ->
135 | (newAxisName : AxisName) ->
138 | rename (a :: as) axisName newAxisName
139 | = (::) (applyWhen (axisName == a.name) (flip rename newAxisName) a) (rename as axisName newAxisName) @{believe_me "consistentAfterRenaming_believe_me"}
141 | namespace RenameByIndex
144 | rename : (shape : TensorShape rank) ->
145 | (axisIndex : Fin rank) ->
146 | (newAxisName : AxisName) ->
148 | rename (a :: as) FZ newAxisName
149 | = (::) (newAxisName ~> a.cont) as @{believe_me "consistentAfterRenamingByIndex"}
150 | rename (a :: as) (FS axisIndex) newAxisName
151 | = (::) a (rename as axisIndex newAxisName) @{believe_me "consistentAfterRenamingByIndex"}
155 | namespace Quantifiers
157 | data All : (p : Axis -> Type) -> TensorShape k -> Type where
159 | (::) : {0 a : Axis} -> {0 as : TensorShape k} ->
161 | a `ConsistentWith` as =>
165 | data Any : (p : Axis -> Type) -> TensorShape k -> Type where
166 | Here : {0 a : Axis} -> {0 as : TensorShape k} ->
167 | a `ConsistentWith` as =>
168 | p a -> Any p (a :: as)
169 | There : {0 a : Axis} -> {0 as : TensorShape k} ->
170 | a `ConsistentWith` as =>
171 | Any p as -> Any p (a :: as)
177 | namespace QuantifierOnContainers
179 | data AllC : (p : Cont -> Type) -> TensorShape k -> Type where
181 | (::) : {0 a : Axis} -> {0 as : TensorShape k} ->
182 | p a.cont -> AllC p as ->
183 | a `ConsistentWith` as =>
187 | data AnyC : (p : Cont -> Type) -> TensorShape k -> Type where
188 | Here : {0 a : Axis} -> {0 as : TensorShape k} ->
189 | a `ConsistentWith` as =>
190 | p a.cont -> AnyC p (a :: as)
191 | There : {0 a : Axis} -> {0 as : TensorShape k} ->
192 | a `ConsistentWith` as =>
193 | AnyC p as -> AnyC p (a :: as)
196 | tensorShapesConsistent : TensorShape k -> TensorShape k' -> Type
197 | tensorShapesConsistent s1 s2 = All (\a => a `ConsistentWith` s2) s1
201 | toVect : TensorShape k -> Vect k Axis
203 | toVect (a :: as) = a :: toVect as
206 | toList : TensorShape k -> List Axis
208 | toList (a :: as) = a :: toList as
213 | conts : TensorShape k -> List Cont
214 | conts ts = cont <$> toList ts
218 | toAll : {0 shape : TensorShape k} ->
219 | AllC p shape -> List.Quantifiers.All.All p (conts shape)
221 | toAll (x :: xs) = x :: toAll xs
225 | renamePreservesConts : (shape : TensorShape rank) ->
226 | (axisName : AxisName) ->
227 | (newAxisName : AxisName) ->
228 | conts (rename shape axisName newAxisName) = conts shape
229 | renamePreservesConts [] _ _ = Refl
230 | renamePreservesConts (a :: as) axisName newAxisName with (axisName == a.name)
231 | _ | True = cong (a.cont ::) (renamePreservesConts as axisName newAxisName)
232 | _ | False = cong (a.cont ::) (renamePreservesConts as axisName newAxisName)
234 | namespace RenameByIndex
237 | renamePreservesConts : (shape : TensorShape rank) ->
238 | (axisIndex : Fin rank) ->
239 | (newAxisName : AxisName) ->
240 | conts (rename shape axisIndex newAxisName) = conts shape
241 | renamePreservesConts (a :: as) FZ newAxisName = Refl
242 | renamePreservesConts (a :: as) (FS axisIndex) newAxisName
243 | = cong (a.cont ::) (renamePreservesConts as axisIndex newAxisName)
247 | axisNames : TensorShape k -> Vect k AxisName
248 | axisNames ts = name <$> toVect ts
252 | axisSizes : TensorShape k -> Vect k Cont
253 | axisSizes ts = cont <$> toVect ts
257 | size : (shape : TensorShape k) -> All IsCubical (conts shape) => Nat
258 | size shape = size (conts shape)
265 | 0 TensorCubEvidence : TensorShape k -> Type
266 | TensorCubEvidence shape = Either (All IsCubical shape) ()
273 | data UniqueElem : AxisName -> TensorShape rank -> Type where
274 | Here : {0 as : TensorShape rank} ->
275 | axisName = ax.name =>
276 | NotElem axisName as =>
277 | ax `ConsistentWith` as =>
278 | UniqueElem axisName (ax :: as)
279 | There : {0 ax : Axis} -> {0 as : TensorShape rank} ->
281 | (uniqueElem : UniqueElem axisName as) =>
282 | (neq : IsNo (decEq axisName ax.name)) =>
283 | ax `ConsistentWith` as =>
284 | UniqueElem axisName (ax :: as)
288 | forgetUnique : {as : TensorShape rank} ->
289 | UniqueElem axisName as ->
291 | forgetUnique {as = (a :: as)} Here = Here
292 | forgetUnique {as = (a :: as)} (There {uniqueElem=elem})
293 | = There {elem=forgetUnique elem}
296 | index : (shape : TensorShape rank) ->
297 | (axisName : AxisName) ->
298 | (uniqueElem : UniqueElem axisName shape) =>
300 | index (a :: _) axisName @{Here} = a.cont
301 | index (_ :: as) axisName @{There} = index as axisName
305 | removeAxis : {rank : Nat} ->
306 | (toRemove : AxisName) ->
307 | (shape : TensorShape (S rank)) ->
308 | (is : UniqueElem toRemove shape) =>
310 | removeAxis toRemove (_ :: as) @{Here} = as
311 | removeAxis toRemove (a :: as) @{There @{ItIsSucc}}
312 | = let cProof = consistentAfterRemoving a as toRemove
313 | in a :: removeAxis toRemove as
318 | removedNotElem : {rank : Nat} ->
319 | (toRemove : AxisName) -> (as : TensorShape (S rank)) ->
320 | (uElem : UniqueElem toRemove as) =>
321 | NotElem toRemove (removeAxis toRemove as)
322 | removedNotElem _ (_ :: _) @{Here @{_} @{tNotElem}} = tNotElem
323 | removedNotElem toRemove (_ :: as) @{There @{ItIsSucc} @{_} @{neqRm}}
324 | = NotInNonEmpty neqRm @{removedNotElem toRemove as} _
328 | notElemAfterRemoving : {rank : Nat} ->
329 | (x : AxisName) -> (as : TensorShape (S rank)) ->
331 | (toRemove : AxisName) ->
332 | (uElem : UniqueElem toRemove as) =>
333 | NotElem x (removeAxis toRemove as)
334 | notElemAfterRemoving _ (_ :: _) (NotInNonEmpty _ @{notElemTail} _) _ @{Here}
336 | notElemAfterRemoving x (_ :: as) (NotInNonEmpty neqX @{notElemTail} _) toRemove @{There @{ItIsSucc}}
337 | = NotInNonEmpty neqX @{notElemAfterRemoving x as notElemTail toRemove} _
342 | indexAfterRemoving : {rank : Nat} ->
343 | (x : AxisName) -> (as : TensorShape (S rank)) ->
345 | (toRemove : AxisName) ->
346 | (uElem : UniqueElem toRemove as) =>
347 | (neq : IsNo (decEq x toRemove)) =>
348 | (e' : Elem x (removeAxis toRemove as)
349 | ** index (removeAxis toRemove as) x = index as x)
350 | indexAfterRemoving _ ((_ ~> _) :: _) (Here @{_} @{Refl}) _ @{Here @{Refl}} @{neq}
351 | = absurd @{UninhabitedIsNoRefl} neq
352 | indexAfterRemoving _ (_ :: _) (There @{_} @{elemTail}) _ @{Here}
353 | = (
elemTail ** Refl)
354 | indexAfterRemoving _ (_ :: _) (Here @{_} @{eqPrf}) _ @{There @{ItIsSucc}}
355 | = (
Here @{_} @{eqPrf} ** Refl)
356 | indexAfterRemoving x (ax :: as) (There @{_} @{elemTail}) toRemove @{There @{ItIsSucc}}
357 | = let (
e' ** prfIdx)
= indexAfterRemoving x as elemTail toRemove
358 | in (
There @{consistentAfterRemoving ax as toRemove} {elem = e'} ** prfIdx)
363 | consistentAfterRemoving : {rank : Nat} ->
364 | (a : Axis) -> (as : TensorShape (S rank)) ->
365 | a `ConsistentWith` as =>
366 | (toRemove : AxisName) ->
367 | (uElem : UniqueElem toRemove as) =>
368 | a `ConsistentWith` (removeAxis toRemove as)
369 | consistentAfterRemoving a as @{cw} toRemove with (decEq a.name toRemove)
371 | = NewAxis (rewrite eqPrf in removedNotElem toRemove as)
372 | _ | No contra = case cw of
374 | NewAxis (notElemAfterRemoving a.name as notElem toRemove)
375 | ExistingAxis e prf =>
376 | let (
e' ** prfIdx)
= indexAfterRemoving a.name as e toRemove
377 | {neq = proofIneqIsNo contra}
378 | in ExistingAxis e' (rewrite prfIdx in prf)
380 | notElemExample1 : NotElem "i" ["g" ~> List, "j" ~> BinTree]
381 | notElemExample1 = %search
383 | tensorShapeTest1 : TensorShape 2
384 | tensorShapeTest1 = ["batchSize" ~> Vect 128, "seqLen" ~> List]
386 | tensorShapeTest2 : TensorShape 3
388 | = ["batchSize" ~> Vect 128, "seqLen" ~> List, "batchSize" ~> Vect 128]
391 | tensorShapeTest3 : TensorShape 2
392 | tensorShapeTest3 = ["batchSize" ~> Vect 128, "batchSize" ~> Vect 13]
394 | uniqueElemExample1 : UniqueElem "j" ["i" ~> List, "j" ~> BinTree, "i" ~> List]
395 | uniqueElemExample1 = %search
398 | uniqueElemExampleFail : UniqueElem "x" ["i" ~> List, "j" ~> BinTree]
399 | uniqueElemExampleFail = %search
401 | uniqueElemExampleFail2 : UniqueElem
"i" [
"i" ~> List
404 | uniqueElemExampleFail2
= %search
407 | TensorTest1 : TensorShape 3
408 | TensorTest1 = ["batchSize" ~> Vect 128, "seqLen" ~> List, "feat" ~> Vect 64]
412 | TensorTest2 : (i : Axis) -> ConsistentWith i [i]
413 | TensorTest2 i = %search
416 | TensorElemTest2 : Elem "asdf" TensorTest1
417 | TensorElemTest2 = %search