Skip to content

Commit 373f3f5

Browse files
authored
VectorQuadratic as VectorAffine (#231)
* VectorQuadratic as VectorAffine * format
1 parent 7116db7 commit 373f3f5

3 files changed

Lines changed: 38 additions & 0 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ docs/build
22
docs/src/release_notes.md
33
Manifest.toml
44
.DS_Store
5+
*.cov

src/MOI_wrapper.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,24 @@ function MOI.add_constraint(
11071107
set::MOI.AbstractVectorSet,
11081108
) where {T}
11091109
if !_has_parameters(f)
1110+
# The user might construct a VectorQuadraticFunction with no actual
1111+
# quadratic terms (e.g. from a JuMP expression that simplifies to
1112+
# affine). Convert to VectorAffineFunction while still recording the
1113+
# outer_to_inner map so that get(ConstraintFunction) can return the
1114+
# original VectorQuadraticFunction type.
1115+
if _is_vector_affine(f)
1116+
fa = MOI.VectorAffineFunction(f.affine_terms, f.constants)
1117+
inner_ci = MOI.add_constraint(model.optimizer, fa, set)
1118+
model.last_vec_quad_add_added += 1
1119+
outer_ci =
1120+
MOI.ConstraintIndex{MOI.VectorQuadraticFunction{T},typeof(set)}(
1121+
model.last_vec_quad_add_added,
1122+
)
1123+
model.vector_quadratic_outer_to_inner[outer_ci] = inner_ci
1124+
model.constraint_outer_to_inner[outer_ci] = inner_ci
1125+
model.vector_quadratic_constraint_cache_set[inner_ci] = set
1126+
return outer_ci
1127+
end
11101128
return _add_constraint_direct_and_cache_map!(model, f, set)
11111129
else
11121130
return _add_constraint_with_parameters_on_function(model, f, set)

test/test_MathOptInterface.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,6 +2346,25 @@ function test_constraint_primal_start_get_for_parameter()
23462346
return
23472347
end
23482348

2349+
function test_vector_quadratic_no_parameters_affine_get_constraint_function()
2350+
# A VectorQuadraticFunction with no parameters and no quadratic terms
2351+
# (empty quadratic_terms) should use the affine fast path. The outer
2352+
# constraint index is a VectorQuadraticFunction index (preserving the
2353+
# original type), but the inner optimizer stores it as VectorAffine.
2354+
# get(ConstraintFunction) must reconstruct the original VQF.
2355+
model = POI.Optimizer(MOI.Utilities.Model{Float64}())
2356+
x = MOI.add_variable(model)
2357+
quadratic_terms = MOI.VectorQuadraticTerm{Float64}[]
2358+
affine_terms = [MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(2.0, x))]
2359+
constants = [1.0]
2360+
f = MOI.VectorQuadraticFunction(quadratic_terms, affine_terms, constants)
2361+
ci = MOI.add_constraint(model, f, MOI.Zeros(1))
2362+
@test MOI.is_valid(model, ci)
2363+
f2 = MOI.get(model, MOI.ConstraintFunction(), ci)
2364+
@test canonical_compare(f, f2)
2365+
return
2366+
end
2367+
23492368
end # module
23502369

23512370
TestMathOptInterfaceTests.runtests()

0 commit comments

Comments
 (0)