Hello Everyone! I am trying to run my code to solve an MILP with optmodel procedure. I am using SAS enterprise Guide 7.1. I was trying to locate optimal number of Depots for storing supplies from fields. My two location sets for Depot and Field are the same, using the county centroids. When I used one state (North Carolina) which has 100 counties, the code ran fine and gave me results. But just when I increased the number of states, my log showed me the error of "Ran out of memory". I am attaching my code here and also attaching the log. What can I do to resolve this issue? Thank you in advance!
/*creating macro variables*/
%let NumFields = 50;
%let NumDepots = 10;
%let DepotCapacity = 25000;
%let MaxDemand = 1000;
%let xmax = 200;
%let ymax = 100;
%let seed = 423;
data fdata(Rename=(County=name));
set UScounties;
if state in ("North Carolina", "South Carolina", "Virgina") then
do;
x=Long;
demand=rand('UNIFORM') * &MaxDemand;
Y=Lat;
output fdata;
keep county x demand y;
end;
run;
data pdata(Rename=(county=name));
set UScounties;
if state in ("North Carolina", "South Carolina", "Virgina") then
do;
x=Long;
y=Lat;
fixed_cost=275000;
output;
keep county x y fixed_cost;
end;
run;
/*Solving the MILP*/
proc optmodel;
set <str> Fields;
/*declares set of fields*/
set <str> Depots init {};
/*declares set of depots*/
num x{Fields union Depots};
/*creating an array of x cooordinate with all the field and depot location, union combines both field and depot*/
num y{Fields union Depots};
/*creating an array of y cooordinate with all the field and depot location*/
num demand{Fields};
num fixed_cost{Depots};
num distance {i in Fields, j in Depots}=sqrt((x[i] - x[j])^2 + (y[i]
- y[j])^2);
/* linear distance between fields and depots*/
read data fdata into Fields=[name] x y demand;
read data pdata into Depots=[name] x y fixed_cost;
var Assign {Fields, Depots} binary;
/* binary value to assign specific fields to specific depots*/
var Build {Depots} binary;
/*objective function*/
/* binary variable to determine which depots will be established*/
min cost=sum{i in Fields, j in Depots} Distance[i, j]*Assign[i, j] + sum{j in
Depots}Fixed_cost[j]*Build[j];
/*Constraints*/
con Assign_fields{i in Fields}: sum{j in Depots}Assign[i, j]=1;
/*each field assigned to one depot only*/
con Build_depot{i in Fields, j in Depots}: Assign[i, j] <=Build[j];
/* if a field is assigned to a depot, it has to be build*/
con Depot_capacity{j in Depots}: sum {i in Fields}Demand[i]*Assign[i,
j]<=&DepotCapacity*Build[j];
/*ensuring total field supply to a depot is within its capacity*/
solve obj Cost with MILP/Primalin;
num varcost=sum {i in FIELDS, j in DEPOTS} distance[i, j] * Assign[i, j].sol;
num fixcost=sum {j in DEPOTS} fixed_cost[j] * Build[j].sol;
for {s in 1.._NSOL_} do;
/*clean up the solution*/
for {i in FIELDS, j in DEPOTS} Assign[i, j]=round(Assign[i, j].sol[s]);
for {j in DEPOTS} Build[j]=round(Build[j].sol[s]);
call symput('varcost', put(varcost, 6.1));
call symput('fixcost', put(fixcost, 5.1));
call symput('totalcost', put(Cost, 6.1));
/*create a data set for use by PROC SGPLOT*/
create data CostFixedCharge_Data from
[FIELD DEPOT]={i in FIELDS, j in DEPOTS: Assign[i, j]=1}
x1=x[i] y1=y[i] x2=x[j] y2=y[j] function='line' drawspace='datavalue'
linethickness=1 linecolor='black';
submit s;
endsubmit;
end;
quit;
Can you please attach the UScounties data set or provide code to generate it?
Thank you so much for your reply. Although I am using the county names now as [name] but later I will use the unique FIPS code as there are duplicate county names within the US. I am attaching the US Counites dataset here.
One suggestion is to omit the Build_depot constraints, which are not strictly necessary. They tighten the formulation but also make it bigger, requiring more memory. The logical implication "if Assign[i,j] = 1 then Build[j]" is already enforced via the Depot_capacity constraints.
You might also try increasing the MEMSIZE option value, as described here.
Note also that Virgina should instead be Virginia.
Two additional suggestions:
1. Consider heuristically reducing the allowed field-to-depot assignments based on a distance threshold. This documentation example shows how to do that efficiently, by omitting variables from the formulation.
2. Use a Benders decomposition approach, as shown in this SAS Communities thread.
Thank you so much for all your great suggestions!
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.
Find more tutorials on the SAS Users YouTube channel.