Warehouse location
Describes the problem and presents the model and data files.
| Bonn | Bordeaux | London | Paris | Rome | |
|---|---|---|---|---|---|
| capacity | 1 | 4 | 2 | 1 | 3 |
| store1 | 20 | 24 | 11 | 25 | 30 |
| store2 | 28 | 27 | 82 | 83 | 74 |
| store3 | 74 | 97 | 71 | 96 | 70 |
| store4 | 2 | 55 | 73 | 69 | 61 |
| store5 | 46 | 96 | 59 | 83 | 4 |
| store6 | 42 | 22 | 29 | 67 | 59 |
| store7 | 1 | 5 | 73 | 59 | 56 |
| store8 | 10 | 73 | 13 | 43 | 96 |
| store9 | 93 | 35 | 63 | 85 | 46 |
| store10 | 47 | 65 | 55 | 71 | 95 |
The key idea in representing a warehouse-location problem as an integer program consists of using a 0-1 variable for each (warehouse, store) pair to represent whether a warehouse supplies a store. In addition, the model also associates a variable with each warehouse to indicate whether the warehouse is selected. Once these variables are declared, the constraints state that each store must be supplied by a warehouse, that each store can be supplied by only an open warehouse, and that each warehouse cannot deliver more stores than its allowed capacity. The most delicate aspect of the modeling is expressing that a warehouse can supply a store only when it is open. These constraints can be expressed by inequalities of the form
forall( w in Warehouses, s in Stores )
ctUseOpenWarehouses:
Supply[s][w] <= Open[w];
forall( w in Warehouses )
ctMaxUseOfWarehouse:
sum( s in Stores )
Supply[s][w] <= Capacity[w];
which ensures that when warehouse w is not open,
it does not supply store s. This follows from the
fact that open[w] == 0 implies supply[w][s]
== 0.
As an alternative, you can write:
forall(c in Connections)
ctCapacity:
sum( <p,c> in Routes )
Trans[<p,c>] <= Capacity;
This formulation implies that a closed warehouse has no capacity.
A warehouse-location model (warehouse.mod) describes an integer program for the warehouse-location problem, and Data for the warehouse-location model (warehouse.dat) depicts some instance data.
A
warehouse-location model (warehouse.mod)
int Fixed = ...;
{string} Warehouses = ...;
int NbStores = ...;
range Stores = 0..NbStores-1;
int Capacity[Warehouses] = ...;
int SupplyCost[Stores][Warehouses] = ...;
dvar boolean Open[Warehouses];
dvar boolean Supply[Stores][Warehouses];
minimize
sum( w in Warehouses )
Fixed * Open[w] +
sum( w in Warehouses , s in Stores )
SupplyCost[s][w] * Supply[s][w];
subject to{
forall( s in Stores )
ctEachStoreHasOneWarehouse:
sum( w in Warehouses )
Supply[s][w] == 1;
forall( w in Warehouses, s in Stores )
ctUseOpenWarehouses:
Supply[s][w] <= Open[w];
forall( w in Warehouses )
ctMaxUseOfWarehouse:
sum( s in Stores )
Supply[s][w] <= Capacity[w];
}
{int} Storesof[w in Warehouses] = { s | s in Stores : Supply[s][w] == 1 };
execute DISPLAY_RESULTS{
writeln("Open=",Open);
writeln("Storesof=",Storesof);
}
Data
for the warehouse-location model (warehouse.dat)
Fixed = 30;
Warehouses = {Bonn,Bordeaux,London,Paris,Rome};
NbStores = 10;
Capacity = [1,4,2,1,3];
SupplyCost = [
[ 20, 24, 11, 25, 30 ],
[ 28, 27, 82, 83, 74 ],
[ 74, 97, 71, 96, 70 ],
[ 2, 55, 73, 69, 61 ],
[ 46, 96, 59, 83, 4 ],
[ 42, 22, 29, 67, 59 ],
[ 1, 5, 73, 59, 56 ],
[ 10, 73, 13, 43, 96 ],
[ 93, 35, 63, 85, 46 ],
[ 47, 65, 55, 71, 95 ] ];
The statement declares the warehouses and the stores, the fixed cost of the warehouses, and the supply cost of a store for each warehouse. The problem variables
dvar boolean Open[Warehouses];
dvar boolean Supply[Stores][Warehouses];
represent which warehouses supply the stores, i.e., supply[s][w] is 1 if
warehouse w supplies store s and
zero otherwise.
The objective function
minimize
sum( w in Warehouses )
Fixed * Open[w] +
sum( w in Warehouses , s in Stores )
SupplyCost[s][w] * Supply[s][w];
expresses the goal that the model minimizes the fixed cost of the selected warehouses and the supply costs of the stores.
The constraint
forall( s in Stores )
ctEachStoreHasOneWarehouse:
sum( w in Warehouses )
Supply[s][w] == 1;
states that a store must be supplied by exactly one warehouse.
The constraint
forall( w in Warehouses, s in Stores )
ctUseOpenWarehouses:
Supply[s][w] <= Open[w];
forall( w in Warehouses )
ctMaxUseOfWarehouse:
sum( s in Stores )
Supply[s][w] <= Capacity[w];
expresses the capacity constraints for the warehouses and makes sure that a warehouse supplies a store only if the warehouse is open.
A solution to warehouse.mod
For the instance data shown in Data for the warehouse-location model (warehouse.dat), OPL returns the optimal solution
Optimal solution found with objective: 383
open= [1 1 1 0 1]
storesof= [{3} {1 5 6 8} {7 9} {} {0 2 4}]