<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Conditionally define a constraint with proc optmodel in Mathematical Optimization, Discrete-Event Simulation, and OR</title>
    <link>https://communities.sas.com/t5/Mathematical-Optimization/Conditionally-define-a-constraint-with-proc-optmodel/m-p/518349#M2502</link>
    <description>&lt;P&gt;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:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;Con ..: - (If (t-DELTATIME[j,i]) in _Time_ Then .. )&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;What I have so far is (problematic row is number 3):&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;Con Balance{&amp;lt;t,i&amp;gt; in _Time_Nodes_}:
      Sum{&amp;lt;(t),(i),j&amp;gt; in _Time_Arcs_} Flow[t,i,j]
   	- (If (t-DELTATIME[j,i]) in _Time_ Then Sum{&amp;lt;(t),j,(i)&amp;gt; in _Time_Arcs_} Flow[t - DELTATIME[j,i],j,i])
	- (If (t-1) in _Time_ Then Inventory[t-1,i])
	+ Inventory[t,i] 
      &amp;lt;= SD[t,i] + Rejected_Qty[t,i];&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;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 -&amp;nbsp;(without using macro code). The entire example code is here:&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;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 &amp;amp;i=1 %Then %Do;
    Data Arcs_Time;
	  Length Time 8.;
	  Set Arcs (Drop=Delta_Time);
      Time = Input(&amp;amp;i., Best.);
	Run;
	Data Nodes_Time;
	  Length Time 8.;
	  Set Nodes;
      Time = Input(&amp;amp;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(&amp;amp;i., Best.);
	Run;
	Proc Append Base=Arcs_Time Data=Arcs_Time_i; Run;
	Data Nodes_Time_i;
	  Length Time 8.;
	  Set Nodes;
      Time = Input(&amp;amp;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) &amp;amp; Node = "n3" Then Supply_Demand = 0;
	If Time in (3) &amp;amp; Node = "n1" Then Supply_Demand = 900;
  Run;
  Data Arcs_Time;
    Set Arcs_Time;
	If Time in(6) &amp;amp; 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 &amp;lt;Num,Str&amp;gt; _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 &amp;lt;Num,Str,Str&amp;gt; _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{&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} t,
    _Tail_ = SetOf{&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} i,
    _Head_ = SetOf{&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} j;
  Set _Arcs_ = SetOf{&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} &amp;lt;i,j&amp;gt;;
  Num DELTATIME{_Arcs_};
  Read Data Arcs Into [Tail Head] DELTATIME=Delta_Time;
  Var Flow{&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} &amp;gt;=0 &amp;lt;=Upper_Bound[t,i,j]; 
  Var Rejected_Qty{&amp;lt;t,i&amp;gt; in _Time_Nodes_} &amp;gt;=0;
  Var Inventory{&amp;lt;t,i&amp;gt; in _Time_Nodes_} &amp;gt;=0 &amp;lt;=MaxInv[t,i]; 
  Con Inventory1{&amp;lt;t,i&amp;gt; in _Time_Nodes_: t=1}: Inventory[t,i] = 0;
  /* interesting part, start  ************************************* */
  /* PROBLEM: Merge constraints for time = 1 and time &amp;gt;= 2 into one */
  %If "&amp;amp;Working."="YES" %Then %Do;
  Con Balance_TimeEQ1{&amp;lt;t,i&amp;gt; in _Time_Nodes_: t=1}:
      Sum{&amp;lt;(t),(i),j&amp;gt; in _Time_Arcs_} Flow[t,i,j] 
    - Sum{&amp;lt;(t),j,(i)&amp;gt; in _Time_Arcs_} Flow[t,j,i] 
    + Inventory[t,i] 
      &amp;lt;= SD[t,i] + Rejected_Qty[t,i]; 
  Con Balance_TimeGE2{&amp;lt;t,i&amp;gt; in _Time_Nodes_: 2&amp;lt;=t&amp;lt;=10}:
      Sum{&amp;lt;(t),(i),j&amp;gt; in _Time_Arcs_} Flow[t,i,j] 
    - Sum{&amp;lt;(t),j,(i)&amp;gt; in _Time_Arcs_} Flow[t - DELTATIME[j,i],j,i] 
    - Inventory[t-1,i] 
    + Inventory[t,i] 
      &amp;lt;= SD[t,i] + Rejected_Qty[t,i];
  %End;
  %Else %Do;
  Con Balance{&amp;lt;t,i&amp;gt; in _Time_Nodes_}:
      Sum{&amp;lt;(t),(i),j&amp;gt; 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{&amp;lt;(t),j,(i)&amp;gt; in _Time_Arcs_} Flow[t - DELTATIME[j,i],j,i])
	- (If (t-1) in _Time_ Then Inventory[t-1,i])
	+ Inventory[t,i] 
      &amp;lt;= SD[t,i] + Rejected_Qty[t,i];
  %End;
  /* interesting part, end ******************************************* */
  Min Objective=Sum{&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} Flow[t,i,j] * Cost[t,i,j] +
                Sum{&amp;lt;t,i&amp;gt; in _Time_Nodes_} Inventory[t,i] * InvCost[t,i] +
                Sum{&amp;lt;t,i&amp;gt; in _Time_Nodes_} Rejected_Qty[t,i] * 1e6;
  Solve;
  *Expand Balance1;
  *Expand Balance;
  Create Data Result_Flow From [Time From To]={&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} DELTATIME[i,j] Flow Upper_Bound Cost;
  Create Data Result_Arcs From [Time Location]={&amp;lt;t,i&amp;gt; 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 */&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Tue, 04 Dec 2018 11:14:31 GMT</pubDate>
    <dc:creator>user24feb</dc:creator>
    <dc:date>2018-12-04T11:14:31Z</dc:date>
    <item>
      <title>Conditionally define a constraint with proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Conditionally-define-a-constraint-with-proc-optmodel/m-p/518349#M2502</link>
      <description>&lt;P&gt;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:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;Con ..: - (If (t-DELTATIME[j,i]) in _Time_ Then .. )&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;What I have so far is (problematic row is number 3):&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;Con Balance{&amp;lt;t,i&amp;gt; in _Time_Nodes_}:
      Sum{&amp;lt;(t),(i),j&amp;gt; in _Time_Arcs_} Flow[t,i,j]
   	- (If (t-DELTATIME[j,i]) in _Time_ Then Sum{&amp;lt;(t),j,(i)&amp;gt; in _Time_Arcs_} Flow[t - DELTATIME[j,i],j,i])
	- (If (t-1) in _Time_ Then Inventory[t-1,i])
	+ Inventory[t,i] 
      &amp;lt;= SD[t,i] + Rejected_Qty[t,i];&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;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 -&amp;nbsp;(without using macro code). The entire example code is here:&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;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 &amp;amp;i=1 %Then %Do;
    Data Arcs_Time;
	  Length Time 8.;
	  Set Arcs (Drop=Delta_Time);
      Time = Input(&amp;amp;i., Best.);
	Run;
	Data Nodes_Time;
	  Length Time 8.;
	  Set Nodes;
      Time = Input(&amp;amp;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(&amp;amp;i., Best.);
	Run;
	Proc Append Base=Arcs_Time Data=Arcs_Time_i; Run;
	Data Nodes_Time_i;
	  Length Time 8.;
	  Set Nodes;
      Time = Input(&amp;amp;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) &amp;amp; Node = "n3" Then Supply_Demand = 0;
	If Time in (3) &amp;amp; Node = "n1" Then Supply_Demand = 900;
  Run;
  Data Arcs_Time;
    Set Arcs_Time;
	If Time in(6) &amp;amp; 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 &amp;lt;Num,Str&amp;gt; _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 &amp;lt;Num,Str,Str&amp;gt; _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{&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} t,
    _Tail_ = SetOf{&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} i,
    _Head_ = SetOf{&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} j;
  Set _Arcs_ = SetOf{&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} &amp;lt;i,j&amp;gt;;
  Num DELTATIME{_Arcs_};
  Read Data Arcs Into [Tail Head] DELTATIME=Delta_Time;
  Var Flow{&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} &amp;gt;=0 &amp;lt;=Upper_Bound[t,i,j]; 
  Var Rejected_Qty{&amp;lt;t,i&amp;gt; in _Time_Nodes_} &amp;gt;=0;
  Var Inventory{&amp;lt;t,i&amp;gt; in _Time_Nodes_} &amp;gt;=0 &amp;lt;=MaxInv[t,i]; 
  Con Inventory1{&amp;lt;t,i&amp;gt; in _Time_Nodes_: t=1}: Inventory[t,i] = 0;
  /* interesting part, start  ************************************* */
  /* PROBLEM: Merge constraints for time = 1 and time &amp;gt;= 2 into one */
  %If "&amp;amp;Working."="YES" %Then %Do;
  Con Balance_TimeEQ1{&amp;lt;t,i&amp;gt; in _Time_Nodes_: t=1}:
      Sum{&amp;lt;(t),(i),j&amp;gt; in _Time_Arcs_} Flow[t,i,j] 
    - Sum{&amp;lt;(t),j,(i)&amp;gt; in _Time_Arcs_} Flow[t,j,i] 
    + Inventory[t,i] 
      &amp;lt;= SD[t,i] + Rejected_Qty[t,i]; 
  Con Balance_TimeGE2{&amp;lt;t,i&amp;gt; in _Time_Nodes_: 2&amp;lt;=t&amp;lt;=10}:
      Sum{&amp;lt;(t),(i),j&amp;gt; in _Time_Arcs_} Flow[t,i,j] 
    - Sum{&amp;lt;(t),j,(i)&amp;gt; in _Time_Arcs_} Flow[t - DELTATIME[j,i],j,i] 
    - Inventory[t-1,i] 
    + Inventory[t,i] 
      &amp;lt;= SD[t,i] + Rejected_Qty[t,i];
  %End;
  %Else %Do;
  Con Balance{&amp;lt;t,i&amp;gt; in _Time_Nodes_}:
      Sum{&amp;lt;(t),(i),j&amp;gt; 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{&amp;lt;(t),j,(i)&amp;gt; in _Time_Arcs_} Flow[t - DELTATIME[j,i],j,i])
	- (If (t-1) in _Time_ Then Inventory[t-1,i])
	+ Inventory[t,i] 
      &amp;lt;= SD[t,i] + Rejected_Qty[t,i];
  %End;
  /* interesting part, end ******************************************* */
  Min Objective=Sum{&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} Flow[t,i,j] * Cost[t,i,j] +
                Sum{&amp;lt;t,i&amp;gt; in _Time_Nodes_} Inventory[t,i] * InvCost[t,i] +
                Sum{&amp;lt;t,i&amp;gt; in _Time_Nodes_} Rejected_Qty[t,i] * 1e6;
  Solve;
  *Expand Balance1;
  *Expand Balance;
  Create Data Result_Flow From [Time From To]={&amp;lt;t,i,j&amp;gt; in _Time_Arcs_} DELTATIME[i,j] Flow Upper_Bound Cost;
  Create Data Result_Arcs From [Time Location]={&amp;lt;t,i&amp;gt; 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 */&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 04 Dec 2018 11:14:31 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Conditionally-define-a-constraint-with-proc-optmodel/m-p/518349#M2502</guid>
      <dc:creator>user24feb</dc:creator>
      <dc:date>2018-12-04T11:14:31Z</dc:date>
    </item>
    <item>
      <title>Re: Conditionally define a constraint with proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Conditionally-define-a-constraint-with-proc-optmodel/m-p/518460#M2503</link>
      <description>&lt;P&gt;Two ways:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;	- Sum{&amp;lt;(t),j,(i)&amp;gt; in _Time_Arcs_} (If (t-DELTATIME[j,i]) in _Time_ Then Flow[t - DELTATIME[j,i],j,i])
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;	- Sum{&amp;lt;(t),j,(i)&amp;gt; in _Time_Arcs_: t-DELTATIME[j,i] in _Time_} Flow[t - DELTATIME[j,i],j,i]
&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Tue, 04 Dec 2018 16:00:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Conditionally-define-a-constraint-with-proc-optmodel/m-p/518460#M2503</guid>
      <dc:creator>RobPratt</dc:creator>
      <dc:date>2018-12-04T16:00:11Z</dc:date>
    </item>
  </channel>
</rss>

