Hi @Milan, in this case the logical constraint as numerical benefits over the other approach since it can avoid numerical issues.
When you had the Use variables, what were the magnitude of the violations? Typically that would be a bug, but if the value of pl[j] is high, then pl[j] * Use[j] <= p[j] can result in p[j] lower than pl[j] since there is integrality tolerance in Gurobi that allows it to be something like 0.99999 which when multiplied by a large number would allow p[j] to be smaller than pl[j].
Thank you for your reply. I have attached the .mod and .dat files (a small example). I tested with Gurobi and COPT. The first approach (logical variable) provides:
subject to LL {j in POP}: pl[j] <= p[j] or 0 == p[j];
specifies that either p[j]=0 or p[j]>=pl[j]. Gurobi’s solution satisfies this requirement, with p[1] equal to 0 and p[2], p[3], and p[4] equal to 0.05 or larger. The other version has
var Use {POP} binary;
subject to LL {j in POP}: pl[j] * Use[j] <= p[j];
which specifies that either p[j]>=0 (when Use[j]=0) or p[j]>=pl[j] (when Use[j]=1) — which is not the same thing. To get the same effect as the previous formulation, you should modify constraints LL and LU as follows:
var Use {POP} binary;
subject to LL {j in POP}: p[j] >= Use[j] * pl[j];
subject to LU {j in POP}: p[j] <= Use[j] * pu[j];
Here you can see that either p[j]>=0 and p[j]<=0, hence pj[j]=0 (when Use[j]=0) or p[j]>=pl[j] and p[j]<=pu[j] (when Use[j]=0).
I prefer the approach that uses the or operator, because it expresses the constraint more clearly.
You might want to experiment with the other approach, just to see if it’s noticeably faster with the solver you are using. Sometimes, different formulation approaches cause the problem to be sent to the solver in different ways, which can possibly make a difference in solve times. I would only recommend this if you have trouble with your solve taking a very long time, however.