• Gurobi Staff

Hi,

There are several syntax mistakes with this snippet, e.g. first import line, $$\texttt{m.addMVar}$$ with no line break with $$\texttt{m.setObjective}$$. Please use a Python syntax highlighter/checker.
Also, to add multiple constraints you need to use $$\texttt{m.addConstrs}$$.

Cheers,
David

Thank you David. I edited the syntax. But my real problems come from  the last 6 lines. I could not get it work based on my idea.

• Gurobi Staff

I think there are several problems in your model:

1. In your first set of constraints, I think you want to use 'max' instead of 'gp.max_'
2. You cannot combine two expressions with "and" in an indicator constraint. You need to split them in two each.
3. You require w[i]=0 and w[i]=1 if f[i]=1? How should this work?
4. I do not understand what you want with temp = ((goal @x ) < 0) ? Do you want to have a constraint which shall be <0 or >=0 dependent from f[i]?
5. Why are you using addMVar? I think it would be better to use addVars.

Thank you Marika.

3. Is it should be if f[i] = 1 if ( w[i] =1 and temp == True)?

4. Yes.  That is what I need.

• Gurobi Staff

Hi,

3. Is it should be if f[i] = 1 if ( w[i] =1 and temp == True)?

It depends on what you want to model. Firstly, both $$\texttt{f}$$ and $$\texttt{w}$$ should be binary in order to use them in indicator constraints. See Model.addGenConstrIndicator().
If you just want to model that $$\texttt{f[i]}=0 \implies \texttt{temp}=0$$ and $$\texttt{f[i]}=1 \implies \texttt{temp}=1$$ regardless of the values of $$\texttt{w}$$. This can be formulated usign  Model.addGenConstrAnd().

Assuming these are binary then you can use some extra variables and constraints to model  $$\texttt{temp}$$. Including Marika's fix and using the tip from Why doesn't Gurobi support strict inequality constraints like x < a? It could be something as shown below.

Note that I would save some lines by adding the objective function as a linear expression straight away, instead of using $$\texttt{goal @ f}$$ which produces a MLinExpr. This would be neater as it would save having to $$\texttt{m.update}$$ then $$\texttt{m.getObjective}$$. This also applies when adding variables as they are all 1-d, as Marika already pointed out.

import gurobipy as gpfrom gurobipy import GRBimport numpy as npm = gp.Model("opt")goal = np.array([2, -4, 5, 3, -2, -3, 2, 6, 3, 6])eps = 1e-3  # for inequalitiesx = np.array([2, -4, 5, 3, -2, -3, 2, 6, 1, 6])# Variablesa = m.addVar(name="a")b = m.addVar(name="b")c = m.addVar(name="c")w = m.addMVar(shape=len(x), name="w", vtype=GRB.BINARY)f = m.addMVar(shape=len(x), name="f", vtype=GRB.BINARY)obj_expr = goal @ fm.setObjective(obj_expr, GRB.MAXIMIZE)m.addConstrs(    (w[i] == 1) >> ((a * max(x[i] - 1, 0) + b * max(1 - x[i], 0) + c) <= 0)    for i in range(10))m.addConstrs(    (w[i] == 0) >> ((-a * max(x[i] - 1, 0) - b * max(1 - x[i], 0) - c) <= 0 - eps)    for i in range(10))m.update()  # Update before get objective neededobj = m.getObjective()obj_var = m.addVar(name="obj_var")m.addConstr(obj == obj_var, "obj_constr")sign_obj = m.addVar(vtype=GRB.BINARY, name="sign_obj")  # 1 if negative, 0 ow.m.addConstr((sign_obj == 1) >> (obj_var <= 0 - eps), "negative_obj")m.addConstr((sign_obj == 0) >> (obj_var >= 0), "non_negative_obj")m.addConstrs((f[i] == gp.and_(sign_obj) for i in range(10)), name="f_and_sign_obj")m.optimize()