Abstract operators extend the syntax typically used for matrices to linear mappings of arbitrary dimensions and nonlinear functions. Unlike matrices however, abstract operators apply the mappings with specific efficient algorithms that minimize memory requirements. This is particularly useful in iterative algorithms and in first order large-scale optimization algorithms.
To install the package, hit ]
from the Julia command line to enter the package manager, then
pkg> add AbstractOperators
With using AbstractOperators
the package imports several methods like multiplication *
and adjoint transposition '
(and their in-place methods mul!
).
For example, one can create a 2-D Discrete Fourier Transform as follows:
julia> A = DFT(3,4)
ℱ ℝ^(3, 4) -> ℂ^(3, 4)
Here, it can be seen that A
has a domain of dimensions size(A,2) = (3,4)
and of type domainType(A) = Float64
and a codomain of dimensions size(A,1) = (3,4)
and type codomainType(A) = Complex{Float64}
.
This linear transformation can be evaluated as follows:
julia> x = randn(3,4); #input matrix
julia> y = A*x
3×4 Array{Complex{Float64},2}:
-1.11412+0.0im 3.58654-0.724452im -9.10125+0.0im 3.58654+0.724452im
-0.905575+1.98446im 0.441199-0.913338im 0.315788+3.29666im 0.174273+0.318065im
-0.905575-1.98446im 0.174273-0.318065im 0.315788-3.29666im 0.441199+0.913338im
julia> mul!(y, A, x) == A*x #in-place evaluation
true
julia> all(A'*y - *(size(x)...)*x .< 1e-12)
true
julia> mul!(x, A',y) #in-place evaluation
3×4 Array{Float64,2}:
-2.99091 9.45611 -19.799 1.6327
-11.1841 11.2365 -26.3614 11.7261
5.04815 7.61552 -6.00498 6.25586
Notice that inputs and outputs are not necessarily Vectors
.
It is also possible to combine multiple AbstractOperators
using different calculus rules.
For example AbstractOperators
can be concatenated horizontally:
julia> B = Eye(Complex{Float64},(3,4))
I ℂ^(3, 4) -> ℂ^(3, 4)
julia> H = [A B]
[ℱ,I] ℝ^(3, 4) ℂ^(3, 4) -> ℂ^(3, 4)
In this case H
has a domain of dimensions size(H,2) = ((3, 4), (3, 4))
and type domainType(H) = (Float64, Complex{Float64})
.
When an AbstractOperators
have multiple domains, this must be multiplied using an ArrayPartition
(using RecursiveArrayTools with corresponding size and domain, for example:
julia> using RecursiveArrayTools
julia> H*ArrayPartition(x, complex(x))
3×4 Array{Complex{Float64},2}:
-16.3603+0.0im 52.4946-8.69342im -129.014+0.0im 44.6712+8.69342im
-22.051+23.8135im 16.5309-10.9601im -22.5719+39.5599im 13.8174+3.81678im
-5.81874-23.8135im 9.70679-3.81678im -2.21552-39.5599im 11.5502+10.9601im
Similarly, when an AbstractOperators
have multiple codomains, this will return an ArrayPartition
, for example:
julia> V = VCAT(Eye(3,3),FiniteDiff((3,3)))
[I;δx] ℝ^(3, 3) -> ℝ^(3, 3) ℝ^(2, 3)
julia> V*ones(3,3)
([1.0 1.0 1.0; 1.0 1.0 1.0; 1.0 1.0 1.0], [0.0 0.0 0.0; 0.0 0.0 0.0])
A list of the available AbstractOperators
and calculus rules can be found in the documentation.
AbstractOperators.jl is developed by Niccolò Antonello and Lorenzo Stella at KU Leuven, ESAT/Stadius,