Skip to content

Commit 23d6e2d

Browse files
authored
Fix PowerCone in MatrixOfConstraints (#1722)
1 parent 731430a commit 23d6e2d

File tree

2 files changed

+161
-3
lines changed

2 files changed

+161
-3
lines changed

src/Utilities/matrix_of_constraints.jl

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -413,16 +413,19 @@ function _load_constants(
413413
set::MOI.AbstractScalarSet,
414414
)
415415
MOI.throw_if_scalar_and_constant_not_zero(func, typeof(set))
416-
return load_constants(constants, offset, set)
416+
load_constants(constants, offset, set)
417+
return
417418
end
418419

419420
function _load_constants(
420421
constants,
421422
offset,
422423
func::MOI.AbstractVectorFunction,
423-
::MOI.AbstractVectorSet,
424+
set::MOI.AbstractVectorSet,
424425
)
425-
return load_constants(constants, offset, func)
426+
load_constants(constants, offset, func)
427+
load_constants(constants, offset, set)
428+
return
426429
end
427430

428431
function _load_constraints(
@@ -523,6 +526,19 @@ function load_constants(
523526
return
524527
end
525528

529+
load_constants(::Vector, ::Any, ::MOI.AbstractVectorSet) = nothing
530+
531+
function load_constants(
532+
::Vector,
533+
::Any,
534+
S::Union{MOI.PowerCone,MOI.DualPowerCone},
535+
)
536+
return error(
537+
"`$(typeof(S))` cannot be used with `Vector` as the set type in " *
538+
"MatrixOfConstraints",
539+
)
540+
end
541+
526542
function_constants(b::Vector, rows) = b[rows]
527543

528544
"""

test/Utilities/matrix_of_constraints.jl

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,148 @@ function test_matrix_sets(::Type{T} = Int) where {T}
443443
return
444444
end
445445

446+
MOI.Utilities.@product_of_sets(
447+
PowerSets,
448+
MOI.PowerCone{T},
449+
MOI.DualPowerCone{T},
450+
)
451+
452+
function test_power_cone_error()
453+
model = MOI.Utilities.Model{Float64}()
454+
x = MOI.add_variables(model, 3)
455+
f = MOI.Utilities.operate(vcat, Float64, 1.0 .* x...)
456+
s = MOI.PowerCone(0.2)
457+
MOI.add_constraint(model, f, s)
458+
cache = MOI.Utilities.GenericOptimizer{
459+
Float64,
460+
MOI.Utilities.ObjectiveContainer{Float64},
461+
MOI.Utilities.VariablesContainer{Float64},
462+
MOI.Utilities.MatrixOfConstraints{
463+
Float64,
464+
MOI.Utilities.MutableSparseMatrixCSC{
465+
Float64,
466+
Int,
467+
MOI.Utilities.OneBasedIndexing,
468+
},
469+
Vector{Float64},
470+
PowerSets{Float64},
471+
},
472+
}()
473+
@test_throws(
474+
ErrorException(
475+
"`$(typeof(s))` cannot be used with `Vector` as the set type in " *
476+
"MatrixOfConstraints",
477+
),
478+
MOI.copy_to(cache, model),
479+
)
480+
return
481+
end
482+
483+
function test_dual_power_cone_error()
484+
model = MOI.Utilities.Model{Float64}()
485+
x = MOI.add_variables(model, 3)
486+
f = MOI.Utilities.operate(vcat, Float64, 1.0 .* x...)
487+
s = MOI.DualPowerCone(0.2)
488+
MOI.add_constraint(model, f, s)
489+
cache = MOI.Utilities.GenericOptimizer{
490+
Float64,
491+
MOI.Utilities.ObjectiveContainer{Float64},
492+
MOI.Utilities.VariablesContainer{Float64},
493+
MOI.Utilities.MatrixOfConstraints{
494+
Float64,
495+
MOI.Utilities.MutableSparseMatrixCSC{
496+
Float64,
497+
Int,
498+
MOI.Utilities.OneBasedIndexing,
499+
},
500+
Vector{Float64},
501+
PowerSets{Float64},
502+
},
503+
}()
504+
@test_throws(
505+
ErrorException(
506+
"`$(typeof(s))` cannot be used with `Vector` as the set type in " *
507+
"MatrixOfConstraints",
508+
),
509+
MOI.copy_to(cache, model),
510+
)
511+
return
512+
end
513+
514+
struct _SetConstants{T}
515+
b::Vector{T}
516+
power_coefficients::Dict{Int,T}
517+
_SetConstants{T}() where {T} = new{T}(T[], Dict{Int,T}())
518+
end
519+
520+
function Base.empty!(x::_SetConstants)
521+
empty!(x.b)
522+
empty!(x.power_coefficients)
523+
return x
524+
end
525+
526+
Base.resize!(x::_SetConstants, n) = resize!(x.b, n)
527+
528+
function MOI.Utilities.load_constants(x::_SetConstants, offset, f)
529+
MOI.Utilities.load_constants(x.b, offset, f)
530+
return
531+
end
532+
533+
function MOI.Utilities.load_constants(
534+
x::_SetConstants{T},
535+
offset,
536+
set::Union{MOI.PowerCone{T},MOI.DualPowerCone{T}},
537+
) where {T}
538+
x.power_coefficients[offset+1] = set.exponent
539+
return
540+
end
541+
542+
function MOI.Utilities.function_constants(x::_SetConstants, rows)
543+
return MOI.Utilities.function_constants(x.b, rows)
544+
end
545+
546+
function MOI.Utilities.set_from_constants(x::_SetConstants, S, rows)
547+
return MOI.Utilities.set_from_constants(x.b, S, rows)
548+
end
549+
550+
function MOI.Utilities.set_from_constants(
551+
x::_SetConstants{T},
552+
::Type{S},
553+
rows,
554+
) where {T,S<:Union{MOI.PowerCone{T},MOI.DualPowerCone{T}}}
555+
@assert length(rows) == 3
556+
return S(x.power_coefficients[first(rows)])
557+
end
558+
559+
function test_dual_power_cone()
560+
model = MOI.Utilities.Model{Float64}()
561+
x = MOI.add_variables(model, 3)
562+
f = MOI.Utilities.operate(vcat, Float64, 1.0 .* x...)
563+
p_cone = MOI.PowerCone(0.1)
564+
p_ref = MOI.add_constraint(model, f, p_cone)
565+
d_cone = MOI.DualPowerCone(0.2)
566+
d_ref = MOI.add_constraint(model, f, d_cone)
567+
cache = MOI.Utilities.GenericOptimizer{
568+
Float64,
569+
MOI.Utilities.ObjectiveContainer{Float64},
570+
MOI.Utilities.VariablesContainer{Float64},
571+
MOI.Utilities.MatrixOfConstraints{
572+
Float64,
573+
MOI.Utilities.MutableSparseMatrixCSC{
574+
Float64,
575+
Int,
576+
MOI.Utilities.OneBasedIndexing,
577+
},
578+
_SetConstants{Float64},
579+
PowerSets{Float64},
580+
},
581+
}()
582+
map = MOI.copy_to(cache, model)
583+
@test MOI.get(cache, MOI.ConstraintSet(), map[p_ref]) == p_cone
584+
@test MOI.get(cache, MOI.ConstraintSet(), map[d_ref]) == d_cone
585+
return
586+
end
587+
446588
end
447589

448590
TestMatrixOfConstraints.runtests()

0 commit comments

Comments
 (0)