Skip to main content

Exponential function in the constraint with gurobi-python

Answered

Comments

14 comments

  • Matthias Miltenberger
    Gurobi Staff Gurobi Staff

    Hi!

    Could you please share what you have tried so far? Please review our guide Posting to the Community Forum โ€“ Gurobi Help Center

    Thanks,
    Matthias

    1
  • Abde
    Conversationalist
    First Question

    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
  • Marika Karbstein
    Gurobi Staff Gurobi Staff

    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
  • Abde
    Conversationalist
    First Question

    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 == x-y)
    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
  • Marika Karbstein
    Gurobi Staff Gurobi Staff

    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 piecewise-linear approximation. So it would be helpful to define reasonable finite bounds on theta (and theta_inf).
    ย 
    ย 
    0
  • Abde
    Conversationalist
    First Question

    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
  • Abde
    Conversationalist
    First Question

    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
  • Marika Karbstein
    Gurobi Staff Gurobi Staff

    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
  • Abde
    Conversationalist
    First Question

    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 == x-y)
    m.addGenConstrLog(z,t)
    m.addConstr(vc==2*theta)
    m.addGenConstrLog(vc,dv)
    m.addConstr(-theta*delta_b4 + 6*(t-dv) <= 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
  • Abde
    Conversationalist
    First Question

    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 == x-y)
    m.addGenConstrLog(z,t)
    m.addConstr(vc==2*theta)
    m.addGenConstrLog(vc,dv)
    m.addConstr(sc==6*(t-dv))
    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
  • Marika Karbstein
    Gurobi Staff Gurobi Staff

    As already noted exponential and logarithmic functions are handled via piecewise-linear 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 == (x-y)*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
  • Abde
    Conversationalist
    First Question

    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
  • Marika Karbstein
    Gurobi Staff Gurobi Staff

    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
  • Abde
    Conversationalist
    First Question

    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.