Exponential function in the constraint with gurobipython
AnsweredI have the following problem;
\[\begin{align} \min ฮ \\ \text{s.t. } ๐*ฮ + ln[\sum_{j} ({exp(๐)}{exp(๐)})/{2*๐} ]<= ln({eps})\end{align}\]
ฮ>=0
๐>0
Where "๐" is an auxiliary decision variable,
"Epsilon" is a parameter.
I have coded the problem on gurobipyhton but it is not working,ย
It says, for the term inside the exponential, ''must be real number, not Var''
could you please provide a hint regarding this issue,
for '๐' as an auxiliary decision variable, could please show how to enforce it to be >0,ย
ย

Hi!
Could you please share what you have tried so far? Please review our guide Posting to the Community Forum โ Gurobi Help Center
Thanks,
Matthias1 
Please find it attached,ย
I would like just to mention that I have read the documentation regarding natural exponential, but I did not get any hint from it;
#calculating the size of the uncertainty set under the assumption that the uncertainty is
#bounded and symmetric which is satisfied in this example
#parameters
eps=0.15
#Decision variables
delta_b4=m.addVar(lb=0, name='delta_b4')
theta=m.addVar(lb=0, name='theta_1')
#Set of Constraints
m.addConstr(theta*(delta_b4)+6*math.log((math.exp(theta)math.exp(theta))/(2*theta))<= math.log(eps))
m.update()
Z=delta_b4
m.setObjective(Z, GRB.MINIMIZE)
m.params.NonConvex = 2
m.optimize()0 
Please have a look at which type of constraints you can add to a Gurobi model. You cannot use math.log or math.exp.
If you want to use exponential expressions on a decision variable, you need to add this as a general constraint, using Model.addGenConstrExp() (For logarithmic expressions there is Model.addGenConstrLog().) Note that you will need additional variables to do this, please also have a look into How do I model logical and general expressions? This gives an example for the abs function but the idea is similar for all general constraints.Concerning your constraint ๐>0, this is not supported. But you can find a workaround in Why doesn't Gurobi support strict inequality constraints like x < a?.
1 
Hi Marika,ย
Thank you for your reply, I have tried to code the problem following the steps in the link still have marginal issue, plaes find below the code, the problem is not considering the Log, so whether I am using that constraint or not, it gives the same results.
ย
#calculating the size of the uncertainty set under the assumption that the uncertainty is
#bounded and symmetric which is satisfied in this example
#parameters
eps=0.15
#Decision variables
delta_b4=m.addVar(lb=0, name='delta_b4')
theta=m.addVar(lb=0, name='theta')
x=m.addVar(lb=0, name='x')
y=m.addVar(lb=0, name='y')
w=m.addVar(lb=gp.GRB.INFINITY, name='w')
f=m.addVar(lb=0, name='f')
z=m.addVar(lb=gp.GRB.INFINITY, name='z')
theta_inf=m.addVar(lb=0, name='theta_inf')
#Set of Constraints
theta_inf== 1*theta
m.addGenConstrExp((theta),x)
m.addGenConstrExp(theta_inf,y)
m.addConstr(w == xy)
m.addConstr(f == w/2*theta)
m.addGenConstrLog(f,z)
m.addConstr(1*theta*delta_b4+ z <= math.log(eps))
Z=delta_b4
m.setObjective(Z, GRB.MINIMIZE)
m.params.NonConvex = 2
m.optimize()ย1 
Some remarks on your model:
 If you allow theta to be 0, the trivial solution is delta_b4=theta=0
 You need to add theta_inf== 1*theta as constraint as well:ย m.addConstr(theta_inf== 1*theta)
 the lb of theta_inf should be equal to ub of theta (and similar for ub of theta_inf)
 Note that the exponential function is handled via piecewiselinear approximation. So it would be helpful to define reasonable finite bounds on theta (and theta_inf).
ยย0 
Hi Marika,ย
Thank you so much for your feedback,ย
in fact, theta_inf is just an decision auxiliary variable, which is 1*theta, I have tried to model it directly by putting;
m.addGenConstrExp(1*theta,y)
but, it is not working this why I introduced delta_inf, I have tried to add it as you mentioned as constraint but it is not working!
The problem is too simple but, having such function make it challenging to code and get a result, still having the same issue the constraint m.addGenConstrLog(f,z) is not considered even when I gave theta a small lower bound, m.addVar(theta=0.0001)
ย
0 
For instance, I wrote it in the beginning like that;
m.addGenConstrExp(theta,x)
m.addGenConstrExp(theta,y)and it gave me the following error;ย
TypeError: 1.0 <gurobi.Var *Awaiting Model Update*> is not a variable
1 
Could you please explain a bit more about what exactly is not working? Do you see any errors? Or are you surprised about the result? If so, what is the result and what do you think should be correct?
1 
Hello Marika, thank you for your feedback, and sorry if I am missing some point to highlight, I got three different outcomes, with some debugging, infeasible, zero, andย 1.37*10^1, the result for this problem should be (delta=2.6704) which still did not get it.
please the original problem is written above; which was my first question,
Here it is another attempt for another modelling code;
#calculating the size of the uncertainty set under the assumption that the uncertainty is
#bounded and symmetric which is satisfied in this example
#parameters
eps=0.15
j=6
#Decision variables
delta_b4=m.addVar(lb=0, name='delta_b4')
theta=m.addVar(lb=0, name='theta')
theta_inf=m.addVar(lb=0, name='theta_inf')
x=m.addVar(name='x')
y=m.addVar(name='y')
z=m.addVar(name='z')
t=m.addVar(name='t')
vc=m.addVar(name='vc')
dv=m.addVar(name='dv')
#Set of Constraints
theta_inf==1*theta
m.addGenConstrExp(theta,x)
m.addGenConstrExp(theta_inf,y)
m.addConstr(z == xy)
m.addGenConstrLog(z,t)
m.addConstr(vc==2*theta)
m.addGenConstrLog(vc,dv)
m.addConstr(theta*delta_b4 + 6*(tdv) <= math.log(eps))
Z=delta_b4
m.setObjective(Z, GRB.MINIMIZE)
m.params.NonConvex = 2
m.optimize()
#for v in m.getVars():
ย ย #print('%s %g' % (v.VarName, v.X))
#print('Obj: %g' % m.ObjVal)
for v in m.getVars():
ย if v.X > 0 :
ย ย print('%s %g' % (v.VarName, v.X))
print('Obj: %g' % m.ObjVal)0 
Please find below another attempt that seems promising, but I did get the target results; I gotย ย ย obj= 4.78
#calculating the size of the uncertainty set under the assumption that the uncertainty is
#bounded and symmetric which is satisfied in this example
#parameters
eps=0.15
j=6
#Decision variables
delta_b4=m.addVar(lb=0, name='delta_b4')
theta=m.addVar(lb=0.00001,ub=15, name='theta')
theta_inf=m.addVar(lb=50 ,ub=15,name='theta_inf')
x=m.addVar(name='x')
y=m.addVar(name='y')
z=m.addVar(name='z')
t=m.addVar(name='t')
vc=m.addVar(name='vc')
dv=m.addVar(name='dv')
sc=m.addVar(name='sc')
#Set of Constraints
#theta_inf==1*theta
m.addConstr(theta_inf==1*theta)
m.addGenConstrExp(theta,x)
m.addGenConstrExp(theta_inf,y)
m.addConstr(z == xy)
m.addGenConstrLog(z,t)
m.addConstr(vc==2*theta)
m.addGenConstrLog(vc,dv)
m.addConstr(sc==6*(tdv))
m.addConstr(theta*delta_b4 + sc <= math.log(eps))
Z=delta_b4
m.setObjective(Z, GRB.MINIMIZE)
m.params.NonConvex = 2
m.optimize()
#for v in m.getVars():
ย ย #print('%s %g' % (v.VarName, v.X))
#print('Obj: %g' % m.ObjVal)
for v in m.getVars():
ย if v.X > 0 :
ย ย print('%s %g' % (v.VarName, v.X))
print('Obj: %g' % m.ObjVal)0 
As already noted exponential and logarithmic functions are handled via piecewiselinear approximation. All pieces have equal width and this could lead to large approximation errors if, for example, the interesting interval is much smaller than the part of the function that is approximated. So, it often helps to include bounds on some of the variables. In your example the following works:
eps=0.15
#Decision variables
delta_b4=m.addVar(lb=0, name='delta_b4')
theta=m.addVar(lb=0.001,ub=15, name='theta')
theta_inf=m.addVar(lb=15 ,ub=0,name='theta_inf')
theta_div = m.addVar(name='theta_div')
x=m.addVar(name='x')
y=m.addVar(name='y')
z=m.addVar(name='z')
t=m.addVar(lb=0, ub=1, name='t') # added bounds
#Set of Constraints
m.addConstr(theta_inf==1*theta)
m.addConstr(theta * theta_div == 1)
m.addGenConstrExp(theta,x)
m.addGenConstrExp(theta_inf,y)
m.addConstr(z == (xy)*0.5*theta_div)
m.addGenConstrLog(z,t)
m.addConstr(delta_b4*theta +6*t <= math.log(eps))
m.setObjective(delta_b4, GRB.MINIMIZE)
m.params.NonConvex = 2
# to reduce appoximation error further
#m.params.FuncPieces = 10000
m.optimize()1 
Thank you so much for your feedback, so I always have to tune the upper and lower bounds when working with exponential and logarithm, the problem is if I don't know what the results should be like, then it will be difficult to judge if it is correct, as well as the bounds if they are small or large.
1 
Maybe you could start with rather lax bounds and then try to improve them similarly as it is done in this Python example gc_pwl_func.py
1 
Thank you so much, I really appreciate your guidance, I will look at it, to understand more how it is done.
0
Please sign in to leave a comment.
Comments
14 comments