Sparse Modeling (omod7)
/***************************************************************/
/* */
/* S A S S A M P L E L I B R A R Y */
/* */
/* NAME: omod7 */
/* TITLE: Sparse Modeling (omod7) */
/* PRODUCT: OR */
/* SYSTEM: ALL */
/* KEYS: OR */
/* PROCS: OPTMODEL */
/* DATA: */
/* */
/* SUPPORT: UPDATE: */
/* REF: */
/* MISC: Example 7 from the OPTMODEL chapter of */
/* Mathematical Programming. */
/* */
/***************************************************************/
%let NumCustomers = 1500;
%let NumSites = 250;
%let SiteCapacity = 50;
%let MaxDemand = 10;
%let xmax = 200;
%let ymax = 100;
%let seed = 938;
/* generate random customer locations */
data cdata(drop=i);
length name $8;
do i = 1 to &NumCustomers;
name = compress('C'||put(i,best.));
x = ranuni(&seed) * &xmax;
y = ranuni(&seed) * &ymax;
demand = 1;
output;
end;
run;
/* generate random site locations and fixed charge */
data sdata(drop=i);
length name $8;
do i = 1 to &NumSites;
name = compress('SITE'||put(i,best.));
x = ranuni(&seed) * &xmax;
y = ranuni(&seed) * &ymax;
fixed_charge = 300 * (abs(&xmax/2-x)/&xmax + abs(&ymax/2-y)/&ymax);
output;
end;
run;
/* Dense Facility Location Model */
proc optmodel;
performance details;
set <str> CUSTOMERS;
set <str> SITES init {};
/* x and y coordinates of CUSTOMERS and SITES */
num x {CUSTOMERS union SITES};
num y {CUSTOMERS union SITES};
num demand {CUSTOMERS};
num fixed_charge {SITES};
/* distance from customer i to site j */
num dist {i in CUSTOMERS, j in SITES}
= sqrt((x[i] - x[j])^2 + (y[i] - y[j])^2);
read data cdata into CUSTOMERS=[name] x y demand;
read data sdata into SITES=[name] x y fixed_charge;
var Assign {CUSTOMERS, SITES} binary;
var Build {SITES} binary;
min CostNoFixedCharge
= sum {i in CUSTOMERS, j in SITES} dist[i,j] * Assign[i,j];
min CostFixedCharge
= CostNoFixedCharge + sum {j in SITES} fixed_charge[j] * Build[j];
/* each customer assigned to exactly one site */
con assign_def {i in CUSTOMERS}:
sum {j in SITES} Assign[i,j] = 1;
/* if customer i assigned to site j, then facility must be built at j */
con link {i in CUSTOMERS, j in SITES}:
Assign[i,j] <= Build[j];
/* each site can handle at most &SiteCapacity demand */
con capacity {j in SITES}:
sum {i in CUSTOMERS} demand[i] * Assign[i,j] <=
&SiteCapacity * Build[j];
/* do not assign customer to site more than 30 units away */
con distance_at_most_30 {i in CUSTOMERS, j in SITES: dist[i,j] > 30}:
Assign[i,j] = 0;
/* solve the MILP */
solve with milp/timetype=real relobjgap=1e-8;
quit;
/* Sparse Facility Location Model */
proc optmodel;
performance details;
set <str> CUSTOMERS;
set <str> SITES init {};
/* x and y coordinates of CUSTOMERS and SITES */
num x {CUSTOMERS union SITES};
num y {CUSTOMERS union SITES};
num demand {CUSTOMERS};
num fixed_charge {SITES};
/* distance from customer i to site j */
num dist {i in CUSTOMERS, j in SITES}
= sqrt((x[i] - x[j])^2 + (y[i] - y[j])^2);
read data cdata into CUSTOMERS=[name] x y demand;
read data sdata into SITES=[name] x y fixed_charge;
set CUSTOMERS_SITES = {i in CUSTOMERS, j in SITES: dist[i,j] <= 30};
var Assign {CUSTOMERS_SITES} binary;
var Build {SITES} binary;
min CostNoFixedCharge
= sum {<i,j> in CUSTOMERS_SITES} dist[i,j] * Assign[i,j];
min CostFixedCharge
= CostNoFixedCharge + sum {j in SITES} fixed_charge[j] * Build[j];
/* each customer assigned to exactly one site */
con assign_def {i in CUSTOMERS}:
sum {<(i),j> in CUSTOMERS_SITES} Assign[i,j] = 1;
/* if customer i assigned to site j, then facility must be built at j */
con link {<i,j> in CUSTOMERS_SITES}:
Assign[i,j] <= Build[j];
/* each site can handle at most &SiteCapacity demand */
con capacity {j in SITES}:
sum {<i,(j)> in CUSTOMERS_SITES} demand[i] * Assign[i,j] <=
&SiteCapacity * Build[j];
/* solve the MILP */
solve with milp/timetype=real relobjgap=1e-8;
quit;