Could not solve optimization problem with max/min in constraints

Hi,
I wonder why JuMP could not solve the following optimization problem with max/min in the constraints. I would really appreciate it if you could show me how to solve this issue.

using JuMP, Ipopt

model = Model(Ipopt.Optimizer);
set_silent(model)
@variable(model, ir1, start = 3.0)
@variable(model, ir2, start = 3.0)
@variable(model, ir3, start = 3.0)
@variable(model, SP, start = 5.0)
@variable(model, yA, start = 1.0)
@variable(model, yF, start = 2.0)

@NLobjective(model, Min, 1.0)
@NLconstraint(model, ir2 - min(ir1, yA*SP) == 0)
@NLconstraint(model, ir2 - yF == 0)
@NLconstraint(model, ir3 - max(ir1, yF) == 0)
@NLconstraint(model, ir3 - yA*SP == 0)
@NLconstraint(model, yA - 1.0 == 0)
@NLconstraint(model, yF - 2.0 == 0)
@NLconstraint(model, SP*yA - yF == 0)
optimize!(model)

First, it is always useful not to set the solver as silent when debugging the problem. By not setting set_silent(model) you would have got

This is Ipopt version 3.14.16, running with linear solver MUMPS 5.7.3.

Number of nonzeros in equality constraint Jacobian...:       17
Number of nonzeros in inequality constraint Jacobian.:        0
Number of nonzeros in Lagrangian Hessian.............:       11

Exception of type: TOO_FEW_DOF in file "Interfaces/IpIpoptApplication.cpp" at line 662:
 Exception message: status != TOO_FEW_DEGREES_OF_FREEDOM evaluated false: Too few degrees of freedom (rethrown)!

EXIT: Problem has too few degrees of freedom.

This already gives some hints, doesn’t it?

Even with a naked eye, I can see that since yA=1 and yF=2, from the last equation SP = yF/ya=2, from the second equation ir2=2, from the fourth equation ir3= 2. What remains are two equations: 2 = min(ir1,2) and 3=max(ir1,2). Just one variable and two equations.

Well, the original problem has six variables and seven equations. We did not know at the beginning if the equations are redundant, that is why I solved the problem, but redundancy of equations would be undesirable anyway.

By the way, it is no longer needed to use the NL-prefix when specifying nonlinear objective and constraints, see Nonlinear Modeling · JuMP.

One last thing: minimising the cost function f(x)=1 is trivial.

1 Like

By the way, the equality constraint

x_1 = \min(x_2,x_3x_4)

containing minimization can be rewritten as a set of common linear/nonlinear equality and inequality constraints upon introducing an auxiliary variable

\begin{aligned} y &\leq x_2\\ y &\leq x_3x_4\\ x_1 &= y. \end{aligned}

But I guess that JuMP does this transformation automatically.

@VPBML, as @zdenek_hurak explains, your problem just doesn’t make much sense. You have 6 variables, seven constraints, and there is a single solution with every variable = 2 except yA = 1.

If you relax some of the constraints like yA == 1 to be fixed variable bounds, we can get a solution:

using JuMP, Ipopt
model = Model(Ipopt.Optimizer);
# set_silent(model)
@variable(model, ir1, start = 3.0)
@variable(model, ir2, start = 3.0)
@variable(model, ir3, start = 3.0)
@variable(model, SP, start = 5.0)
@variable(model, yA, start = 1.0)
@variable(model, yF, start = 2.0)
@constraint(model, ir2 == min(ir1, yA*SP))
@constraint(model, ir2 == yF)
@constraint(model, ir3 == max(ir1, yF))
@constraint(model, ir3 == yA*SP)
fix(yA, 1.0)
fix(yF, 2.0)
@constraint(model, SP*yA == yF)
optimize!(model)

Nope. We use the non-smooth formulation z = min(x, y) directly.

2 Likes

Apparently, essentially the same problem is also discussed in the parallel thread How to solve a nonlinear system with redundancy with NonlinearSolve.jl.

1 Like

I was just wondering, is there any general advantage or disadvantage in one or the other formulation of the constraints from the perspective of solvers?

In particular, the formulation containing the min, that is, defining f(x,y,z) = x - min(y,z), the equality constraint is f(x,y,z) = 0. And the formulation avoiding the min, that is, defining F(x,y,z) = [x-y; x-z], the vector inequality constraint is F(x,y,z) <= [0; 0] ? The function f defining the former is nonsmooth, while the function F defining the latter is smooth.