BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
user24feb
Barite | Level 11

I would like to conditionally define a part of a constraint for a network model. The goal is to limit an constraint element to a range of feasible time periods (1 to 10 in this example, 0 and negative periods not allowed) using something like:

Con ..: - (If (t-DELTATIME[j,i]) in _Time_ Then .. )

What I have so far is (problematic row is number 3): 

Con Balance{<t,i> in _Time_Nodes_}:
      Sum{<(t),(i),j> in _Time_Arcs_} Flow[t,i,j]
   	- (If (t-DELTATIME[j,i]) in _Time_ Then Sum{<(t),j,(i)> in _Time_Arcs_} Flow[t - DELTATIME[j,i],j,i])
	- (If (t-1) in _Time_ Then Inventory[t-1,i])
	+ Inventory[t,i] 
      <= SD[t,i] + Rejected_Qty[t,i];

which throws an error because I do not properly define the indices of the constant/number matrix DELTATIME. My question is, is it possible to fix this - (without using macro code). The entire example code is here: 

Data Arcs;
  Length Tail $20. Head $20.;
  Input Tail $ Head $ Cost Upper_Limit Delta_Time;
  Datalines;
n1 n2 20 500 0
n2 n3 10 400 1
;
Data Nodes;
  Length Node $20.;
  Input Node $ Supply_Demand Max_Inventory Storage_Costs;
  Datalines;
n1 300 0 100
n2 0 940 1
n3 -300 0 100
;
%Macro CreateTime;
%Do i=1 %To 10;
  %If &i=1 %Then %Do;
    Data Arcs_Time;
	  Length Time 8.;
	  Set Arcs (Drop=Delta_Time);
      Time = Input(&i., Best.);
	Run;
	Data Nodes_Time;
	  Length Time 8.;
	  Set Nodes;
      Time = Input(&i., Best.);
	  If Find(Node, "customer") Then Supply_Demand=0;
	Run;
  %End;
  %Else %Do;
    Data Arcs_Time_i;
	  Length Time 8.;
	  Set Arcs (Drop=Delta_Time);
      Time = Input(&i., Best.);
	Run;
	Proc Append Base=Arcs_Time Data=Arcs_Time_i; Run;
	Data Nodes_Time_i;
	  Length Time 8.;
	  Set Nodes;
      Time = Input(&i., Best.);
	Run;
	Proc Append Base=Nodes_Time Data=Nodes_Time_i; Run;
  %End;
  Data Nodes_Time;
    Set Nodes_Time;
	If Time in (1,2,3) & Node = "n3" Then Supply_Demand = 0;
	If Time in (3) & Node = "n1" Then Supply_Demand = 900;
  Run;
  Data Arcs_Time;
    Set Arcs_Time;
	If Time in(6) & Tail = "n1" Then Upper_Limit=0;
  Run;
  Proc Datasets NoList NoWarn;
    Delete Nodes_Time_i;
	Delete Arcs_Time_i;
  Run;
%End;
%Mend;
%CreateTime;

%Macro MacroOpt(Working=);
Proc Optmodel;
  Set <Num,Str> _Time_Nodes_;
  Num SD{_Time_Nodes_};
  Num MaxInv{_Time_Nodes_};
  Num InvCost{_Time_Nodes_};
  Read Data Nodes_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 Arcs_Time Into _Time_Arcs_=[Time Tail Head] Cost=Cost Upper_Bound=Upper_Limit;
  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;
  Set _Arcs_ = SetOf{<t,i,j> in _Time_Arcs_} <i,j>;
  Num DELTATIME{_Arcs_};
  Read Data Arcs Into [Tail Head] DELTATIME=Delta_Time;
  Var Flow{<t,i,j> in _Time_Arcs_} >=0 <=Upper_Bound[t,i,j]; 
  Var Rejected_Qty{<t,i> in _Time_Nodes_} >=0;
  Var Inventory{<t,i> in _Time_Nodes_} >=0 <=MaxInv[t,i]; 
  Con Inventory1{<t,i> in _Time_Nodes_: t=1}: Inventory[t,i] = 0;
  /* interesting part, start  ************************************* */
  /* PROBLEM: Merge constraints for time = 1 and time >= 2 into one */
  %If "&Working."="YES" %Then %Do;
  Con Balance_TimeEQ1{<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] + Rejected_Qty[t,i]; 
  Con Balance_TimeGE2{<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 - DELTATIME[j,i],j,i] 
    - Inventory[t-1,i] 
    + Inventory[t,i] 
      <= SD[t,i] + Rejected_Qty[t,i];
  %End;
  %Else %Do;
  Con Balance{<t,i> in _Time_Nodes_}:
      Sum{<(t),(i),j> in _Time_Arcs_} Flow[t,i,j]
   /* Is it possible to create a dynamic expression for flows with (transportation) times directly */
   /* linked to the arc like for the inventory constraint with the hard-coded t-1 below? */
	- (If (t-DELTATIME[j,i]) in _Time_ Then Sum{<(t),j,(i)> in _Time_Arcs_} Flow[t - DELTATIME[j,i],j,i])
	- (If (t-1) in _Time_ Then Inventory[t-1,i])
	+ Inventory[t,i] 
      <= SD[t,i] + Rejected_Qty[t,i];
  %End;
  /* interesting part, end ******************************************* */
  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] +
                Sum{<t,i> in _Time_Nodes_} Rejected_Qty[t,i] * 1e6;
  Solve;
  *Expand Balance1;
  *Expand Balance;
  Create Data Result_Flow From [Time From To]={<t,i,j> in _Time_Arcs_} DELTATIME[i,j] Flow Upper_Bound Cost;
  Create Data Result_Arcs From [Time Location]={<t,i> in _Time_Nodes_} Inventory MaxInv InvCost Rejected_Qty SD;
Quit;
%Mend;
%MacroOpt(Working=NO) /* this call produces an error */
%MacroOpt(Working=YES) /* this optimization run works syntactically */

 

1 ACCEPTED SOLUTION

Accepted Solutions
RobPratt
SAS Super FREQ

Two ways:

	- Sum{<(t),j,(i)> in _Time_Arcs_} (If (t-DELTATIME[j,i]) in _Time_ Then Flow[t - DELTATIME[j,i],j,i])
	- Sum{<(t),j,(i)> in _Time_Arcs_: t-DELTATIME[j,i] in _Time_} Flow[t - DELTATIME[j,i],j,i]

View solution in original post

1 REPLY 1
RobPratt
SAS Super FREQ

Two ways:

	- Sum{<(t),j,(i)> in _Time_Arcs_} (If (t-DELTATIME[j,i]) in _Time_ Then Flow[t - DELTATIME[j,i],j,i])
	- Sum{<(t),j,(i)> in _Time_Arcs_: t-DELTATIME[j,i] in _Time_} Flow[t - DELTATIME[j,i],j,i]