Properties and Traits
Size and Domains
Base.size — Function
size(A::AbstractOperator, [dom,])Returns the size of an AbstractOperator. Type size(A,1) for the size of the codomain and size(A,2) for the size of the codomain.
Note that the size is always returned as a Tuple, so for a 2D operator the size of the codomain will be (m,) and the size of the domain will be (n,) for an m x n operator.
julia> size(FiniteDiff((10,20), 1))
((9, 20), (10, 20))
julia> size(FiniteDiff((10,20), 1),1)
(9, 20)
julia> size(FiniteDiff((10,20), 1),2)
(10, 20)Base.ndims — Function
ndims(A::AbstractOperator, [dom,])Returns a Tuple with the number of dimensions of the codomain and domain of an AbstractOperator. Type ndims(A,1) for the number of dimensions of the codomain and ndims(A,2) for the number of dimensions of the codomain.
julia> V = Variation((2,3,4))
Ʋ ℝ^(2, 3, 4) -> ℝ^(24, 3)
julia> ndims(V)
(2, 3)
julia> ndims(V,1)
2
julia> ndims(V,2)
3AbstractOperators.ndoms — Function
ndoms(L::AbstractOperator, [dom::Int]) -> (number of codomains, number of domains)Returns the number of codomains and domains of a AbstractOperator. Optionally you can specify the codomain (with dom = 1) or the domain (with dom = 2)
julia> ndoms(Eye(10,10))
(1, 1)
julia> ndoms(hcat(Eye(10,10),Eye(10,10)))
(1, 2)
julia> ndoms(hcat(Eye(10,10),Eye(10,10)),2)
2
julia> ndoms(DCAT(Eye(10,10),Eye(10,10)))
(2, 2)AbstractOperators.domain_type — Function
domain_type(A::AbstractOperator)Returns the type of the domain.
julia> domain_type(DiagOp(rand(10)))
Float64
julia> domain_type(hcat(Eye(Complex{Float64},(10,)),DiagOp(rand(ComplexF64, 10))))
(ComplexF64, ComplexF64)AbstractOperators.codomain_type — Function
codomain_type(A::AbstractOperator)Returns the type of the codomain.
julia> codomain_type(DiagOp(rand(ComplexF64, 10)))
ComplexF64 (alias for Complex{Float64})
julia> codomain_type(vcat(Eye(Complex{Float64},(10,)),DiagOp(rand(ComplexF64, 10))))
(ComplexF64, ComplexF64)AbstractOperators.domain_storage_type — Function
domain_storage_type(L::AbstractOperator)Returns the type of the storage for the domain of the operator.
julia> domain_storage_type(DiagOp(rand(10)))
Array{Float64}
julia> domain_storage_type(hcat(Eye(Complex{Float64},(10,)),DiagOp(rand(ComplexF64, 10))))
RecursiveArrayTools.ArrayPartition{ComplexF64, Tuple{Array{ComplexF64}, Array{ComplexF64}}}AbstractOperators.codomain_storage_type — Function
codomain_storage_type(L::AbstractOperator)Returns the type of the storage of for the codomain of the operator.
julia> codomain_storage_type(DiagOp(rand(ComplexF64,10)))
Array{ComplexF64}
julia> codomain_storage_type(vcat(Eye(Complex{Float64},(10,)),DiagOp(rand(ComplexF64,10))))
RecursiveArrayTools.ArrayPartition{ComplexF64, Tuple{Array{ComplexF64}, Array{ComplexF64}}}Traits
The functions in this package allows querying properties of the operators to be used by other packages for optimization and trait-based custumized behavior.
LinearAlgebra traits
AbstractOperators.jl's operators is defined for following functions from standard library LinearAlgebra.
LinearAlgebra.diag — Function
LinearAlgebra.diag(A::AbstractOperator)Returns the diagonal of A. If A is not diagonal, an error is thrown.
The diagonal is defined as the vector d such that A * x = d .* x for all x in the domain of A, where .* is the element-wise multiplication.
LinearAlgebra.opnorm — Function
LinearAlgebra.opnorm(A::AbstractOperator)Returns the operator norm of A. The operator norm is defined as the maximum singular value of A. It is computed using the power method by default, unless the operator has a fast implementation.
The operator norm is defined as: ‖A‖ = sup_{x != 0} ‖A*x‖ / ‖x‖.
Parameters of power iteration:
- Maximum number of iterations: 100
- Tolerance for convergence: 1e-6
These parameters can be adjusted in the estimate_opnorm function.
OperatorCore.jl traits
AbstractOperators.jl's operators satisfies the interface for matrix-like objects provided by OperatorCore.jl with the following functions:
OperatorCore.is_linear — Function
is_linear(A)Returns true if A is a linear operator. Operator A is linear if A * (x+y) = A * x + A * y and A * (α * x) = α * A * x for all x and y in the domain of A and all scalars α.
OperatorCore.is_eye — Function
is_eye(A)Returns true if A is an identity operator. Operator A is an identity operator if A * x = x for all x in the domain of A.
OperatorCore.is_null — Function
is_null(A)Returns true if A is a null operator. Operator A is null if A * x = 0 for all x in the domain of A, where 0 is the zero element of the codomain of A (e.g. zero vector).
OperatorCore.is_symmetric — Function
is_symmetric(A)Returns true if A is a symmetric operator. Operator A is symmetric if A * x = A' * x for all x in the domain of A, where A' is the adjoint of A. In other words, A is symmetric if it is equal to its adjoint.
OperatorCore.is_diagonal — Function
is_diagonal(A)Returns true if A is a diagonal operator. Operator A is diagonal if (A * x)[i] = (A * eᵢ)[i] for all x in the domain of A and all i, where eᵢ is the i-th canonical basis vector. In other words, (A * x)[i] depends only on x[i].
OperatorCore.is_AcA_diagonal — Function
is_AcA_diagonal(A)Returns true if A*A' is diagonal, where A' is the adjoint of A. Compounds A*A' is diagonal if ((A*A') * x)[i] = (A*A') * eᵢ)[i] for all x in the domain of A and all i, where eᵢ is the i-th canonical basis vector. In other words, ((A*A') * x)[i] depends only on x[i].
OperatorCore.diag_AcA — Function
diag_AcA(A)Returns the diagonal of A*A', where A' is the adjoint of A. If A*A' is not diagonal, an error is thrown.
OperatorCore.is_AAc_diagonal — Function
is_AAc_diagonal(A)Returns true if A'*A is diagonal, where A' is the adjoint of A. Compounds A'*A is diagonal if ((A'*A) * x)[i] = (A'*A) * eᵢ)[i] for all x in the domain of A and all i, where eᵢ is the i-th canonical basis vector. In other words, ((A'*A) * x)[i] depends only on x[i].
OperatorCore.diag_AAc — Function
diag_AAc(A)Returns the diagonal of A'*A, where A' is the adjoint of A. If A'*A is not diagonal, an error is thrown.
OperatorCore.is_orthogonal — Function
is_orthogonal(A)Returns true if A is an orthogonal operator. Operator A is orthogonal if A * A' = A' * A = I, where A' is the adjoint of A and I is the identity operator.
OperatorCore.is_invertible — Function
is_invertible(A)Returns true if A is an invertible operator. Operator A is invertible if there exists an operator B such that A * B = B * A = I, where I is the identity operator.
OperatorCore.is_full_row_rank — Function
is_full_row_rank(A)Returns true if A has full row rank. Operator A has full row rank if the rows of A are linearly independent. In other words, the number of linearly independent rows of A is equal to the number of rows of A.
OperatorCore.is_full_column_rank — Function
is_full_row_rank(A)Returns true if A has full column rank. Operator A has full column rank if the columns of A are linearly independent. In other words, the number of linearly independent columns of A is equal to the number of columns of A.
Additional traits
AbstractOperators.jl's operators also defines the following functions:
AbstractOperators.displacement — Function
displacement(A::AbstractOperator)Returns the displacement of the operator.
julia> A = AffineAdd(Eye(4),[1.;2.;3.;4.])
I+d ℝ^4 -> ℝ^4
julia> displacement(A)
4-element Vector{Float64}:
1.0
2.0
3.0
4.0
AbstractOperators.remove_displacement — Function
remove_displacement(A::AbstractOperator)Removes the displacement of the operator.
AbstractOperators.is_sliced — Function
is_sliced(A)Returns true if A is a sliced operator. Operator A is sliced if it applies to only a subset of the input values.
julia> is_sliced(DiagOp(rand(10)))
false
julia> is_sliced(DiagOp(rand(10)) * GetIndex((20,), 1:10))
trueAbstractOperators.remove_slicing — Function
remove_slicing(A)Returns the operator A without slicing. Operator A is sliced if it applies to only a subset of the input values.
AbstractOperators.is_thread_safe — Function
is_thread_safe(L::AbstractOperator)Returns whether the operator is thread safe (i.e. it can be used on multiple arrays simulaneously).
AbstractOperators.estimate_opnorm — Function
estimate_opnorm(A::AbstractOperator)Estimates the operator norm of A. The operator norm is defined as the maximum singular value of A. It is computed using the power method with reduced iterations unless the operator has a fast implementation.
The operator norm is defined as: ‖A‖ = sup_{x != 0} ‖A*x‖ / ‖x‖.
Parameters of power iteration:
- Maximum number of iterations: 20
- Tolerance for convergence: 0.01
These parameters can be adjusted by passing maxit and tol keyword arguments. E.g.:
julia> estimate_opnorm(A; maxit=50, tol=1e-6)