Mercurial > repos > public > sbplib_julia
comparison test/LazyTensors/lazy_tensor_operations_test.jl @ 1101:1e8270c18edb feature/lazy_tensors/pretty_printing
Merge default
author | Jonatan Werpers <jonatan@werpers.com> |
---|---|
date | Thu, 12 May 2022 21:52:47 +0200 |
parents | 2c1a0722ddb9 2e606d4c0ab1 |
children |
comparison
equal
deleted
inserted
replaced
1014:67969bd7e642 | 1101:1e8270c18edb |
---|---|
34 @test range_size(m') == :domain_size | 34 @test range_size(m') == :domain_size |
35 @test domain_size(m') == :range_size | 35 @test domain_size(m') == :range_size |
36 end | 36 end |
37 | 37 |
38 | 38 |
39 @testset "LazyTensorApplication" begin | 39 @testset "TensorApplication" begin |
40 m = SizeDoublingMapping{Int, 1, 1}((3,)) | 40 m = SizeDoublingMapping{Int, 1, 1}((3,)) |
41 mm = SizeDoublingMapping{Int, 1, 1}((6,)) | 41 mm = SizeDoublingMapping{Int, 1, 1}((6,)) |
42 v = [0,1,2] | 42 v = [0,1,2] |
43 @test size(m*v) == 2 .*size(v) | 43 @test size(m*v) == 2 .*size(v) |
44 @test (m*v)[1] == (:apply,v,(1,)) | 44 @test (m*v)[1] == (:apply,v,(1,)) |
157 @test_throws RangeSizeMismatch SizeDoublingMapping{Float64,1,1}((2,)) + ScalingTensor(2.0, (2,)) | 157 @test_throws RangeSizeMismatch SizeDoublingMapping{Float64,1,1}((2,)) + ScalingTensor(2.0, (2,)) |
158 end | 158 end |
159 end | 159 end |
160 | 160 |
161 | 161 |
162 @testset "LazyTensorComposition" begin | 162 @testset "TensorComposition" begin |
163 A = rand(2,3) | 163 A = rand(2,3) |
164 B = rand(3,4) | 164 B = rand(3,4) |
165 | 165 |
166 Ã = LazyLinearMap(A, (1,), (2,)) | 166 Ã = DenseTensor(A, (1,), (2,)) |
167 B̃ = LazyLinearMap(B, (1,), (2,)) | 167 B̃ = DenseTensor(B, (1,), (2,)) |
168 | 168 |
169 @test Ã∘B̃ isa LazyTensorComposition | 169 @test Ã∘B̃ isa TensorComposition |
170 @test range_size(Ã∘B̃) == (2,) | 170 @test range_size(Ã∘B̃) == (2,) |
171 @test domain_size(Ã∘B̃) == (4,) | 171 @test domain_size(Ã∘B̃) == (4,) |
172 @test_throws DomainSizeMismatch B̃∘Ã | 172 @test_throws DomainSizeMismatch B̃∘Ã |
173 | 173 |
174 # @test @inbounds B̃∘Ã # Should not error even though dimensions don't match. (Since ]test runs with forced boundschecking this is currently not testable 2020-10-16) | 174 # @test @inbounds B̃∘Ã # Should not error even though dimensions don't match. (Since ]test runs with forced boundschecking this is currently not testable 2020-10-16) |
179 v = rand(2) | 179 v = rand(2) |
180 @test (Ã∘B̃)'*v ≈ B'*A'*v rtol=1e-14 | 180 @test (Ã∘B̃)'*v ≈ B'*A'*v rtol=1e-14 |
181 | 181 |
182 @test (Ã∘B̃*ComplexF64[1.,2.,3.,4.])[1] isa ComplexF64 | 182 @test (Ã∘B̃*ComplexF64[1.,2.,3.,4.])[1] isa ComplexF64 |
183 @test ((Ã∘B̃)'*ComplexF64[1.,2.])[1] isa ComplexF64 | 183 @test ((Ã∘B̃)'*ComplexF64[1.,2.])[1] isa ComplexF64 |
184 end | 184 |
185 | 185 a = 2. |
186 | 186 v = rand(3) |
187 @testset "InflatedLazyTensor" begin | 187 @test a*Ã isa TensorComposition |
188 @test a*Ã == Ã*a | |
189 @test range_size(a*Ã) == range_size(Ã) | |
190 @test domain_size(a*Ã) == domain_size(Ã) | |
191 @test a*Ã*v == a.*A*v | |
192 end | |
193 | |
194 | |
195 @testset "InflatedTensor" begin | |
188 I(sz...) = IdentityTensor(sz...) | 196 I(sz...) = IdentityTensor(sz...) |
189 | 197 |
190 Ã = rand(4,2) | 198 Ã = rand(4,2) |
191 B̃ = rand(4,2,3) | 199 B̃ = rand(4,2,3) |
192 C̃ = rand(4,2,3) | 200 C̃ = rand(4,2,3) |
193 | 201 |
194 A = LazyLinearMap(Ã,(1,),(2,)) | 202 A = DenseTensor(Ã,(1,),(2,)) |
195 B = LazyLinearMap(B̃,(1,2),(3,)) | 203 B = DenseTensor(B̃,(1,2),(3,)) |
196 C = LazyLinearMap(C̃,(1,),(2,3)) | 204 C = DenseTensor(C̃,(1,),(2,3)) |
197 | 205 |
198 @testset "Constructors" begin | 206 @testset "Constructors" begin |
199 @test InflatedLazyTensor(I(3,2), A, I(4)) isa LazyTensor{Float64, 4, 4} | 207 @test InflatedTensor(I(3,2), A, I(4)) isa LazyTensor{Float64, 4, 4} |
200 @test InflatedLazyTensor(I(3,2), B, I(4)) isa LazyTensor{Float64, 5, 4} | 208 @test InflatedTensor(I(3,2), B, I(4)) isa LazyTensor{Float64, 5, 4} |
201 @test InflatedLazyTensor(I(3), C, I(2,3)) isa LazyTensor{Float64, 4, 5} | 209 @test InflatedTensor(I(3), C, I(2,3)) isa LazyTensor{Float64, 4, 5} |
202 @test InflatedLazyTensor(C, I(2,3)) isa LazyTensor{Float64, 3, 4} | 210 @test InflatedTensor(C, I(2,3)) isa LazyTensor{Float64, 3, 4} |
203 @test InflatedLazyTensor(I(3), C) isa LazyTensor{Float64, 2, 3} | 211 @test InflatedTensor(I(3), C) isa LazyTensor{Float64, 2, 3} |
204 @test InflatedLazyTensor(I(3), I(2,3)) isa LazyTensor{Float64, 3, 3} | 212 @test InflatedTensor(I(3), I(2,3)) isa LazyTensor{Float64, 3, 3} |
205 end | 213 end |
206 | 214 |
207 @testset "Range and domain size" begin | 215 @testset "Range and domain size" begin |
208 @test range_size(InflatedLazyTensor(I(3,2), A, I(4))) == (3,2,4,4) | 216 @test range_size(InflatedTensor(I(3,2), A, I(4))) == (3,2,4,4) |
209 @test domain_size(InflatedLazyTensor(I(3,2), A, I(4))) == (3,2,2,4) | 217 @test domain_size(InflatedTensor(I(3,2), A, I(4))) == (3,2,2,4) |
210 | 218 |
211 @test range_size(InflatedLazyTensor(I(3,2), B, I(4))) == (3,2,4,2,4) | 219 @test range_size(InflatedTensor(I(3,2), B, I(4))) == (3,2,4,2,4) |
212 @test domain_size(InflatedLazyTensor(I(3,2), B, I(4))) == (3,2,3,4) | 220 @test domain_size(InflatedTensor(I(3,2), B, I(4))) == (3,2,3,4) |
213 | 221 |
214 @test range_size(InflatedLazyTensor(I(3), C, I(2,3))) == (3,4,2,3) | 222 @test range_size(InflatedTensor(I(3), C, I(2,3))) == (3,4,2,3) |
215 @test domain_size(InflatedLazyTensor(I(3), C, I(2,3))) == (3,2,3,2,3) | 223 @test domain_size(InflatedTensor(I(3), C, I(2,3))) == (3,2,3,2,3) |
216 | 224 |
217 @inferred range_size(InflatedLazyTensor(I(3,2), A, I(4))) == (3,2,4,4) | 225 @inferred range_size(InflatedTensor(I(3,2), A, I(4))) == (3,2,4,4) |
218 @inferred domain_size(InflatedLazyTensor(I(3,2), A, I(4))) == (3,2,2,4) | 226 @inferred domain_size(InflatedTensor(I(3,2), A, I(4))) == (3,2,2,4) |
219 end | 227 end |
220 | 228 |
221 @testset "Application" begin | 229 @testset "Application" begin |
222 # Testing regular application and transposed application with inflation "before", "after" and "before and after". | 230 # Testing regular application and transposed application with inflation "before", "after" and "before and after". |
223 # The inflated tensor mappings are chosen to preserve, reduce and increase the dimension of the result compared to the input. | 231 # The inflated tensor mappings are chosen to preserve, reduce and increase the dimension of the result compared to the input. |
224 tests = [ | 232 cases = [ |
225 ( | 233 ( |
226 InflatedLazyTensor(I(3,2), A, I(4)), | 234 InflatedTensor(I(3,2), A, I(4)), |
227 (v-> @tullio res[a,b,c,d] := Ã[c,i]*v[a,b,i,d]), # Expected result of apply | 235 (v-> @tullio res[a,b,c,d] := Ã[c,i]*v[a,b,i,d]), # Expected result of apply |
228 (v-> @tullio res[a,b,c,d] := Ã[i,c]*v[a,b,i,d]), # Expected result of apply_transpose | 236 (v-> @tullio res[a,b,c,d] := Ã[i,c]*v[a,b,i,d]), # Expected result of apply_transpose |
229 ), | 237 ), |
230 ( | 238 ( |
231 InflatedLazyTensor(I(3,2), B, I(4)), | 239 InflatedTensor(I(3,2), B, I(4)), |
232 (v-> @tullio res[a,b,c,d,e] := B̃[c,d,i]*v[a,b,i,e]), | 240 (v-> @tullio res[a,b,c,d,e] := B̃[c,d,i]*v[a,b,i,e]), |
233 (v-> @tullio res[a,b,c,d] := B̃[i,j,c]*v[a,b,i,j,d]), | 241 (v-> @tullio res[a,b,c,d] := B̃[i,j,c]*v[a,b,i,j,d]), |
234 ), | 242 ), |
235 ( | 243 ( |
236 InflatedLazyTensor(I(3,2), C, I(4)), | 244 InflatedTensor(I(3,2), C, I(4)), |
237 (v-> @tullio res[a,b,c,d] := C̃[c,i,j]*v[a,b,i,j,d]), | 245 (v-> @tullio res[a,b,c,d] := C̃[c,i,j]*v[a,b,i,j,d]), |
238 (v-> @tullio res[a,b,c,d,e] := C̃[i,c,d]*v[a,b,i,e]), | 246 (v-> @tullio res[a,b,c,d,e] := C̃[i,c,d]*v[a,b,i,e]), |
239 ), | 247 ), |
240 ( | 248 ( |
241 InflatedLazyTensor(I(3,2), A), | 249 InflatedTensor(I(3,2), A), |
242 (v-> @tullio res[a,b,c] := Ã[c,i]*v[a,b,i]), | 250 (v-> @tullio res[a,b,c] := Ã[c,i]*v[a,b,i]), |
243 (v-> @tullio res[a,b,c] := Ã[i,c]*v[a,b,i]), | 251 (v-> @tullio res[a,b,c] := Ã[i,c]*v[a,b,i]), |
244 ), | 252 ), |
245 ( | 253 ( |
246 InflatedLazyTensor(I(3,2), B), | 254 InflatedTensor(I(3,2), B), |
247 (v-> @tullio res[a,b,c,d] := B̃[c,d,i]*v[a,b,i]), | 255 (v-> @tullio res[a,b,c,d] := B̃[c,d,i]*v[a,b,i]), |
248 (v-> @tullio res[a,b,c] := B̃[i,j,c]*v[a,b,i,j]), | 256 (v-> @tullio res[a,b,c] := B̃[i,j,c]*v[a,b,i,j]), |
249 ), | 257 ), |
250 ( | 258 ( |
251 InflatedLazyTensor(I(3,2), C), | 259 InflatedTensor(I(3,2), C), |
252 (v-> @tullio res[a,b,c] := C̃[c,i,j]*v[a,b,i,j]), | 260 (v-> @tullio res[a,b,c] := C̃[c,i,j]*v[a,b,i,j]), |
253 (v-> @tullio res[a,b,c,d] := C̃[i,c,d]*v[a,b,i]), | 261 (v-> @tullio res[a,b,c,d] := C̃[i,c,d]*v[a,b,i]), |
254 ), | 262 ), |
255 ( | 263 ( |
256 InflatedLazyTensor(A,I(4)), | 264 InflatedTensor(A,I(4)), |
257 (v-> @tullio res[a,b] := Ã[a,i]*v[i,b]), | 265 (v-> @tullio res[a,b] := Ã[a,i]*v[i,b]), |
258 (v-> @tullio res[a,b] := Ã[i,a]*v[i,b]), | 266 (v-> @tullio res[a,b] := Ã[i,a]*v[i,b]), |
259 ), | 267 ), |
260 ( | 268 ( |
261 InflatedLazyTensor(B,I(4)), | 269 InflatedTensor(B,I(4)), |
262 (v-> @tullio res[a,b,c] := B̃[a,b,i]*v[i,c]), | 270 (v-> @tullio res[a,b,c] := B̃[a,b,i]*v[i,c]), |
263 (v-> @tullio res[a,b] := B̃[i,j,a]*v[i,j,b]), | 271 (v-> @tullio res[a,b] := B̃[i,j,a]*v[i,j,b]), |
264 ), | 272 ), |
265 ( | 273 ( |
266 InflatedLazyTensor(C,I(4)), | 274 InflatedTensor(C,I(4)), |
267 (v-> @tullio res[a,b] := C̃[a,i,j]*v[i,j,b]), | 275 (v-> @tullio res[a,b] := C̃[a,i,j]*v[i,j,b]), |
268 (v-> @tullio res[a,b,c] := C̃[i,a,b]*v[i,c]), | 276 (v-> @tullio res[a,b,c] := C̃[i,a,b]*v[i,c]), |
269 ), | 277 ), |
270 ] | 278 ] |
271 | 279 |
272 @testset "apply" begin | 280 @testset "$tm" for (tm, true_apply, true_apply_transpose) ∈ cases |
273 for i ∈ 1:length(tests) | 281 v = rand(domain_size(tm)...) |
274 tm = tests[i][1] | 282 @test tm*v ≈ true_apply(v) rtol=1e-14 |
275 v = rand(domain_size(tm)...) | 283 |
276 true_value = tests[i][2](v) | 284 v = rand(range_size(tm)...) |
277 @test tm*v ≈ true_value rtol=1e-14 | 285 @test tm'*v ≈ true_apply_transpose(v) rtol=1e-14 |
278 end | |
279 end | 286 end |
280 | 287 |
281 @testset "apply_transpose" begin | |
282 for i ∈ 1:length(tests) | |
283 tm = tests[i][1] | |
284 v = rand(range_size(tm)...) | |
285 true_value = tests[i][3](v) | |
286 @test tm'*v ≈ true_value rtol=1e-14 | |
287 end | |
288 end | |
289 | |
290 @testset "application to other type" begin | 288 @testset "application to other type" begin |
291 tm = InflatedLazyTensor(I(3,2), A, I(4)) | 289 tm = InflatedTensor(I(3,2), A, I(4)) |
292 | 290 |
293 v = rand(ComplexF64, domain_size(tm)...) | 291 v = rand(ComplexF64, domain_size(tm)...) |
294 @test (tm*v)[1,2,3,1] isa ComplexF64 | 292 @test (tm*v)[1,2,3,1] isa ComplexF64 |
295 | 293 |
296 v = rand(ComplexF64, domain_size(tm')...) | 294 v = rand(ComplexF64, domain_size(tm')...) |
297 @test (tm'*v)[1,2,2,1] isa ComplexF64 | 295 @test (tm'*v)[1,2,2,1] isa ComplexF64 |
298 end | 296 end |
299 | 297 |
300 @testset "Inference of application" begin | 298 @testset "Inference of application" begin |
301 tm = InflatedLazyTensor(I(2,3),ScalingTensor(2.0, (3,2)),I(3,4)) | 299 tm = InflatedTensor(I(2,3),ScalingTensor(2.0, (3,2)),I(3,4)) |
302 v = rand(domain_size(tm)...) | 300 v = rand(domain_size(tm)...) |
303 | 301 |
304 @inferred apply(tm,v,1,2,3,2,2,4) | 302 @inferred apply(tm,v,1,2,3,2,2,4) |
305 @inferred (tm*v)[1,2,3,2,2,4] | 303 @inferred (tm*v)[1,2,3,2,2,4] |
306 end | 304 end |
307 end | 305 end |
308 | 306 |
309 @testset "InflatedLazyTensor of InflatedLazyTensor" begin | 307 @testset "InflatedTensor of InflatedTensor" begin |
310 A = ScalingTensor(2.0,(2,3)) | 308 A = ScalingTensor(2.0,(2,3)) |
311 itm = InflatedLazyTensor(I(3,2), A, I(4)) | 309 itm = InflatedTensor(I(3,2), A, I(4)) |
312 @test InflatedLazyTensor(I(4), itm, I(2)) == InflatedLazyTensor(I(4,3,2), A, I(4,2)) | 310 @test InflatedTensor(I(4), itm, I(2)) == InflatedTensor(I(4,3,2), A, I(4,2)) |
313 @test InflatedLazyTensor(itm, I(2)) == InflatedLazyTensor(I(3,2), A, I(4,2)) | 311 @test InflatedTensor(itm, I(2)) == InflatedTensor(I(3,2), A, I(4,2)) |
314 @test InflatedLazyTensor(I(4), itm) == InflatedLazyTensor(I(4,3,2), A, I(4)) | 312 @test InflatedTensor(I(4), itm) == InflatedTensor(I(4,3,2), A, I(4)) |
315 | 313 |
316 @test InflatedLazyTensor(I(2), I(2), I(2)) isa InflatedLazyTensor # The constructor should always return its type. | 314 @test InflatedTensor(I(2), I(2), I(2)) isa InflatedTensor # The constructor should always return its type. |
317 end | 315 end |
318 | 316 |
319 @testset "Pretty printing" begin | 317 @testset "Pretty printing" begin |
320 cases = [ | 318 cases = [ |
321 InflatedLazyTensor(I(4), ScalingTensor(2., (3,2)), I(2)) => ( | 319 InflatedTensor(I(4), ScalingTensor(2., (3,2)), I(2)) => ( |
322 regular="I(4)⊗ScalingTensor{Float64}(2.0, (3, 2))⊗I(2)", | 320 regular="I(4)⊗ScalingTensor{Float64}(2.0, (3, 2))⊗I(2)", |
323 compact="I(4)⊗2.0*I(3,2)⊗I(2)" | 321 compact="I(4)⊗2.0*I(3,2)⊗I(2)" |
324 ) | 322 ) |
325 ] | 323 ] |
326 | 324 |
357 B = rand(2,4,3) | 355 B = rand(2,4,3) |
358 | 356 |
359 v₁ = rand(2,4,3) | 357 v₁ = rand(2,4,3) |
360 v₂ = rand(4,3,2) | 358 v₂ = rand(4,3,2) |
361 | 359 |
362 Ã = LazyLinearMap(A,(1,),(2,)) | 360 Ã = DenseTensor(A,(1,),(2,)) |
363 B̃ = LazyLinearMap(B,(1,),(2,3)) | 361 B̃ = DenseTensor(B,(1,),(2,3)) |
364 | 362 |
365 ÃB̃ = LazyOuterProduct(Ã,B̃) | 363 ÃB̃ = LazyOuterProduct(Ã,B̃) |
366 @tullio ABv[i,k] := A[i,j]*B[k,l,m]*v₁[j,l,m] | 364 @tullio ABv[i,k] := A[i,j]*B[k,l,m]*v₁[j,l,m] |
367 @test ÃB̃*v₁ ≈ ABv | 365 @test ÃB̃*v₁ ≈ ABv |
368 | 366 |
371 @test B̃Ã*v₂ ≈ BAv | 369 @test B̃Ã*v₂ ≈ BAv |
372 | 370 |
373 @testset "Indentity mapping arguments" begin | 371 @testset "Indentity mapping arguments" begin |
374 @test LazyOuterProduct(IdentityTensor(3,2), IdentityTensor(1,2)) == IdentityTensor(3,2,1,2) | 372 @test LazyOuterProduct(IdentityTensor(3,2), IdentityTensor(1,2)) == IdentityTensor(3,2,1,2) |
375 | 373 |
376 Ã = LazyLinearMap(A,(1,),(2,)) | 374 Ã = DenseTensor(A,(1,),(2,)) |
377 @test LazyOuterProduct(IdentityTensor(3,2), Ã) == InflatedLazyTensor(IdentityTensor(3,2),Ã) | 375 @test LazyOuterProduct(IdentityTensor(3,2), Ã) == InflatedTensor(IdentityTensor(3,2),Ã) |
378 @test LazyOuterProduct(Ã, IdentityTensor(3,2)) == InflatedLazyTensor(Ã,IdentityTensor(3,2)) | 376 @test LazyOuterProduct(Ã, IdentityTensor(3,2)) == InflatedTensor(Ã,IdentityTensor(3,2)) |
379 | 377 |
380 I1 = IdentityTensor(3,2) | 378 I1 = IdentityTensor(3,2) |
381 I2 = IdentityTensor(4) | 379 I2 = IdentityTensor(4) |
382 @test I1⊗Ã⊗I2 == InflatedLazyTensor(I1, Ã, I2) | 380 @test I1⊗Ã⊗I2 == InflatedTensor(I1, Ã, I2) |
383 end | 381 end |
384 end | 382 end |