I'm solving a LP / MILP problem using ILOG CPLEX.
int n = ...;
range time =1..n;
dvar float+ c[time] in 0..0.3;
dvar float+ d[time] in 0..0.3;
dvar float+ x[time];
int beta[time]=...;
float pc[time]=...;
float pd[time]=...;
//Expressions
dexpr float funtion = sum(t in time) (d[t]*pd[t]-c[t]*pc[t]);
//Model
maximize function;
subject to {
x[1] == 0.5;
c[1] == 0;
d[1] == 0;
forall(t in time)
const1:
x[t] <= 1;
forall(t in time: t!=1)
const2:
(x[t] == x[t-1] + c[t] - d[t]);
forall(t in time: t!=1)
const3:
( d[t] <= 0) || (c[t] <= 0);
As you can see I've forced c[t] and d[t] to never be bigger than 0 at the same time with "const3".
My question is, how would this constraint be represented in a LP/MILP mathematical formulation?
Is adding this new variable enough? :
y[t]≤c[t]+d[t]
y[t]≥c[t]
y[t]≥d[t]
0≤y[t]≤M (M is the maximum value of both c or d)
As far as I can tell, the constraints you suggested would allow this setting:
c[t] = 0.1
d[t] = 0.1
y[t] = 0.2
Which has c
and d
different from 0 simultaneously.
I can see these options to formulate your condition without logical constraints:
1) Use an SOS constraint that contains just c[t]
and d[t]
. By definition of SOS only one of the two can be non-zero in any feasible solution.
2) Use a boolean variable y[t]
and add constraints
c[t] <= M * y[t]
d[t] <= M * (1 - y[t])
3) Again, use boolean y[t]
and then indicator constraints
(y[t] == 0) => (c[t] == 0);
(y[t] == 1) => (d[t] == 0);
4) You can just state c[t] * d[t] == 0
but that will make the model non-linear.
In any case, a solver will probably be able to reduce your original formulation to either 2 or 3. So reformulating the constraint may not make things faster but only more obscure.