Skip to content

Commit f0c96d8

Browse files
authored
Merge pull request #139 from vpuri3/islinear
remove abstractscimllinearoperator in favor or trait islinear(L)
2 parents a50d084 + e1f4ced commit f0c96d8

File tree

13 files changed

+119
-51
lines changed

13 files changed

+119
-51
lines changed

src/SciMLOperators.jl

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,7 @@ abstract type AbstractSciMLOperator{T} end
2626
"""
2727
$(TYPEDEF)
2828
"""
29-
abstract type AbstractSciMLLinearOperator{T} <: AbstractSciMLOperator{T} end
30-
31-
"""
32-
$(TYPEDEF)
33-
"""
34-
abstract type AbstractSciMLScalarOperator{T} <: AbstractSciMLLinearOperator{T} end
29+
abstract type AbstractSciMLScalarOperator{T} <: AbstractSciMLOperator{T} end
3530

3631
include("utils.jl")
3732
include("interface.jl")
@@ -58,6 +53,9 @@ export update_coefficients!,
5853

5954
cache_operator,
6055

56+
issquare,
57+
islinear,
58+
6159
has_adjoint,
6260
has_expmv,
6361
has_expmv!,

src/basic.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
22
$(TYPEDEF)
33
"""
4-
struct IdentityOperator{N} <: AbstractSciMLLinearOperator{Bool} end
4+
struct IdentityOperator{N} <: AbstractSciMLOperator{Bool} end
55

66
# constructors
77
IdentityOperator(u::AbstractArray) = IdentityOperator{size(u,1)}()
@@ -28,7 +28,7 @@ end
2828

2929
getops(::IdentityOperator) = ()
3030
isconstant(::IdentityOperator) = true
31-
islinear(L::IdentityOperator) = true
31+
islinear(::IdentityOperator) = true
3232
has_adjoint(::IdentityOperator) = true
3333
has_mul!(::IdentityOperator) = true
3434
has_ldiv(::IdentityOperator) = true
@@ -92,7 +92,7 @@ end
9292
"""
9393
$(TYPEDEF)
9494
"""
95-
struct NullOperator{N} <: AbstractSciMLLinearOperator{Bool} end
95+
struct NullOperator{N} <: AbstractSciMLOperator{Bool} end
9696

9797
# constructors
9898
NullOperator(u::AbstractArray) = NullOperator{size(u,1)}()
@@ -120,7 +120,7 @@ LinearAlgebra.isposdef(::NullOperator) = false
120120

121121
getops(::NullOperator) = ()
122122
isconstant(::NullOperator) = true
123-
islinear(L::NullOperator) = true
123+
islinear(::NullOperator) = true
124124
Base.iszero(::NullOperator) = true
125125
has_adjoint(::NullOperator) = true
126126
has_mul!(::NullOperator) = true
@@ -229,8 +229,8 @@ Base.conj(L::ScaledOperator) = conj(L.λ) * conj(L.L)
229229
LinearAlgebra.opnorm(L::ScaledOperator, p::Real=2) = abs(L.λ) * opnorm(L.L, p)
230230

231231
getops(L::ScaledOperator) = (L.λ, L.L,)
232-
islinear(L::ScaledOperator) = all(islinear, L.ops)
233232
isconstant(L::ScaledOperator) = isconstant(L.L) & isconstant(L.λ)
233+
islinear(L::ScaledOperator) = islinear(L.L)
234234
Base.iszero(L::ScaledOperator) = iszero(L.L) | iszero(L.λ)
235235
has_adjoint(L::ScaledOperator) = has_adjoint(L.L)
236236
has_mul(L::ScaledOperator) = has_mul(L.L)
@@ -375,6 +375,7 @@ end
375375
Base.conj(L::AddedOperator) = AddedOperator(conj.(L.ops))
376376

377377
getops(L::AddedOperator) = L.ops
378+
islinear(L::AddedOperator) = all(islinear, getops(L))
378379
Base.iszero(L::AddedOperator) = all(iszero, getops(L))
379380
has_adjoint(L::AddedOperator) = all(has_adjoint, L.ops)
380381

@@ -667,6 +668,7 @@ Base.adjoint(L::InvertedOperator) = InvertedOperator(adjoint(L.L); cache = L.iss
667668
Base.conj(L::InvertedOperator) = InvertedOperator(conj(L.L); cache=L.cache)
668669

669670
getops(L::InvertedOperator) = (L.L,)
671+
islinear(L::InvertedOperator) = islinear(L.L)
670672

671673
has_mul(L::InvertedOperator) = has_ldiv(L.L)
672674
has_mul!(L::InvertedOperator) = has_ldiv!(L.L)

src/batch.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ by `update_coefficients!` and is assumed to have the following signature:
88
99
update_func(diag::AbstractVector,u,p,t) -> [modifies diag]
1010
"""
11-
struct BatchedDiagonalOperator{T,D,F} <: AbstractSciMLLinearOperator{T}
11+
struct BatchedDiagonalOperator{T,D,F} <: AbstractSciMLOperator{T}
1212
diag::D
1313
update_func::F
1414

@@ -58,7 +58,7 @@ end
5858
LinearAlgebra.isposdef(L::BatchedDiagonalOperator) = isposdef(Diagonal(vec(L.diag)))
5959

6060
isconstant(L::BatchedDiagonalOperator) = L.update_func == DEFAULT_UPDATE_FUNC
61-
issquare(L::BatchedDiagonalOperator) = true
61+
islinear(::BatchedDiagonalOperator) = true
6262
has_adjoint(L::BatchedDiagonalOperator) = true
6363
has_ldiv(L::BatchedDiagonalOperator) = all(x -> !iszero(x), L.diag)
6464
has_ldiv!(L::BatchedDiagonalOperator) = has_ldiv(L)

src/func.jl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,12 @@ function FunctionOperator(op,
104104
t::Union{Number,Nothing}=nothing,
105105

106106
# traits
107-
opnorm=nothing,
108-
issymmetric::Bool=false,
109-
ishermitian::Bool=false,
110-
isposdef::Bool=false,
107+
islinear::Bool = false,
108+
109+
opnorm = nothing,
110+
issymmetric::Bool = false,
111+
ishermitian::Bool = false,
112+
isposdef::Bool = false,
111113
)
112114

113115
sz = (size(output, 1), size(input, 1))
@@ -148,6 +150,8 @@ function FunctionOperator(op,
148150
end
149151

150152
traits = (;
153+
islinear = islinear,
154+
151155
opnorm = opnorm,
152156
issymmetric = issymmetric,
153157
ishermitian = ishermitian,
@@ -282,6 +286,7 @@ LinearAlgebra.ishermitian(L::FunctionOperator) = L.traits.ishermitian
282286
LinearAlgebra.isposdef(L::FunctionOperator) = L.traits.isposdef
283287

284288
getops(::FunctionOperator) = ()
289+
islinear(L::FunctionOperator) = L.traits.islinear
285290
has_adjoint(L::FunctionOperator) = !(L.op_adjoint isa Nothing)
286291
has_mul(L::FunctionOperator{iip}) where{iip} = true
287292
has_mul!(L::FunctionOperator{iip}) where{iip} = iip

src/interface.jl

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,12 @@ Base.eltype(::AbstractSciMLOperator{T}) where T = T
7575
Base.oneunit(L::AbstractSciMLOperator) = one(L)
7676
Base.oneunit(LType::Type{<:AbstractSciMLOperator}) = one(LType)
7777

78-
issquare(L::AbstractSciMLOperator) = isequal(size(L)...)
79-
80-
Base.iszero(::AbstractSciMLOperator) = false
81-
82-
islinear(::AbstractSciMLOperator) = false
83-
islinear(::AbstractSciMLLinearOperator) = true
78+
Base.iszero(::AbstractSciMLOperator) = false # TODO
8479

8580
has_adjoint(L::AbstractSciMLOperator) = false # L', adjoint(L)
8681
has_expmv!(L::AbstractSciMLOperator) = false # expmv!(v, L, t, u)
8782
has_expmv(L::AbstractSciMLOperator) = false # v = exp(L, t, u)
88-
has_exp(L::AbstractSciMLOperator) = false # v = exp(L, t)*u
83+
has_exp(L::AbstractSciMLOperator) = islinear(L)
8984
has_mul(L::AbstractSciMLOperator) = true # du = L*u
9085
has_mul!(L::AbstractSciMLOperator) = false # mul!(du, L, u)
9186
has_ldiv(L::AbstractSciMLOperator) = false # du = L\u
@@ -97,7 +92,9 @@ isconstant(L) = true
9792
isconstant(L::AbstractSciMLOperator) = all(isconstant, getops(L))
9893
#isconstant(L::AbstractSciMLOperator) = L.update_func = DEFAULT_UPDATE_FUNC
9994

100-
islinear(L) = false
95+
#islinear(L) = false
96+
islinear(::AbstractSciMLOperator) = false
97+
10198
islinear(::Union{
10299
# LinearAlgebra
103100
AbstractMatrix,
@@ -106,23 +103,20 @@ islinear(::Union{
106103

107104
# Base
108105
Number,
109-
110-
# SciMLOperators
111-
AbstractSciMLLinearOperator,
112106
}
113107
) = true
114108

115109
has_mul(L) = false
116110
has_mul(::Union{
117-
# LinearAlgebra
118-
AbstractVecOrMat,
119-
AbstractMatrix,
120-
UniformScaling,
111+
# LinearAlgebra
112+
AbstractVecOrMat,
113+
AbstractMatrix,
114+
UniformScaling,
121115

122-
# Base
123-
Number,
124-
}
125-
) = true
116+
# Base
117+
Number,
118+
}
119+
) = true
126120

127121
has_mul!(L) = false
128122
has_mul!(::Union{
@@ -152,7 +146,7 @@ has_ldiv!(::Union{
152146
}
153147
) = true
154148

155-
has_adjoint(L) = false
149+
has_adjoint(L) = islinear(L)
156150
has_adjoint(::Union{
157151
# LinearAlgebra
158152
AbstractMatrix,
@@ -161,13 +155,10 @@ has_adjoint(::Union{
161155

162156
# Base
163157
Number,
164-
165-
# SciMLOperators
166-
AbstractSciMLLinearOperator,
167158
}
168159
) = true
169160

170-
issquare(A) = size(A,1) === size(A,2)
161+
issquare(L) = isequal(size(L)...)
171162
issquare(::Union{
172163
# LinearAlgebra
173164
UniformScaling,
@@ -182,7 +173,6 @@ Base.isreal(L::AbstractSciMLOperator{T}) where{T} = T <: Real
182173
Base.Matrix(L::AbstractSciMLOperator) = Matrix(convert(AbstractMatrix, L))
183174

184175
LinearAlgebra.exp(L::AbstractSciMLOperator,t) = exp(t*L)
185-
has_exp(L::AbstractSciMLLinearOperator) = true
186176
expmv(L::AbstractSciMLOperator,u,p,t) = exp(L,t)*u
187177
expmv!(v,L::AbstractSciMLOperator,u,p,t) = mul!(v,exp(L,t),u)
188178

src/left.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ AbstractAdjointVecOrMat = Adjoint{ T,<:AbstractVecOrMat} where{T}
6060
AbstractTransposedVecOrMat = Transpose{T,<:AbstractVecOrMat} where{T}
6161

6262
has_adjoint(::AdjointOperator) = true
63+
#has_adjoint(::TransposedOperator) = ??
64+
65+
islinear(L::AdjointOperator) = islinear(L.L)
66+
islinear(L::TransposedOperator) = islinear(L.L)
6367

6468
Base.transpose(L::AdjointOperator) = conj(L.L)
6569
Base.adjoint(L::TransposedOperator) = conj(L.L)

src/matrix.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ the following signature:
88
99
update_func(A::AbstractMatrix,u,p,t) -> [modifies A]
1010
"""
11-
struct MatrixOperator{T,AType<:AbstractMatrix{T},F} <: AbstractSciMLLinearOperator{T}
11+
struct MatrixOperator{T,AType<:AbstractMatrix{T},F} <: AbstractSciMLOperator{T}
1212
A::AType
1313
update_func::F
1414
MatrixOperator(A::AType; update_func=DEFAULT_UPDATE_FUNC) where{AType} =
@@ -28,6 +28,8 @@ Base.similar(L::MatrixOperator, ::Type{T}, dims::Dims) where{T} = MatrixOperator
2828
has_ldiv,
2929
has_ldiv!,
3030
)
31+
islinear(::MatrixOperator) = true
32+
3133
Base.size(L::MatrixOperator) = size(L.A)
3234
for op in (
3335
:adjoint,
@@ -121,7 +123,7 @@ Like MatrixOperator, but stores a Factorization instead.
121123
122124
Supports left division and `ldiv!` when applied to an array.
123125
"""
124-
struct InvertibleOperator{T,FType} <: AbstractSciMLLinearOperator{T}
126+
struct InvertibleOperator{T,FType} <: AbstractSciMLOperator{T}
125127
F::FType
126128

127129
function InvertibleOperator(F)
@@ -131,7 +133,7 @@ struct InvertibleOperator{T,FType} <: AbstractSciMLLinearOperator{T}
131133
end
132134

133135
# constructor
134-
function LinearAlgebra.factorize(L::AbstractSciMLLinearOperator)
136+
function LinearAlgebra.factorize(L::AbstractSciMLOperator)
135137
fact = factorize(convert(AbstractMatrix, L))
136138
InvertibleOperator(fact)
137139
end
@@ -172,6 +174,7 @@ LinearAlgebra.opnorm(L::InvertibleOperator{T}, p=2) where{T} = one(T) / opnorm(L
172174
LinearAlgebra.issuccess(L::InvertibleOperator) = issuccess(L.F)
173175

174176
getops(L::InvertibleOperator) = (L.F,)
177+
islinear(L::InvertibleOperator) = islinear(L.F)
175178

176179
@forward InvertibleOperator.F (
177180
# LinearAlgebra

src/scalar.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ Base.adjoint(α::AbstractSciMLScalarOperator) = conj(α)
2626
Base.transpose::AbstractSciMLScalarOperator) = α
2727

2828
has_mul!(::AbstractSciMLScalarOperator) = true
29-
issquare(L::AbstractSciMLScalarOperator) = true
29+
issquare(::AbstractSciMLScalarOperator) = true
30+
islinear(::AbstractSciMLScalarOperator) = true
3031
has_adjoint(::AbstractSciMLScalarOperator) = true
3132

3233
Base.:*::AbstractSciMLScalarOperator, u::AbstractVecOrMat) = convert(Number, α) * u

test/basic.jl

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ K = 12
2727
β = rand()
2828
Id = IdentityOperator{N}()
2929

30+
@test issquare(Id)
31+
@test islinear(Id)
3032
@test IdentityOperator(u) isa IdentityOperator{N}
3133
@test one(A) isa IdentityOperator{N}
3234
@test convert(AbstractMatrix, Id) == Matrix(I, N, N)
@@ -61,6 +63,8 @@ end
6163
β = rand()
6264
Z = NullOperator{N}()
6365

66+
@test issquare(Z)
67+
@test islinear(Z)
6468
@test NullOperator(u) isa NullOperator{N}
6569
@test zero(A) isa NullOperator{N}
6670
@test convert(AbstractMatrix, Z) == zeros(size(Z))
@@ -99,6 +103,8 @@ end
99103
op = ScaledOperator(α, MatrixOperator(A))
100104

101105
@test op isa ScaledOperator
106+
@test issquare(op)
107+
@test islinear(op)
102108

103109
@test α * A * u op * u
104110
@test* op) * u β * α * A * u
@@ -164,10 +170,14 @@ end
164170

165171
@test op isa ComposedOperator
166172
@test *(op.ops...) isa ComposedOperator
173+
@test issquare(op)
174+
@test islinear(op)
167175

168176
opF = factorize(op)
169177

170178
@test opF isa ComposedOperator
179+
@test issquare(opF)
180+
@test islinear(opF)
171181

172182
@test ABCmulu op * u
173183
@test ABCdivu op \ u opF \ u
@@ -202,10 +212,14 @@ end
202212

203213
@testset "Adjoint, Transpose" begin
204214

205-
for (op, LType, VType) in (
206-
(adjoint, AdjointOperator, AbstractAdjointVecOrMat ),
207-
(transpose, TransposedOperator, AbstractTransposedVecOrMat),
208-
)
215+
for (op,
216+
LType,
217+
VType
218+
) in (
219+
(adjoint, AdjointOperator, AbstractAdjointVecOrMat ),
220+
(transpose, TransposedOperator, AbstractTransposedVecOrMat),
221+
)
222+
209223
A = rand(N,N)
210224
D = Bidiagonal(rand(N,N), :L)
211225
u = rand(N,K)
@@ -215,7 +229,13 @@ end
215229
b = rand()
216230

217231
At = op(A)
218-
Dt = op(A)
232+
Dt = op(D)
233+
234+
@test issquare(At)
235+
@test issquare(Dt)
236+
237+
@test islinear(At)
238+
@test islinear(Dt)
219239

220240
AA = MatrixOperator(A)
221241
DD = MatrixOperator(D)
@@ -247,6 +267,9 @@ end
247267

248268
Di = cache_operator(Di, u)
249269

270+
@test issquare(Di)
271+
@test islinear(Di)
272+
250273
@test Di * u u ./ s
251274
v=rand(N); @test mul!(v, Di, u) u ./ s
252275
v=rand(N); w=copy(v); @test mul!(v, Di, u, α, β) α *(u ./ s) + β*w

0 commit comments

Comments
 (0)