Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to JuMP v0.22, MOI v0.14, MP v0.4, MA, v0.3 #224

Merged
merged 11 commits into from
Nov 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ SymbolicWedderburn = "858aa9a9-4c7c-4c62-b466-2421203962a2"

[compat]
Combinatorics = "1"
ComplexOptInterface = "0.0.2"
ComplexOptInterface = "0.0.3"
DataStructures = "0.18"
DynamicPolynomials = "0.3.6"
JuMP = "0.21.7"
MathOptInterface = "0.9.18"
DynamicPolynomials = "0.4.1"
JuMP = "0.22"
MathOptInterface = "0.10"
MultivariateBases = "0.1.2"
MultivariateMoments = "0.3"
MultivariatePolynomials = "~0.3.5"
MutableArithmetics = "0.2"
PolyJuMP = "0.4.2"
MultivariatePolynomials = "0.4"
MutableArithmetics = "0.3"
PolyJuMP = "0.5.1"
Reexport = "0.2, 1.0"
SemialgebraicSets = "0.2"
SymbolicWedderburn = "0.2"
Expand Down
2 changes: 1 addition & 1 deletion docs/src/constraints.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ This approach adds the flexibility to choose the default cone for
* constraints of the form
`@constraint(mode, ..., some_matrix_of_polynomial in PSDCone(), ...)`
or
`@SDconstraint(mode, ..., some_matrix_of_polynomial other_matrix_of_polynomial, ...)`
`@constraint(mode, ..., some_matrix_of_polynomial >= other_matrix_of_polynomial, PSDCone(), ...)`
which is the cone given as default to `PolyJuMP.NonNegPolyMatrix`.

For instance, to use the diagonally-dominant-sum-of-squares cone (see
Expand Down
4 changes: 4 additions & 0 deletions docs/src/tutorials/Extension/univariate_solver.jl
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ function MOI.add_constraint(optimizer::Optimizer, func::MOI.VectorAffineFunction
return MOI.ConstraintIndex{typeof(func),typeof(set)}(1) # There will be only ever one constraint so the index does not matter.
end

MOI.supports_incremental_interface(::Optimizer) = true
function MOI.copy_to(optimizer::Optimizer, model::MOI.ModelLike)
return MOI.Utilities.default_copy_to(optimizer, model)
end
function MOI.optimize!(optimizer::Optimizer)
optimizer.decomposition = decompose(optimizer.p, optimizer.tol)
end
Expand Down
4 changes: 2 additions & 2 deletions src/Bridges/Constraint/diagonally_dominant.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function MOIB.Constraint.bridge_constraint(
koff += 1
# abs ≥ |Qij|
abs_vars[koff] = MOI.add_variable(model)
fabs = MOI.SingleVariable(abs_vars[koff])
fabs = abs_vars[koff]
MOIU.operate!(-, T, g[j], fabs)
MOIU.operate!(-, T, g[i], fabs)
abs_plus[koff] = MOI.add_constraint(
Expand Down Expand Up @@ -71,7 +71,7 @@ function MOIB.Constraint.concrete_bridge_type(
::Type{SOS.DiagonallyDominantConeTriangle}) where T

S = MOIU.scalar_type(G)
F = MOIU.promote_operation(-, T, S, MOI.SingleVariable)
F = MOIU.promote_operation(-, T, S, MOI.VariableIndex)
return DiagonallyDominantBridge{T, F, G}
end

Expand Down
2 changes: 1 addition & 1 deletion src/Bridges/Constraint/sos_polynomial.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function MOI.Bridges.Constraint.bridge_constraint(
g, Q, cQ = SOS.add_gram_matrix(model, MCT, gram_basis, T)
# MOI does not modify the coefficients of the functions so we can modify `r`.
# without altering `f`.
q = MA.operate!(-, r, g)
q = MA.operate!!(-, r, g)
set = PolyJuMP.ZeroPolynomialSet(s.domain, SOS.Certificate.zero_basis(s.certificate), MP.monomials(q))
coefs = MOIU.vectorize(MP.coefficients(q))
zero_constraint = MOI.add_constraint(model, coefs, set)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function MOI.Bridges.Constraint.bridge_constraint(
# `set.domain.V` is `FullSpace` or `FixedPolynomialsSet`.
g = Certificate.get(set.certificate, Certificate.Generator(), index, preprocessed)
# TODO replace with `MA.sub_mul` when it works.
p = MA.operate!(MA.add_mul, p, -one(T), λ, MP.changecoefficienttype(g, T))
p = MA.operate!!(MA.add_mul, p, -one(T), λ, MP.changecoefficienttype(g, T))
end
new_set = SOS.SOSPolynomialSet(
set.domain.V, MP.monomials(p),
Expand Down
14 changes: 7 additions & 7 deletions src/Bridges/Variable/copositive_inner.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ function offdiag_vector_index(i, j)
end

function MOI.get(model::MOI.ModelLike, attr::MOI.VariablePrimal,
bridge::CopositiveInnerBridge, i::MOIB.Variable.IndexInVector)
bridge::CopositiveInnerBridge, i::MOIB.IndexInVector)
value = MOI.get(model, attr, bridge.matrix_variables[i.value])
row, col = matrix_indices(i.value)
if row != col
Expand All @@ -103,22 +103,22 @@ function MOI.get(model::MOI.ModelLike, attr::MOI.VariablePrimal,
end

function MOIB.bridged_function(bridge::CopositiveInnerBridge{T},
i::MOIB.Variable.IndexInVector) where T
i::MOIB.IndexInVector) where T
func = convert(MOI.ScalarAffineFunction{T},
MOI.SingleVariable(bridge.matrix_variables[i.value]))
bridge.matrix_variables[i.value])
row, col = matrix_indices(i.value)
if row != col
func = MOIU.operate!(+, T, func, MOI.SingleVariable(
bridge.nonneg_variables[vector_index(row, col - 1)]))
func = MOIU.operate!(+, T, func,
bridge.nonneg_variables[vector_index(row, col - 1)])
end
return func
end
function MOIB.Variable.unbridged_map(
bridge::CopositiveInnerBridge{T},
vi::MOI.VariableIndex, i::MOIB.Variable.IndexInVector) where T
vi::MOI.VariableIndex, i::MOIB.IndexInVector) where T

F = MOI.ScalarAffineFunction{T}
func = convert(F, MOI.SingleVariable(vi))
func = convert(F, vi)
map = bridge.matrix_variables[i.value] => func
row, col = matrix_indices(i.value)
if row == col
Expand Down
17 changes: 8 additions & 9 deletions src/Bridges/Variable/psd2x2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function MOI.get(model::MOI.ModelLike,
return [dual[1], dual[3] / √2, dual[2]]
end

function _variable_map(i::MOIB.Variable.IndexInVector)
function _variable_map(i::MOIB.IndexInVector)
if i.value == 1
return 1
elseif i.value == 2
Expand All @@ -82,12 +82,12 @@ function _variable_map(i::MOIB.Variable.IndexInVector)
end
end
function _variable(bridge::PositiveSemidefinite2x2Bridge,
i::MOIB.Variable.IndexInVector)
i::MOIB.IndexInVector)
return bridge.variables[_variable_map(i)]
end

function MOI.get(model::MOI.ModelLike, attr::MOI.VariablePrimal,
bridge::PositiveSemidefinite2x2Bridge, i::MOIB.Variable.IndexInVector)
bridge::PositiveSemidefinite2x2Bridge, i::MOIB.IndexInVector)
value = MOI.get(model, attr, _variable(bridge, i))
if i.value == 2
value /= √2
Expand All @@ -96,8 +96,8 @@ function MOI.get(model::MOI.ModelLike, attr::MOI.VariablePrimal,
end

function MOIB.bridged_function(bridge::PositiveSemidefinite2x2Bridge{T},
i::MOIB.Variable.IndexInVector) where T
func = MOI.SingleVariable(_variable(bridge, i))
i::MOIB.IndexInVector) where T
func = _variable(bridge, i)
if i.value == 2
return MOIU.operate(/, T, func, convert(T, √2))
else
Expand All @@ -106,13 +106,12 @@ function MOIB.bridged_function(bridge::PositiveSemidefinite2x2Bridge{T},
end
function MOIB.Variable.unbridged_map(
bridge::PositiveSemidefinite2x2Bridge{T},
vi::MOI.VariableIndex, i::MOIB.Variable.IndexInVector) where T
vi::MOI.VariableIndex, i::MOIB.IndexInVector) where T

sv = MOI.SingleVariable(vi)
if i.value == 2
func = MOIU.operate(*, T, convert(T, √2), sv)
func = MOIU.operate(*, T, convert(T, √2), vi)
else
func = convert(MOI.ScalarAffineFunction{T}, sv)
func = convert(MOI.ScalarAffineFunction{T}, vi)
end
return (_variable(bridge, i) => func,)
end
12 changes: 6 additions & 6 deletions src/Bridges/Variable/scaled_diagonally_dominant.jl
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ end
trimap(i, j) = div(j * (j - 1), 2) + i

function MOI.get(model::MOI.ModelLike, attr::MOI.VariablePrimal,
bridge::ScaledDiagonallyDominantBridge{T}, i::MOIB.Variable.IndexInVector) where T
bridge::ScaledDiagonallyDominantBridge{T}, i::MOIB.IndexInVector) where T
i, j = matrix_indices(i.value)
if i == j
value = zero(T)
Expand All @@ -115,22 +115,22 @@ function MOI.get(model::MOI.ModelLike, attr::MOI.VariablePrimal,
end

function MOIB.bridged_function(bridge::ScaledDiagonallyDominantBridge{T},
i::MOIB.Variable.IndexInVector) where T
i::MOIB.IndexInVector) where T
i, j = matrix_indices(i.value)
if i == j
func = zero(MOI.ScalarAffineFunction{T})
for k in 1:(i - 1)
idx = offdiag_vector_index(k, i)
MOIU.operate!(+, T, func, MOI.SingleVariable(bridge.variables[idx][3]))
MOIU.operate!(+, T, func, bridge.variables[idx][3])
end
for k in (i + 1):bridge.side_dimension
idx = offdiag_vector_index(i, k)
MOIU.operate!(+, T, func, MOI.SingleVariable(bridge.variables[idx][1]))
MOIU.operate!(+, T, func, bridge.variables[idx][1])
end
return func
else
idx = offdiag_vector_index(i, j)
return MOI.convert(MOI.ScalarAffineFunction{T}, MOI.SingleVariable(bridge.variables[idx][2]))
return MOI.convert(MOI.ScalarAffineFunction{T}, bridge.variables[idx][2])
end
end
function MOIB.Variable.unbridged_map(
Expand All @@ -141,7 +141,7 @@ function MOIB.Variable.unbridged_map(
umap = Pair{MOI.VariableIndex, SAF}[]
k = 0
z = zero(SAF)
saf(i) = convert(SAF, MOI.SingleVariable(vis[i]))
saf(i) = convert(SAF, vis[i])
# vis[trimap(j, j)] is replaced by a sum of several variables.
# The strategy is to replace all of them by zero except one.
for j in 1:bridge.side_dimension
Expand Down
8 changes: 4 additions & 4 deletions src/gram_matrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,17 @@ function gram_operate(::typeof(+), p::GramMatrix{S, B, US, SymMatrix{S}}, q::Gra
U = MA.promote_operation(+, S, T)
n = length(basis)
Qvec = Vector{U}(undef, div(n * (n + 1), 2))
MA.mutable_operate!(zero, Qvec)
MA.operate!(zero, Qvec)
Q = SymMatrix(Qvec, n)
for j in 1:n
for i in 1:j
if !iszero(Ip[j]) && !iszero(Ip[i])
MultivariateMoments.symmetric_setindex!(
Q, MA.add!(Q[i, j], p.Q[Ip[i], Ip[j]]), i, j)
Q, MA.add!!(Q[i, j], p.Q[Ip[i], Ip[j]]), i, j)
end
if !iszero(Iq[j]) && !iszero(Iq[i])
MultivariateMoments.symmetric_setindex!(
Q, MA.add!(Q[i, j], q.Q[Iq[i], Iq[j]]), i, j)
Q, MA.add!!(Q[i, j], q.Q[Iq[i], Iq[j]]), i, j)
end
end
end
Expand Down Expand Up @@ -140,5 +140,5 @@ end

Base.zero(::Type{SparseGramMatrix{T, B, U, MT}}) where {T, B, U, MT} = SparseGramMatrix(GramMatrix{T, B, U, MT}[])
function MP.polynomial(p::SparseGramMatrix)
return mapreduce(identity, MA.add!, p.sub_gram_matrices, init = zero(MP.polynomialtype(p)))
return mapreduce(identity, MA.add!!, p.sub_gram_matrices, init = zero(MP.polynomialtype(p)))
end
12 changes: 2 additions & 10 deletions src/sos_polynomial.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,6 @@ function vectorized_matrix(Q, basis, ::Type{COI.HermitianPositiveSemidefiniteCon
end

# Need these two methods to avoid ambiguity
function build_gram_matrix(q::Vector{MOI.VariableIndex},
basis::AbstractPolynomialBasis, matrix_cone_type, T::Type)
return build_gram_matrix([MOI.SingleVariable(vi) for vi in q], basis, matrix_cone_type, T)
end
#function build_gram_matrix(q::Vector{MOI.VariableIndex},
# basis::AbstractPolynomialBasis, T::Type, vectorization::HermitianVectorized)
# return build_gram_matrix([MOI.SingleVariable(vi) for vi in q], basis, T, vectorization)
#end
function build_gram_matrix(q::Vector,
basis::AbstractPolynomialBasis, matrix_cone_type, T::Type)
n = length(basis)
Expand Down Expand Up @@ -50,10 +42,10 @@ end
# for j in 1:n
# for i in 1:j
# k_real += 1
# C[k_real] = MA.operate!(MA.add_mul, C[k_real], one(T), q[k_real])
# C[k_real] = MA.operate!!(MA.add_mul, C[k_real], one(T), q[k_real])
# if i != j
# k_imag += 1
# C[k_real] = MA.operate!(MA.add_mul, C[k_real], one(T) * im, q[N + k_imag])
# C[k_real] = MA.operate!!(MA.add_mul, C[k_real], one(T) * im, q[N + k_imag])
# end
# end
# end
Expand Down
14 changes: 6 additions & 8 deletions src/utilities.jl
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
# The second type is ignored. For `T = VariableRef`, it should be `Float64` anyway
# since JuMP only supports `Float64`.
_promote_sum(T::Type, ::Type=Float64) = MA.promote_operation(+, T, T)
# `+` is not defined between `MOI.SingleVariable`.
_promote_sum(::Type{MOI.SingleVariable}, T::Type=Float64) = MOI.ScalarAffineFunction{T}
# `+` is not defined between `MOI.VariableIndex`.
_promote_sum(::Type{MOI.VariableIndex}, T::Type=Float64) = MOI.ScalarAffineFunction{T}

_promote_add_mul(T::Type) = MA.promote_operation(MA.add_mul, T, T, T)
_promote_add_mul(::Type{MOI.SingleVariable}) = MOI.ScalarQuadraticFunction{Float64}
function MP.polynomial(p::GramMatrix{MOI.SingleVariable, B, U}) where {B, U}
_promote_add_mul(::Type{MOI.VariableIndex}) = MOI.ScalarQuadraticFunction{Float64}
function MP.polynomial(p::GramMatrix{MOI.VariableIndex, B, U}) where {B, U}
Q = convert(Vector{U}, p.Q.Q)
return MP.polynomial(GramMatrix(SymMatrix(Q, p.Q.n), p.basis))
end
#function MP.polynomial(p::GramMatrix{F}) where {F <: MOI.AbstractFunction}
# MP.polynomial(p, MOIU.promote_operation(+, Float64, F, F))
#end

function primal_value(model, p::GramMatrix{MOI.SingleVariable})
# TODO [perf] use MOI typed mapped array
Q = MOI.get(model, MOI.VariablePrimal(),
MOI.VariableIndex[sv.variable for sv in p.Q.Q])
function primal_value(model, p::GramMatrix{MOI.VariableIndex})
Q = MOI.get(model, MOI.VariablePrimal(), p.Q.Q)
return GramMatrix(SymMatrix(Q, p.Q.n), p.basis)
end

Expand Down
28 changes: 21 additions & 7 deletions test/Mock/BPT12e399.jl
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
config = MOI.Test.TestConfig()
optimize!_max(mock) = MOIU.mock_optimize!(mock, [ 6.0, 1.0, 9.0, -3.0*√2],
config = MOI.Test.Config()
optimize!_max_bridged(mock) = MOIU.mock_optimize!(mock, [ 6.0, 1.0, 9.0, -3.0*√2],
(MOI.VectorAffineFunction{Float64}, MOI.Zeros) => [[3, 1, 1/3]],
(MOI.VectorOfVariables, MOI.RotatedSecondOrderCone) => [[3, 1/3, √2]]
)
optimize!_min(mock) = MOIU.mock_optimize!(mock, [-6.0, 1.0, 9.0, 3.0*√2],
optimize!_min_bridged(mock) = MOIU.mock_optimize!(mock, [-6.0, 1.0, 9.0, 3.0*√2],
(MOI.VectorAffineFunction{Float64}, MOI.Zeros) => [[3, -1, 1/3]],
(MOI.VectorOfVariables, MOI.RotatedSecondOrderCone) => [[3, 1/3, -√2]]
)
for mock in mocks(optimize!_max, optimize!_min)
optimize!_max_cached(mock) = MOIU.mock_optimize!(mock, [1.0, 9.0, -3.0*√2, 6.0],
(MOI.VectorAffineFunction{Float64}, MOI.Zeros) => [[3, 1, 1/3]],
(MOI.VectorOfVariables, MOI.RotatedSecondOrderCone) => [[3, 1/3, √2]]
)
optimize!_min_cached(mock) = MOIU.mock_optimize!(mock, [1.0, 9.0, 3.0*√2, -6.0],
(MOI.VectorAffineFunction{Float64}, MOI.Zeros) => [[3, -1, 1/3]],
(MOI.VectorOfVariables, MOI.RotatedSecondOrderCone) => [[3, 1/3, -√2]]
)
for mock in [bridged_mock(optimize!_max_bridged, optimize!_min_bridged), cached_mock(optimize!_max_cached, optimize!_min_cached)]
Tests.BPT12e399_rem_test(mock, config)
end
optimize!_max(mock) = MOIU.mock_optimize!(mock, [ 10.0, 4.0, 0.0, 5.0, 0.0, -5.0, 5.0],
optimize!_max_bridged(mock) = MOIU.mock_optimize!(mock, [ 10.0, 4.0, 0.0, 5.0, 0.0, -5.0, 5.0],
(MOI.VectorAffineFunction{Float64}, MOI.Zeros) => [[0.0, 1, 0, 1, 1]]
)
optimize!_min_bridged(mock) = MOIU.mock_optimize!(mock, [-10.0, 4.0, 0.0, 5.0, 0.0, 5.0, 5.0],
(MOI.VectorAffineFunction{Float64}, MOI.Zeros) => [[0.0, 1, 0, -1, 1]]
)
optimize!_max_cached(mock) = MOIU.mock_optimize!(mock, [4.0, 0.0, 5.0, 0.0, -5.0, 5.0, 10.0],
(MOI.VectorAffineFunction{Float64}, MOI.Zeros) => [[0.0, 1, 0, 1, 1]]
)
optimize!_min(mock) = MOIU.mock_optimize!(mock, [-10.0, 4.0, 0.0, 5.0, 0.0, 5.0, 5.0],
optimize!_min_cached(mock) = MOIU.mock_optimize!(mock, [4.0, 0.0, 5.0, 0.0, 5.0, 5.0, -10.0],
(MOI.VectorAffineFunction{Float64}, MOI.Zeros) => [[0.0, 1, 0, -1, 1]]
)
for mock in mocks(optimize!_max, optimize!_min)
for mock in [bridged_mock(optimize!_max_bridged, optimize!_min_bridged), cached_mock(optimize!_max_cached, optimize!_min_cached)]
Tests.BPT12e399_maxdegree_test(mock, config)
end
7 changes: 4 additions & 3 deletions test/Mock/chebyshev.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
config = MOI.Test.TestConfig()
optimize!(mock) = MOIU.mock_optimize!(mock, [[128.0, 0.0, -256.0, 0.0, 160.0, 0.0, -32.0, 0.0, 1.0]; zeros(90)])
for mock in mocks(optimize!)
config = MOI.Test.Config()
optimize_bridged!(mock) = MOIU.mock_optimize!(mock, [[128.0, 0.0, -256.0, 0.0, 160.0, 0.0, -32.0, 0.0, 1.0]; zeros(90)])
optimize_cached!(mock) = MOIU.mock_optimize!(mock, [zeros(90); [128.0, 0.0, -256.0, 0.0, 160.0, 0.0, -32.0, 0.0, 1.0]])
for mock in [bridged_mock(optimize_bridged!), cached_mock(optimize_cached!)]
Tests.chebyshev_test(mock, config)
end
6 changes: 3 additions & 3 deletions test/Mock/choi.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
config = MOI.Test.TestConfig()
optimize!(mock) = MOIU.mock_optimize!(mock, MOI.INFEASIBLE, tuple(),
MOI.INFEASIBILITY_CERTIFICATE)
config = MOI.Test.Config()
optimize!(mock) = MOIU.mock_optimize!(
mock, MOI.INFEASIBLE, MOI.NO_SOLUTION, MOI.INFEASIBILITY_CERTIFICATE)
for mock in mocks(optimize!)
Tests.choi_test(mock, config)
end
Loading