Skip to content

Commit 9abcbea

Browse files
authored
Clearer error message with constrained variables in VectorOfVariables (#3061)
1 parent 9bddcb7 commit 9abcbea

2 files changed

Lines changed: 56 additions & 0 deletions

File tree

src/Utilities/functions.jl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,36 @@ function substitute_variables(
543543
return MOI.ScalarNonlinearFunction(f.head, new_args)
544544
end
545545

546+
function substitute_variables(
547+
variable_map::F,
548+
f::MOI.VectorOfVariables,
549+
) where {F<:Function}
550+
variables = MOI.VariableIndex[]
551+
for (i, x) in enumerate(f.variables)
552+
y = variable_map(x)
553+
try
554+
push!(variables, convert(MOI.VariableIndex, y))
555+
catch err
556+
@assert err isa InexactError
557+
error(
558+
"""
559+
Cannot substitute variables in the `VectorOfVariables` \
560+
function because the result is not representable as a \
561+
`VectorOfVariables` function.
562+
563+
The variable `$x` in index `$i` is mapped to the expression \
564+
`$y`, not directly to another `VariableIndex`.
565+
566+
Note that variables constrained on creation can be used in a \
567+
`VectorOfVariables` function only when their bridge maps each \
568+
one directly to another variable, without a transformation.
569+
""",
570+
)
571+
end
572+
end
573+
return MOI.VectorOfVariables(variables)
574+
end
575+
546576
function substitute_variables(
547577
variable_map::F,
548578
f::MOI.VectorAffineFunction{T},

test/Utilities/test_functions.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,32 @@ function test_substitute_variables()
332332
return
333333
end
334334

335+
function test_substitute_variables_vector_of_variables()
336+
w, x, y, z = MOI.VariableIndex.(1:4)
337+
f1 = MOI.VectorOfVariables([w, x])
338+
f2 = MOI.VectorOfVariables([y, z])
339+
v_map = Dict(w => y, x => z)
340+
@test MOI.Utilities.substitute_variables(v -> v_map[v], f1) == f2
341+
@test_throws(
342+
ErrorException(
343+
"""
344+
Cannot substitute variables in the `VectorOfVariables` function \
345+
because the result is not representable as a `VectorOfVariables` \
346+
function.
347+
348+
The variable `$w` in index `1` is mapped to the expression \
349+
`$(2.0 * w)`, not directly to another `VariableIndex`.
350+
351+
Note that variables constrained on creation can be used in a \
352+
`VectorOfVariables` function only when their bridge maps each \
353+
one directly to another variable, without a transformation.
354+
""",
355+
),
356+
MOI.Utilities.substitute_variables(vi -> 2.0 * vi, f1),
357+
)
358+
return
359+
end
360+
335361
function test_substitute_variables_vector_nonlinear_function()
336362
model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}())
337363
x = MOI.add_variable(model)

0 commit comments

Comments
 (0)