I solve the problem of placing factories and warehouses at the same time. At first I wrote a programme using the standard CPLEX tools, but then I was faced with the task of rewriting this programme using CP. Here is my original project: .mod file:
int l = ...;
int n = ...;
int t = ...;
int m = ...;
range j = 1..m;
range i = 1..n;
range h = 1..l;
range e = 1..t;
int D[j] = ...;
int K[i] = ...;
int S[h] = ...;
int W[e] = ...;
float F[i] = ...;
float f[e] = ...;
float c1[h][i] = ...;
float c2[i][e] = ...;
float c3[e][j] = ...;
dvar boolean y1[i];
dvar boolean y2[e];
dvar int+ x1[e][j];
dvar int+ x2[i][e];
dvar int+ x3[h][i];
minimize
sum(I in i) (F[I] * y1[I]) +
sum(E in e) (f[E] * y2[E]) +
sum(H in h, I in i) (c1[H][I] * x3[H][I]) +
sum(I in i, E in e) (c2[I][E] * x2[I][E]) +
sum(E in e, J in j) (c3[E][J] * x1[E][J]);
subject to {
forall(H in h)
sum(I in i) x3[H][I] <= S[H];
forall(I in i)
sum(H in h) (x3[H][I]) - sum(E in e) (x2[I][E]) >= 0;
forall(I in i)
sum(E in e) x2[I][E] <= K[I] * y1[I];
forall(E in e)
sum(I in i) (x2[I][E]) - sum(J in j) (x1[E][J]) >= 0;
forall(E in e)
sum(J in j) x1[E][J] <= W[E] * y2[E];
forall(J in j)
sum(E in e) x1[E][J] == D[J];
}
.dat file:
l = 3; //number of suppliers
n = 4; //number of potential factory locations
t = 5; //number of potential warehouse locations
m = 7; //number of markets or demand points
SheetConnection sheet("Task.xlsx");
D from SheetRead(sheet, "PWL!b26:h26"); //annual demand from customer
K from SheetRead(sheet, "PWL!h12:h15"); //potential capacity of factory at site
S from SheetRead(sheet, "PWL!f4:f6"); //supply capacity at supplier
W from SheetRead(sheet, "PWL!j21:j25"); //potential warehouse capacity at site
F from SheetRead(sheet, "PWL!g12:g15"); //fixed cost of locating a plant at site
f from SheetRead(sheet, "PWL!i21:i25"); //fixed cost of locating a warehouse at site
c1 from SheetRead(sheet, "PWL!b4:e6"); //cost of shipping one unit from supply source to factory
c2 from SheetRead(sheet, "PWL!b12:f15"); //cost of producing and shipping one unit from factory to warehouse
c3 from SheetRead(sheet, "PWL!b21:h25"); // cost of shipping one unit from warehouse to customer
x3 to SheetWrite(sheet, "PWL!m4:p6"); //quantity shipped from warehouse to market
x2 to SheetWrite(sheet, "PWL!m12:q15"); //quantity shipped from factory to warehouse
x1 to SheetWrite(sheet, "PWL!m21:s25"); //quantity shipped from supplier to factory at site
y1 to SheetWrite(sheet, "PWL!r12:r15"); //1 if factory is located at site i, 0 otherwise
y2 to SheetWrite(sheet, "PWL!t21:t25"); //1 if warehouse is located at site e, 0 otherwise
I don't know many of the intricacies of CP, any help would be greatly appreciated
So far, I've written a .dat file:
nSuppliers = 3;
nFactories = 4;
nWarehouses = 5;
nMarkets = 7;
D = [150, 150, 100, 100, 100, 150, 100];
K = [350, 280, 400, 300];
S = [350, 290, 310];
W = [350, 350, 350, 350, 350];
F = [450000, 500000, 450000, 450000];
f = [30000, 40000, 35000, 20000, 35000];
c1 = [
[1.9, 1.9, 1.8, 1.9],
[2.0, 2.0, 1.9, 1.8],
[1.8, 2.0, 1.9, 2.0]
];
c2 = [
[6.1, 7.8, 7.9, 7.9, 7.8],
[7.7, 7.1, 6.9, 7.8, 7.7],
[6.7, 6.0, 7.1, 6.9, 6.7],
[7.0, 6.0, 6.5, 7.6, 6.6]
];
c3 = [
[4.5, 5.0, 4.6, 5.5, 4.8, 4.1, 4.9],
[4.8, 4.6, 4.9, 5.7, 5.7, 5.9, 4.0],
[5.2, 5.1, 5.1, 4.2, 4.7, 4.0, 5.0],
[5.2, 5.9, 4.3, 5.9, 5.7, 4.1, 4.7],
[4.9, 5.3, 4.1, 4.5, 4.7, 5.6, 4.0]
];
After adding it to the project:
using CP;
execute
{
cp.param.timelimit=10;
}
I got this result, I am confused by the number of branches in this solution:
! Time = 9,86s, Explored branches = 2 081 170, Memory usage = 28,5 MB
! Best Branches Non-fixed W Branch decision
1 445 819 179k 11 2 1 != x2(4)(1)
1 445 819 164k 31 3 0 != x3(3)(2)
1 445 819 182k 25 5 25 != x3(2)(4)
1 445 819 183k 21 6 1 != x1(5)(1)
1 445 819 167k 30 7 198 != x2(3)(5)
1 445 819 174k 76 8 F -
1 445 819 159k 32 9 0 = x3(2)(2)
1 445 819 172k 21 10 54 != x1(1)(5)
1 445 819 175k 25 11 104 != x2(4)(5)
1 445 819 168k 76 12 F 23 = x1(1)(5)
1 445 819 183k 32 1 34 != x1(1)(6)
1 445 819 180k 15 4 1 != x1(4)(7)
1 445 819 183k 9 5 214 != x2(4)(5)
1 445 819 184k 76 6 F -
1 445 819 175k 76 8 F 1 = x1(4)(4)
1 445 819 160k 34 9 54 != x2(1)(4)
1 445 819 173k 28 10 60 != x1(1)(4)
1 445 819 176k 10 11 4 != x2(1)(3)
1 445 819 169k 23 12 1 != x1(4)(4)
! ----------------------------------------------------------------------------
! Search terminated by limit, 26 solutions found.
! Best objective : 1 445 819
! Number of branches : 2 104 124
! Number of fails : 1 007 321
! Total memory usage : 29,2 MB (28,6 MB CP Optimizer + 0,6 MB Concert)
! Time spent in solve : 10,01s (10,01s engine + 0,00s extraction)
! Search speed (br. / s) : 210 160,2
! ----------------------------------------------------------------------------
In your model, you can simply add
using CP;
execute
{
cp.param.timelimit=10;
}
at the beginning of your model
On my machine I see
! Time = 9,98s, Average fail depth = 34, Memory usage = 26,2 MB
! Current bound is 475520.7 (gap is 67,11%)
! Best Branches Non-fixed W Branch decision
1.445820e+06 155k 12 8 1 != x3(2)(3)
1.445820e+06 159k 29 9 F 24 = x1(3)(5)
! ----------------------------------------------------------------------------
! Search terminated by limit, 178 solutions found.
! Best objective : 1.445820e+06 (gap is 67,11%)
! Best bound : 475520.7