GLPK - Minimize a variable value - variables

I'm working in virtual network embedding, and I'm creating a model with glpk to embed the networks.
I have this following objective function:
minimize cost: sum{(i,j) in VEdges} sum{u in SNodes, v in SNodes} weight[u,v] * fw[i,j,u,v] * secSupEdge[u,v] + sum{u in SNodes, v in SNodes} r[u,v] * secSupEdge[u,v];
Then I have the following two restrictions (among others)
s.t. relConst2{(i,j) in VEdges, u in AllNodes, v in AllNodes}: bwDem[i,j] * phiw[i,j,u,v] >= fw[i,j,u,v];
s.t. linkSecConst0{(i,j) in VEdges, u in SNodes, v in SNodes}: phiw[i,j,u,v] * secDemEdge[i,j] <= secSupEdge[u,v];
"phiw" is a binary variable
"fw" and "r" are variables that take any value >= 0
all the others ("weight", "bwDem", "secDemEdges", "secSupEdge") are just params
I want to relate phiw with fw. When fw > 0, phiw should take the value 1. When fw == 0, phiw should take the value 0.
Normally it does what I want, but sometimes phiw takes the value 1 when fw has the value 0, which is not what I want. This happens because the restrictions are met:
Example 1:
s.t. relConst2: 4 * 1 >= 0
s.t. linkSecConst0: 1 * 2 <= 2
Is there a way to minimize the value of phiw variable but not putting it in the objective function? Or putting it in the objective function but not changing the value of the result neither the value of all other variables?

The question is about minimizing phiw, however, the description of the problem suggests that what you want to do is link the values of phiw and fw, and specifically to have phiw = 1 when fw > 0, and phiw = 0 otherwise (i.e., fw = 0).
I would suggest that you add constraint that directly maps the conditional on fw to the value of phiw, such as:
s.t. LinkConstraint { (i,j) in VEdges, u in AllNodes, v in AllNodes }:
if fw[i,j,u,v] > 0 then 1 else 0 = phiw[i,j,u,v] ;

Related

How to convert the following if conditions to Linear integer programming constraints?

These are the conditions:
if(x > 0)
{
y >= a;
z <= b;
}
It is quite easy to convert the conditions into Linear Programming constraints if x were binary variable. But I am not finding a way to do this.
You can do this in 2 steps
Step 1: Introduce a binary dummy variable
Since x is continuous, we can introduce a binary 0/1 dummy variable. Let's call it x_positive
if x>0 then we want x_positive =1. We can achieve that via the following constraint, where M is a very large number.
x < x_positive * M
Note that this forces x_positive to become 1, if x is itself positive. If x is negative, x_positive can be anything. (We can force it to be zero by adding it to the objective function with a tiny penalty of the appropriate sign.)
Step 2: Use the dummy variable to implement the next 2 constraints
In English: if x_positive = 1, then y >= a
However, if x_positive = 0, y can be anything (y > -inf)
y > a - M (1 - x_positive)
Similarly,
if x_positive = 1, then z <= b
z <= b + M * (1 - x_positive)
Both the linear constraints above will kick in if x>0 and will be trivially satisfied if x <=0.

how to force succesive variable to be of same value?

I have a binary variable y[k][t], where k = 1..3 (machines) and t = 1..10 (time). Variable Y is 1 if machine is active and 0 otherwise.
In the optimization if machine 1 is active in period 1 e.g. Y[1][1] = 1, i want the machine to continue to operate for at least 3 time periods. i.e. Y[1][1] = Y[1][2] = Y[1][3] = Y[1][4] = 1.
I only want the succesive variable for t+1,t+2,t+3 to be same as t if it is active.
how can i do that in cplex studio?
This is sometimes called a minimum run length. There are different approaches to handle this. Say we have x(t) as our binary variables indicating if the machine is operating at time t. The first thing is to introduce a binary variable start(t) that indicates when a run starts. This is what I mean:
t 1 2 3 4 5 6 7 8
x 0 1 1 1 0 1 1 0
start 0 1 0 0 0 1 0 0
A run starts when x(t-1)=0 and x(t)=1, or more formally:
start(t) = x(t)*(1-x(t-1))
This is nonlinear. We can linearize this using:
start(t) <= x(t)
start(t) <= 1-x(t-1)
start(t) >= x(t)-x(t-1)
Often we just use the bound:
start(t) >= x(t)-x(t-1)
Next we need:
start(t) = 1 ==> x(t)...x(t+K-1) = 1
where K is the minimum run length.
This can be modeled as:
x(t+1) >= start(t)
...
x(t+K-1) >= start(t)
(we already know that x(t)=1 if start(t)=1).
what Erwin wrote about minimum run length is fine. If you rely on logical constraints that are available in CPLEX the model is a bit easier:
range K=1..3;
range T=1..10;
dvar boolean Y[K][T];
dvar boolean start[K][T];
subject to
{
forall(k in K) start[k][1]==Y[k][1];
forall(k in K,t in T:t!=1) start[k][t] == ((Y[k][t]==1) && (Y[k][t-1]==0));
forall(k in K) forall(l in 1..3)
forall(t in T:(t+l) in T) (start[k][t]==1) => (Y[k][t+l]==1);
}
But what could lead to long solve time if you grow the time horizon is that we enumerate time. Within CPLEX and OPL you may also use CPOptimizer and its dedicated scheduling concepts : intervals.
Then you would write
using CP;
range K=1..3;
range T=1..10;
int nbMaxIntervals=4;
dvar interval itvs[K][1..nbMaxIntervals] optional in T size 3..10;
subject to
{
forall(k in K) forall(i in 1..nbMaxIntervals-1)
endBeforeStart(itvs[k][i],itvs[k][i+1]);
}
What makes sure that you are on for at least 3 time periods is
size 3..10;
NB: More about CPOptimizer

Optimization of MiniZinc model

I have a MiniZinc model which is supposed to find d[1 .. n] and o[1..k, 0 .. n] such that
x[k] = o[k,0] + d[1]*o[k,1] + d[2]*o[k,2] ... d[n]+o[k,n] and the sum of absolute values of o[k,i]'s is minimized.
I have many different x[i] and d[1..n] should remain the same for all of them.
I have a working model which is pasted below, which finds a good solution in the n=2 case really quickly (less than a second) however, if I go to n=3 (num_dims in the code) even after an hour I get no answer except the trivial one (xi=o0), even though the problem is somewhat recursive, in that a good answer for 2 dimensions can serve as a starting point for 3 dimensions by using o0 as xi for a new 2 dimensional problem.
I have used MiniZinc before, however, I do not have a background in OR or Optimization, thus I do not really know how to optimize my model. I would be helpful for any hints on how to do that, either by adding constraints or somehow directing the search. Is there a way to debug such performance problems in MiniZinc?
My current model:
% the 1d offsets
array [1 .. num_stmts] of int : x;
x = [-10100, -10001, -10000, -9999, -9900, -101, -100, -99, -1, 1, 99, 100, 101, 9900, 9999, 10000, 10001, 10100];
int : num_stmts = 18;
% how many dimensions we decompose into
int : num_dims = 2;
% the dimension sizes
array [1 .. num_dims] of var int : dims;
% the access offsets
array [1 .. num_stmts, 1 .. num_dims] of var int : offsets;
% the cost function: make access distance (absolute value of offsets) as small as possible
var int : cost = sum (s in 1 .. num_stmts, d in 1 .. num_dims) (abs(offsets[s,d]));
% dimensions must be positive
constraint forall (d in 1 .. num_dims) (dims[d] >= 0);
% offsets * dimensions must be equal to the original offsets
constraint forall (s in 1 .. num_stmts) (
x[s] = offsets[s,1] + sum(d in 2 .. num_dims) (offsets[s,d] * dims[d-1])
);
% disallow dimension crossing
constraint forall (s in 1 .. num_stmts, d in 1 .. num_dims) (
abs(offsets[s,d]) < dims[d]
);
% all dims together need to match the array size
constraint product (d in 1..num_dims) (dims[d]) = 1300000;
solve minimize cost;
output ["dims = ", show(dims), "\n"] ++
[ if d == 1 then show_int(6, x[s]) ++ " = " else "" endif ++
" " ++ show_int(4, offsets[s, d]) ++ if d>1 then " * " ++ show(dims[d-1]) else "" endif ++
if d == num_dims then "\n" else " + " endif |
s in 1 .. num_stmts, d in 1 .. num_dims];
Are you using the MiniZinc IDE? Have you tried using a different solver?
I was struggling with a problem of dividing n random positive integers into m groups (m < n) where the sum of each group was supposed to be as close as possible to some other number.
When n reached about 100 and m about 10, it took significantly longer time (30 min+) and the result was not satisfying. This was using the default Gecode (bundled) solver. By chance I went through each and everyone of the solvers and found that the COIN-OR CBC (bundled) found an optimal solution within 15 s.

Conditional Graphing Plot?

I am trying to graph two functions, but i want to graph one function for a condition but graph using another function if another condition is met.
A simple example would be:
if x > 0
then sin(x)
else cos(x)
It would then graph cos and sin depending on the x value, there being an obvious gap at x = 0, as cos(0) = 1 and sin(0) = 0.
EDIT: There is a built-in way. I'll leave my original answer below for posterity, but try using the piecewise() function:
plot(piecewise(((cos(x),x<0), (sin(x), 0<x))))
See it here.
I would guess that there's a built-in way to do this, but I don't know it. You can multiply your functions by the Heaviside Step Function to accomplish this task. The step function is 1 if x > 0 and 0 if x < 0, so multiplying this into your functions and then summing them together will select only one of them based on the sign of x, that is to say:
f(x) := heaviside(x) * sin(x) + heaviside(-x) * cos(x)
If x > 0, heaviside(x) = 1 and heaviside(-x) = 0, so f(x) = sin(x).
If x < 0, heaviside(x) = 0 and heaviside(-x) = 1, so f(x) = cos(x).
See it in action here. In general, note that if you want the transition to be at x = a, then you could do heaviside(x-a) and heaviside(-x+a), respectively. If you want N functions, you'll have to have (N-1) multiplied step functions on each term, each with their own (x-a_i) argument. I hope someone else can contribute a cleaner solution.

AMPL "Locking" a derived variable to a value

I want to investigate whether it is profitable to invest in an additional production facility, and hence I have to account for an capitilization in my objective function.
As such I am wondering if it is possible to, say, if y[t] = 1, then y[g] = 1
for g != t, g > t and where g,t is a subset of the time interval set T.
My first thought was to have:
subject to Constraint1:
y[t] = y[t-1] for all t in T
But that must surely render the solution of y to become the start value in y[0] which is something I obviously do not want.
For clarification. Assume that y[t] is a binary variable whose value is 1 if the investment is undertaken in time t, otherwise 0.
Hope anyone can shed some light into this!
Regards
The constraint y[t] = 1, then y[g] = 1 for g != t, g > t can be represented in AMPL as something like:
s.t. c{t in T: t != t0}: y[t + 1] >= y[t];
where t0 is the first element of set T. Note the use of >= instead of =. If y[t] is 1 for some t, it will drive y for all subsequent values of t to 1.