Product of binary and integer constraint - Linear Programming - optimization

I am trying to formulate a linear program that will assign different number of employees to start in different days. Each group of employees starting on a day will get two days off during the week. However, the schedule is unknown. For example, employees starting Monday can be off any two days in the week. Since the number that will start on day (i) is unknown and whether they will have a day off or not is unknown, I will have the product of two decision variables - one is an integer xi (employees starting on day i) and a binary variable yij (whether the employees starting on day i have a day off on day j).
I am done with formulation and here it is:
Decision variables 1: xi (employees starting on day i)
Decision variables 2: yij (1 if employees starting on day i are working on day j, or 0 if employees starting on day i are off on day j)
Objective function:
Minimize total employees-- sum (i in 1..7) xi
Subject to:
xi*yij >= Requiredj (the number of available workers on day j have to satisfy the demand on day j)
I am trying to code this on CPLEX but i dont know how to make xi*yij linear and write the code....can anyone please help me?
Thank you.

In How to with OPL How to multiply a decision variable by a boolean decision variable in CPLEX ?
// suppose we want b * x <= 7
dvar int x in 2..10;
dvar boolean b;
dvar int bx;
maximize x;
subject to
{
// Linearization
bx<=7;
2*b<=bx;
bx<=10*b;
bx<=x-2*(1-b);
bx>=x-10*(1-b);
// if we use CP we could write directly
// b*x<=7
// or rely on logical constraints within CPLEX
// (b==1) => (bx==x);
// (b==0) => (bx==0);
}

Related

Using NewBoolVar in Google OR-Tools

I am wondering the syntax for logical constraints in Google OR-Tools. I have a nurse scheduling project I have done in CPLEX that I am translating over to Google OR-Tools. I have come across the documentation for channeling constraints in Google OR-Tools, but I am confused. Can you help me understand how I would implement this CPLEX logical constraint in Google OR-Tools? I have an attempt, but it is not working as intended :(
Context:
working_assignment_vars_long[r,h,i] is a binary decision variable that denotes whether nurse i in role r is working at the 15-minute interval h (i.e. 1:15PM).
lunch_break_assignment_vars_long[r,h,i] is a binary decision variable that denotes whether nurse i in role r is on break at the 15-minute interval h (i.e. 1:15PM).
simple_break_assignment_vars_long[r,h,i] is a binary decision variable that denotes whether nurse i in role r is on break at 15-minute interval h.
Thus, this constraint in CPLEX is saying that if a given nurse is working 31 or less 15-minute intervals, then they should have 0 lunch breaks and 1 simple break.
CPLEX logical constraint:
for r, num_role in role_dict.items():
for i in range(0,num_role):
model.add_if_then(
model.sum(model.working_assignment_vars_long[r,h,i] for h in range(0,144))
<= 31,
(model.sum(model.lunch_break_assignment_vars_long[r,h,i] for h in range(0,144)) ==
0) + (model.sum(model.simple_break_assignment_vars_long[r,h,i] for h in range(0,144)) ==
1) >= 2,
'less_than_8_hr_0_lunch_break_1_simple_break'
)
I have attempted this in OR-Tools with the following code:
for r, num_role in role_dict.items():
for i in range(0,num_role):
b=model.NewBoolVar(‘b’)
model.Add(sum(working.assignment_vars_long[r,h,i] for h in range(0,144)) <= 31).OnlyEnforceIf(b)
model.Add(sum(lunch_break_assignment_vars_long[r,h,i] for h in range(0,144)) == 0).OnlyEnforceIf(b)
model.Add(sum(simple_break_assignment_vars_long[r,h,i] for h in range(0,144)) == 1).OnlyEnforceIf(b)
This is not working as intended though :( as I see nurses working less than 32 15-minute intervals with both no lunch breaks and no simple breaks. Any insight/help is greatly appreciated. I have been stuck on this problem for so long now :(
In the official documentation it is documented how to do an If-Then-Else expression.
You aren't constraining b.Not():
model.Add(sum(working.assignment_vars_long[r,h,i] for h in range(0,144)) > 31).OnlyEnforceIf(b.Not())

How do I run a simulation experiment (iterative procedure) in CPLEX?

I am a beginner of programming. I'm trying to practice run a simulation with CPLEX.
Since I want to be a person who wants to work in an area in optimization.
Therefore, I am trying to study some journals from different areas by myself.
The attached image is the objective function and constraints.
I made up the code written below. I am not sure I made it right or wrong.
enter image description here
//Data
{string} product = ...;
{string} interval = ...;
// Limit
float low[interval] = ...;
float upper[interval] = ...;
// Maximum demand
float A[product] = ...;
// Slope of demand function
float varphi[product][interval] = ...;
// Price
float p[product] = ...;
// Setup cost
float f[product] = ...;
// Inventory holding cost rate
float h[product][interval] = ...;
// Variable cost rate
float v[product][interval] = ...;
// Variables
dvar float+ X[product][interval]; enter code here
dvar float+ D[product][interval];
dvar float+ a[interval];
dvar float+ beta[product][interval];
// Objective
maximize sum(i in product, j in interval) p[i]*X[i][j]-f[i]*beta[i][j]-v[i][j]*X[i][j]-0.5*h[i][j]*X[i][j] - F;
// Constraint
subject to{
forall(j in interval) sum(j in interval) a[j] == 1;
forall(i in product, j in interval) beta[i][j] <= a[j];
forall(i in product, j in interval) sum(i in product, j in interval) X[i][j] <= C;
forall(i in product, j in interval) X[j][i] <= D[i][j]*beta[i][j];
forall(j in interval) sum(i in product) beta[i][j] <= upper[j]*a[j];
forall(j in interval) sum(i in product) beta[i][j] >= low[j]*a[j];
forall(i in product, j in interval) D[i][j] = (A[i]-varphi[i][j]*p[i])*a[j];
}
I want to demonstrate how an iterative procedure may be applied to progressively narrow the interval of search to precisely determine the optimal number of products to produce in order to maximize profit.
The journal explains as "The cost and revenue data for these smaller intervals are provided as new inputs to the model which then identifies one of these new intervals as best in the subsequent iteration. The procedure is repeated in successive iterations until the last interval has only one or two levels (i.e., numbers of products) from which the model is able to make a final choice of product variety. In order to save time when the marginal benefit from successive iterations is very small, we also terminate the process if the difference between the objective function values (profit) of successive iterations is below a small predetermined convergence parameter. The model determines which of the levels of the final interval is optimal and also identifies which particular products to produce and in what quantities.
The first stage of this process begins with 100 products (as before) and a configuration involving price structure 3 and cost structure 3 (please see Tables 2–5). The product variety range is divided into four intervals with interval boundaries shown in Table 1. The result from this stage is that the third interval is selected as optimal, with 75 products and their corresponding optimal production quantities identified. The data are shown in Table 9 and the results are provided in Table 12, Table 13 (which also provide results from subsequent stages)."
Tables are attached below.
enter image description here
enter image description here
enter image description here
enter image description here
Product is total 100.
I have not decided the values of other parameters.
What I want to know is how to run the following iterative procedure?
When I run CPLEX, the objective function in the code keeps telling there is an error?
Thank you for your kind answers and you are the bests.
Regards,
forall(j in interval) sum(j in interval) a[j] == 1;
Looks bad since you used j twice !
For errors you should share dat file so that Other users could try

CPLEX - adding min in constraints & how to write sum with different values

I am new to this platform CPLEX which means a beginner of programming.
I'm trying to write the code for CPLEX for below questions.
Question 1.
∑j (X^D(i,j,t) <= min(k^P(i,t),k^A(i,t) for all i, t
enter image description here
I tried to write the code like something below
forall(i in plants,t in years)
{
sum(j in products:j!)(X[i,j,t]) <= kP[i,t];
sum(j in products:j!)(X[i,j,t]) <= kA[i,t];
}
Is this right?
First, how do you write the code (sum of j, without having specific values)
Second, is there a way to express 'min' constraint in CPLEX?
The next question is how do you write the code of sum of four values.
It's the advanced version of the upper question.
cost_t=∑s,i,m,j(c^S(s,i,m,j,t)*X^S(s,i,m,j,t)+∑i,j,t(c(i,j,t)*X(i,j,t)+∑i,r,j,t(c^D(i,r,j,t)*X^D(i,r,j,t)
enter image description here
How do you write the sum part with four or three index?
Thank you for your kind answers and you are the bests.
Regards,
range plants=1..10;
range years=2021..2022;
range products=1..4;
dvar int+ X[plants][products][years];
int kP[i in plants,t in years]=i*t;
int kA[i in plants,t in years]=i*t+2;
dvar float cost;
subject to
{
forall(i in plants,t in years)
{
sum(j in products:j!=1)(X[i,j,t]) <= minl(kP[i,t],kA[i,t]);
}
cost==sum(i,i2 in plants,t in years,j in products:i!=j) (X[i][j][t]+X[i2][j][t]);
}
works fine
minl means minimum of a few values

AMPL double summation

I am new to ampl and I am trying to formulate a mathematical model, and I need a double summation
I am trying to write :
600+ (the total capacity of the generators installed until year j) >= (demand of year j)
the capacity is being denoted by x[i,j], i in GENERATOR, j in YEAR.
600+ \sum_{j}(\sum_{i} x[i,j])>=demand[j]
subject to dem{j in YEAR}:600+sum{i in GENERATOR, j in YEAR}x[i,j]>=demand[j];
I tried this way but it gives me an error. Please help me to write a double summation.
If I've understood your requirements, what you need is something like this:
subject to dem{j_current in YEAR}:
600 + sum{i in GENERATOR, j_past in YEAR: j_past <= j_current}x[i,j_past]
>= demand[j_current];
(adds all x[i,j] UP TO current year)
or this:
subject to dem{j_current in YEAR}:
600 + sum{i in GENERATOR}x[i,j_current]
>= demand[j_current];
(adds all x[i,j] AT current year)
The way you had it will get you error messages because each constraint created by that statement already has a specific value of j so you can't then iterate over different values of j within the constraint.

Ranking Big O Functions By Complexity

I am trying to rank these functions — 2n, n100, (n + 1)2, n·lg(n), 100n, n!, lg(n), and n99 + n98 — so that each function is the big-O of the next function, but I do not know a method of determining if one function is the big-O of another. I'd really appreciate if someone could explain how I would go about doing this.
Assuming you have some programming background. Say you have below code:
void SomeMethod(int x)
{
for(int i = 0; i< x; i++)
{
// Do Some Work
}
}
Notice that the loop runs for x iterations. Generalizing, we say that you will get the solution after N iterations (where N will be the value of x ex: number of items in array/input etc).
so This type of implementation/algorithm is said to have Time Complexity of Order of N written as O(n)
Similarly, a Nested For (2 Loops) is O(n-squared) => O(n^2)
If you have Binary decisions made and you reduce possibilities into halves and pick only one half for solution. Then complexity is O(log n)
Found this link to be interesting.
For: Himanshu
While the Link explains how log(base2)N complexity comes into picture very well, Lets me put the same in my words.
Suppose you have a Pre-Sorted List like:
1,2,3,4,5,6,7,8,9,10
Now, you have been asked to Find whether 10 exists in the list. The first solution that comes to mind is Loop through the list and Find it. Which means O(n). Can it be made better?
Approach 1:
As we know that List of already sorted in ascending order So:
Break list at center (say at 5).
Compare the value of Center (5) with the Search Value (10).
If Center Value == Search Value => Item Found
If Center < Search Value => Do above steps for Right Half of the List
If Center > Search Value => Do above steps for Left Half of the List
For this simple example we will find 10 after doing 3 or 4 breaks (at: 5 then 8 then 9) (depending on how you implement)
That means For N = 10 Items - Search time was 3 (or 4). Putting some mathematics over here;
2^3 + 2 = 10 for simplicity sake lets say
2^3 = 10 (nearly equals --- this is just to do simple Logarithms base 2)
This can be re-written as:
Log-Base-2 10 = 3 (again nearly)
We know 10 was number of items & 3 was the number of breaks/lookup we had to do to find item. It Becomes
log N = K
That is the Complexity of the alogorithm above. O(log N)
Generally when a loop is nested we multiply the values as O(outerloop max value * innerloop max value) n so on. egfor (i to n){ for(j to k){}} here meaning if youll say for i=1 j=1 to k i.e. 1 * k next i=2,j=1 to k so i.e. the O(max(i)*max(j)) implies O(n*k).. Further, if you want to find order you need to recall basic operations with logarithmic usage like O(n+n(addition)) <O(n*n(multiplication)) for log it minimizes the value in it saying O(log n) <O(n) <O(n+n(addition)) <O(n*n(multiplication)) and so on. By this way you can acheive with other functions as well.
Approach should be better first generalised the equation for calculating time complexity. liken! =n*(n-1)*(n-2)*..n-(n-1)so somewhere O(nk) would be generalised formated worst case complexity like this way you can compare if k=2 then O(nk) =O(n*n)