<?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 Re: Looping proc optmodel in Mathematical Optimization, Discrete-Event Simulation, and OR</title>
    <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934730#M4188</link>
    <description>&lt;P&gt;I am not able to replicate the behavior you are seeing.&amp;nbsp; Please attach the full log from a fresh session.&lt;/P&gt;</description>
    <pubDate>Fri, 05 Jul 2024 04:12:06 GMT</pubDate>
    <dc:creator>RobPratt</dc:creator>
    <dc:date>2024-07-05T04:12:06Z</dc:date>
    <item>
      <title>Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934077#M4167</link>
      <description>&lt;P&gt;Hi Rob&lt;/P&gt;&lt;P&gt;I have a question related to this &lt;A href="https://communities.sas.com/t5/Mathematical-Optimization/Optimizing-vehicles-to-depot/m-p/932120#M4161" target="_self"&gt;thread.&lt;/A&gt;&lt;/P&gt;&lt;P&gt;The VRO model solves just fine. I am trying to run the model in a loop automatically. Basically, I want to run for two Depots (A and B) and for 26 weeks for each Depot. Weeknumbers are 1..26. For each Depot and for each week number, there are two modes (mode 1 and mode2).&amp;nbsp; Here is the code: How do I set this up in a loop? or can i set this up in a loop so that if i run the run button once, all the combinations get run. Right now I am manually running it for all combinations.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=""&gt;/*Variables*/
%let capacity = 5000;
%let num_vehicles=20;
%let dist=3000;
%let max_stops=400;
%let Depot='A'; (I want to loop this one, one for Depot A and one for Depot B)
%let DepotID=99999; /* 88888 for A and 99999 for B*/
%Let WeekNumber='2'; (I want to loop this for 26 weeks for each Depot)
%Let Mode='Mode1'; /* Mode1 or Mode2 */ (I want to loop this for 2 modes, Mode1 and Mode2)
%let Scenario='xxx';

proc fedsql sessref=mysess;
create table CASUSER.vrpdata {options replace='TRUE'} AS
select ModelWeekNumber_2WK as ModelWeekNumber
      ,ModelNode
      ,ModelCity
      ,ModelLat
      ,ModelLong
      ,ModelZip
      ,ModelState
      ,Case_Count
      ,Unit_Count
      ,round(Volume)as Volume
      ,Weight
      ,Declared_Value
      ,ModelDepotState
      ,ModelDepotCity
      ,ModelDepotZip
     ,NodeID
     ,Mode
     ,WeekNumbers
     ,WeekNumber_EarliestStartDate
      ,WeekNumber_LatestEndDate
 from DataSource
where ModelDepotCity=&amp;amp;Depot
and ModelWeekNumber_2WK=&amp;amp;WeekNumber
and Mode=&amp;amp;Mode;
;
QUIT;

proc optmodel;
   /* read the node location and demand data */
   set NODES;
   str ModelNode {NODES};
   num ModelLat {NODES};
   num ModelLong {NODES};
   num Volume {NODES};
   num capacity = &amp;amp;capacity;
   num num_vehicles = &amp;amp;num_vehicles;
   str Mode {NODES};
   read data CASUSER.vrpdata into NODES =[NodeID] ModelNode ModelLat ModelLong Volume Mode;
   set ARCS = {i in NODES, j in NODES: i ne j};
   set VEHICLES = 1..num_vehicles;

   num depot = &amp;amp;DepotID;
	
   /* define the arc dist as the rounded Euclidean distance */
num dist {&amp;lt;i,j&amp;gt; in ARCS} = (if i ne depot then GEODIST(ModelLat[i],ModelLong[i],ModelLat[j],ModelLong[j],'M') else 0);


    /* Creating an Sparse Matrix to remove any unwanted arcs*/
	set LOGICAL_ARCS = {&amp;lt;i,j&amp;gt; in ARCS: dist[i,j] &amp;lt;= &amp;amp;dist};
	/*print {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS} dist; */


   /* Flow[k] is the amount of demand carried by vehicle k */
    var Flow {LOGICAL_ARCS, VEHICLES} &amp;gt;= 0 &amp;lt;= capacity;

/* UseNode[i,k] = 1, if and only if node i is serviced by vehicle k */
   var UseNode {NODES, VEHICLES} binary;
   /* UseArc[i,j,k] = 1, if and only if arc (i,j) is traversed by vehicle k */
   var UseArc {LOGICAL_ARCS, VEHICLES} binary;

  
   /*-----------------------OBJECTIVE FUNCTION-------------------------------*/
   /* minimize the total distance traversed */
   min TotalCost = sum {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS, k in VEHICLES} dist[i,j] * UseArc[i,j,k];

  /*----------------------------CONSTRAINTS-------------------------------------*/
  /* each non-depot node must be serviced by at least one vehicle */
           /*ASSIGNMENT CONSTRAINT*/ 
   con Assignment {i in NODES diff {depot}}:
      sum {k in VEHICLES} UseNode[i,k] &amp;gt;= 1;


/*   for{k in VEHICLES} fix UseNode[depot,k] = 1; */
   con VisitDepot {i in NODES diff {depot}, k in VEHICLES}:
      UseNode[i,k] &amp;lt;= UseNode[depot,k]
   suffixes=(block=k);

  /*DISTANCE CONSTRAINT*/
	CON Distance {k in VEHICLES}: 
/* 	SUM {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS: j not in {depot}} (dist[i, j] * UseArc[i, j, k]) &amp;lt;= &amp;amp;dist_limit; */
    sum {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS} dist[i,j] * UseArc[i,j,k] &amp;lt;= &amp;amp;dist;

     	  /*STOPS CONSTRAINT*/
	CON Stops {k in VEHICLES}: 
    sum {i in NODES diff {depot}} UseNode[i,k] &amp;lt;= &amp;amp;max_stops; 

/*   some vehicle k traverses an arc that leaves node i if and only if UseNode[i,k] = 1 */
/* 			LEAVE NODE CONSTRAINT */
   con LeaveNode {i in NODES, k in VEHICLES}:
      sum {&amp;lt;(i),j&amp;gt; in LOGICAL_ARCS} UseArc[i,j,k] = UseNode[i,k];

/*   some vehicle k traverses an arc that enters node i if and only if UseNode[i,k] = 1 */
/* 			ENTER NODE CONSTRAINT   */
   con EnterNode {i in NODES, k in VEHICLES}:
      sum {&amp;lt;j,(i)&amp;gt; in LOGICAL_ARCS} UseArc[j,i,k] = UseNode[i,k];

  /* the amount of Volume supplied by vehicle k to node i must equal Volume if UseNode[i,k] = 1; otherwise, it must equal 0 */

/*FLOW BALANCE CONSTRAINT*/ 

  con FlowBalance {i in NODES diff {depot}, k in VEHICLES}:
       sum {&amp;lt;(i),j&amp;gt; in LOGICAL_ARCS} Flow[i,j,k] - sum {&amp;lt;j,(i)&amp;gt; in LOGICAL_ARCS} Flow[j,i,k]
       = Volume[i] * UseNode[i,k];

/* each vehicle is empty when it leaves the depot */
   for {&amp;lt;(depot),j&amp;gt; in LOGICAL_ARCS, k in VEHICLES} fix Flow[depot,j,k] = 0;

/* if UseArc[i,j,k] = 1, then the flow on arc (i,j) must be at most capacity
  if UseArc[i,j,k] = 0, then no flow is allowed on arc (i,j) */
			
/*VEHICLE CAPACITY CONSTRAINT*/ 
   con VehicleCapacity {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS, k in VEHICLES}:
      Flow[i,j,k] &amp;lt;= Flow[i,j,k].ub * UseArc[i,j,k];

/*Constraint VehicleCapacity[3,4,1]: Flow[3,4,1] - 3650*UseArc[3,4,1] &amp;lt;= 0  /*

 /* decomp by vehicle *//*DECOMPOSITION*/
   for {i in NODES, k in VEHICLES} do;
      LeaveNode[i,k].block = k;
      EnterNode[i,k].block = k;
   end;
   for {k in VEHICLES} Distance[k].block = k;
   for {k in VEHICLES} Stops[k].block = k;
   for {i in NODES diff {depot}, k in VEHICLES} FlowBalance[i,k].block = k;
   for {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS, k in VEHICLES} VehicleCapacity[i,j,k].block = k;

  /* solve using decomp (aggregate formulation) */
   
solve with MILP / decomp varsel=ryanfoster presolver=basic maxtime=300;  


   /* OUTPUT */
   /* create solution data set */
 

create data solution_data from [i j k]= 
{&amp;lt;i,j&amp;gt; in LOGICAL_ARCS, k in VEHICLES: UseArc[i,j,k].sol &amp;gt; 0.5 and i ne depot} 
StartNode=ModelNode[i] StartCity=ModelNode[i] x1=ModelLat[i] y1=ModelLong[i] 
EndNode=ModelNode[j] EndCity=ModelNode[j] x2=ModelLat[j] y2=ModelLong[j] 
flow=Flow[i,j,k] dist=dist[i,j] 
function='line' drawspace='datavalue'
; 
quit;

proc sgplot data=solution_data noautolegend;
   scatter x=x1 y=y1 / datalabel=i;
   vector x=x2 y=y2 / xorigin=x1 yorigin=y1 group=k noarrowheads;
   xaxis display=none;
   yaxis display=none;
run;


DATA WORK.VRO_OUTPUT;
set WORK.solution_data; 
Depot=&amp;amp;Depot;
WeekNumber=&amp;amp;WeekNumber;
VehicleByScenarioByWeekNumber= cat(Depot,'-',k,'-',WeekNumber);
Mode=&amp;amp;Mode;
Scenario=&amp;amp;Scenario;
;
run;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 28 Jun 2024 14:58:01 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934077#M4167</guid>
      <dc:creator>Santha</dc:creator>
      <dc:date>2024-06-28T14:58:01Z</dc:date>
    </item>
    <item>
      <title>Re: Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934098#M4168</link>
      <description>&lt;P&gt;The following examples illustrate how to do what you want:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://support.sas.com/kb/42/332.html" target="_blank"&gt;42332 - BY group processing with PROC OPTMODEL and the runOptmodel action (sas.com)&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://go.documentation.sas.com/doc/en/pgmsascdc/v_052/ormpex/ormpex_ex22_toc.htm" target="_blank"&gt;SAS Help Center: Efficiency Analysis: How to Use Data Envelopment Analysis to Compare Efficiencies of Garages&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Fri, 28 Jun 2024 15:23:38 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934098#M4168</guid>
      <dc:creator>RobPratt</dc:creator>
      <dc:date>2024-06-28T15:23:38Z</dc:date>
    </item>
    <item>
      <title>Re: Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934162#M4169</link>
      <description>&lt;P&gt;Awesome. Thanks. I will explore this and get back .&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 29 Jun 2024 12:40:42 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934162#M4169</guid>
      <dc:creator>Santha</dc:creator>
      <dc:date>2024-06-29T12:40:42Z</dc:date>
    </item>
    <item>
      <title>Re: Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934518#M4179</link>
      <description>&lt;P&gt;Rob. I went through these two examples that you had mentioned in addition to this &lt;A href="https://communities.sas.com/t5/Mathematical-Optimization/Complicated-loop-with-PROC-OPTMODEL/td-p/525002" target="_self"&gt;one&lt;/A&gt; as well where you had helped. I really get the idea theoretically and able to understand. But when i tried to implement , I found difficult. Here is my code. I have relaxed my earlier ask of nested loop. There is only one loop that I want the model to do and that is ModelWeekNumber. I want the VRO model to loop through just that. Can you help me with that? I tried till creating Logical_ARCS but was not successful at all . I have attached the dataset . only 2 weeknumbers (3 and 4). just 81 observations in total.&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=""&gt;/*Variables*/
%let capacity = 5000;
%let num_vehicles=20;
%let dist=3000;
%let max_stops=400;
%let Depot='A';
%let DepotID=99999; /* 88888 for B and 99999 for A*/
%Let Mode='Mode1'; /* Mode1 or Mode2 */
%let Scenario='Routing Alternates';
%let byvar=ModelWeekNumber;

proc fedsql sessref=mysess;
create table CASUSER.vrpdata {options replace='TRUE'} AS
select ModelWeekNumber_2WK as ModelWeekNumber
      ,ModelNode
      ,ModelCity
      ,ModelLat
      ,ModelLong
      ,ModelZip
      ,ModelState
      ,Case_Count
      ,Unit_Count
      ,round(Volume)as Volume
      ,Weight
      ,Declared_Value
      ,ModelDepotState
      ,ModelDepotCity
      ,ModelDepotZip
     ,NodeID
     ,Mode
     ,WeekNumbers
     ,WeekNumber_EarliestStartDate
      ,WeekNumber_LatestEndDate
from DATA
where ModelWeekNumber_2WK in ('3','4')
and ModelDepotCity=&amp;amp;Depot
and Mode=&amp;amp;Mode;
quit;

proc optmodel;
   /* read the node location and demand data */
   set NODES; 
   str ModelNode {NODES};
   num NodeID {NODES};
   num ModelLat {NODES};
   num ModelLong {NODES};
   num Volume {NODES};
   num capacity = &amp;amp;capacity;
   num num_vehicles = &amp;amp;num_vehicles;
   str Mode {NODES};
   
   num ModelWeekNumber {NODES};
   read data CASUSER.vrpdata into NODES =[_N_] NodeID ModelNode ModelLat ModelLong Volume Mode ModelWeekNumber;
   set ARCS = {i in NODES, j in NODES: i ne j};

   set VEHICLES = 1..num_vehicles;

   num depot = &amp;amp;DepotID;

/* Collect values of BY variable into an index set */
         set BYSET = setof {i in NODES} &amp;amp;byvar.[i];
         put BYSET=;
         num by;

/* Declare the variable */
set OBS_BY = {i in NODES, j in NODES:&amp;amp;byvar.[i] = by};

   /* define the arc dist as the rounded Euclidean distance */
num dist {&amp;lt;i,j&amp;gt; in OBS_BY} = (if i ne depot then GEODIST(ModelLat[i],ModelLong[i],ModelLat[j],ModelLong[j],'M') else 0);
print dist;

    /* Creating an Sparse Matrix to remove any unwanted arcs*/
	set LOGICAL_ARCS {o in OBS_BY} = {&amp;lt;i,j&amp;gt; in ARCS: dist[i,j,o] &amp;lt;= &amp;amp;dist};
       print {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS} dist; 

   /* Flow[k] is the amount of demand carried by vehicle k */
    var Flow {LOGICAL_ARCS, VEHICLES} &amp;gt;= 0 &amp;lt;= capacity;

/* UseNode[i,k] = 1, if and only if node i is serviced by vehicle k */
   var UseNode {NODES, VEHICLES} binary;
   /* UseArc[i,j,k] = 1, if and only if arc (i,j) is traversed by vehicle k */
   var UseArc {LOGICAL_ARCS, VEHICLES} binary;

  
   /*-----------------------OBJECTIVE FUNCTION-------------------------------*/
   /* minimize the total distance traversed */
   min TotalCost = sum {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS, k in VEHICLES} dist[i,j] * UseArc[i,j,k];

  /*----------------------------CONSTRAINTS-------------------------------------*/
  /* each non-depot node must be serviced by at least one vehicle */
           /*ASSIGNMENT CONSTRAINT*/ 
   con Assignment {i in NODES diff {depot}}:
      sum {k in VEHICLES} UseNode[i,k] &amp;gt;= 1;


/*   for{k in VEHICLES} fix UseNode[depot,k] = 1; */
   con VisitDepot {i in NODES diff {depot}, k in VEHICLES}:
      UseNode[i,k] &amp;lt;= UseNode[depot,k]
   suffixes=(block=k);

	  /*DISTANCE CONSTRAINT*/
	CON Distance {k in VEHICLES}: 
/* 	SUM {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS: j not in {depot}} (dist[i, j] * UseArc[i, j, k]) &amp;lt;= &amp;amp;dist_limit; */
    sum {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS} dist[i,j] * UseArc[i,j,k] &amp;lt;= &amp;amp;dist;

     	  /*STOPS CONSTRAINT*/
	CON Stops {k in VEHICLES}: 
    sum {i in NODES diff {depot}} UseNode[i,k] &amp;lt;= &amp;amp;max_stops; 

/*   some vehicle k traverses an arc that leaves node i if and only if UseNode[i,k] = 1 */
/* 			LEAVE NODE CONSTRAINT */
   con LeaveNode {i in NODES, k in VEHICLES}:
      sum {&amp;lt;(i),j&amp;gt; in LOGICAL_ARCS} UseArc[i,j,k] = UseNode[i,k];

/*   some vehicle k traverses an arc that enters node i if and only if UseNode[i,k] = 1 */
/* 			ENTER NODE CONSTRAINT   */
   con EnterNode {i in NODES, k in VEHICLES}:
      sum {&amp;lt;j,(i)&amp;gt; in LOGICAL_ARCS} UseArc[j,i,k] = UseNode[i,k];

  /* the amount of Volume supplied by vehicle k to node i must equal Volume if UseNode[i,k] = 1; otherwise, it must equal 0 */
			/*FLOW BALANCE CONSTRAINT*/ 

  con FlowBalance {i in NODES diff {depot}, k in VEHICLES}:
       sum {&amp;lt;(i),j&amp;gt; in LOGICAL_ARCS} Flow[i,j,k] - sum {&amp;lt;j,(i)&amp;gt; in LOGICAL_ARCS} Flow[j,i,k]
       = Volume[i] * UseNode[i,k];

/* each vehicle is empty when it leaves the depot */
   for {&amp;lt;(depot),j&amp;gt; in LOGICAL_ARCS, k in VEHICLES} fix Flow[depot,j,k] = 0;

/* if UseArc[i,j,k] = 1, then the flow on arc (i,j) must be at most capacity
  if UseArc[i,j,k] = 0, then no flow is allowed on arc (i,j) */
			
/*VEHICLE CAPACITY CONSTRAINT*/ 
   con VehicleCapacity {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS, k in VEHICLES}:
      Flow[i,j,k] &amp;lt;= Flow[i,j,k].ub * UseArc[i,j,k];

 /* decomp by vehicle *//*DECOMPOSITION*/
   for {i in NODES, k in VEHICLES} do;
      LeaveNode[i,k].block = k;
      EnterNode[i,k].block = k;
   end;
   for {k in VEHICLES} Distance[k].block = k;
   for {k in VEHICLES} Stops[k].block = k;
   for {i in NODES diff {depot}, k in VEHICLES} FlowBalance[i,k].block = k;
   for {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS, k in VEHICLES} VehicleCapacity[i,j,k].block = k;

 /* solve using decomp (aggregate formulation) */
 
solve with MILP / decomp varsel=ryanfoster presolver=basic maxtime=1200;  

   /* OUTPUT */
 /* create solution data set */
create data solution_data from [i j k]= 
{&amp;lt;i,j&amp;gt; in LOGICAL_ARCS, k in VEHICLES: UseArc[i,j,k].sol &amp;gt; 0.5 and i ne depot} 
StartNode=ModelNode[i] StartCity=ModelNode[i] x1=ModelLat[i] y1=ModelLong[i] 
EndNode=ModelNode[j] EndCity=ModelNode[j] x2=ModelLat[j] y2=ModelLong[j] 
flow=Flow[i,j,k] dist=dist[i,j] 
; 
quit;

proc sgplot data=solution_data noautolegend;
   scatter x=x1 y=y1 / datalabel=i;
   vector x=x2 y=y2 / xorigin=x1 yorigin=y1 group=k noarrowheads;
   xaxis display=none;
   yaxis display=none;
run;

DATA WORK.VRO_OUTPUT;
set WORK.solution_data; 
Depot=&amp;amp;Depot;
WeekNumber=&amp;amp;WeekNumber;
VehicleByScenarioByWeekNumber= cat(Depot,'-',k,'-',WeekNumber);
Mode=&amp;amp;Mode;
Scenario=&amp;amp;Scenario;
;
run;

Data WORK.VRO_OUTPUT_Adjusted;
length StartNode $ 60;
length StartCity $ 60;
length EndNode $ 60;
length EndCity $ 60;
length Depot $ 60;
length WeekNumber $60;
length VehicleByScenarioByWeekNumber $ 200;
length Mode $ 60;
length Scenario $60;
set WORK.VRO_OUTPUT;
run;&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 03 Jul 2024 07:23:17 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934518#M4179</guid>
      <dc:creator>Santha</dc:creator>
      <dc:date>2024-07-03T07:23:17Z</dc:date>
    </item>
    <item>
      <title>Re: Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934590#M4180</link>
      <description>&lt;P&gt;The simplest way is to use the &lt;A href="https://go.documentation.sas.com/doc/en/pgmsascdc/v_052/casactmopt/casactmopt_optimization_details05.htm" target="_self"&gt;runOptmodel action with the groupBy parameter&lt;/A&gt;.&amp;nbsp; The idea is to write the OPTMODEL code as if you are solving for only one BY group and then make the following modifications.&lt;/P&gt;
&lt;P&gt;Call PROC CAS instead of PROC OPTMODEL:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;/*proc optmodel;*/
proc cas noqueue;
   source pgm;
   put _BY_LINE_;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Use NodeID instead of _N_ as the key column (always a good idea to avoid _N_ with CAS because the data order is unpredictable):&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;   read data vrpdata into NODES =[NodeID] ModelNode ModelLat ModelLong Volume Mode;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;After the end of your OPTMODEL code, call the runOptmodel action:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;/*quit;*/
   endsource;
   action optimization.runOptmodel / code=pgm groupBy='ModelWeekNumber';
quit;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The resulting solution_data CAS table will automatically include any BY variables, so you can use a BY statement in the PROC SGPLOT call to plot one BY group at a time:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sgplot data=casuser.solution_data noautolegend;
   by ModelWeekNumber;
   scatter x=x1 y=y1 / datalabel=i;
   vector x=x2 y=y2 / xorigin=x1 yorigin=y1 group=k noarrowheads;
   xaxis display=none;
   yaxis display=none;
run;&lt;/CODE&gt;&amp;nbsp;&lt;/PRE&gt;
&lt;P&gt;It is worth noting that you can optionally get a summary table with one row per BY group as follows:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;   action optimization.runOptmodel / code=pgm groupBy='ModelWeekNumber' statusOut='statusOut';
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The resulting statusOut table contains information about the solver call for each BY group.&lt;/P&gt;</description>
      <pubDate>Wed, 03 Jul 2024 17:42:50 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934590#M4180</guid>
      <dc:creator>RobPratt</dc:creator>
      <dc:date>2024-07-03T17:42:50Z</dc:date>
    </item>
    <item>
      <title>Re: Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934675#M4181</link>
      <description>&lt;P&gt;Rob. I want exactly this.&amp;nbsp; I tried the approach. It is giving me errors. See below. I have the code as well after this one. I think i am not setting the model to read it correctly.&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=""&gt;256    endsource;
257    action optimization.runOptmodel / code=pgm groupBy='ModelWeekNumber' statusOut='statusOut';
258  quit;
NOTE: Active Session now MYSESS.
ModelWeekNumber=3
NOTE: There were 1 rows read from table 'VRPDATA' in caslib 'CASUSER(SRHY-Exp)'.
NOTE: Problem generation will use 16 threads.
ERROR: The array subscript 'UseNode[99999,1]' is invalid at line 51 column 23.
ERROR: The array subscript 'UseNode[99999,2]' is invalid at line 51 column 23.
ERROR: The array subscript 'UseNode[99999,3]' is invalid at line 51 column 23.
ERROR: The array subscript 'UseNode[99999,4]' is invalid at line 51 column 23.
ERROR: The array subscript 'UseNode[99999,5]' is invalid at line 51 column 23.
ERROR: The array subscript 'UseNode[99999,6]' is invalid at line 51 column 23.
ERROR: The array subscript 'UseNode[99999,7]' is invalid at line 51 column 23.
ERROR: The array subscript 'UseNode[99999,8]' is invalid at line 51 column 23.
ERROR: The array subscript 'UseNode[99999,9]' is invalid at line 51 column 23.
ERROR: The array subscript 'UseNode[99999,10]' is invalid at line 51 column 23.
NOTE: The maximum error limit was reached during OPTMODEL problem generation.&lt;/CODE&gt;&lt;/PRE&gt;&lt;PRE&gt;&lt;CODE class=""&gt;/*Variables*/
%let capacity = 3400;
%let num_vehicles=20;
%let dist=3000;
%let max_stops=5;
%let Depot='A';
%let DepotID=99999; /* Bfor Lebanon and Afor Lebec*/
/*%Let WeekNumber='2'; */
%Let Mode='Mode1'; /* Mode1 or Mode2*/
%let Scenario='Routing Alternates';

proc fedsql sessref=mysess;
create table CASUSER.vrpdata {options replace='TRUE'} AS
select ModelWeekNumber_2WK as ModelWeekNumber
      ,ModelNode
      ,ModelCity
      ,ModelLat
      ,ModelLong
      ,ModelZip
      ,ModelState
      ,Case_Count
      ,Unit_Count
      ,round(Volume)as Volume
      ,Weight
      ,Declared_Value
      ,ModelDepotState
      ,ModelDepotCity
      ,ModelDepotZip
     ,NodeID
     ,Mode
     ,WeekNumbers
     ,WeekNumber_EarliestStartDate
      ,WeekNumber_LatestEndDate
 from Data
where ModelDepotCity=&amp;amp;Depot
and ModelWeekNumber_2WK in ('3','4')
and Mode=&amp;amp;Mode;
;
QUIT;

proc cas;
source pgm;
put _BY_LINE_;


   /* read the node location and demand data */
   set NODES;
   str ModelNode {NODES};
   num ModelLat {NODES};
   num ModelLong {NODES};
   num Volume {NODES};
   num capacity = &amp;amp;capacity;
   num num_vehicles = &amp;amp;num_vehicles;
   str Mode {NODES};
   read data CASUSER.vrpdata into NODES =[NodeID] ModelNode ModelLat ModelLong Volume Mode;
   set ARCS = {i in NODES, j in NODES: i ne j};
   set VEHICLES = 1..num_vehicles;

   num depot = &amp;amp;DepotID;
	
   /* define the arc dist as the rounded Euclidean distance */
num dist {&amp;lt;i,j&amp;gt; in ARCS} = (if i ne depot then GEODIST(ModelLat[i],ModelLong[i],ModelLat[j],ModelLong[j],'M') else 0);

/*print dist;*/

    /* Creating an Sparse Matrix to remove any unwanted arcs*/
	set LOGICAL_ARCS = {&amp;lt;i,j&amp;gt; in ARCS: dist[i,j] &amp;lt;= &amp;amp;dist};
	/*print {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS} dist; */


   /* Flow[k] is the amount of demand carried by vehicle k */
    var Flow {LOGICAL_ARCS, VEHICLES} &amp;gt;= 0 &amp;lt;= capacity;

/* UseNode[i,k] = 1, if and only if node i is serviced by vehicle k */
   var UseNode {NODES, VEHICLES} binary;
   /* UseArc[i,j,k] = 1, if and only if arc (i,j) is traversed by vehicle k */
   var UseArc {LOGICAL_ARCS, VEHICLES} binary;

  
   /*-----------------------OBJECTIVE FUNCTION-------------------------------*/
   /* minimize the total distance traversed */
   min TotalCost = sum {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS, k in VEHICLES} dist[i,j] * UseArc[i,j,k];

  /*----------------------------CONSTRAINTS-------------------------------------*/
  /* each non-depot node must be serviced by at least one vehicle */
           /*ASSIGNMENT CONSTRAINT*/ 
   con Assignment {i in NODES diff {depot}}:
      sum {k in VEHICLES} UseNode[i,k] &amp;gt;= 1;


/*   for{k in VEHICLES} fix UseNode[depot,k] = 1; */
   con VisitDepot {i in NODES diff {depot}, k in VEHICLES}:
      UseNode[i,k] &amp;lt;= UseNode[depot,k]
   suffixes=(block=k);


	  /*DISTANCE CONSTRAINT*/
	CON Distance {k in VEHICLES}: 
/* 	SUM {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS: j not in {depot}} (dist[i, j] * UseArc[i, j, k]) &amp;lt;= &amp;amp;dist_limit; */
    sum {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS} dist[i,j] * UseArc[i,j,k] &amp;lt;= &amp;amp;dist;

     	  /*STOPS CONSTRAINT*/
	CON Stops {k in VEHICLES}: 
    sum {i in NODES diff {depot}} UseNode[i,k] &amp;lt;= &amp;amp;max_stops; 

/*   some vehicle k traverses an arc that leaves node i if and only if UseNode[i,k] = 1 */
/* 			LEAVE NODE CONSTRAINT */
   con LeaveNode {i in NODES, k in VEHICLES}:
      sum {&amp;lt;(i),j&amp;gt; in LOGICAL_ARCS} UseArc[i,j,k] = UseNode[i,k];


/*   some vehicle k traverses an arc that enters node i if and only if UseNode[i,k] = 1 */
/* 			ENTER NODE CONSTRAINT   */
   con EnterNode {i in NODES, k in VEHICLES}:
      sum {&amp;lt;j,(i)&amp;gt; in LOGICAL_ARCS} UseArc[j,i,k] = UseNode[i,k];

  /* the amount of Volume supplied by vehicle k to node i must equal Volume if UseNode[i,k] = 1; otherwise, it must equal 0 */
			/*FLOW BALANCE CONSTRAINT*/ 

  con FlowBalance {i in NODES diff {depot}, k in VEHICLES}:
       sum {&amp;lt;(i),j&amp;gt; in LOGICAL_ARCS} Flow[i,j,k] - sum {&amp;lt;j,(i)&amp;gt; in LOGICAL_ARCS} Flow[j,i,k]
       = Volume[i] * UseNode[i,k];

/* each vehicle is empty when it leaves the depot */
   for {&amp;lt;(depot),j&amp;gt; in LOGICAL_ARCS, k in VEHICLES} fix Flow[depot,j,k] = 0;

/* if UseArc[i,j,k] = 1, then the flow on arc (i,j) must be at most capacity
  if UseArc[i,j,k] = 0, then no flow is allowed on arc (i,j) */
			
/*VEHICLE CAPACITY CONSTRAINT*/ 
   con VehicleCapacity {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS, k in VEHICLES}:
      Flow[i,j,k] &amp;lt;= Flow[i,j,k].ub * UseArc[i,j,k];

/*Constraint VehicleCapacity[3,4,1]: Flow[3,4,1] - 3650*UseArc[3,4,1] &amp;lt;= 0  /*
/* expand; */


 /* decomp by vehicle *//*DECOMPOSITION*/
   for {i in NODES, k in VEHICLES} do;
      LeaveNode[i,k].block = k;
      EnterNode[i,k].block = k;
   end;
   for {k in VEHICLES} Distance[k].block = k;
   for {k in VEHICLES} Stops[k].block = k;
   for {i in NODES diff {depot}, k in VEHICLES} FlowBalance[i,k].block = k;
   for {&amp;lt;i,j&amp;gt; in LOGICAL_ARCS, k in VEHICLES} VehicleCapacity[i,j,k].block = k;

  /* solve using decomp (aggregate formulation) */
   
solve with MILP / decomp varsel=ryanfoster presolver=basic maxtime=1200;  

   /* OUTPUT */
   /* create solution data set */
 

create data solution_data from [i j k]= 
{&amp;lt;i,j&amp;gt; in LOGICAL_ARCS, k in VEHICLES: UseArc[i,j,k].sol &amp;gt; 0.5 and i ne depot} 
StartNode=ModelNode[i] StartCity=ModelNode[i] x1=ModelLat[i] y1=ModelLong[i] 
EndNode=ModelNode[j] EndCity=ModelNode[j] x2=ModelLat[j] y2=ModelLong[j] 
flow=Flow[i,j,k] dist=dist[i,j] 
; 


  endsource;
  action optimization.runOptmodel / code=pgm groupBy='ModelWeekNumber' statusOut='statusOut';
quit;



proc sgplot data=solution_data noautolegend;
   scatter x=x1 y=y1 / datalabel=i;
   vector x=x2 y=y2 / xorigin=x1 yorigin=y1 group=k noarrowheads;
   xaxis display=none;
   yaxis display=none;
run;


DATA WORK.VRO_OUTPUT;
set WORK.solution_data; 
Depot=&amp;amp;Depot;
WeekNumber=&amp;amp;WeekNumber;
VehicleByScenarioByWeekNumber= cat(Depot,'-',k,'-',WeekNumber);
Mode=&amp;amp;Mode;
Scenario=&amp;amp;Scenario;
run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Thu, 04 Jul 2024 10:44:32 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934675#M4181</guid>
      <dc:creator>Santha</dc:creator>
      <dc:date>2024-07-04T10:44:32Z</dc:date>
    </item>
    <item>
      <title>Re: Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934688#M4182</link>
      <description>From your log:&lt;BR /&gt;ModelWeekNumber=3&lt;BR /&gt;NOTE: There were 1 rows read from table 'VRPDATA' in caslib 'CASUSER(SRHY-Exp)'.&lt;BR /&gt;&lt;BR /&gt;I recommend checking your vrpdata table, which seems to have only one observation with ModelWeekNumber=3.</description>
      <pubDate>Thu, 04 Jul 2024 12:55:39 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934688#M4182</guid>
      <dc:creator>RobPratt</dc:creator>
      <dc:date>2024-07-04T12:55:39Z</dc:date>
    </item>
    <item>
      <title>Re: Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934689#M4183</link>
      <description>&lt;P&gt;Rob I just ran the model again. I checked the VRP data. It has 29 observations. I get the same error. I have attached the excel file as well in the previous mail from me. So I am not sure why it says only observation for WeekNumber 3.&lt;/P&gt;</description>
      <pubDate>Thu, 04 Jul 2024 13:09:12 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934689#M4183</guid>
      <dc:creator>Santha</dc:creator>
      <dc:date>2024-07-04T13:09:12Z</dc:date>
    </item>
    <item>
      <title>Re: Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934691#M4184</link>
      <description>&lt;P&gt;What does the following yield?&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc print data=casuser.vrpdata(where=(ModelWeekNumber=3));
run;
&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Thu, 04 Jul 2024 14:13:41 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934691#M4184</guid>
      <dc:creator>RobPratt</dc:creator>
      <dc:date>2024-07-04T14:13:41Z</dc:date>
    </item>
    <item>
      <title>Re: Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934695#M4185</link>
      <description>&lt;P&gt;Rob&amp;nbsp;&lt;/P&gt;&lt;P&gt;I ran the proc print data=casuser.vrpdata(where=(ModelWeekNumber=3));&lt;BR /&gt;run;&lt;/P&gt;&lt;P&gt;It gives me that exact 29 observations for Model week number=3. So that is correct. I do not know why inside the model it says only 1 and after the UseNode error that I showed earlier. It is beyond me to know why this would happen, as the actual optmodel solved just fine if i were to manually run weeknumber by weeknumber.&lt;/P&gt;</description>
      <pubDate>Thu, 04 Jul 2024 15:11:49 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934695#M4185</guid>
      <dc:creator>Santha</dc:creator>
      <dc:date>2024-07-04T15:11:49Z</dc:date>
    </item>
    <item>
      <title>Re: Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934697#M4186</link>
      <description>&lt;P&gt;Here is the data attached (82 obs) just in case.&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 04 Jul 2024 15:32:13 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934697#M4186</guid>
      <dc:creator>Santha</dc:creator>
      <dc:date>2024-07-04T15:32:13Z</dc:date>
    </item>
    <item>
      <title>Re: Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934730#M4188</link>
      <description>&lt;P&gt;I am not able to replicate the behavior you are seeing.&amp;nbsp; Please attach the full log from a fresh session.&lt;/P&gt;</description>
      <pubDate>Fri, 05 Jul 2024 04:12:06 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934730#M4188</guid>
      <dc:creator>RobPratt</dc:creator>
      <dc:date>2024-07-05T04:12:06Z</dc:date>
    </item>
    <item>
      <title>Re: Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934734#M4189</link>
      <description>&lt;P&gt;Rob Okay. I will replicate it and let you know soon. Thank you&lt;/P&gt;</description>
      <pubDate>Fri, 05 Jul 2024 04:26:03 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934734#M4189</guid>
      <dc:creator>Santha</dc:creator>
      <dc:date>2024-07-05T04:26:03Z</dc:date>
    </item>
    <item>
      <title>Re: Looping proc optmodel</title>
      <link>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934772#M4192</link>
      <description>&lt;P&gt;Hi Rob&lt;/P&gt;&lt;P&gt;Figured it out. It was a datatype issue. Fixed it and now it took all the 29 observations. It solved exactly. Thanks a lot for your support as always. You are the best&lt;/P&gt;</description>
      <pubDate>Fri, 05 Jul 2024 12:15:01 GMT</pubDate>
      <guid>https://communities.sas.com/t5/Mathematical-Optimization/Looping-proc-optmodel/m-p/934772#M4192</guid>
      <dc:creator>Santha</dc:creator>
      <dc:date>2024-07-05T12:15:01Z</dc:date>
    </item>
  </channel>
</rss>

