Search code examples
mathematical-optimizationcplexconstraint-programmingopl

What is the correct way to rewrite a programme from CPLEX to CP?


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
 ! ----------------------------------------------------------------------------

Solution

  • 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