setting division in objective function
Answeredi took example from https://docs.gurobi.com/projects/examples/en/current/examples/gc_funcnonlinear.html#sectiongc-funcnonlinearexamples
and changed objective function to division. The code stopped working. Here is new code:
import gurobipy as gp
from gurobipy import GRB
def printsol(m, x):
print(f"x = {x.X}")
print(f"Obj = {m.ObjVal}")
try:
# Create a new model
m = gp.Model()
# Create variables
x = m.addVar(lb=-1, ub=4, name="x")
twox = m.addVar(lb=-2, ub=8, name="2x")
sinx = m.addVar(lb=-1, ub=1, name="sinx")
cos2x = m.addVar(lb=-1, ub=1, name="cos2x")
expx = m.addVar(name="expx")
# Set objective
m.setObjective(sinx / (cos2x + 1), GRB.MINIMIZE)
# Add linear constraints
lc1 = m.addConstr(0.25 * expx - x <= 0)
lc2 = m.addConstr(2.0 * x - twox == 0)
# Add general function constraints
# sinx = sin(x)
gc1 = m.addGenConstrSin(x, sinx, "gc1")
# cos2x = cos(twox)
gc2 = m.addGenConstrCos(twox, cos2x, "gc2")
# expx = exp(x)
gc3 = m.addGenConstrExp(x, expx, "gc3")
# Approach 1) Set FuncNonlinear parameter
m.params.FuncNonlinear = 1
# Optimize the model
m.optimize()
except gp.GurobiError as e:
print(f"Error code {e.errno}: {e}")
except AttributeError:
print("Encountered an attribute error")
the error:
Error code -1: Objective must be linear or quadratic
-
Hi Audrius,
As the error message states, the objective function must be linear or quadratic. This can be resolved using auxiliary variable and addGenConstrNL method:
obj = m.addVar(name="obj")
m.addGenConstrNL(obj,sinx/(cos2x+1))
m.setObjective(obj, GRB.MINIMIZE)Moreover, you can also define an obj directly (without the variables "sinx","cos2x"...)
obj = m.addVar(name="obj")
m.addGenConstrNL(obj, gp.nlfunc.sin(x)/(gp.nlfunc.cos(2*x) + 1))
m.setObjective(obj, GRB.MINIMIZE)Thanks,
Ryuta0 -
this is good. what if at initial point we get division by 0? i'v changed the objective a little bit to force get division by 0:
import gurobipy as gp
from gurobipy import GRB
def printsol(m, x):
print(f"x = {x.X}")
print(f"Obj = {m.ObjVal}")
try:
# Create a new model
m = gp.Model()# Create variables
x = m.addVar(lb=-4, ub=4, name="x")
twox = m.addVar(lb=-8, ub=8, name="2x")
sinx = m.addVar(lb=-1, ub=1, name="sinx")
cos2x = m.addVar(lb=-1, ub=1, name="cos2x")
expx = m.addVar(name="expx")# Set objective
obj = m.addVar(name="obj")
m.addGenConstrNL(obj,sinx/(cos2x-1))
m.setObjective(obj, GRB.MINIMIZE)
# Add linear constraints
lc1 = m.addConstr(0.25 * expx - x <= 0)
lc2 = m.addConstr(2.0 * x - twox == 0)# Add general function constraints
# sinx = sin(x)
gc1 = m.addGenConstrSin(x, sinx, "gc1")
# cos2x = cos(twox)
gc2 = m.addGenConstrCos(twox, cos2x, "gc2")
# expx = exp(x)
gc3 = m.addGenConstrExp(x, expx, "gc3")# Approach 1) Set FuncNonlinear parameter
m.params.FuncNonlinear = 1
# Optimize the model
m.optimize()
except gp.GurobiError as e:
print(f"Error code {e.errno}: {e}")except AttributeError:
print("Encountered an attribute error")Model has 3 function constraints treated as nonlinear 1 EXP, 1 SIN, 1 COS Model has 1 general nonlinear constraint (1 nonlinear terms) Variable types: 6 continuous, 0 integer (0 binary) Coefficient statistics: Matrix range [2e-01, 2e+00] Objective range [1e+00, 1e+00] Bounds range [1e+00, 8e+00] RHS range [0e+00, 0e+00] Presolve time: 0.00s Explored 0 nodes (0 simplex iterations) in 0.01 seconds (0.00 work units) Thread count was 1 (of 112 available processors) Solution count 0 Model is infeasible Best objective -, best bound -, gap -
0 -
Hi,
Please see this description. Gurobi implicitly tries to avoid division by zero. However, to avoid unexpected behavior, it is recommended to explicitly constrain the denominator to be non-zero so that division by zero does not occur.
Thanks,
Ryuta0 -
if this happens at stage of initial point selection, so how I can prevent this? I'd like to try something like numerator = 10
denominator = 0
result = numerator / denominator if denominator != 0 else float('inf')
Would it work within gurobi environment?0 -
This model will be Infeasible:
m = gp.Model()
x = m.addVar(lb=10, ub=10, name="x")
y = m.addVar(lb=0,ub=0, name="y")
z = m.addVar(name="z")
m.addGenConstrNL(z,x/y)
m.optimize()As this description states, the denominator cannot be 0. So it should be taken into account that the denominator should not be zero at the stage of building a math model (before solving).
Thanks,
Ryuta0
Please sign in to leave a comment.
Comments
5 comments