src/autograd/tensor_vjp_LAWS.bend
bendtorch-core@0.1.0.0 · 626 lines · 25 definitions
1import Base
2import bendtorch-core@0.1.0.0/src/shape/core.bend as Shape
3import bendtorch-core@0.1.0.0/src/storage/LAWS.bend as StorageLaws
4import bendtorch-core@0.1.0.0/src/tensor/core.bend as Core
5import bendtorch-core@0.1.0.0/src/tensor/layout.bend as Layout
6import bendtorch-core@0.1.0.0/src/tensor/lifecycle.bend as Lifecycle
7import bendtorch-core@0.1.0.0/src/tensor/elementwise.bend as Elementwise
8import bendtorch-core@0.1.0.0/src/tensor/reduction.bend as Reduction
9import bendtorch-core@0.1.0.0/src/tensor/matmul.bend as Matrix
10import bendtorch-core@0.1.0.0/src/tensor/dot_fold.bend as DotFold
11import bendtorch-core@0.1.0.0/src/tensor/transpose_spec.bend as Transpose
12import bendtorch-core@0.1.0.0/src/tensor/observation.bend as Values
13import bendtorch-core@0.1.0.0/src/tensor/contracts/replayed.bend as Replayed
14import bendtorch-core@0.1.0.0/src/tensor/contracts/LAWS.bend as Contracts
15import bendtorch-core@0.1.0.0/src/tensor/contracts/binary_LAWS.bend as Binary
16import bendtorch-core@0.1.0.0/src/autograd/sum_to_size_fold_LAWS.bend as SumToSizeFold
17import bendtorch-core@0.1.0.0/src/autograd/tensor_backward.bend as Backward
18import bendtorch-core@0.1.0.0/src/autograd/loss.bend as Loss
19import bendtorch-core@0.1.0.0/src/autograd/tensor_backward_LAWS.bend as TensorBackward
20
21
22
23
24
25
26
27
28
29
30def cells(+operation: Elementwise.Operation, +plan: Shape.BroadcastPlan,
31 +left: Shape.Shape, +left_fill: F32, +left_ops: List<&2, StorageLaws.Op>,
32 +right: Shape.Shape, +right_fill: F32, +right_ops: List<&2, StorageLaws.Op>, +count: Nat) -> List<&2, F32>:
33 Binary.cells(operation, plan, left, left_fill, left_ops, right, right_fill, right_ops, count)
34
35
36
37
38def reduced(+target: Shape.Shape, +shape: Shape.Shape, +plan: Shape.BroadcastPlan, +values: List<&2, F32>, +index: U32) ->
39 Maybe<&2, F32>:
40 SumToSizeFold.summed(Layout.words_same(Shape.dimensions(shape), Shape.dimensions(target)), plan,
41 Shape.logical_numel(Shape.dimensions(shape)), values, index)
42
43
44
45
46def ProductWith(+operation: Elementwise.Operation, +plan: Shape.BroadcastPlan,
47 +left: Shape.Shape, +left_fill: F32, +left_ops: List<&2, StorageLaws.Op>,
48 +right: Shape.Shape, +right_fill: F32, +right_ops: List<&2, StorageLaws.Op>,
49 -P: (Core.Dynamic & Core.Dynamic) & Result<&2, &1, Core.Error, Core.Dynamic> -> Type) -> Type:
50 Binary.BinaryWith(operation, plan, left, left_fill, left_ops, right, right_fill, right_ops, P)
51
52
53
54
55
56
57
58
59
60law tensor_product_replayed:
61 for +operation: Elementwise.Operation
62 for +left: Shape.Shape
63 for +right: Shape.Shape
64 for +plan: Shape.BroadcastPlan
65 for planned: {Shape.broadcast_checked(left, right) == Done{plan} : Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
66 for +left_fill: F32
67 for +left_ops: List<&2, StorageLaws.Op>
68 for -left_fits: {Lifecycle.logical_length(Replayed.storage(left, left_fill, left_ops)) == Shape.logical_numel(Shape.dimensions(left)) : Nat}
69 for +right_fill: F32
70 for +right_ops: List<&2, StorageLaws.Op>
71 for -right_fits: {Lifecycle.logical_length(Replayed.storage(right, right_fill, right_ops)) == Shape.logical_numel(Shape.dimensions(right)) : Nat}
72 for -P: (Core.Dynamic & Core.Dynamic) & Result<&2, &1, Core.Error, Core.Dynamic> -> Type
73 for h: ProductWith(operation, plan, left, left_fill, left_ops, right, right_fill, right_ops, P)
74 P(Elementwise.binary(operation, Core.Packed{left, Core.TTensor{Replayed.storage(left, left_fill, left_ops), left_fits}},
75 Core.Packed{right, Core.TTensor{Replayed.storage(right, right_fill, right_ops), right_fits}}))
76
77
78def first_of(pass: Backward.Pass) -> Maybe<&1, Backward.Contribution>:
79 Backward.Pass{saved, g, contributions} = pass
80 match contributions:
81 case Fail{error}:
82 None{}
83 case Done{Nil{}}:
84 None{}
85 case Done{Con{first, Nil{}}}:
86 None{}
87 case Done{Con{first, Con{second, Nil{}}}}:
88 Some{first}
89 case Done{Con{first, Con{second, Con{other, rest}}}}:
90 None{}
91
92def second_of(pass: Backward.Pass) -> Maybe<&1, Backward.Contribution>:
93 Backward.Pass{saved, g, contributions} = pass
94 match contributions:
95 case Fail{error}:
96 None{}
97 case Done{Nil{}}:
98 None{}
99 case Done{Con{first, Nil{}}}:
100 None{}
101 case Done{Con{first, Con{second, Nil{}}}}:
102 Some{second}
103 case Done{Con{first, Con{second, Con{other, rest}}}}:
104 None{}
105
106
107
108
109type PairContract<-a: Nat, -left: Shape.Shape, -left_cell: U32 -> Maybe<&2, F32>,
110 -b: Nat, -right: Shape.Shape, -right_cell: U32 -> Maybe<&2, F32>, -pass: Backward.Pass> is Type:
111 PairContract{
112 first_target: {TensorBackward.sole_target(first_of(pass)) == Some{a} : Maybe<&2, Nat>},
113 first_dimensions: {TensorBackward.sole_dimensions(first_of(pass)) == Some{Shape.dimensions(left)} : Maybe<&2, List<&2, U32>>},
114 first_value: @+index: U32 -> @inside: {Nat.is_lt(U32.to_nat(index), Shape.logical_numel(Shape.dimensions(left))) == True{} : Bool} ->
115 {TensorBackward.sole_point(first_of(pass), index) == left_cell(index) : Maybe<&2, F32>},
116 second_target: {TensorBackward.sole_target(second_of(pass)) == Some{b} : Maybe<&2, Nat>},
117 second_dimensions: {TensorBackward.sole_dimensions(second_of(pass)) == Some{Shape.dimensions(right)} : Maybe<&2, List<&2, U32>>},
118 second_value: @+index: U32 -> @inside: {Nat.is_lt(U32.to_nat(index), Shape.logical_numel(Shape.dimensions(right))) == True{} : Bool} ->
119 {TensorBackward.sole_point(second_of(pass), index) == right_cell(index) : Maybe<&2, F32>}}
120
121
122
123
124
125
126
127law tensor_add_vjp_values:
128 for +a: Nat
129 for +b: Nat
130 for +left: Shape.Shape
131 for +right: Shape.Shape
132 for +shape: Shape.Shape
133 for +left_plan: Shape.BroadcastPlan
134 for left_planned: {Shape.broadcast_checked(left, shape) == Done{left_plan} : Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
135 for left_same: {Shape.dimensions(Shape.output_shape(left_plan)) == Shape.dimensions(shape) : List<&2, U32>}
136 for +right_plan: Shape.BroadcastPlan
137 for right_planned: {Shape.broadcast_checked(right, shape) == Done{right_plan} : Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
138 for right_same: {Shape.dimensions(Shape.output_shape(right_plan)) == Shape.dimensions(shape) : List<&2, U32>}
139 for saved: Backward.Saved
140 for +fill: F32
141 for +ops: List<&2, StorageLaws.Op>
142 for -fits: {Lifecycle.logical_length(Replayed.storage(shape, fill, ops)) == Shape.logical_numel(Shape.dimensions(shape)) : Nat}
143 PairContract<a, left, index => reduced(left, shape, left_plan, Contracts.words(shape, fill, ops, Shape.logical_numel(Shape.dimensions(shape))), index),
144 b, right, index => reduced(right, shape, right_plan, Contracts.words(shape, fill, ops, Shape.logical_numel(Shape.dimensions(shape))), index),
145 Backward.vjp(Backward.Add{a, b, left, right}, saved, Core.Packed{shape, Core.TTensor{Replayed.storage(shape, fill, ops), fits}})>
146
147
148
149
150
151
152law tensor_sub_vjp_values:
153 for +a: Nat
154 for +b: Nat
155 for +left: Shape.Shape
156 for +right: Shape.Shape
157 for +shape: Shape.Shape
158 for +left_plan: Shape.BroadcastPlan
159 for left_planned: {Shape.broadcast_checked(left, shape) == Done{left_plan} : Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
160 for left_same: {Shape.dimensions(Shape.output_shape(left_plan)) == Shape.dimensions(shape) : List<&2, U32>}
161 for +negated: Shape.BroadcastPlan
162 for negated_planned: {Shape.broadcast_checked(shape, Reduction.scalar_shape()) == Done{negated} :
163 Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
164 for +right_plan: Shape.BroadcastPlan
165 for right_planned: {Shape.broadcast_checked(right, Shape.output_shape(negated)) == Done{right_plan} :
166 Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
167 for right_same: {Shape.dimensions(Shape.output_shape(right_plan)) == Shape.dimensions(Shape.output_shape(negated)) : List<&2, U32>}
168 for saved: Backward.Saved
169 for +fill: F32
170 for +ops: List<&2, StorageLaws.Op>
171 for -fits: {Lifecycle.logical_length(Replayed.storage(shape, fill, ops)) == Shape.logical_numel(Shape.dimensions(shape)) : Nat}
172 PairContract<a, left, index => reduced(left, shape, left_plan, Contracts.words(shape, fill, ops, Shape.logical_numel(Shape.dimensions(shape))), index),
173 b, right, index => reduced(right, Shape.output_shape(negated), right_plan,
174 cells(Elementwise.NegateLeft{}, negated, shape, fill, ops, Reduction.scalar_shape(), 0.0, Nil{},
175 Shape.logical_numel(Shape.dimensions(Shape.output_shape(negated)))), index),
176 Backward.vjp(Backward.Sub{a, b, left, right}, saved, Core.Packed{shape, Core.TTensor{Replayed.storage(shape, fill, ops), fits}})>
177
178
179
180
181
182
183law tensor_mul_vjp_values:
184 for +a: Nat
185 for +b: Nat
186 for +left: Shape.Shape
187 for +right: Shape.Shape
188 for +shape: Shape.Shape
189 for +first: Shape.BroadcastPlan
190 for first_planned: {Shape.broadcast_checked(shape, right) == Done{first} : Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
191 for +left_plan: Shape.BroadcastPlan
192 for left_planned: {Shape.broadcast_checked(left, Shape.output_shape(first)) == Done{left_plan} :
193 Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
194 for left_same: {Shape.dimensions(Shape.output_shape(left_plan)) == Shape.dimensions(Shape.output_shape(first)) : List<&2, U32>}
195 for +second: Shape.BroadcastPlan
196 for second_planned: {Shape.broadcast_checked(shape, left) == Done{second} : Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
197 for +right_plan: Shape.BroadcastPlan
198 for right_planned: {Shape.broadcast_checked(right, Shape.output_shape(second)) == Done{right_plan} :
199 Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
200 for right_same: {Shape.dimensions(Shape.output_shape(right_plan)) == Shape.dimensions(Shape.output_shape(second)) : List<&2, U32>}
201 for +fill: F32
202 for +ops: List<&2, StorageLaws.Op>
203 for -fits: {Lifecycle.logical_length(Replayed.storage(shape, fill, ops)) == Shape.logical_numel(Shape.dimensions(shape)) : Nat}
204 for +left_fill: F32
205 for +left_ops: List<&2, StorageLaws.Op>
206 for -left_fits: {Lifecycle.logical_length(Replayed.storage(left, left_fill, left_ops)) == Shape.logical_numel(Shape.dimensions(left)) : Nat}
207 for +right_fill: F32
208 for +right_ops: List<&2, StorageLaws.Op>
209 for -right_fits: {Lifecycle.logical_length(Replayed.storage(right, right_fill, right_ops)) == Shape.logical_numel(Shape.dimensions(right)) : Nat}
210 PairContract<a, left, index => reduced(left, Shape.output_shape(first), left_plan,
211 cells(Elementwise.Mul{}, first, shape, fill, ops, right, right_fill, right_ops, Shape.logical_numel(Shape.dimensions(Shape.output_shape(first)))),
212 index),
213 b, right, index => reduced(right, Shape.output_shape(second), right_plan,
214 cells(Elementwise.Mul{}, second, shape, fill, ops, left, left_fill, left_ops, Shape.logical_numel(Shape.dimensions(Shape.output_shape(second)))),
215 index),
216 Backward.vjp(Backward.Mul{a, b, left, right},
217 Backward.Operands{Core.Packed{left, Core.TTensor{Replayed.storage(left, left_fill, left_ops), left_fits}},
218 Core.Packed{right, Core.TTensor{Replayed.storage(right, right_fill, right_ops), right_fits}}},
219 Core.Packed{shape, Core.TTensor{Replayed.storage(shape, fill, ops), fits}})>
220
221
222
223def swapped(+shape: Shape.Shape) -> List<&2, U32>:
224 Transpose.swapped_axes(shape, 0, 1)
225
226def transposed(+shape: Shape.Shape, +plan: Layout.Plan<shape, swapped(shape)>) -> Shape.Shape:
227 Layout.output(shape, swapped(shape), plan)
228
229
230
231
232
233def right_transposed_factors(+row: Nat, +column: Nat, +inner: Nat, +columns: Nat,
234 +left: Shape.Shape, +left_fill: F32, +left_ops: List<&2, StorageLaws.Op>,
235 +right: Shape.Shape, +right_fill: F32, +right_ops: List<&2, StorageLaws.Op>, +axes: List<&2, U32>, +count: Nat) ->
236 List<&2, DotFold.Factors>:
237 match count:
238 case 0n:
239 Nil{}
240 case 1n+previous:
241 List.append(&2, DotFold.Factors,
242 right_transposed_factors(row, column, inner, columns, left, left_fill, left_ops, right, right_fill, right_ops, axes, previous),
243 [DotFold.Factors{Replayed.value(left, left_fill, left_ops, U32.from_nat(Nat.add(Nat.mul(row, inner), previous))),
244 Replayed.value(right, right_fill, right_ops,
245 U32.from_nat(Values.permute_source_index(right, axes, Nat.add(Nat.mul(previous, columns), column))))}])
246
247
248
249
250
251def left_transposed_factors(+row: Nat, +column: Nat, +inner: Nat, +columns: Nat,
252 +left: Shape.Shape, +left_fill: F32, +left_ops: List<&2, StorageLaws.Op>, +axes: List<&2, U32>,
253 +right: Shape.Shape, +right_fill: F32, +right_ops: List<&2, StorageLaws.Op>, +count: Nat) -> List<&2, DotFold.Factors>:
254 match count:
255 case 0n:
256 Nil{}
257 case 1n+previous:
258 List.append(&2, DotFold.Factors,
259 left_transposed_factors(row, column, inner, columns, left, left_fill, left_ops, axes, right, right_fill, right_ops, previous),
260 [DotFold.Factors{Replayed.value(left, left_fill, left_ops,
261 U32.from_nat(Values.permute_source_index(left, axes, Nat.add(Nat.mul(row, inner), previous)))),
262 Replayed.value(right, right_fill, right_ops, U32.from_nat(Nat.add(Nat.mul(previous, columns), column)))}])
263
264
265
266
267
268type MatmulPairContract<-a: Nat, -left: Shape.Shape, -left_rows: Nat, -left_columns: Nat, -left_cell: Nat -> Nat -> F32,
269 -b: Nat, -right: Shape.Shape, -right_rows: Nat, -right_columns: Nat, -right_cell: Nat -> Nat -> F32, -pass: Backward.Pass> is Type:
270 MatmulPairContract{
271 first_target: {TensorBackward.sole_target(first_of(pass)) == Some{a} : Maybe<&2, Nat>},
272 first_dimensions: {TensorBackward.sole_dimensions(first_of(pass)) == Some{Shape.dimensions(left)} : Maybe<&2, List<&2, U32>>},
273 first_value: @+row: Nat -> @row_below: {Nat.is_lt(row, left_rows) == True{} : Bool} ->
274 @+column: Nat -> @column_below: {Nat.is_lt(column, left_columns) == True{} : Bool} ->
275 {TensorBackward.sole_point(first_of(pass), U32.from_nat(Nat.add(Nat.mul(row, left_columns), column))) ==
276 Some{left_cell(row, column)} : Maybe<&2, F32>},
277 second_target: {TensorBackward.sole_target(second_of(pass)) == Some{b} : Maybe<&2, Nat>},
278 second_dimensions: {TensorBackward.sole_dimensions(second_of(pass)) == Some{Shape.dimensions(right)} : Maybe<&2, List<&2, U32>>},
279 second_value: @+row: Nat -> @row_below: {Nat.is_lt(row, right_rows) == True{} : Bool} ->
280 @+column: Nat -> @column_below: {Nat.is_lt(column, right_columns) == True{} : Bool} ->
281 {TensorBackward.sole_point(second_of(pass), U32.from_nat(Nat.add(Nat.mul(row, right_columns), column))) ==
282 Some{right_cell(row, column)} : Maybe<&2, F32>}}
283
284
285
286
287
288
289
290
291
292law tensor_matmul_vjp_values:
293 for +a: Nat
294 for +b: Nat
295 for +left: Shape.Shape
296 for +right: Shape.Shape
297 for +shape: Shape.Shape
298 for right_inside: {True{} == Transpose.valid(right, 0, 1) : Bool}
299 for +right_plan: Layout.Plan<right, swapped(right)>
300 for right_laid: {Layout.permutation(right, swapped(right)) == Done{right_plan} : Result<&2, &2, Layout.Error, Layout.Plan<right, swapped(right)>>}
301 for +first: Matrix.Plan<shape, transposed(right, right_plan)>
302 for first_planned: {Matrix.plan(shape, transposed(right, right_plan)) == Done{first} :
303 Result<&2, &2, Matrix.Error, Matrix.Plan<shape, transposed(right, right_plan)>>}
304 for first_same: {Shape.dimensions(Matrix.output_shape(shape, transposed(right, right_plan), first)) == Shape.dimensions(left) : List<&2, U32>}
305 for left_inside: {True{} == Transpose.valid(left, 0, 1) : Bool}
306 for +left_plan: Layout.Plan<left, swapped(left)>
307 for left_laid: {Layout.permutation(left, swapped(left)) == Done{left_plan} : Result<&2, &2, Layout.Error, Layout.Plan<left, swapped(left)>>}
308 for +second: Matrix.Plan<transposed(left, left_plan), shape>
309 for second_planned: {Matrix.plan(transposed(left, left_plan), shape) == Done{second} :
310 Result<&2, &2, Matrix.Error, Matrix.Plan<transposed(left, left_plan), shape>>}
311 for second_same: {Shape.dimensions(Matrix.output_shape(transposed(left, left_plan), shape, second)) == Shape.dimensions(right) : List<&2, U32>}
312 for +fill: F32
313 for +ops: List<&2, StorageLaws.Op>
314 for -fits: {Lifecycle.logical_length(Replayed.storage(shape, fill, ops)) == Shape.logical_numel(Shape.dimensions(shape)) : Nat}
315 for +left_fill: F32
316 for +left_ops: List<&2, StorageLaws.Op>
317 for -left_fits: {Lifecycle.logical_length(Replayed.storage(left, left_fill, left_ops)) == Shape.logical_numel(Shape.dimensions(left)) : Nat}
318 for +right_fill: F32
319 for +right_ops: List<&2, StorageLaws.Op>
320 for -right_fits: {Lifecycle.logical_length(Replayed.storage(right, right_fill, right_ops)) == Shape.logical_numel(Shape.dimensions(right)) : Nat}
321 MatmulPairContract<a, left,
322 Contracts.matrix_rows(shape, transposed(right, right_plan), first), Contracts.matrix_columns(shape, transposed(right, right_plan), first),
323 row => column => DotFold.dot_fold(right_transposed_factors(row, column,
324 Contracts.matrix_inner(shape, transposed(right, right_plan), first), Contracts.matrix_columns(shape, transposed(right, right_plan), first),
325 shape, fill, ops, right, right_fill, right_ops, swapped(right), Contracts.matrix_inner(shape, transposed(right, right_plan), first)), 0.0),
326 b, right,
327 Contracts.matrix_rows(transposed(left, left_plan), shape, second), Contracts.matrix_columns(transposed(left, left_plan), shape, second),
328 row => column => DotFold.dot_fold(left_transposed_factors(row, column,
329 Contracts.matrix_inner(transposed(left, left_plan), shape, second), Contracts.matrix_columns(transposed(left, left_plan), shape, second),
330 left, left_fill, left_ops, swapped(left), shape, fill, ops, Contracts.matrix_inner(transposed(left, left_plan), shape, second)), 0.0),
331 Backward.vjp(Backward.Matmul{a, b, left, right},
332 Backward.Operands{Core.Packed{left, Core.TTensor{Replayed.storage(left, left_fill, left_ops), left_fits}},
333 Core.Packed{right, Core.TTensor{Replayed.storage(right, right_fill, right_ops), right_fits}}},
334 Core.Packed{shape, Core.TTensor{Replayed.storage(shape, fill, ops), fits}})>
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349law tensor_matmul_nt_vjp_values:
350 for +a: Nat
351 for +b: Nat
352 for +left: Shape.Shape
353 for +right: Shape.Shape
354 for +shape: Shape.Shape
355 for +first: Matrix.Plan<shape, right>
356 for first_planned: {Matrix.plan(shape, right) == Done{first} : Result<&2, &2, Matrix.Error, Matrix.Plan<shape, right>>}
357 for first_same: {Shape.dimensions(Matrix.output_shape(shape, right, first)) == Shape.dimensions(left) : List<&2, U32>}
358 for +second: Matrix.Product<Matrix.Swapped{}, Matrix.Swapped{}, shape, left>
359 for second_planned: {Matrix.product_plan(Matrix.Swapped{}, Matrix.Swapped{}, shape, left) == Done{second} :
360 Result<&2, &2, Matrix.Error, Matrix.Product<Matrix.Swapped{}, Matrix.Swapped{}, shape, left>>}
361 for second_same: {Shape.dimensions(Matrix.product_shape(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second)) ==
362 Shape.dimensions(right) : List<&2, U32>}
363 for +fill: F32
364 for +ops: List<&2, StorageLaws.Op>
365 for -fits: {Lifecycle.logical_length(Replayed.storage(shape, fill, ops)) == Shape.logical_numel(Shape.dimensions(shape)) : Nat}
366 for +left_fill: F32
367 for +left_ops: List<&2, StorageLaws.Op>
368 for -left_fits: {Lifecycle.logical_length(Replayed.storage(left, left_fill, left_ops)) == Shape.logical_numel(Shape.dimensions(left)) : Nat}
369 for +right_fill: F32
370 for +right_ops: List<&2, StorageLaws.Op>
371 for -right_fits: {Lifecycle.logical_length(Replayed.storage(right, right_fill, right_ops)) == Shape.logical_numel(Shape.dimensions(right)) : Nat}
372 MatmulPairContract<a, left, Contracts.matrix_rows(shape, right, first), Contracts.matrix_columns(shape, right, first),
373 row => column => DotFold.dot_fold(Contracts.factors(row, column,
374 Contracts.matrix_inner(shape, right, first), Contracts.matrix_columns(shape, right, first),
375 shape, fill, ops, right, right_fill, right_ops, Contracts.matrix_inner(shape, right, first)), 0.0),
376 b, right,
377 Contracts.product_rows(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second),
378 Contracts.product_columns(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second),
379 row => column => DotFold.dot_fold(Contracts.product_factors(row, column, Matrix.Swapped{}, Matrix.Swapped{},
380 Contracts.product_inner(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second),
381 Contracts.product_rows(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second),
382 Contracts.product_columns(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second),
383 shape, fill, ops, left, left_fill, left_ops, Contracts.product_inner(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second)), 0.0),
384 Backward.vjp(Backward.MatmulNT{a, b, left, right},
385 Backward.Operands{Core.Packed{left, Core.TTensor{Replayed.storage(left, left_fill, left_ops), left_fits}},
386 Core.Packed{right, Core.TTensor{Replayed.storage(right, right_fill, right_ops), right_fits}}},
387 Core.Packed{shape, Core.TTensor{Replayed.storage(shape, fill, ops), fits}})>
388
389
390
391
392type MatmulSoleContract<-b: Nat, -target: Shape.Shape, -rows: Nat, -columns: Nat, -cell: Nat -> Nat -> F32,
393 -pass: Backward.Pass> is Type:
394 MatmulSoleContract{
395 target_id: {TensorBackward.sole_target(TensorBackward.sole(pass)) == Some{b} : Maybe<&2, Nat>},
396 dimensions: {TensorBackward.sole_dimensions(TensorBackward.sole(pass)) == Some{Shape.dimensions(target)} : Maybe<&2, List<&2, U32>>},
397 value: @+row: Nat -> @row_below: {Nat.is_lt(row, rows) == True{} : Bool} ->
398 @+column: Nat -> @column_below: {Nat.is_lt(column, columns) == True{} : Bool} ->
399 {TensorBackward.sole_point(TensorBackward.sole(pass), U32.from_nat(Nat.add(Nat.mul(row, columns), column))) ==
400 Some{cell(row, column)} : Maybe<&2, F32>}}
401
402
403
404
405
406
407
408law tensor_matmul_nt_frozen_vjp_values:
409 for +a: Nat
410 for +b: Nat
411 for apart: {Nat.is_eq(a, b) == False{} : Bool}
412 for +left: Shape.Shape
413 for +right: Shape.Shape
414 for +shape: Shape.Shape
415 for +second: Matrix.Product<Matrix.Swapped{}, Matrix.Swapped{}, shape, left>
416 for second_planned: {Matrix.product_plan(Matrix.Swapped{}, Matrix.Swapped{}, shape, left) == Done{second} :
417 Result<&2, &2, Matrix.Error, Matrix.Product<Matrix.Swapped{}, Matrix.Swapped{}, shape, left>>}
418 for second_same: {Shape.dimensions(Matrix.product_shape(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second)) ==
419 Shape.dimensions(right) : List<&2, U32>}
420 for +fill: F32
421 for +ops: List<&2, StorageLaws.Op>
422 for -fits: {Lifecycle.logical_length(Replayed.storage(shape, fill, ops)) == Shape.logical_numel(Shape.dimensions(shape)) : Nat}
423 for +left_fill: F32
424 for +left_ops: List<&2, StorageLaws.Op>
425 for -left_fits: {Lifecycle.logical_length(Replayed.storage(left, left_fill, left_ops)) == Shape.logical_numel(Shape.dimensions(left)) : Nat}
426 for +right_fill: F32
427 for +right_ops: List<&2, StorageLaws.Op>
428 for -right_fits: {Lifecycle.logical_length(Replayed.storage(right, right_fill, right_ops)) == Shape.logical_numel(Shape.dimensions(right)) : Nat}
429 MatmulSoleContract<b, right,
430 Contracts.product_rows(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second),
431 Contracts.product_columns(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second),
432 row => column => DotFold.dot_fold(Contracts.product_factors(row, column, Matrix.Swapped{}, Matrix.Swapped{},
433 Contracts.product_inner(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second),
434 Contracts.product_rows(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second),
435 Contracts.product_columns(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second),
436 shape, fill, ops, left, left_fill, left_ops, Contracts.product_inner(Matrix.Swapped{}, Matrix.Swapped{}, shape, left, second)), 0.0),
437 Backward.vjp(Backward.Frozen{a, Backward.MatmulNT{a, b, left, right}},
438 Backward.Operands{Core.Packed{left, Core.TTensor{Replayed.storage(left, left_fill, left_ops), left_fits}},
439 Core.Packed{right, Core.TTensor{Replayed.storage(right, right_fill, right_ops), right_fits}}},
440 Core.Packed{shape, Core.TTensor{Replayed.storage(shape, fill, ops), fits}})>
441
442
443
444
445
446
447
448
449law nt_reads_transpose:
450 for +row: Nat
451 for +column: Nat
452 for +rows: Nat
453 for +left: Shape.Shape
454 for +left_fill: F32
455 for +left_ops: List<&2, StorageLaws.Op>
456 for +right: Shape.Shape
457 for +right_fill: F32
458 for +right_ops: List<&2, StorageLaws.Op>
459 for +columns: U32
460 for +inner: U32
461 for matrix: {Shape.dimensions(right) == [columns, inner] : List<&2, U32>}
462 for column_below: {Nat.is_lt(column, U32.to_nat(columns)) == True{} : Bool}
463 for +count: Nat
464 for room: {Nat.is_le(count, U32.to_nat(inner)) == True{} : Bool}
465 {Contracts.product_factors(row, column, Matrix.Kept{}, Matrix.Kept{}, U32.to_nat(inner), rows, U32.to_nat(columns),
466 left, left_fill, left_ops, right, right_fill, right_ops, count) ==
467 right_transposed_factors(row, column, U32.to_nat(inner), U32.to_nat(columns), left, left_fill, left_ops,
468 right, right_fill, right_ops, swapped(right), count) : List<&2, DotFold.Factors>}
469
470
471
472
473
474
475law tn_reads_transpose:
476 for +row: Nat
477 for +column: Nat
478 for +columns: Nat
479 for +left: Shape.Shape
480 for +left_fill: F32
481 for +left_ops: List<&2, StorageLaws.Op>
482 for +right: Shape.Shape
483 for +right_fill: F32
484 for +right_ops: List<&2, StorageLaws.Op>
485 for +inner: U32
486 for +rows: U32
487 for matrix: {Shape.dimensions(left) == [inner, rows] : List<&2, U32>}
488 for row_below: {Nat.is_lt(row, U32.to_nat(rows)) == True{} : Bool}
489 for +count: Nat
490 for room: {Nat.is_le(count, U32.to_nat(inner)) == True{} : Bool}
491 {Contracts.product_factors(row, column, Matrix.Swapped{}, Matrix.Swapped{}, U32.to_nat(inner), U32.to_nat(rows), columns,
492 left, left_fill, left_ops, right, right_fill, right_ops, count) ==
493 left_transposed_factors(row, column, U32.to_nat(inner), columns, left, left_fill, left_ops, swapped(left),
494 right, right_fill, right_ops, count) : List<&2, DotFold.Factors>}
495
496
497
498type OneContract<-a: Nat, -target: Shape.Shape, -cell: U32 -> Maybe<&2, F32>, -pass: Backward.Pass> is Type:
499 OneContract{
500 target_id: {TensorBackward.sole_target(TensorBackward.sole(pass)) == Some{a} : Maybe<&2, Nat>},
501 dimensions: {TensorBackward.sole_dimensions(TensorBackward.sole(pass)) == Some{Shape.dimensions(target)} : Maybe<&2, List<&2, U32>>},
502 value: @+index: U32 -> @inside: {Nat.is_lt(U32.to_nat(index), Shape.logical_numel(Shape.dimensions(target))) == True{} : Bool} ->
503 {TensorBackward.sole_point(TensorBackward.sole(pass), index) == cell(index) : Maybe<&2, F32>}}
504
505
506
507
508
509
510
511
512law tensor_relu_vjp_values:
513 for +a: Nat
514 for +input: Shape.Shape
515 for +shape: Shape.Shape
516 for +plan: Shape.BroadcastPlan
517 for planned: {Shape.broadcast_checked(input, shape) == Done{plan} : Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
518 for +input_plan: Shape.BroadcastPlan
519 for input_planned: {Shape.broadcast_checked(input, Shape.output_shape(plan)) == Done{input_plan} :
520 Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
521 for input_same: {Shape.dimensions(Shape.output_shape(input_plan)) == Shape.dimensions(Shape.output_shape(plan)) : List<&2, U32>}
522 for zero: Core.Dynamic
523 for +fill: F32
524 for +ops: List<&2, StorageLaws.Op>
525 for -fits: {Lifecycle.logical_length(Replayed.storage(shape, fill, ops)) == Shape.logical_numel(Shape.dimensions(shape)) : Nat}
526 for +input_fill: F32
527 for +input_ops: List<&2, StorageLaws.Op>
528 for -input_fits: {Lifecycle.logical_length(Replayed.storage(input, input_fill, input_ops)) == Shape.logical_numel(Shape.dimensions(input)) : Nat}
529 OneContract<a, input, index => reduced(input, Shape.output_shape(plan), input_plan,
530 cells(Elementwise.ReluBackward{}, plan, input, input_fill, input_ops, shape, fill, ops,
531 Shape.logical_numel(Shape.dimensions(Shape.output_shape(plan)))),
532 index),
533 Backward.vjp(Backward.Relu{a, input},
534 Backward.Operands{Core.Packed{input, Core.TTensor{Replayed.storage(input, input_fill, input_ops), input_fits}}, zero},
535 Core.Packed{shape, Core.TTensor{Replayed.storage(shape, fill, ops), fits}})>
536
537
538
539
540
541
542
543
544
545law tensor_mse_vjp_values:
546 for +a: Nat
547 for +b: Nat
548 for +left: Shape.Shape
549 for +right: Shape.Shape
550 for +diff: Shape.Shape
551 for +shape: Shape.Shape
552 for +plan: Shape.BroadcastPlan
553 for planned: {Shape.broadcast_checked(shape, diff) == Done{plan} : Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
554 for +left_plan: Shape.BroadcastPlan
555 for left_planned: {Shape.broadcast_checked(left, Shape.output_shape(plan)) == Done{left_plan} :
556 Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
557 for left_same: {Shape.dimensions(Shape.output_shape(left_plan)) == Shape.dimensions(Shape.output_shape(plan)) : List<&2, U32>}
558 for +right_plan: Shape.BroadcastPlan
559 for right_planned: {Shape.broadcast_checked(right, Shape.output_shape(plan)) == Done{right_plan} :
560 Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
561 for right_same: {Shape.dimensions(Shape.output_shape(right_plan)) == Shape.dimensions(Shape.output_shape(plan)) : List<&2, U32>}
562 for +fill: F32
563 for +ops: List<&2, StorageLaws.Op>
564 for -fits: {Lifecycle.logical_length(Replayed.storage(shape, fill, ops)) == Shape.logical_numel(Shape.dimensions(shape)) : Nat}
565 for +e_fill: F32
566 for +e_ops: List<&2, StorageLaws.Op>
567 for -e_fits: {Lifecycle.logical_length(Replayed.storage(diff, e_fill, e_ops)) == Shape.logical_numel(Shape.dimensions(diff)) : Nat}
568 for +d_fill: F32
569 for +d_ops: List<&2, StorageLaws.Op>
570 for -d_fits: {Lifecycle.logical_length(Replayed.storage(diff, d_fill, d_ops)) == Shape.logical_numel(Shape.dimensions(diff)) : Nat}
571 PairContract<a, left, index => reduced(left, Shape.output_shape(plan), left_plan,
572 cells(Elementwise.MseGrad{Loss.mse_scale(diff)}, plan, shape, fill, ops, diff, d_fill, d_ops,
573 Shape.logical_numel(Shape.dimensions(Shape.output_shape(plan)))),
574 index),
575 b, right, index => reduced(right, Shape.output_shape(plan), right_plan,
576 cells(Elementwise.MseGrad{Loss.mse_scale(diff)}, plan, shape, fill, ops, diff, e_fill, e_ops,
577 Shape.logical_numel(Shape.dimensions(Shape.output_shape(plan)))),
578 index),
579 Backward.vjp(Backward.MseLoss{a, b, left, right},
580 Backward.Operands{Core.Packed{diff, Core.TTensor{Replayed.storage(diff, e_fill, e_ops), e_fits}},
581 Core.Packed{diff, Core.TTensor{Replayed.storage(diff, d_fill, d_ops), d_fits}}},
582 Core.Packed{shape, Core.TTensor{Replayed.storage(shape, fill, ops), fits}})>
583
584
585
586
587
588
589
590
591
592
593
594
595
596law tensor_cross_entropy_vjp_values:
597 for +a: Nat
598 for +input: Shape.Shape
599 for +shape: Shape.Shape
600 for +plan: Shape.BroadcastPlan
601 for planned: {Shape.broadcast_checked(shape, input) == Done{plan} : Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
602 for +input_plan: Shape.BroadcastPlan
603 for input_planned: {Shape.broadcast_checked(input, Shape.output_shape(plan)) == Done{input_plan} :
604 Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
605 for input_same: {Shape.dimensions(Shape.output_shape(input_plan)) == Shape.dimensions(Shape.output_shape(plan)) : List<&2, U32>}
606 for +fill: F32
607 for +ops: List<&2, StorageLaws.Op>
608 for -fits: {Lifecycle.logical_length(Replayed.storage(shape, fill, ops)) == Shape.logical_numel(Shape.dimensions(shape)) : Nat}
609 for +lp_fill: F32
610 for +lp_ops: List<&2, StorageLaws.Op>
611 for -lp_fits: {Lifecycle.logical_length(Replayed.storage(input, lp_fill, lp_ops)) == Shape.logical_numel(Shape.dimensions(input)) : Nat}
612 for +hot_fill: F32
613 for +hot_ops: List<&2, StorageLaws.Op>
614 for -hot_fits: {Lifecycle.logical_length(Replayed.storage(input, hot_fill, hot_ops)) == Shape.logical_numel(Shape.dimensions(input)) : Nat}
615 PairContract<a, input, index => reduced(input, Shape.output_shape(plan), input_plan,
616 cells(Elementwise.OneHotGrad{Loss.count_f32(Loss.rows(input))}, plan, shape, fill, ops, input, hot_fill, hot_ops,
617 Shape.logical_numel(Shape.dimensions(Shape.output_shape(plan)))),
618 index),
619 a, input, index => reduced(input, Shape.output_shape(plan), input_plan,
620 cells(Elementwise.SoftmaxGrad{Loss.count_f32(Loss.rows(input)), Loss.one_class(input)}, plan, shape, fill, ops, input, lp_fill, lp_ops,
621 Shape.logical_numel(Shape.dimensions(Shape.output_shape(plan)))),
622 index),
623 Backward.vjp(Backward.CrossEntropy{a, input},
624 Backward.Operands{Core.Packed{input, Core.TTensor{Replayed.storage(input, lp_fill, lp_ops), lp_fits}},
625 Core.Packed{input, Core.TTensor{Replayed.storage(input, hot_fill, hot_ops), hot_fits}}},
626 Core.Packed{shape, Core.TTensor{Replayed.storage(shape, fill, ops), fits}})>