How to write Max[] constraint in model?
AnsweredHi all,
I am using Java to call gurobi to solve a MILP problem, and I encountered difficulties while creating constraints. I have created an integer variable Z that is ≥ 0 and want to implement the following constraints:
(0.5 * Z + Max [0, (Z-2)] + Max [0, (Z-4)] + Max [0, (Z-6)]+...+ Max [0, (Z-20)]) / Z, which means the numerator is 0.5 * Z plus a set of piecewise functions, and the denominator is Z.
I would appreciate it if you can give me some suggestions.
Thanks a lot!
-
Hi Haoxing,
I could not fully understand the constraint that you are trying to generate, but have you tried using max_() function? You can find the documentation here:
https://www.gurobi.com/documentation/current/refman/py_max_.html
In your case I believe you can represent your constraint like (0.5 Z + max_((Z-2), constant = 0 ) + ... + max_((Z-20), constant = 0)
0 -
To add \(\max\) constraints in Gurobi, you will have to introduce auxiliary variables for each \(\max\) term. This means that your expression becomes
\[\begin{align*}
(0.5 \cdot Z &+ a_1 + a_2 + \dots + a_{10})/Z \\
a_1 &= \max \{0, b_1\} \\
b_1 &= Z - 2 \quad(*)\\
a_2 &= \max \{0, b_2\}\\
b_2 &= Z - 4 \quad(*)\\
\dots\\
a_{10} &= \max \{0, b_{10}\}\\
b_{10} &= Z - 20 \quad(*)\\
\end{align*}\]Note that you might need to adjust the lower bounds of the \(b_i\) variables, because the default lower bound for variables in Gurobi is \(0\). Once you have implemented all auxiliary variables \(a_i, b_i\) and all \((*)\) equality constraints, you can use the addGenConstrMax method to implement the remaining \(\max\) constraints.
For the division by \(Z\), please refer to the Knowledge Base article How do I divide by a variable in Gurobi?
Best regards,
Jaromił0 -
Hi Jaromił,
Thanks for your reply. I followed your instructions to add Max constraints, it worked.
But I am facing the problem with the division constraint.
According to your reply, I refer to the Knowledge Base article How do I divide by a variable in Gurobi?
The formula I wrote above is just a simplified version. In my model, I created an Integer variable: sumZ[i][k], and I want to divide by sumZ[i][k], so I have to calculate its reciprocal: reverseSumZ[i][k].
Firstly, I creating these tow varialbes:
GRBVar sumZ[][] = new GRBVar[instance.nodesNum][instance.vehiclesNum];
GRBVar reverseSumZ[][] = new GRBVar[instance.nodesNum][instance.vehiclesNum];Secondly, I built their bounds and types:
for (int k = 0; k < instance.vehiclesNum; k++) {
for (int i = 0; i < instance.nodesNum; i++) {
sumZ[i][k] = model.addVar(0, GRB.INFINITY, 0.0, GRB.INTEGER, "sumZ_" + i + "_" + k);
reverseSumZ[i][k] = model.addVar(0, 1, 0.0, GRB.CONTINUOUS, "reverseSumZ_" + i + "_" + k);
}
}Thirdly, I created the constraint:
//reverseSumZ[i][k] * sumZ[i][k] = 1
for (int k = 0; k < instance.vehiclesNum; k++) {
for (int i = 1; i < instance.nodesNum - 1; i++) {
GRBQuadExpr expr = new GRBQuadExpr();
expr.addTerm(1, reverseSumZ[i][k], sumZ[i][k]);
model.addQConstr(expr, GRB.EQUAL, 1, "internalVar_adverse_" + i + "_" + k);
}
}The range for i is from 1 to instance.nodesNum -1, to make sure that the sumZ[i][k] is not equal to zero.
But running the program will prompt that the model has no solution. And I ensure that the model only has no solution after adding this constraint.
Can you help me answer this?
Best regards,
Haoxing
0 -
Hi Jaromił,
I would like to add is:
Integer variable sumZ[i][k] >=0, only when i∈N \ {0,n+1} will sumZ[i][k] ≠ 0.
0 -
Hi Haoxing,
But running the program will prompt that the model has no solution. And I ensure that the model only has no solution after adding this constraint.
Is your model declared infeasible? Did you try to determine why it is infeasible, see How do I determine why my model is infeasible? and How do I use 'compute IIS' to find a subset of constraints that are causing model infeasibility? The 0 in your reverse sum might be an issue, because this would mean that you allow division by 0.
Integer variable sumZ[i][k] >=0, only when i∈N \ {0,n+1} will sumZ[i][k] ≠ 0.
I am not sure what you mean. Do you mean to add constraint sumZ[i][k] >=0 for all i∈N \ {0,n+1}? Or do you mean to add sumZ[i][k] >=0 only when sumZ[i][k] ≠ 0?
Best regards,
Jaromił0 -
Hi Jaromił,
Thanks for your reply. I am sorry for my confusious answered.
In my model, sumZ[i][k] is >=0(sumZ[i][k] = 0 ← when i == 0 && i == instances.nodesNum), and I want to calculate its count backwards, so I construct a constraintin://reverseSumZ[i][k] * sumZ[i][k] = 1 for (int k = 0; k < instance.vehiclesNum; k++) { for (int i = 1; i < instance.nodesNum - 1; i++) { GRBQuadExpr expr = new GRBQuadExpr(); expr.addTerm(1, reverseSumZ[i][k], sumZ[i][k]); model.addQConstr(expr, GRB.EQUAL, 1, "internalVar_adverse_" + i + "_" + k); } }
In the constraint I set the range for i between 1 and instamce.nodesNum-1, to avoid divide by 0.
I think this is reasonable in logical, but the model is infeasible, that I consider the situation of dividing by 0 has not been ruled out yet.0 -
I think this is reasonable in logical, but the model is infeasible, that I consider the situation of dividing by 0 has not been ruled out yet.
In this case, you should try to follow the steps in How do I determine why my model is infeasible? and How do I use 'compute IIS' to find a subset of constraints that are causing model infeasibility? With that you should be able to find the source of infeasibility for your model.
0
Please sign in to leave a comment.
Comments
7 comments