Optimizing with binary variables

Hi,
So I’ve built this simple model, but I cant make it work because I dont know how to integrate the binary part with the non linear optimization. Im getting error 53 Endogenous $ operation not allowed, can anyone help me with this please? Thank you!!


Sets
t time periods /t1*t10/;

Parameter

cap max generation capacity /325/
sto max storage capacity /2600/
pump max pumping capacity /253/
price(T) price at period t
/t1 131.55,
t2 168.78,
t3 158.78,
t4 151.95,
t5 147.31,
t6 145.55,
t7 144.79,
t8 144.94,
t9 144.67,
t10 147.31/;

Variables
x(t) ‘pumping quantity in time period t’
y(t) ‘generation quantity in time period t’
s(t) ‘storage quantity at period in time period t’
bx(t) ‘boolean pumping in time period t’
by(t) ‘boolean generation in time period t’
cf ‘capacity factor %’
z ‘total revenue in thousands of dollars’;

Positive Variable x,y,s;
Binary Variable bx,by;

Equations

revenue “define objective function”
pumping(t) “pumping at period t”
max_pump(t) “max pumping at period t”
max_gen(t) “max gen at period t”
generation(t) “generation at period t”
storage (t) “storage at period t”
max_storage(t) “max storage at period t”
capacityfactor “capacity factor of the plant”;

storage(t)… s(t)=e=x(t-1) +s(t-1) +y(t);
revenue… z =e= sum(t,by(t)*y(t)*price(t)-bx(t)*x(t)price(t));
pumping(t)… bx(t)(by(t)=1)=e=0; max_pump(t).. x(t)=l=pump; max_storage(t).. s(t) =l= sto; generation(t).. by(t)(bx(t)=1) =e=0;
max_gen(t)… y(t)=l=cap;
capacityfactor… cf =e= sum(t,y(t)/(17520
cap));
y.fx(‘t1’) = 0;

Model batteries_model /all/ ;
option nlp=conopt;
option mip=cplex;
option rminlp=conopt;
option minlp=dicopt;
Solve batteries_model using minlp maximizing z;

You are not allowed to put $ conditions on variables as the solvers see it as one program and not a sequential set of operations as in normal programming.

You want to state if by(t) is 1 then bx(t) is 0.
You can do it as follows:
bx(t) =l= 1-by(t);

this will ensure that when by(t) is 1, bx(t) is 0 and when by(t) is 0, bx(t) is free.
Same applies to both equations pumping(t) and generation(t)\

  • Atharv

Hi!

Thank you for your quick response, it helped to compile the model, however, i cant seem to get an answer that makes sense:
Captura 1.PNG
it seems im getting values=1 for bx, and for by. (z is not being maximized neither).

This is how the code looks like now:

*Pumping & Generation optimization

Sets
t time periods /t1*t10/;

Parameter

cap max generation capacity /325/
sto max storage capacity /2600/
pump max pumping capacity /253/
price(T) price at period t
/t1 131.55,
t2 168.78,
t3 158.78,
t4 151.95,
t5 147.31,
t6 145.55,
t7 144.79,
t8 144.94,
t9 144.67,
t10 147.31/;


Variables
x(t) ‘pumping quantity in time period t’
y(t) ‘generation quantity in time period t’
s(t) ‘storage quantity at period in time period t’
bx(t) ‘boolean pumping in time period t’
by(t) ‘boolean generation in time period t’
cf ‘capacity factor %’
z ‘total revenue in thousands of dollars’;

Positive Variable x,y,s;
Binary Variable bx,by;

Equations

revenue “define objective function”
pumping(t) “pumping at period t”
max_pump(t) “max pumping at period t”
max_gen(t) “max gen at period t”
generation(t) “generation at period t”
storage (t) “storage at period t”
max_storage(t) “max storage at period t”
capacityfactor “capacity factor of the plant”;

storage(t)… s(t)=e=x(t-1) +s(t-1) +y(t);
revenue… z =e= sum(t,by(t)*y(t)*price(t)-bx(t)*x(t)price(t));
pumping(t)… bx(t) =l= 1-by(t);
max_pump(t)… x(t)=l=pump;
max_storage(t)… s(t) =l= sto;
generation(t)… by(t) =l= 1-bx(t);
max_gen(t)… y(t)=l=cap;
capacityfactor… cf =e= sum(t,y(t)/(17520
cap));
y.fx(‘t1’) = 0;

Model batteries_model /all/ ;
option nlp=conopt;
option mip=cplex;
option rminlp=conopt;
option minlp=dicopt;
Solve batteries_model using minlp maximizing z;

I misunderstood your constraint earlier. You would want only one of bx(t) and by(t) to be 1. It is not clear if you want to allow both to be zero. I will give you both solutions:

  1. If you want only one of bx(t) and by(t) to be 1 but at least one of them has to be one then you could do the following:
    bx(t) + by(t) =e= 1;

  2. If you want only one of bx(t) and by(t) to be 1 but both of them can be zero, then you could add the following equation:
    bx(t) + by(t) =l= 1;

In both cases you could get rid of pumping and generation equations.

  • Atharv

Thanks a lot!! I have 3 more questions if you dont mind,
(1) if I want to put a constraint saying:

if bx(t)=1, then x(t)>0 and y(t)=0
or the same in other words,
if by(t)=0 then y(t)=0
if bx(t) = 0 , then x(t)=0

how can i put this without using $ symbols, since x(t) and y(t) are not binary variables?

(2) Also, in this equation Im defining the storage formula:
storage(t)… s(t)=e=x(t-1) +s(t-1) +y(t);
and then Im saying that it any period t , storage cant be larger than the max storage capacity:
max_storage(t)… s(t) =l= sto;

but this doesnt seem to be right either, because it seems I’m redefining the equation and in the output I’m getting the storage value in every period t is the max storage (which is wrong).

So this constraint should be sth like:

storage(t)… s(t)=e=x(t-1) +s(t-1) +y(t); → =l= sto (or sth like that)
or…

if storage (t) >= sto then bx(t)=0


(3) Finally I would also like to add a constraint that if by(t)=1, (meaning that y(t) will then be >0), which implies there’s generation… then…

if the storage amount in period t-1 is >0, and that in case the storage amount is larger than the max capacity, then y(t) can be 325 (which is the max capacity in this case) or less, if the storage amount in t-1 is less than tha max capacity, then y(t) can be whatever its in storage or less.

In other words:

if by(t)=1 then
if storage(t-1) > 0 then:
if storage(t-1)>cap then:
y(t)=l=cap
else
y(t)=l=storage(t-1)
end if
else
y(t)=0
end if
end if

Sorry for the long post, Im having trouble understanding how to write the constraints without the “if”, “then” logic.

Thanks!

  1. If the quantities in your problem cannot be negative then it might be a good idea to define x(t) and y(t) as positive variables instead of free variables.
    positive variables
    x(t)
    y(t)
    ;

You would like to have y(t) = 0 if by(t) = 0
This can be done using Big-M formulation.
y(t) =l= M*by(t);
If you know the upper bound for y(t) then you can set M to be the upper bound. Otherwise, set a large enough value (not too large).
This constraint enforces if by(t) is 0 then y(t) is 0 and if by(t) is 1 y(t) is unbounded.


2. There is no problem in having both of those constraints as the optimization solvers do not solve your problem sequentially. In your results, you see that s(t) is at the maximum which could simply be because that is the solution according to your formulation.
A good practice would be to write bounds using .up and .lo notation instead of the notation.
s.lo(t) = sto;

  1. Once you define bounds using .lo or .up notation then it is out of question that the storage will be larger than the capacity. Also if you define it as positive variable, then it won’t be negative.
    That trims down your question to follows:
    if by(t) is 1 then you want y(t) = storage(t-1).

This can be done as follows:
y(t) =l= storage(t - 1) + M*(1 - by(t));
y(t) =g= storage(t - 1) - M*(1 - by(t));
In the above equations, if you put by(t) = 1 then y(t) becomes storage(t - 1). If by(t) is 0 then -M<= y(t) <= M
Again, you have to choose M carefully. To understand more about these formulations, please take a look at big-M formulations.

  • Atharv

hola, saludos a toda la comunidad
estoy aprendiendo a usar gams y mi escuela me dejó un ejercicio de optimización de ubicación y maneja variables binarias, lo programé y no me presenta errores, pero el resultado es cero, me pueden ayudar ?
esta es la tarea

Usted debe decidir la ubicación de dos ambulancias, que prestaran sus servicios a seis poblados. La ubicación de cada
poblado se encuentra en la siguiente tabla1:

Poblado Cord x Coord y
1 82 76
2 96 44
3 50 5
4 49 8
5 13 7
6 29 89

Para que una ambulancia pueda atender a un poblado a tiempo, debe estar localizada a una distancia inferior o igual
a 20. Usted escoger la ubicación de las dos ambulancias, de manera tal que el numero de poblados atendidos por
estas sea máximo. Este problema corresponde al problema de maximización de cobertura.

de ahí pide variar la distancia max de recorrido tal que las ambulancias puedes prestar a todos el servicio

le agradezco