Alpine+JuMP gives error for quadratic functions

I am using Alpine with JuMP and Alpine fails for quadratic functions. Using the example from nlp3 here: https://github.com/lanl-ansi/Alpine.jl/blob/master/examples/MINLPs/nlp.jl, I have a working example:

#Working example
using JuMP, Alpine, Ipopt, Juniper, Cbc

m = Model(optimizer_with_attributes(Alpine.Optimizer, "nlp_solver"=>Ipopt.Optimizer,
 "mip_solver"=>Cbc.Optimizer, "minlp_solver" =>optimizer_with_attributes(Juniper.Optimizer,
MOI.Silent() => true,"mip_solver" => Cbc.Optimizer,"nl_solver" => Ipopt.Optimizer)))

LB = [100, 1000, 1000, 10, 10, 10, 10, 10]
UB = [10000, 10000, 10000,  1000, 1000, 1000, 1000, 1000]

@variable(m, LB[i] <= x[i=1:8] <= UB[i])

@constraint(m, 0.0025*(x[4] + x[6]) <= 1)
@constraint(m, 0.0025*(x[5] - x[4] + x[7]) <= 1)
@constraint(m, 0.01(x[8]-x[5]) <= 1)
@NLconstraint(m, 100*x[1] - x[1]*x[6] + 833.33252*x[4] <= 83333.333) ###The multiplication here is with two different variables
@NLconstraint(m, x[2]*x[4] - x[2]*x[7] - 1250*x[4] + 1250*x[5] <= 0)
@NLconstraint(m, x[3]*x[5] - x[3]*x[8] - 2500*x[5] + 1250000 <= 0)

@objective(m, Min, x[1]+x[2]+x[3])

optimize!(m)

but if I change one nonlinear constraint slightly to have x[1]*x[1] instead of x[1]*x[6] I am getting an error on MOI.ScalarQuadraticFunction:

#Not working 
using JuMP, Alpine, Ipopt, Juniper, Cbc

m = Model(optimizer_with_attributes(Alpine.Optimizer, "nlp_solver"=>Ipopt.Optimizer,
 "mip_solver"=>Cbc.Optimizer, "minlp_solver" =>optimizer_with_attributes(Juniper.Optimizer,
MOI.Silent() => true,"mip_solver" => Cbc.Optimizer,"nl_solver" => Ipopt.Optimizer)))

LB = [100, 1000, 1000, 10, 10, 10, 10, 10]
UB = [10000, 10000, 10000,  1000, 1000, 1000, 1000, 1000]

@variable(m, LB[i] <= x[i=1:8] <= UB[i])

@constraint(m, 0.0025*(x[4] + x[6]) <= 1)
@constraint(m, 0.0025*(x[5] - x[4] + x[7]) <= 1)
@constraint(m, 0.01(x[8]-x[5]) <= 1)
@NLconstraint(m, 100*x[1] - x[1]*x[1] + 833.33252*x[4] <= 83333.333) ###The multiplication here is with x[1]*x[1]
@NLconstraint(m, x[2]*x[4] - x[2]*x[7] - 1250*x[4] + 1250*x[5] <= 0)
@NLconstraint(m, x[3]*x[5] - x[3]*x[8] - 2500*x[5] + 1250000 <= 0)

@objective(m, Min, x[1]+x[2]+x[3])

optimize!(m)

The first part of the error I am getting:

I thought it was due to my choice of underlying solvers (Juniper and Cbc), but Juniper seems to be able to handle quadratic expressions. Should I formulate the problem in a different way?

Also, quadratic/bilinear expressions are a bit unclear to use as JuMP allows the use of @constraint to define them but Alpine requires as least one @NLconstraint (or an @NLobjective). That’s probably a minor documentation issue.

I thought it was due to my choice of underlying solvers (Juniper and Cbc)

That looks like a bug. Do you have at the full error message?

but Alpine requires as least one @NLconstraint (or an @NLobjective )

That’s presumably a bug that could be fixed. You should open an issue if one isn’t already.

Full error message:

ERROR: LoadError: `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.GreaterThan{Float64}` constraints are not supported and cannot be bridged into supported constrained variables and constraints. See details below:
 [1] constrained variables in `MOI.RotatedSecondOrderCone` are not supported because:
   Cannot use `MOIB.Variable.RSOCtoSOCBridge{Float64}` because:
   [2] constrained variables in `MOI.SecondOrderCone` are not supported
   Cannot use `MOIB.Variable.RSOCtoPSDBridge{Float64}` because:
   [5] constrained variables in `MOI.PositiveSemidefiniteConeTriangle` are not supported
   Cannot add free variables and then constrain them because:
   (9) `MOI.VectorOfVariables`-in-`MOI.RotatedSecondOrderCone` constraints are not supported
 [2] constrained variables in `MOI.SecondOrderCone` are not supported because:
   Cannot use `MOIB.Variable.SOCtoRSOCBridge{Float64}` because:
   [1] constrained variables in `MOI.RotatedSecondOrderCone` are not supported
   Cannot add free variables and then constrain them because:
   (11) `MOI.VectorOfVariables`-in-`MOI.SecondOrderCone` constraints are not supported
 [5] constrained variables in `MOI.PositiveSemidefiniteConeTriangle` are not supported because no added bridge supports bridging it.
   Cannot add free variables and then constrain them because:
   (18) `MOI.VectorOfVariables`-in-`MOI.PositiveSemidefiniteConeTriangle` constraints are not supported
 (1) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.GreaterThan{Float64}` constraints are not supported because:
   Cannot use `MOIB.Constraint.GreaterToIntervalBridge{Float64, MOI.ScalarQuadraticFunction{Float64}}` because:
   (2) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.Interval{Float64}` constraints are not supported
   Cannot use `MOIB.Constraint.GreaterToLessBridge{Float64, MOI.ScalarQuadraticFunction{Float64}, MOI.ScalarQuadraticFunction{Float64}}` because:
   (7) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.LessThan{Float64}` constraints are not supported
   Cannot use `MOIB.Constraint.VectorizeBridge{Float64, MOI.VectorQuadraticFunction{Float64}, MOI.Nonnegatives, MOI.ScalarQuadraticFunction{Float64}}` because:
   (5) `MOI.VectorQuadraticFunction{Float64}`-in-`MOI.Nonnegatives` constraints are not supported
   Cannot use `MOIB.Constraint.ScalarSlackBridge{Float64, MOI.ScalarQuadraticFunction{Float64}, MOI.GreaterThan{Float64}}` because:
   (3) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.EqualTo{Float64}` constraints are not supported
   Cannot use `MOIB.Constraint.QuadtoSOCBridge{Float64}` because:
   (8) `MOI.VectorAffineFunction{Float64}`-in-`MOI.RotatedSecondOrderCone` constraints are not supported
 (2) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.Interval{Float64}` constraints are not supported because:
   Cannot use `MOIB.Constraint.ScalarSlackBridge{Float64, MOI.ScalarQuadraticFunction{Float64}, MOI.Interval{Float64}}` because:
   (3) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.EqualTo{Float64}` constraints are not supported
   Cannot use `MOIB.Constraint.SplitIntervalBridge{Float64, MOI.ScalarQuadraticFunction{Float64}, MOI.Interval{Float64}, MOI.GreaterThan{Float64}, MOI.LessThan{Float64}}` because:
   (1) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.GreaterThan{Float64}` constraints are not supported
   (7) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.LessThan{Float64}` constraints are not supported
 (3) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.EqualTo{Float64}` constraints are not supported because:
   Cannot use `MOIB.Constraint.VectorizeBridge{Float64, MOI.VectorQuadraticFunction{Float64}, MOI.Zeros, MOI.ScalarQuadraticFunction{Float64}}` because:
   (4) `MOI.VectorQuadraticFunction{Float64}`-in-`MOI.Zeros` constraints are not supported
   Cannot use `MOIB.Constraint.SplitIntervalBridge{Float64, MOI.ScalarQuadraticFunction{Float64}, MOI.EqualTo{Float64}, MOI.GreaterThan{Float64}, MOI.LessThan{Float64}}` because:
   (1) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.GreaterThan{Float64}` constraints are not supported
   (7) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.LessThan{Float64}` constraints are not supported
 (4) `MOI.VectorQuadraticFunction{Float64}`-in-`MOI.Zeros` constraints are not supported because:
   Cannot use `MOIB.Constraint.ScalarizeBridge{Float64, MOI.ScalarQuadraticFunction{Float64}, MOI.EqualTo{Float64}}` because:
   (3) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.EqualTo{Float64}` constraints are not supported
   Cannot use `MOIB.Constraint.SplitIntervalBridge{Float64, MOI.VectorQuadraticFunction{Float64}, MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives}` because:
   (5) `MOI.VectorQuadraticFunction{Float64}`-in-`MOI.Nonnegatives` constraints are not supported
   (6) `MOI.VectorQuadraticFunction{Float64}`-in-`MOI.Nonpositives` constraints are not supported
 (5) `MOI.VectorQuadraticFunction{Float64}`-in-`MOI.Nonnegatives` constraints are not supported because:
   Cannot use `MOIB.Constraint.NonnegToNonposBridge{Float64, MOI.VectorQuadraticFunction{Float64}, MOI.VectorQuadraticFunction{Float64}}` because:
   (6) `MOI.VectorQuadraticFunction{Float64}`-in-`MOI.Nonpositives` constraints are not supported
   Cannot use `MOIB.Constraint.ScalarizeBridge{Float64, MOI.ScalarQuadraticFunction{Float64}, MOI.GreaterThan{Float64}}` because:
   (1) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.GreaterThan{Float64}` constraints are not supported
   Cannot use `MOIB.Constraint.VectorSlackBridge{Float64, MOI.VectorQuadraticFunction{Float64}, MOI.Nonnegatives}` because:
   (4) `MOI.VectorQuadraticFunction{Float64}`-in-`MOI.Zeros` constraints are not supported
 (6) `MOI.VectorQuadraticFunction{Float64}`-in-`MOI.Nonpositives` constraints are not supported because:
   Cannot use `MOIB.Constraint.NonposToNonnegBridge{Float64, MOI.VectorQuadraticFunction{Float64}, MOI.VectorQuadraticFunction{Float64}}` because:
   (5) `MOI.VectorQuadraticFunction{Float64}`-in-`MOI.Nonnegatives` constraints are not supported
   Cannot use `MOIB.Constraint.ScalarizeBridge{Float64, MOI.ScalarQuadraticFunction{Float64}, MOI.LessThan{Float64}}` because:
   (7) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.LessThan{Float64}` constraints are not supported
   Cannot use `MOIB.Constraint.VectorSlackBridge{Float64, MOI.VectorQuadraticFunction{Float64}, MOI.Nonpositives}` because:
   (4) `MOI.VectorQuadraticFunction{Float64}`-in-`MOI.Zeros` constraints are not supported
 (7) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.LessThan{Float64}` constraints are not supported because:
   Cannot use `MOIB.Constraint.LessToIntervalBridge{Float64, MOI.ScalarQuadraticFunction{Float64}}` because:
   (2) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.Interval{Float64}` constraints are not supported
   Cannot use `MOIB.Constraint.LessToGreaterBridge{Float64, MOI.ScalarQuadraticFunction{Float64}, MOI.ScalarQuadraticFunction{Float64}}` because:
   (1) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.GreaterThan{Float64}` constraints are not supported
   Cannot use `MOIB.Constraint.VectorizeBridge{Float64, MOI.VectorQuadraticFunction{Float64}, MOI.Nonpositives, MOI.ScalarQuadraticFunction{Float64}}` because:
   (6) `MOI.VectorQuadraticFunction{Float64}`-in-`MOI.Nonpositives` constraints are not supported
   Cannot use `MOIB.Constraint.ScalarSlackBridge{Float64, MOI.ScalarQuadraticFunction{Float64}, MOI.LessThan{Float64}}` because:
   (3) `MOI.ScalarQuadraticFunction{Float64}`-in-`MOI.EqualTo{Float64}` constraints are not supported
   Cannot use `MOIB.Constraint.QuadtoSOCBridge{Float64}` because:
   (8) `MOI.VectorAffineFunction{Float64}`-in-`MOI.RotatedSecondOrderCone` constraints are not supported
 (8) `MOI.VectorAffineFunction{Float64}`-in-`MOI.RotatedSecondOrderCone` constraints are not supported because:
   Cannot use `MOIB.Constraint.VectorSlackBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.RotatedSecondOrderCone}` because:
   [1] constrained variables in `MOI.RotatedSecondOrderCone` are not supported
   Cannot use `MOIB.Constraint.RSOCBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.VectorAffineFunction{Float64}}` because:
   (10) `MOI.VectorAffineFunction{Float64}`-in-`MOI.SecondOrderCone` constraints are not supported
   Cannot use `MOIB.Constraint.RSOCtoPSDBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.VectorAffineFunction{Float64}}` because:
   (17) `MOI.VectorAffineFunction{Float64}`-in-`MOI.PositiveSemidefiniteConeTriangle` constraints are not supported
 (9) `MOI.VectorOfVariables`-in-`MOI.RotatedSecondOrderCone` constraints are not supported because:
   Cannot use `MOIB.Constraint.VectorFunctionizeBridge{Float64, MOI.RotatedSecondOrderCone}` because:
   (8) `MOI.VectorAffineFunction{Float64}`-in-`MOI.RotatedSecondOrderCone` constraints are not supported
   Cannot use `MOIB.Constraint.RSOCBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.VectorOfVariables}` because:
   (10) `MOI.VectorAffineFunction{Float64}`-in-`MOI.SecondOrderCone` constraints are not supported
   Cannot use `MOIB.Constraint.RSOCtoPSDBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.VectorOfVariables}` because:
   (17) `MOI.VectorAffineFunction{Float64}`-in-`MOI.PositiveSemidefiniteConeTriangle` constraints are not supported
 (10) `MOI.VectorAffineFunction{Float64}`-in-`MOI.SecondOrderCone` constraints are not supported because:
   Cannot use `MOIB.Constraint.VectorSlackBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.SecondOrderCone}` because:
   [2] constrained variables in `MOI.SecondOrderCone` are not supported
   Cannot use `MOIB.Constraint.SOCRBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.VectorAffineFunction{Float64}}` because:
   (8) `MOI.VectorAffineFunction{Float64}`-in-`MOI.RotatedSecondOrderCone` constraints are not supported
 (11) `MOI.VectorOfVariables`-in-`MOI.SecondOrderCone` constraints are not supported because:
   Cannot use `MOIB.Constraint.VectorFunctionizeBridge{Float64, MOI.SecondOrderCone}` because:
   (10) `MOI.VectorAffineFunction{Float64}`-in-`MOI.SecondOrderCone` constraints are not supported
   Cannot use `MOIB.Constraint.SOCRBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.VectorOfVariables}` because:
   (8) `MOI.VectorAffineFunction{Float64}`-in-`MOI.RotatedSecondOrderCone` constraints are not supported
 (17) `MOI.VectorAffineFunction{Float64}`-in-`MOI.PositiveSemidefiniteConeTriangle` constraints are not supported because:
   Cannot use `MOIB.Constraint.VectorSlackBridge{Float64, MOI.VectorAffineFunction{Float64}, MOI.PositiveSemidefiniteConeTriangle}` because:
   [5] constrained variables in `MOI.PositiveSemidefiniteConeTriangle` are not supported
 (18) `MOI.VectorOfVariables`-in-`MOI.PositiveSemidefiniteConeTriangle` constraints are not supported because:
   Cannot use `MOIB.Constraint.VectorFunctionizeBridge{Float64, MOI.PositiveSemidefiniteConeTriangle}` because:
   (17) `MOI.VectorAffineFunction{Float64}`-in-`MOI.PositiveSemidefiniteConeTriangle` constraints are not supported

And stacktrace:

Stacktrace:
  [1] error(s::String)
    @ Base .\error.jl:33
  [2] moi_add_constraint(model::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}}, f::MathOptInterface.ScalarQuadraticFunction{Float64}, s::MathOptInterface.GreaterThan{Float64})
    @ JuMP C: \.julia\packages\JuMP\e0Uc2\src\constraints.jl:384
  [3] add_constraint(model::Model, con::ScalarConstraint{QuadExpr, MathOptInterface.GreaterThan{Float64}}, name::String)
    @ JuMP C: \.julia\packages\JuMP\e0Uc2\src\constraints.jl:402
  [4] macro expansion
    @ C: \.julia\packages\JuMP\e0Uc2\src\macros.jl:441 [inlined]
  [5] amp_post_convhull_constrs(m::Alpine.Optimizer, λ::Dict{Any, Any}, α::Dict{Any, Any}, monomial_idx::Int64, dim::Tuple{Int64}, discretization::Dict{Any, Any})
    @ Alpine C: \.julia\packages\Alpine\P4M4a\src\multi.jl:323
  [6] amp_convexify_monomial(m::Alpine.Optimizer, k::Vector{Expr}, λ::Dict{Any, Any}, α::Dict{Any, Any}, discretization::Dict{Any, Any})
    @ Alpine C: \.julia\packages\Alpine\P4M4a\src\multi.jl:60
  [7] amp_post_convhull(m::Alpine.Optimizer; kwargs::Base.Iterators.Pairs{Symbol, Dict{Any, Any}, Tuple{Symbol}, NamedTuple{(:use_disc,), Tuple{Dict{Any, Any}}}})
    @ Alpine C: \.julia\packages\Alpine\P4M4a\src\multi.jl:17
  [8] amp_post_convexification(m::Alpine.Optimizer; use_disc::Dict{Any, Any})
    @ Alpine C: \.julia\packages\Alpine\P4M4a\src\amp.jl:53
  [9] create_bound_tightening_model(m::Alpine.Optimizer, discretization::Dict{Any, Any}, bound::Float64; kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Alpine C: \.julia\packages\Alpine\P4M4a\src\presolve.jl:188
 [10] create_bound_tightening_model(m::Alpine.Optimizer, discretization::Dict{Any, Any}, bound::Float64)
    @ Alpine C:\.julia\packages\Alpine\P4M4a\src\presolve.jl:184
 [11] minmax_bound_tightening(m::Alpine.Optimizer; use_bound::Bool, timelimit::Float64, kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Alpine C:\.julia\packages\Alpine\P4M4a\src\presolve.jl:97
 [12] bound_tightening(m::Alpine.Optimizer; use_bound::Bool, kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Alpine C:\.julia\packages\Alpine\P4M4a\src\presolve.jl:18
 [13] presolve(m::Alpine.Optimizer)
    @ Alpine C:\.julia\packages\Alpine\P4M4a\src\algorithm.jl:97
 [14] optimize!(m::Alpine.Optimizer)
    @ Alpine C:\.julia\packages\Alpine\P4M4a\src\algorithm.jl:22
 [15] optimize!(b::MathOptInterface.Bridges.LazyBridgeOptimizer{Alpine.Optimizer})
    @ MathOptInterface.Bridges C:\.julia\packages\MathOptInterface\YDdD3\src\Bridges\bridge_optimizer.jl:319
 [16] optimize!(m::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.GenericModel{Float64, MathOptInterface.Utilities.ModelFunctionConstraints{Float64}}}})
    @ MathOptInterface.Utilities C:\.julia\packages\MathOptInterface\YDdD3\src\Utilities\cachingoptimizer.jl:252
 [17] optimize!(model::Model, optimizer_factory::Nothing; bridge_constraints::Bool, ignore_optimize_hook::Bool, kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})  
    @ JuMP C:\.julia\packages\JuMP\e0Uc2\src\optimizer_interface.jl:130
 [18] optimize! (repeats 2 times)
    @ C:\.julia\packages\JuMP\e0Uc2\src\optimizer_interface.jl:106 [inlined]
 [19] top-level scope
    @ D: \JuMPTests\AlpineCompare2.jl:21
 [20] eval
    @ .\boot.jl:360 [inlined]
 [21] include_string(mapexpr::typeof(identity), mod::Module, code::String, filename::String)
    @ Base .\loading.jl:1116
in expression starting at D: \JuMPTests\AlpineCompare2.jl:21
1 Like

Open an issue in Alpine.jl. That looks like a bug.

1 Like

@mzagorowska Interestingly, I just looked at this issue. This isn’t an issue/bug in Alpine. Since you have created a quadratic monomial in x[1]*x[1], this automatically gets reformulated as x[1]^2 within Alpine. Once this is a quadratic function, you can use Gurobi as the underlying mip_solver and it runs without any issue. Although not the best, if you still prefer to use an open-source mip_solver, note that Cbc/HiGHS solver does not support quadratic functions. Instead, you will need to use Pavito.jl solver and then use Cbc/HiGHS and Ipopt as the underlying mip_solver and cont_solver, respectively. Similar to the way it is invoked here: Alpine.jl/runtests.jl at 22c44020fe3c56c4e11bafaebf9c86b313da0714 · lanl-ansi/Alpine.jl · GitHub I tested this and it works fine.