Version history
What's new in v3.11
- The
tr
function fromLinearAlgebra.jl
is now overloaded both for genericLinearMap
types and specialized for most providedLinearMap
types. In the generic case, this is computationally as expensive as computing the whole matrix representation, though the latter is, of course, not stored.
What's new in v3.10
- A new
MulStyle
trait calledTwoArg
has been added. It should be used forLinearMap
s that do not admit a mutating multiplication à la (3-arg or 5-arg)mul!
, but only out-of-place multiplication à laA * x
. Products (akaCompositeMap
s) and sums (akaLinearCombination
s) ofTwoArg
-LinearMap
s now have memory-optimized multiplication kernels. For instance,A*B*C*x
for threeTwoArg
-LinearMap
sA
,B
andC
now allocates onlyy = C*x
,z = B*y
and the result ofA*z
. - The construction of function-based
LinearMap
s, typedFunctionMap
, has been rearranged. Additionally to the convenience constructorLinearMap{T=Float64}(f, [fc,] M, N=M; kwargs...)
, the newly exported constructorFunctionMap{T,iip}(f, [fc], M, N; kwargs...)
is readily available. Here,iip
is eithertrue
orfalse
, and encodes whetherf
(andfc
if present) are mutating functions. In the convenience constructor, this is determined via theBool
keyword argumentismutating
and may not be fully inferred.
What's new in v3.9
- The application of
LinearMap
s to vectors operation, i.e.,(A,x) -> A*x = A(x)
, is now differentiable w.r.t. to the inputx
for integration with machine learning frameworks such asFlux.jl
. The reverse differentiation rule makesA::LinearMap
usable as a static, i.e., non-trainable, layer in a network, and requires the adjointA'
ofA
to be defined. - New map types called
KhatriRaoMap
andFaceSplittingMap
are introduced. These correspond to lazy representations of the column-wise Kronecker product and the row-wise Kronecker product (or "transposed Khatri-Rao product"), respectively. They can be constructed from two matricesA
andB
viakhatrirao(A, B)
andfacesplitting(A, B)
, respectively. The first is particularly efficient as it makes use of the vec-trick for Kronecker products and computesy = khatrirao(A, B) * x
for a vectorx
asy = vec(B * Diagonal(x) * transpose(A))
. As such, the Khatri-Rao product can actually be built for generalLinearMap
s, including function-based types. Even for moderate sizes of 5 or more columns, this map-vector product is faster than first creating the explicit Khatri-Rao product in memory and then multiplying with the vector; not to mention the memory savings. Unfortunately, similar efficiency cannot be achieved for the face-splitting product.
What's new in v3.8
- A new map called
InverseMap
is introduced. Letting anInverseMap
act on a vector is equivalent to solving the linear system, i.e.InverseMap(A) * b
is the same asA \ b
. The default solver isldiv!
, but can be specified with thesolver
keyword argument to the constructor (see the docstring for details). Note thatA
must be compatible with the solver:A
can, for example, be a factorization, or anotherLinearMap
in combination with an iterative solver. - New constructors for lazy representations of Kronecker products (
squarekron
) and sums (sumkronsum
) for square factors and summands, respectively, are introduced. They target cases with 3 or more factors/summands, and benchmarking intended use cases for comparison withKroneckerMap
(constructed viaBase.kron
) andKroneckerSumMap
(constructed viakronsum
) is recommended.
What's new in v3.7
mul!(M::AbstractMatrix, A::LinearMap, s::Number, a, b)
methods are provided, mimicking similar methods inBase.LinearAlgebra
. This version allows for the memory efficient implementation of in-place addition and conversion of aLinearMap
toMatrix
. Efficient specialisations forWrappedMap
,ScaledMap
, andLinearCombination
are provided. If users supply the corresponding_unsafe_mul!
method for their custom maps, conversion, construction, and inplace addition will benefit from this supplied efficient implementation. If no specialisation is supplied, a generic fallback is used that is based on feeding the canonical basis of unit vectors to the linear map.A new map type called
EmbeddedMap
is introduced. It is a wrapper of a "small"LinearMap
(or a suitably convertedAbstractVecOrMat
) embedded into a "larger" zero map. Hence, the "small" map acts only on a subset of the coordinates and maps to another subset of the coordinates of the "large" map. The large mapL
can therefore be imagined as the composition of a sampling/projection mapP
, of the small mapA
, and of an embedding mapE
:L = E ⋅ A ⋅ P
. It is implemented, however, by acting on a view of the vectorx
and storing the result into a view of the result vectory
. Such maps can be constructed by the new methods:LinearMap(A::MapOrVecOrMat, dims::Dims{2}, index::NTuple{2, AbstractVector{Int}})
, wheredims
is the dimensions of the "large" map and index is a tuple of thex
- andy
-indices that interact withA
, respectively;LinearMap(A::MapOrVecOrMat, dims::Dims{2}; offset::Dims{2})
, where the keyword argumentoffset
determines the dimension of a virtual upper-left zero block, to whichA
gets (virtually) diagonally appended.
An often requested new feature has been added: slicing (i.e., non-scalar indexing) any
LinearMap
object viaBase.getindex
overloads. Note, however, that only rather efficient complete slicing operations are implemented:A[:,j]
,A[:,J]
, andA[:,:]
, wherej::Integer
andJ
is either of typeAbstractVector{<:Integer>}
or anAbstractVector{Bool}
of appropriate length ("logical slicing"). Partial slicing operations such asA[I,j]
andA[I,J]
whereI
is asJ
above are disallowed.Scalar indexing
A[i::Integer,j::Integer]
as well as other indexing operations that fall back on scalar indexing such as logical indexing by someAbstractMatrix{Bool}
, or indexing by vectors of (linear or Cartesian) indices are not supported; as an exception,getindex
calls on wrappedAbstractVecOrMat
s is forwarded to correspondinggetindex
methods fromBase
and therefore allow any type of usual indexing/slicing. If scalar indexing is really required, consider usingA[:,j][i]
which is as efficient as a reasonable generic implementation forLinearMap
s can be.Furthermore, (predominantly) horizontal slicing operations require the adjoint operation of the
LinearMap
type to be defined, or will fail otherwise. Important note:LinearMap
objects are meant to model objects that act on vectors efficiently, and are in general not backed up by storage-like types likeArray
s. Therefore, slicing ofLinearMap
s is potentially slow, and it may require the (repeated) allocation of standard unit vectors. As a consequence, generic algorithms relying heavily on indexing and/or slicing are likely to run much slower than expected forAbstractArray
s. To avoid repeated indexing operations which may involve redundant computations, it is strongly recommended to considerconvert
ingLinearMap
-typed objects toMatrix
orSparseMatrixCSC
first, if memory permits.
What's new in v3.6
- Support for Julia versions below v1.6 has been dropped.
Block[Diagonal]Map
,CompositeMap
,KroneckerMap
andLinearCombination
type objects can now be backed by aVector
ofLinearMap
-type elements. This can be beneficial in cases where these higher-orderLinearMap
s are constructed from many maps where a tuple backend may get inefficient or impose hard work for the compiler at construction. The default behavior, however, does not change, and construction of vector-basedLinearMap
s requires usage of the unexported constructors ("expert usage"), except for constructions likesum([A, B, C])
orprod([A, B, C])
(== C*B*A
), whereA
,B
andC
are of someLinearMap
type.
What's new in v3.5
WrappedMap
,ScaledMap
,LinearCombination
,AdjointMap
,TransposeMap
andCompositeMap
, instead of using the defaultaxes(A) = map(oneto, size(A))
, now forward calls toaxes
to the underlying wrapped linear map. This allows allocating operations such as*
to determine the appropriate storage and axes type of their outputs. For example, linear maps that wrapBlockArrays
will, upon multiplicative action, produce aBlockArrays.PseudoBlockVector
with block structure inherited from the operator's output axesaxes(A,1)
.
What's new in v3.4
- In
WrappedMap
constructors, as implicitly called in addition and multiplication ofLinearMap
s andAbstractMatrix
objects, (conjugate) symmetry and positive definiteness are only determined for matrix types for which these checks are expected to be very cheap or even known at compile time based on the concrete type. The default forLinearMap
subtypes is to call, for instance,issymmetric
, because symmetry properties are either stored or easily obtained from constituting maps. For custom matrix types, define corresponding methodsLinearMaps._issymmetric
,LinearMaps._ishermitian
andLinearMaps._isposdef
to hook into the property checking mechanism.
What's new in v3.3
AbstractVector
s can now be wrapped by aLinearMap
just likeAbstractMatrix
typed objects. Upon wrapping, they are not implicitly reshaped to matrices. This feature might be helpful, for instance, in the lazy representation of rank-1 operators
kron(LinearMap(u), v') == ⊗(u, v') == u ⊗ v'for vectors
uand
v. The action on vectors,
(u⊗v')x, is implemented optimally via
u(v'x)`.
What's new in v3.2
- In-place left-multiplication
mul!(Y, X, A::LinearMap)
is now allowed forX::AbstractMatrix
and implemented via the adjoint equationY' = A'X'
.
What's new in v3.1
- In Julia v1.3 and above,
LinearMap
-typed objects are callable onAbstractVector
s: ForL::LinearMap
andx::AbstractVector
,L(x) = L*x
.
What's new in v3.0
- BREAKING change: Internally, any dependence on former
A*_mul_B!
methods is abandoned. For customLinearMap
subtypes, there are now two options:- In case your type is invariant under adjoint/transposition (i.e.,
adjoint(L::MyLinearMap)::MyLinearMap
similar to, for instance,LinearCombination
s orCompositeMap
s),At_mul_B!
andAc_mul_B!
do not require any replacement! Rather, multiplication byL'
is, in this case, handled bymul!(y, L::MyLinearMap, x[, α, β])
. - Otherwise, you will need to define
mul!
methods with the signaturemul!(y, L::TransposeMap{<:Any,MyLinearMap}, x[, α, β])
andmul!(y, L::AdjointMap{<:Any,MyLinearMap}, x[, α, β])
.
- In case your type is invariant under adjoint/transposition (i.e.,
- Left multiplying by a transpose or adjoint vector (e.g.,
y'*A
) produces a transpose or adjoint vector output, rather than a compositeLinearMap
. - Block concatenation now handles matrices and vectors directly by internal promotion to
LinearMap
s. For[h/v/hc]cat
it suffices to have aLinearMap
object anywhere in the list of arguments. For the block-diagonal concatenation viaSparseArrays.blockdiag
, aLinearMap
object has to appear among the first 8 arguments. This restriction, however, does not apply to block-diagonal concatenation viaBase.cat(As...; dims=(1,2))
. - Introduction of more expressive and visually appealing
show
methods, replacing the fallback to the genericshow
.
What's new in v2.7
- Potential reduction of memory allocations in multiplication of
LinearCombination
s,BlockMap
s, and real- or complex-scaledLinearMap
s. For the latter, a new internal typeScaledMap
has been introduced. - Multiplication code for
CompositeMap
s has been refactored to facilitate to provide memory for storage of intermediate results by directly calling helper functions.
What's new in v2.6
- New feature: "lazy" Kronecker product, Kronecker sums, and powers thereof for
LinearMap
s.AbstractMatrix
objects are promoted toLinearMap
s if one of the first 8 Kronecker factors is aLinearMap
object. - Compatibility with the generic multiply-and-add interface (a.k.a. 5-arg
mul!
) introduced in julia v1.3
What's new in v2.5
- New feature: concatenation of
LinearMap
s objects withUniformScaling
s, consistent with (h-, v-, and hc-)concatenation of matrices. Note, matricesA
must be wrapped asLinearMap(A)
,UniformScaling
s are promoted toLinearMap
s automatically.
What's new in v2.4
- Support restricted to Julia v1.0+.
What's new in v2.3
- Fully Julia v0.7/v1.0/v1.1 compatible.
- Full support of noncommutative number types such as quaternions.
What's new in v2.2
- Fully Julia v0.7/v1.0 compatible.
- A
convert(SparseMatrixCSC, A::LinearMap)
function, that calls thesparse
matrix generating function.
What's new in v2.1
- Fully Julia v0.7 compatible; dropped compatibility for previous versions of Julia from LinearMaps.jl v2.0.0 on.
- A 5-argument version for
mul!(y, A::LinearMap, x, α=1, β=0)
, which computesy := α * A * x + β * y
and implements the usual 3-argumentmul!(y, A, x)
for the defaultα
andβ
. - Synonymous
convert(Matrix, A::LinearMap)
andconvert(Array, A::LinearMap)
functions, that call theMatrix
constructor and return the matrix representation ofA
. - Multiplication with matrices, interpreted as a block row vector of vectors:
mul!(Y::AbstractArray, A::LinearMap, X::AbstractArray, α=1, β=0)
: appliesA
to each column ofX
and stores the result in-place in the corresponding column ofY
;- for the out-of-place multiplication, the approach is to compute
convert(Matrix, A * X)
; this is equivalent to applyingA
to each column ofX
. In generic code which handles bothA::AbstractMatrix
andA::LinearMap
, the additional call toconvert
is a noop whenA
is a matrix.
- Full compatibility with Arpack.jl's
eigs
andsvds
; previously onlyeigs
was working. For more, nicely collaborating packages see the Example section.