I have a large nonlinear and nonconvex problem. It also has sin (theta) and cos(theta).

While gurobipy accepts sin or cos using the general constraint. gurobipy uses piecewise linear approximation, which means gurobipy introduces binary variables.

If theta dimension is 10,000; gurobipy introduces at least 10,000 binary variables to formulate the sin(theta) or cos(theta). Does that mean it would be better to solve the problem with ipopt, if the computation speed is important? As we want to avoid adding a huge number of binary variables.

ipopt can solve the nonlinear problem without introducing binary variables.

I guess ipopt will be faster, but gurobipy will converge to a better solution.

Any thought?

  • 1
    $\begingroup$ What is your domain? Do you have a non-convex feasible region? Is the trigonometry just in the objective function? $\endgroup$
    – Brannon
    Dec 26, 2022 at 13:32
  • $\begingroup$ The trigonometry is the constraint. The objective function is linear. $\endgroup$ Dec 26, 2022 at 13:44

1 Answer 1


Gurobi can currently solve mixed-integer (non)convex problems with (bi)linear terms, i.e., the only nonlinearities allowed are squares and products of 2 variables. If your model is nonconvex, you have to set the NonConvex parameter to 2.

If your problem involves any other nonlinear functions, you can use Gurobi's general functions feature. There, Gurobi approximates nonlinear functions via piecewise-linear constraints.

You don't have to change the "solver", you just have to possibly set the NonConvex parameter. Unless you mean whether you can change to a different MINLP solver. Then yes, you could for example change to the open-source MINLP solver SCIP.

Also, the following example can give some good starting points to you:

import gurobipy as gp
from gurobipy import GRB
import math

def f(u):
  return math.atan(u)

m = gp.Model()

lbz = -2
ubz =  2
z = m.addVar(lb=lbz, ub=ubz, vtype=GRB.CONTINUOUS, name="z")
y = m.addVar(lb=-math.pi/2, ub=math.pi/2, vtype=GRB.CONTINUOUS, name="y")

# Compute piecewise-linear arctan function for z
npts = 101
ptu = []
ptf = []
for i in range(npts):
    ptu.append(lbz + (ubz - lbz) * i / (npts - 1))

# Add constraint y = arctan(z) as piecewise-linear approximation

For more details please, see these links:

  • 1
    $\begingroup$ Your welcome. :) $\endgroup$
    – A.Omidi
    Dec 20, 2022 at 11:57
  • $\begingroup$ Thanks. I believe piecewise-linear approximation is based on using binary variables. I try to avoid having binary variables to reduce the problem's complexity. I also believe gurobi can formulate the cos like this: /* y = cos(x) */ error = GRBaddgenconstrCos(model, "cos", xvar, yvar, "FuncPieces=-2") $\endgroup$ Dec 20, 2022 at 11:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.