Skip to content

Commit dce3899

Browse files
authored
Merge branch 'master' into isconstant
2 parents fef139f + f0c96d8 commit dce3899

File tree

13 files changed

+117
-52
lines changed

13 files changed

+117
-52
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")
@@ -60,6 +55,9 @@ export update_coefficients!,
6055

6156
cache_operator,
6257

58+
issquare,
59+
islinear,
60+
6361
has_adjoint,
6462
has_expmv,
6563
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
@@ -106,7 +101,9 @@ isconstant(::Union{
106101
) = true
107102
isconstant(L::AbstractSciMLOperator) = all(isconstant, getops(L))
108103

109-
islinear(L) = false
104+
#islinear(L) = false
105+
islinear(::AbstractSciMLOperator) = false
106+
110107
islinear(::Union{
111108
# LinearAlgebra
112109
AbstractMatrix,
@@ -115,23 +112,20 @@ islinear(::Union{
115112

116113
# Base
117114
Number,
118-
119-
# SciMLOperators
120-
AbstractSciMLLinearOperator,
121115
}
122116
) = true
123117

124118
has_mul(L) = false
125119
has_mul(::Union{
126-
# LinearAlgebra
127-
AbstractVecOrMat,
128-
AbstractMatrix,
129-
UniformScaling,
120+
# LinearAlgebra
121+
AbstractVecOrMat,
122+
AbstractMatrix,
123+
UniformScaling,
130124

131-
# Base
132-
Number,
133-
}
134-
) = true
125+
# Base
126+
Number,
127+
}
128+
) = true
135129

136130
has_mul!(L) = false
137131
has_mul!(::Union{
@@ -161,7 +155,7 @@ has_ldiv!(::Union{
161155
}
162156
) = true
163157

164-
has_adjoint(L) = false
158+
has_adjoint(L) = islinear(L)
165159
has_adjoint(::Union{
166160
# LinearAlgebra
167161
AbstractMatrix,
@@ -170,13 +164,10 @@ has_adjoint(::Union{
170164

171165
# Base
172166
Number,
173-
174-
# SciMLOperators
175-
AbstractSciMLLinearOperator,
176167
}
177168
) = true
178169

179-
issquare(A) = size(A,1) === size(A,2)
170+
issquare(L) = isequal(size(L)...)
180171
issquare(::Union{
181172
# LinearAlgebra
182173
UniformScaling,
@@ -191,7 +182,6 @@ Base.isreal(L::AbstractSciMLOperator{T}) where{T} = T <: Real
191182
Base.Matrix(L::AbstractSciMLOperator) = Matrix(convert(AbstractMatrix, L))
192183

193184
LinearAlgebra.exp(L::AbstractSciMLOperator,t) = exp(t*L)
194-
has_exp(L::AbstractSciMLLinearOperator) = true
195185
expmv(L::AbstractSciMLOperator,u,p,t) = exp(L,t)*u
196186
expmv!(v,L::AbstractSciMLOperator,u,p,t) = mul!(v,exp(L,t),u)
197187

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,
@@ -123,7 +125,7 @@ Like MatrixOperator, but stores a Factorization instead.
123125
124126
Supports left division and `ldiv!` when applied to an array.
125127
"""
126-
struct InvertibleOperator{T,FType} <: AbstractSciMLLinearOperator{T}
128+
struct InvertibleOperator{T,FType} <: AbstractSciMLOperator{T}
127129
F::FType
128130

129131
function InvertibleOperator(F)
@@ -133,7 +135,7 @@ struct InvertibleOperator{T,FType} <: AbstractSciMLLinearOperator{T}
133135
end
134136

135137
# constructor
136-
function LinearAlgebra.factorize(L::AbstractSciMLLinearOperator)
138+
function LinearAlgebra.factorize(L::AbstractSciMLOperator)
137139
fact = factorize(convert(AbstractMatrix, L))
138140
InvertibleOperator(fact)
139141
end
@@ -174,6 +176,7 @@ LinearAlgebra.opnorm(L::InvertibleOperator{T}, p=2) where{T} = one(T) / opnorm(L
174176
LinearAlgebra.issuccess(L::InvertibleOperator) = issuccess(L.F)
175177

176178
getops(L::InvertibleOperator) = (L.F,)
179+
islinear(L::InvertibleOperator) = islinear(L.F)
177180

178181
@forward InvertibleOperator.F (
179182
# 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: 27 additions & 6 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)
@@ -62,6 +64,8 @@ end
6264
β = rand()
6365
Z = NullOperator{N}()
6466

67+
@test issquare(Z)
68+
@test islinear(Z)
6569
@test NullOperator(u) isa NullOperator{N}
6670
@test isconstant(Z)
6771
@test zero(A) isa NullOperator{N}
@@ -102,6 +106,8 @@ end
102106

103107
@test op isa ScaledOperator
104108
@test isconstant(op)
109+
@test issquare(op)
110+
@test islinear(op)
105111

106112
@test α * A * u op * u
107113
@test* op) * u β * α * A * u
@@ -175,11 +181,15 @@ end
175181
@test isconstant(op)
176182

177183
@test *(op.ops...) isa ComposedOperator
184+
@test issquare(op)
185+
@test islinear(op)
178186

179187
opF = factorize(op)
180188

181189
@test opF isa ComposedOperator
182190
@test isconstant(opF)
191+
@test issquare(opF)
192+
@test islinear(opF)
183193

184194
@test ABCmulu op * u
185195
@test ABCdivu op \ u opF \ u
@@ -214,10 +224,14 @@ end
214224

215225
@testset "Adjoint, Transpose" begin
216226

217-
for (op, LType, VType) in (
218-
(adjoint, AdjointOperator, AbstractAdjointVecOrMat ),
219-
(transpose, TransposedOperator, AbstractTransposedVecOrMat),
220-
)
227+
for (op,
228+
LType,
229+
VType
230+
) in (
231+
(adjoint, AdjointOperator, AbstractAdjointVecOrMat ),
232+
(transpose, TransposedOperator, AbstractTransposedVecOrMat),
233+
)
234+
221235
A = rand(N,N)
222236
D = Bidiagonal(rand(N,N), :L)
223237
u = rand(N,K)
@@ -227,7 +241,13 @@ end
227241
b = rand()
228242

229243
At = op(A)
230-
Dt = op(A)
244+
Dt = op(D)
245+
246+
@test issquare(At)
247+
@test issquare(Dt)
248+
249+
@test islinear(At)
250+
@test islinear(Dt)
231251

232252
AA = MatrixOperator(A)
233253
DD = MatrixOperator(D)
@@ -261,8 +281,9 @@ end
261281
β = rand()
262282

263283
Di = cache_operator(Di, u)
264-
265284
@test isconstant(Di)
285+
@test issquare(Di)
286+
@test islinear(Di)
266287

267288
@test Di * u u ./ s
268289
v=rand(N); @test mul!(v, Di, u) u ./ s

0 commit comments

Comments
 (0)