I am trying to create a dynamic transportation optimization model (with suppliers, production plants, customers, and inventories). The problem (at hand - might be more to come) I am having is how to define upper capacity restrictions for the flows (problem 1 below in the code) and upper capacity limits for the inventories. It seems that the constants ("num") are in long format and the variables are in wide format. (Please be kind, I just started with the model.)
Data Nodes;
Length Tail $20. Head $20.;
Input Tail $ Head $ Cost Upper_Limit;
Datalines;
supplier_1 plant_1 20 100
supplier_1 plant_2 30 150
supplier_2 plant_1 35 200
supplier_2 plant_2 31 170
plant_1 customer_1 10 200
plant_1 customer_2 16 230
plant_2 customer_1 20 22
plant_2 customer_2 18 11
;
Data Arcs;
Length Node $20.;
Input Node $ Supply_Demand Max_Inventory Storage_Costs;
Datalines;
supplier_1 120 60 10
supplier_2 80 500 15
plant_1 0 300 1
plant_2 0 300 2
customer_1 -70 0 1e6
customer_2 -90 0 1e6
;
%Macro CreateTime;
%Do i=1 %To 10;
%If &i=1 %Then %Do;
Data Nodes_Time;
Length Time 8.;
Set Nodes;
Time = Input(&i., Best.);
Run;
Data Arcs_Time;
Length Time 8.;
Set Arcs;
Time = Input(&i., Best.);
If Find(Node, "customer") Then Supply_Demand=0;
Run;
%End;
%Else %Do;
Data Nodes_Time_i;
Length Time 8.;
Set Nodes;
Time = Input(&i., Best.);
%If &i.=4 OR &i.=7 %Then %Do;
If Tail="supplier_2" Then Upper_Limit=0;
If Tail="plant_1" Then Upper_Limit=0;
%End;
Run;
Proc Append Base=Nodes_Time Data=Nodes_Time_i; Run;
Data Arcs_Time_i;
Length Time 8.;
Set Arcs;
Time = Input(&i., Best.);
%If &i.=8 %Then %Do;
Max_Inventory=0;
%End;
Run;
Proc Append Base=Arcs_Time Data=Arcs_Time_i; Run;
%End;
Proc Datasets NoList NoWarn;
Delete Nodes_Time_i;
Delete Arcs_Time_i;
Run;
%End;
%Mend;
%CreateTime;
Proc Optmodel;
Set <Num,Str> _Time_Nodes_;
Num SD{_Time_Nodes_};
Num MaxInv{_Time_Nodes_};
Num InvCost{_Time_Nodes_};
Read Data Arcs_Time Into _Time_Nodes_=[Time Node] SD=Supply_Demand MaxInv=Max_Inventory InvCost=Storage_Costs;
Set <Num,Str,Str> _Time_Arcs_;
Num Upper_Bound{_Time_Arcs_};
Num Cost{_Time_Arcs_};
Read Data Nodes_Time Into _Time_Arcs_=[Time Tail Head] Cost=Cost Upper_Bound=Upper_Limit;
*Print Upper_Bound;
Set _Time_ = SetOf{<t,i,j> in _Time_Arcs_} t,
_Tail_ = SetOf{<t,i,j> in _Time_Arcs_} i,
_Head_ = SetOf{<t,i,j> in _Time_Arcs_} j;
Var Flow{_Time_Arcs_} >=0 ; *<=Upper_Bound[_Time_Arcs_]; * <-- MY PROBLEM 1 !!!;
Var Inventory{_Time_Nodes_} >=0 ; *<=MaxInv[_Time_Nodes_]; * <-- MY PROBLEM 2 !!!;
*Print Inventory; * "long" format of Upper_Bound and Inventory "wide"?;
Con Balance1{<t,i> in _Time_Nodes_: t=1}:Sum{<(t),(i),j> in _Time_Arcs_} Flow[t,i,j]
- Sum{<(t),j,(i)> in _Time_Arcs_} Flow[t,j,i] - Inventory[t,i] <= SD[t,i]; * no previous time point;
Con Balance{<t,i> in _Time_Nodes_: 2<=t<=10}:Sum{<(t),(i),j> in _Time_Arcs_} Flow[t,i,j]
- Sum{<(t),j,(i)> in _Time_Arcs_} Flow[t,j,i] + Inventory[t-1,i] - Inventory[t,i] = SD[t,i]; * flows;
Min Objective=Sum{<t,i,j> in _Time_Arcs_} Flow[t,i,j] * Cost[t,i,j] +
Sum{<t,i> in _Time_Nodes_} Inventory[t,i] * InvCost[t,i];
*Expand;
Solve;
Create Data Result_Flow From [Time From To]={<t,i,j> in _Time_Arcs_} Flow Upper_Bound Cost;
Create Data Result_Inventory From [Time Location]={<t,i> in _Time_Nodes_} Inventory MaxInv InvCost;
Quit;
Proc Print Data=Result_Flow Noobs; Run;
Proc Print Data=Result_Inventory Noobs; Run;
The proper syntax is:
Var Flow{<t,i,j> in _Time_Arcs_} >=0 <=Upper_Bound[t,i,j];
Similar change for your other VAR statement.
The proper syntax is:
Var Flow{<t,i,j> in _Time_Arcs_} >=0 <=Upper_Bound[t,i,j];
Similar change for your other VAR statement.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 16. Read more here about why you should contribute and what is in it for you!
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.