lanl-ansi / Juniper.jl

A JuMP-based Nonlinear Integer Program Solver
https://lanl-ansi.github.io/Juniper.jl/stable/
MIT License
180 stars 22 forks source link

JuMP's SecondOrderCone() interface broken? #212

Closed pqrz closed 2 years ago

pqrz commented 3 years ago

Good work!

Going by [0] - we assume Juniper do support MISOCP problems.

But while executing a naïve MISOCP problem, i.e.

using Juniper, Ipopt, JuMP, LinearAlgebra
u0 = [3,5]
nl_solver = optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0)
m = Model(optimizer_with_attributes(Juniper.Optimizer, "nl_solver"=>nl_solver))
@variable(m, x[1:2], Int)
@objective(m, Min, dot(u0,x))
@constraint(m, [10, x[1], x[2]] in SecondOrderCone())
optimize!(m)

it breaks, and throws Error:

ERROR: LoadError: MathOptInterface.UnsupportedConstraint{MathOptInterface.VectorAffineFunction{Float64},MathOptInterface.SecondOrderCone}: `MathOptInterface.VectorAffineFunction{Float64}`-in-`MathOptInterface.SecondOrderCone` constraint is not supported by the model.

So, I had two questions:

A. Can Juniper really handle MISOCP problem type? (asking because couldn't find any reference of MISOCP on our docs [1]) B. If it can handle MISOCP, then why can it not handle JuMP's SecondOrderCone(), otherwise how to specify MISOCP constraints?

0 - https://jump.dev/JuMP.jl/v0.20/installation/#Getting-Solvers-1 1 - https://lanl-ansi.github.io/Juniper.jl/dev/

Wikunia commented 3 years ago

It seems like Ipopt doesn't support SOC constraints and we basically just pass it over to the nl solver. Additionally I think [10, x[1], x[2]] isn't working generally as 10 isn't a variable and it only allows the VectorOfVariables constraint there but I might be wrong. @ccoffrin have you tested Juniper with an MISOCP? I actually wasn't aware that Juniper is listed as an MISOCP solver in the JuMP table.

ccoffrin commented 3 years ago

If you use KNITRO instead of Ipopt, MISOCP should work. The quick fix to use Ipopt is to transform your SOC constraints into QCQP constraints of the form x[1]^2 + x[2]^2 <= 10^2. There may also be a solution where you ask JuMP to do this transformation for you by enabling a non-default Bridge; I'll let @blegat comment on that.

odow commented 3 years ago

[10, x[1], x[2]] is fine. You can see it gets converted into a VectorAffineFunction in the error message.

You should manually transform your constraint into the quadratic form. I guess we could add support for SOC (and some other cones) to Ipopt.

blegat commented 3 years ago

You should use the SOCtoNonConvexQuadBridge. That is, after this line: https://github.com/lanl-ansi/Juniper.jl/blob/f88cfbeb016947fd8da1f71671363691f14b8e95/src/model.jl#L7 add

MOI.Bridges.add_bridge(jp.model, MOI.Bridges.Constraint.SOCtoNonConvexQuadBridge{Float64})
pqrz commented 3 years ago

Thanks everyone for your time!

To @Wikunia @ccoffrin,

To @odow,

To @blegat,

blegat commented 3 years ago

The line needs to be added inside Juniper's source code

pqrz commented 3 years ago

Thanks @blegat (since I am naïve with Julia, would have to once learn on editing the pacage's source code, would then try this)

So, if I get it correctly, after adding this line - Juniper would start to handle SecondOrderCone()?

blegat commented 3 years ago

Yes, exactly. It also need to be added in fpump.jl after MOI.instantiate for fpump to work too though

pqrz commented 3 years ago

Thanks @blegat

If possible could you please once confirm on - Solving MISOCP isn't the property of Juniper solver, rather that of underlying NLP solver we passed

So, we that we can finally close this issue.

odow commented 3 years ago

Solving MISOCP isn't the property of Juniper solver, rather that of underlying NLP solver we passed

Correct.

blegat commented 3 years ago

Reopening so that we remember to do the change suggested in https://github.com/lanl-ansi/Juniper.jl/issues/212#issuecomment-788253307 and add tests that MISOCP problems can be solved with Ipopt

pqrz commented 3 years ago

Just wanted to share the results.

I had finally added the line for SOCP constraints handling in my models.jl and it worked fine. I also took the liberty to add line for RSOCP constraints and again Juniper worked fine.

So, my models.jl looked like:

7    . 
8    MOI.Bridges.add_bridge(jp.model, MOI.Bridges.Constraint.SOCtoNonConvexQuadBridge{Float64})
9    MOI.Bridges.add_bridge(jp.model, MOI.Bridges.Constraint.RSOCtoNonConvexQuadBridge{Float64})
10   . 

Thank you so much to @blegat. Really admire your understanding of the codebase. Keep doing the great work!