A Julia Linear Operator Package

Operators behave like matrices (with exceptions) but are defined by their effect when applied to a vector. They can be transposed, conjugated, or combined with other operators cheaply. The costly operation is deferred until multiplied with a vector.

Compatibility

Julia 1.6 and up.

How to Install

pkg> add LinearOperators
pkg> test LinearOperators

Operators Available

OperatorDescription
LinearOperatorBase class. Useful to define operators from functions
TimedLinearOperatorLinear operator instrumented with timers from TimerOutputs
BlockDiagonalOperatorBlock-diagonal linear operator
opEyeIdentity operator
opOnesAll ones operator
opZerosAll zeros operator
opDiagonalSquare (equivalent to diagm()) or rectangular diagonal operator
opInverseEquivalent to \
opCholeskyMore efficient than opInverse for symmetric positive definite matrices
opLDLSimilar to opCholesky, for general sparse symmetric matrices
opHouseholderApply a Householder transformation I-2hh'
opHermitianRepresent a symmetric/hermitian operator based on the diagonal and strict lower triangle
opRestrictionRepresent a selection of "rows" when composed on the left with an existing operator
opExtensionRepresent a selection of "columns" when composed on the right with an existing operator
LBFGSOperatorLimited-memory BFGS approximation in operator form (damped or not)
InverseLBFGSOperatorInverse of a limited-memory BFGS approximation in operator form (damped or not)
LSR1OperatorLimited-memory SR1 approximation in operator form
kronKronecker tensor product in linear operator form

Utility Functions

FunctionDescription
check_ctransposeCheap check that A' is correctly implemented
check_hermitianCheap check that A = A'
check_positive_definiteCheap check that an operator is positive (semi-)definite
diagExtract the diagonal of an operator
MatrixConvert an abstract operator to a dense array
hermitianDetermine whether the operator is Hermitian
push!For L-BFGS or L-SR1 operators, push a new pair {s,y}
reset!For L-BFGS or L-SR1 operators, reset the data
showDisplay basic information about an operator
sizeReturn the size of a linear operator
symmetricDetermine whether the operator is symmetric
normestEstimate the 2-norm

Other Operations on Operators

Operators can be transposed (A.'), conjugated (conj(A)) and conjugate-transposed (A'). Operators can be sliced (A[:,3], A[2:4,1:5], A[1,1]), but unlike matrices, slices always return operators (see differences).

Differences

Unlike matrices, an operator never reduces to a vector or a number.

using LinearOperators
A = rand(5,5)
opA = LinearOperator(A)
A[:,1] * 3 isa Vector
true
opA[:,1] * 3 isa LinearOperator
true
opA[:,1] * [3] isa Vector
true

However, the following returns an error

A[:,1] * [3]

This is also true for A[i,:], which would return a vector and for the scalar A[i,j]. Similarly, opA[1,1] is an operator of size (1,1):"

(opA[1,1] * [3])[1] - A[1,1] * 3
0.0

In the same spirit, the operator Matrix always returns a matrix.

Matrix(opA[:,1])
5×1 Matrix{Float64}:
 0.16020814312432063
 0.6514589370303275
 0.7233087667435946
 0.20105623666790973
 0.3789448071142515

Other Operators

  • LLDL features a limited-memory LDLᵀ factorization operator that may be used as preconditioner in iterative methods
  • MUMPS.jl features a full distributed-memory factorization operator that may be used to represent the preconditioner in, e.g., constraint-preconditioned Krylov methods.

Testing

julia> Pkg.test("LinearOperators")

Bug reports and discussions

If you think you found a bug, feel free to open an issue. Focused suggestions and requests can also be opened as issues. Before opening a pull request, start an issue or a discussion on the topic, please.

If you want to ask a question not suited for a bug report, feel free to start a discussion here. This forum is for general discussion about this repository and the JuliaSmoothOptimizers organization, so questions about any of our packages are welcome.