Mercurial > repos > public > sbplib_julia
changeset 426:51870d80fbb9
Merge feature/tensor_composition. Implement TensorMappingComposition
author | Jonatan Werpers <jonatan@werpers.com> |
---|---|
date | Mon, 19 Oct 2020 09:47:33 +0200 |
parents | 10a67ac48d6e (current diff) 40f793b40339 (diff) |
children | 1c41f4fd3e61 7327a3e41df0 |
files | |
diffstat | 2 files changed, 48 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/src/LazyTensors/lazy_tensor_operations.jl Sun Oct 18 22:21:43 2020 +0200 +++ b/src/LazyTensors/lazy_tensor_operations.jl Mon Oct 19 09:47:33 2020 +0200 @@ -74,34 +74,38 @@ Base.:+(tm1::TensorMapping{T,R,D}, tm2::TensorMapping{T,R,D}) where {T,R,D} = LazyTensorMappingBinaryOperation{:+,T,R,D}(tm1,tm2) Base.:-(tm1::TensorMapping{T,R,D}, tm2::TensorMapping{T,R,D}) where {T,R,D} = LazyTensorMappingBinaryOperation{:-,T,R,D}(tm1,tm2) +""" + TensorMappingComposition{T,R,K,D} -# TODO: Write tests and documentation for LazyTensorMappingComposition -# struct LazyTensorMappingComposition{T,R,K,D} <: TensorMapping{T,R,D} -# t1::TensorMapping{T,R,K} -# t2::TensorMapping{T,K,D} -# end - -# Base.:∘(s::TensorMapping{T,R,K}, t::TensorMapping{T,K,D}) where {T,R,K,D} = LazyTensorMappingComposition(s,t) - -# function range_size(tm::LazyTensorMappingComposition{T,R,K,D}, domain_size::NTuple{D,Integer}) where {T,R,K,D} -# range_size(tm.t1, domain_size(tm.t2, domain_size)) -# end +Lazily compose two TensorMappings, so that they can be handled as a single TensorMapping. +""" +struct TensorMappingComposition{T,R,K,D, TM1<:TensorMapping{T,R,K}, TM2<:TensorMapping{T,K,D}} <: TensorMapping{T,R,D} + t1::TM1 + t2::TM2 -# function domain_size(tm::LazyTensorMappingComposition{T,R,K,D}, range_size::NTuple{R,Integer}) where {T,R,K,D} -# domain_size(tm.t1, domain_size(tm.t2, range_size)) -# end - -# function apply(c::LazyTensorMappingComposition{T,R,K,D}, v::AbstractArray{T,D}, I::NTuple{R,Int}) where {T,R,K,D} -# apply(c.t1, LazyTensorMappingApplication(c.t2,v), I...) -# end + @inline function TensorMappingComposition(t1::TensorMapping{T,R,K}, t2::TensorMapping{T,K,D}) where {T,R,K,D} + @boundscheck if domain_size(t1) != range_size(t2) + throw(DimensionMismatch("the first argument has domain size $(domain_size(t1)) while the second has range size $(range_size(t2)) ")) + end + return new{T,R,K,D, typeof(t1), typeof(t2)}(t1,t2) + end + # Add check for matching sizes as a boundscheck +end +export TensorMappingComposition -# function apply_transpose(c::LazyTensorMappingComposition{T,R,K,D}, v::AbstractArray{T,D}, I::NTuple{D,Int}) where {T,R,K,D} -# apply_transpose(c.t2, LazyTensorMappingApplication(c.t1',v), I...) -# end +range_size(tm::TensorMappingComposition) = range_size(tm.t1) +domain_size(tm::TensorMappingComposition) = domain_size(tm.t2) + +function apply(c::TensorMappingComposition{T,R,K,D}, v::AbstractArray{T,D}, I::Vararg{S,R} where S) where {T,R,K,D} + apply(c.t1, c.t2*v, I...) +end -# # Have i gone too crazy with the type parameters? Maybe they aren't all needed? +function apply_transpose(c::TensorMappingComposition{T,R,K,D}, v::AbstractArray{T,R}, I::Vararg{S,D} where S) where {T,R,K,D} + apply_transpose(c.t2, c.t1'*v, I...) +end -# export → +Base.@propagate_inbounds Base.:∘(s::TensorMapping, t::TensorMapping) = TensorMappingComposition(s,t) + """ LazyLinearMap{T,R,D,...}(A, range_indicies, domain_indicies)
--- a/test/testLazyTensors.jl Sun Oct 18 22:21:43 2020 +0200 +++ b/test/testLazyTensors.jl Mon Oct 19 09:47:33 2020 +0200 @@ -213,6 +213,27 @@ end +@testset "TensorMappingComposition" begin + A = rand(2,3) + B = rand(3,4) + + Ã = LazyLinearMap(A, (1,), (2,)) + B̃ = LazyLinearMap(B, (1,), (2,)) + + @test Ã∘B̃ isa TensorMappingComposition + @test range_size(Ã∘B̃) == (2,) + @test domain_size(Ã∘B̃) == (4,) + @test_throws DimensionMismatch B̃∘Ã + + # @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) + + v = rand(4) + @test Ã∘B̃*v ≈ A*B*v rtol=1e-16 + + v = rand(2) + @test (Ã∘B̃)'*v ≈ B'*A'*v rtol=1e-16 +end + @testset "LazyLinearMap" begin # Test a standard matrix-vector product # mapping vectors of size 4 to vectors of size 3.