Mercurial > repos > public > sbplib_julia
comparison src/LazyTensors/lazy_tensor_operations.jl @ 468:a52f38e72258 feature/outer_product
Start implementing function for outer products
author | Jonatan Werpers <jonatan@werpers.com> |
---|---|
date | Thu, 22 Oct 2020 10:18:57 +0200 |
parents | a0e40d16ba0e |
children | 481e86e77c22 |
comparison
equal
deleted
inserted
replaced
461:a0e40d16ba0e | 468:a52f38e72258 |
---|---|
271 Takes a nested tuple and flattens the whole structure | 271 Takes a nested tuple and flattens the whole structure |
272 """ | 272 """ |
273 flatten_tuple(t::NTuple{N, Number} where N) = t | 273 flatten_tuple(t::NTuple{N, Number} where N) = t |
274 flatten_tuple(t::Tuple) = ((flatten_tuple.(t)...)...,) # simplify? | 274 flatten_tuple(t::Tuple) = ((flatten_tuple.(t)...)...,) # simplify? |
275 flatten_tuple(ts::Vararg) = flatten_tuple(ts) | 275 flatten_tuple(ts::Vararg) = flatten_tuple(ts) |
276 | |
277 | |
278 """ | |
279 LazyOuterProduct(tms...) | |
280 | |
281 Creates a `TensorComposition` for the outerproduct of `tms...`. | |
282 This is done by separating the outer product into regular products of outer products involving only identity mappings and one non-identity mapping. | |
283 | |
284 First let | |
285 ```math | |
286 A = A_{I,J} | |
287 B = B_{M,N} | |
288 C = C_{P,Q} | |
289 ``` | |
290 | |
291 where ``I``, ``M``, ``P`` are multi-indexes for the ranges of ``A``, ``B``, ``C``, and ``J``, ``N``, ``Q`` are multi-indexes of the domains. | |
292 | |
293 We use ``⊗`` to denote the outer product | |
294 ```math | |
295 (A⊗B)_{IM,JN} = A_{I,J}B_{M,N} | |
296 ``` | |
297 | |
298 We note that | |
299 ```math | |
300 A⊗B⊗C = (A⊗B⊗C)_{IMP,JNQ} = A_{I,J}B_{M,N}C_{P,Q} | |
301 ``` | |
302 And that | |
303 ```math | |
304 A⊗B⊗C = (A⊗I_{|M|}⊗I_{|P|})(I_{|J|}⊗B⊗I_{|P|})(I_{|J|}⊗I_{|N|}⊗C) | |
305 ``` | |
306 where |.| of a multi-index is a vector of sizes for each dimension. ``I_v`` denotes the identity tensor of size ``v[i]`` in each direction | |
307 To apply ``A⊗B⊗C`` we evaluate | |
308 | |
309 (A⊗B⊗C)v = [(A⊗I_{|M|}⊗I_{|P|}) [(I_{|J|}⊗B⊗I_{|P|}) [(I_{|J|}⊗I_{|N|}⊗C)v]]] | |
310 """ | |
311 function LazyOuterProduct end | |
312 export LazyOuterProduct | |
313 | |
314 function LazyOuterProduct(tm1::TensorMapping, tm2::TensorMapping) | |
315 itm1 = InflatedTensorMapping(tm1, IdentityMapping(range_size(tm2))) | |
316 itm2 = InflatedTensorMapping(IdentityMapping(domain_size(tm1)),tm2) | |
317 | |
318 return itm1∘itm2 | |
319 end | |
320 | |
321 # length(tms) is always >= 1 since the two argument method is more specific. Right?? | |
322 LazyOuterProduct(tm::TensorMapping, tms::Vararg{TensorMapping}) = tm∘LazyOuterProduct(tms...) | |
323 | |
324 ⊗(a::TensorMapping,b::TensorMapping) = LazyOuterProduct(a,b) | |
325 ⊗(a,b,cs::Vararg{TensorMapping}) = ⊗(a⊗b, cs...) | |
326 | |
327 # TODO: Can we implement compositions and kroneckers of LazyIdentities to just return new LazyIdentities? |