BilevelJuMP: Symmetric variables not supported?

HSt
Tue, 25 Mar 2025 12:46:16 +0000
Optimization (Mathematical)

I’ve build functions to add specific variables and constraints one after another, to modularize model creation.
Some of the variables should be symmetric, which is fine in regular JuMP when constrained on creation.
However, in BilevelJuMP, this seems to be unsupported / unimplemented.

julia> using JuMP
julia> N = 4;
julia> model1 = JuMP.Model();
julia> @variable(model1, q1[i=1:N,j=1:N], Bin, Symmetric)
4×4 Symmetric{VariableRef, Matrix{VariableRef}}:
 q1[1,1]  q1[1,2]  q1[1,3]  q1[1,4]
 q1[1,2]  q1[2,2]  q1[2,3]  q1[2,4]
 q1[1,3]  q1[2,3]  q1[3,3]  q1[3,4]
 q1[1,4]  q1[2,4]  q1[3,4]  q1[4,4]

regular JuMP works fine, but BilevelJuMP doesn’t accept the symmetric constraint:

julia> using BilevelJuMP
julia> model2 = BilevelJuMP.BilevelModel();
julia> @variable(Upper(model2), q2[i=1:N,j=1:N], Bin)
4×4 Matrix{BilevelVariableRef}:
 q2[1,1]  q2[1,2]  q2[1,3]  q2[1,4]
 q2[2,1]  q2[2,2]  q2[2,3]  q2[2,4]
 q2[3,1]  q2[3,2]  q2[3,3]  q2[3,4]
 q2[4,1]  q2[4,2]  q2[4,3]  q2[4,4]
julia> @variable(Upper(model2), q3[i=1:N,j=1:N], Bin, Symmetric)
ERROR: MethodError: no method matching add_variable(::BilevelJuMP.UpperModel, ::VariablesConstrainedOnCreation{…}, ::Matrix{…})

Closest candidates are:
  add_variable(::GenericModel{T}, ::VariablesConstrainedOnCreation, ::Any) where T
   @ JuMP C:\Users\SOMEUSER\.julia\packages\JuMP\xlp0s\src\variables.jl:2221
  add_variable(::BilevelJuMP.InnerBilevelModel, ::AbstractVariable)
   @ BilevelJuMP C:\Users\SOMEUSER\.julia\packages\BilevelJuMP\0Me8v\src\jump_variables.jl:59
  add_variable(::BilevelJuMP.InnerBilevelModel, ::AbstractVariable, ::String)
   @ BilevelJuMP C:\Users\SOMEUSER\.julia\packages\BilevelJuMP\0Me8v\src\jump_variables.jl:59
  ...

Stacktrace:
 [1] macro expansion
   @ C:\Users\SOMEUSER\.julia\packages\JuMP\xlp0s\src\macros\@variable.jl:314 [inlined]
 [2] macro expansion
   @ C:\Users\SOMEUSER\.julia\packages\JuMP\xlp0s\src\macros.jl:408 [inlined]
 [3] top-level scope
   @ REPL[14]:1
Some type information was truncated. Use `show(err)` to see complete types.

Is there a deeper reason, why this is not supported?

Creating all N^2 and then setting an external constraint would also be possible.

I could create about 0.5 N^2 - N variables manually, shape them to a triangular matrix and wrap the containner as symmetric view (as discussed here for 2-D symmetry of cubic variables).

Is one way preferrable over the other because of some internals of BilevelJuMP reformulations, solver support, etc.?

2 posts - 2 participants