Hello All! I am using SAS Enterprise Guide. I have a optimization code where I have many constraints and decision variables. It is a facility location problem using multimodal (truck and rail) and I have created routes using location j and k. I have two constraints right now where I am putting conditions if j and k does not have rail access, it can not ship using rail. I tried to combine the two constraints (freight_depot and freight_bioref) into one but it only considered the first condition before the constraint and not the one I join using AND. Is there anyway I can use the AND operator to join two conditions before a constraint, so that I can make the two constraints into one. I don't have all my constraints here. Just put some of them.
This is how I want to write them together-
Con freight {<j,k> in ROUTES2: (s[j]=0 and l[k] =0)}: sum{<f,'1'> in tr} Amount2[j,k,f,'1'] = 0;
Also, my code is very memory intensive as it deals with inputs of 2000 rows and millions of constraints and decision variables. Is there any way I can solve the out of memory issue? Right now, after reaching an error gap of 8%, I am going out of memory.
Thank you so much for all of your help.
@RobPratt, any help from you would be greatly appreciated. Thank you again!
proc optmodel ;
*****DECLARE SETS AND PARAMETERS*******;
set <str> Fields;
set <str> Depots init {};
set <str> Bioref;
set <str> Feedstock;
set <str> Price;
set Mode = {'0', '1'};
set <num> Capacity;
set <str,str,str> TRIPLES;
set DOUBLES = setof {<i,f,p> in TRIPLES} <i,f>;
set <str,str,str> ROUTES;
set <str,str> ROUTES2;
set <str,str> ROUTES3;
set <str,str> tr;
*Parameters for fields;
num sifp{Fields,Feedstock,Price} init 0; *Available biomass in field i of feedstock f at price p;
num maif{Fields,Feedstock} init 0; *binary assignment of type f from field i;
num gp {Price} init 0; *Farmgate price including grower payment and harvest and collection cost;
num fsb {Feedstock}init 0; *field site storage in bales;
num dmloss {Feedstock}init 0; *dry matter loss from bales;
num aifp{i in Fields,f in Feedstock,p in Price} = round(sifp[i,f,p]*(1-dmloss[f])); *available biomass in the fields after considering the dry matter loss;
*Transportation parameters;
num x{Fields union Depots}; *union combines both field and depot;
num y{Fields union Depots};
num s{Depots};
num l{Bioref};
*Calculating distances between fields and depots;
num a{i in Fields, j in Depots}= (sin((y[j]-y[i])*&C/2))**2+cos(y[i]*&C)*cos(y[j]*&C)*(sin((x[j]-x[i])*&C/2))**2;
num sij{i in Fields, j in Depots} = ifn(x[i]=x[j] and y[i]=y[j],0,2*atan2(sqrt(a[i,j]),sqrt(1-a[i,j]))*3957.143);*converted the distance to miles;
num dij{i in Fields, j in Depots} = round(sij[i,j],0.01);
*Calculating distances between depots and biorefineries;
num b{j in Depots, k in Bioref}= (sin((y[k]-y[j])*&C/2))**2+cos(y[j]*&C)*cos(y[k]*&C)*(sin((x[k]-x[j])*&C/2))**2;
num sjk{j in Depots, k in Bioref} = ifn(x[j]=x[k] and y[j]=y[k],0,2*atan2(sqrt(b[j,k]),sqrt(1-b[j,k]))*3957.143);*converted the distance to miles;
num djk{j in Depots, k in Bioref} = round(sjk[j,k],0.01);
*Transportation costs;
num vfb {Feedstock}; *variable cost of transporting bales of feedstock f;
num cfb {Feedstock}; *fixed/constant cost of transporting bales of feedstock f;
num vfp {Feedstock, Mode}; *variable cost of transporting pellets of feedstock f using mode t;
num cfp {Feedstock, Mode}; *fixed/constant cost of transporting pellets of feedstock f using mode t;
num tijf {i in Fields, j in Depots, f in Feedstock}= ifn (dij[i,j] = 0, 0, cfb[f] + vfb[f]*1.2*dij[i,j]); *Transportation cost for bales;
num tjkf_pellets {j in Depots, k in Bioref, f in Feedstock, t in Mode}= ifn (djk[j,k] = 0, 0, cfp[f,t] + vfp[f,t]*1.2*djk[j,k]); *Transportation cost for pellets;
*Parameters for Depots;
num qh{Feedstock}init 0; *Handling and queuing of bales at depot: $1.21 for CS and $1.34 for SW;
num pf{Feedstock}init 0; *preprocessing cost at depot: $22.65-3.18=$19.47 for CS and $22.05-3.18=$18.77 for SW;
num ds{Feedstock}init 0; *depot storage in pellet form;
num U = 0.9; *depot utilization factor;
num max_distance1 = 200;
num max_distance2 = 1300;
num max_distance3 = 400;
num min_distance = 300;
*quality parameters;
num Ash{Feedstock};
num Moisture{Feedstock};
num Carb{Feedstock};
num Ash_dock{Feedstock};
num Moist_dock{Feedstock};
num Ash_diff{f in Feedstock} = ifn(&Max_Ash>=Ash[f],0, Ash[f] - &Max_Ash);
num Moist_diff{f in Feedstock} = ifn(&Min_moisture<=Moisture[f],0, &Min_moisture-Moisture[f]);
read data out.fields_&year into Fields = [fips] x y;
read data out.INLdepots_&year into Depots = [fips] x y s=site;
read data out.INLdepots_&year into Bioref = [fips] x y l=site;
read data out.Price into Price = [name] gp = Pr ; *gp= grower payment;
read data out.feedstockpropertiesbales_MS into Feedstock=[Feed] vfb=TranspCostVar cfb=TranspCostFixed fsb=StorageCost
qh=HandlingQueuingCost dmloss=BiomassLoss;
read data out.feedstockpropertiespellets_MS into Feedstock=[Feed] ds=StorageCost pf=ProcessingCost;
read data out.Supplymod_&year into TRIPLES=[fips Feed Price] sifp=Supply; *same as line commented below;
read data out.Supplymin_&year into [fips Feed] maif=MinAssign; *minimum assignment (binary);
read data out.quality_MS into Feedstock = [feed] Ash Moisture carb Ash_dock Moist_dock;
read data out.transport into tr=[Feed Mode] vfp=TranspCostVar cfp=TranspCostFixed;
ROUTES = {<i,f> in DOUBLES, j in DEPOTS: dij[i,j] < max_distance1};
ROUTES2 = {j in DEPOTS, k in BIOREF: djk[j,k] <max_distance2};
*****DECLARE MODEL ELEMENTS*******;
******DECISION VARIABLES*****;
var Build {DEPOTS} binary; *binary value to build depots with specific capacity;
var CapacityChunks {DEPOTS} >= 0; *integer value to determine depot capacity;
var Build2 {Bioref} binary; *binary value to build biorefineries with fixed capacity of 725000 dry tons;
var CapacityBioRef {Bioref} >= 0; *to determine biorefinery capacity;
var AnyPurchased {TRIPLES} binary;
var AmountPurchased {TRIPLES} >= 0;
var AmountShipped {ROUTES} >= 0;
var Amount2{ROUTES2,tr} >= 0;
impvar BuildingCost {j in DEPOTS} =
132717 * Build[j] + 2.297 * 25000 * CapacityChunks[j];
impvar VariableCost = sum{<i,f,p> in TRIPLES} 0.977*gp[p] * AmountPurchased[i,f,p] +
sum{<i,f,j> in ROUTES} (fsb[f]+ tijf[i,j,f]+ qh[f]+ ds[f]+ pf[f]) * AmountShipped[i,f,j]
+ sum{<j,k> in ROUTES2, <f,t> in tr}
(tjkf_pellets[j,k,f,t]+(Ash_dock[f]*Ash_diff[f])
+ (Moist_dock[f]*Moist_diff[f])) * Amount2[j,k,f,t];
impvar FixedCost = sum {j in Depots} BuildingCost[j];
*****OBJECTIVE FUNCTION******;
max Supply = sum{<j,k> in ROUTES2,<f,t> in tr} Amount2[j,k,f,t];
*****CONSTRAINTS******;
*Flow balance between field-depot and depot-biorefinery;
Con Depot_avail {j in Depots,f in Feedstock}:
sum {<i,(f),(j)> in ROUTES} AmountShipped[i,f,j]
= sum{<(j),k> in ROUTES2, <(f),t> in tr} Amount2[j,k,f,t];
*Depot locations which have do not freight access;
Con freight_depot {j in Depots: s[j]=0}:
sum{<f,'1'> in tr} Amount2[j,k,f,'1'] = 0;
*Biorefinery Locations which have do not freight access;
Con freight_bioref {k in Bioref: l[k]=0}:
sum{<j,(k)> in ROUTES2,<f,'1'> in tr} Amount2[j,k,f,'1'] = 0;
Con rail_minimum {<j,k> in ROUTES2: djk[j,k]<= min_distance}:
sum{<f,'1'> in tr} Amount2[j,k,f,'1'] = 0;
/**/
Con truck_maximum {<j,k> in ROUTES2: djk[j,k] > max_distance3 }:
sum{<f,'0'> in tr} Amount2[j,k,f,'0'] = 0;
*****SOLVE*******;
solve obj Supply with milp / maxtime=&MaxRunTime relobjgap=0.03; * To force the code to stop after maxtime;
run;
... View more