Vector affine function with SOC not supported in JuMP (.18 -> .19 breaking change?)

jump
#1

Hey all!

Quick question (it is quite likely this question has a simple solution), but I’m working on doing a quick overhaul of some code for a paper. The original code was written on JuMP .17/.18, but with some of the breaking changes in .19, I’m having a hard time fixing stuff up.

In particular, in the original case, I had an affine expression which needed to belong to the second-order cone, but doing the replacements mentioned in the NEWS.md file and suggested by the errors yields the following statement:

ERROR: Constraints of type MathOptInterface.VectorAffineFunction{Float64}-in-MathOptInterface.SecondOrderCone are not supported by the solver and there are no bridges that can reformulate it into supported constraints.

It seems that having an affine expression is (now) not supported(?) unless I’m missing something simple, so I’m wondering if there is a straightforward way of rephrasing this constraint in a way that JuMP will generate the corresponding conic program?

It is possibly quite simple to do directly (by adding a new dummy variable constrained to be equal to the affine expression), but—considering the current size of the program—I don’t want to double the number of variables.

A simple MWE:

using JuMP
import Gurobi

A = randn(2, 2)

m = Model(with_optimizer(Gurobi.Optimizer))

@variable(m, v[1:2])
@constraint(m, A*v ∈ SecondOrderCone())
@objective(m, Max, sum(v))
solve!(m)

Thanks!

#2

Please take a read of:

Which solver are you using? Not all solvers support all types of constraints.

#3

Fair point, added an MWE! Hopefully that makes it easier :slight_smile:

Also, I’m using Gurobi which supports SOCs (e.g., this worked, for example, in the previous version of JuMP).

#4

See https://github.com/JuliaOpt/LinQuadOptInterface.jl/issues/78#issuecomment-444681606. Gurobi doesn’t have a native interface for precisely second-order cone constraints, so the MOI wrapper rightly reports that it doesn’t support them. However, Gurobi does support quadratic constraints, and SOC constraints can of course be reformulated as quadratic constraints. The intention is for this to be handled by adding a bridge to your optimizer, http://www.juliaopt.org/JuMP.jl/v0.19.0/extensions/#Adding-a-bridge-1. However, the PR that adds a bridge for going from SOC to quadratic has not yet been merged, https://github.com/JuliaOpt/MathOptInterface.jl/pull/478.
Edit: and note this comment: https://github.com/JuliaOpt/MathOptInterface.jl/pull/478#discussion_r211120417.

1 Like
#5

Ah, interesting. I guess this makes sense: I always thought Gurobi solved general SOCPs (or conic programs), rather than doing a QCQP reduction. In either case, it’s very easy to rewrite this problem as a QCQP, so I’ll just go ahead and do that. Thanks!

#6

Maybe I should refine my statement a little bit: Gurobi does have specialized handling of SOC constraints if it recognizes that that’s what you’re trying to specify using its generic quadratic constraint interface.

#7

Hm, I’m not quite sure what you mean here, then… so Gurobi will detect if the construction is of a specific form (say x' * x ≤ y^2) and then perform the appropriate reduction? I see something like what you reference in the accepted forms for quadratic constraints—pg. 582 of the reference manual—but it’s absolutely unclear to me what is happening under the hood.

In either case, it seems difficult to pin down the performance tradeoffs (e.g., when Gurobi’s preserve does or doesn’t actually change the quadratic constraint to a rotated SOC, for example), but this is all independent of JuMP