BookmarkSubscribeRSS Feed
Mbs270
Obsidian | Level 7

I need to loop over the attached code 5000 times. I want to pick 400 random observations from the main dataset then run the optmodel code. I want to save this output to "storage". I thought I would be able to use the sample id from the random sample output but optmodel does not allow by processing the way I want. Any ideas on how to implement this.

 

 

The main dataset looks like this:

 

cat_1 cat_2 cat_3 ... cat_12 dwpi_hours

       6       4        5 ...          5             23.4

 

 

%Let no_obs = 400; *how many observations in bootstrap/Must be less than 468 since you only have 468 employee pins;
%Let no_runs = 5000; *how many runs of the resampling you want/this is how many solution sets you'll get/average of which will be mean time value/BIGGER IS BETTER;

data storage; /*THIS WILL STORE THE OUTPUTS FROM EACH RUN*/
INFILE DATALINES;
input cat_1 cat_2 cat_3 cat_4 cat_5 cat_6 cat_7 cat_8 cat_9 cat_10 cat_11 cat_12 cat_13;
DATALINES;
0 0 0 0 0 0 0 0 0 0 0 0 0
;
RUN;



%macro do_optmodel;
%do i=1 %to &no_runs;

proc surveyselect data=work.work1 NOPRINT method = urs sampsize = &no_obs reps=1 /*seed=12345*/ out = now_1 outhits; 
run;

proc optmodel;
by SampleID;
ods output PrintTable = exss; /*THIS PRODUCES THE SOLUTION SET OF TIME COEFFICIENTS*/
set S = 1..&no_obs;   /*Number of observations in the data set*/
number cat_1{S};  *Initializing variables;
number cat_2{S};
number cat_3{S};
number cat_4{S};
number cat_5{S};
number cat_6{S};
number cat_7{S};
number cat_8{S};
number cat_9{S};
number cat_10{S};
number cat_11{S};
number cat_12{S};
number dwpi_hours{S};
var x{1..13} init .5;  *initializing coefficients/Must update here if category count changes;
min f = sum{i in S}(dwpi_hours[i] - (cat_1[i]*x[1]+         /*declaring objective function*/
cat_2[i]*x[2]+
cat_3[i]*x[3]+
cat_4[i]*x[4]+
cat_5[i]*x[5]+
cat_6[i]*x[6]+
cat_7[i]*x[7]+
cat_8[i]*x[8]+
cat_9[i]*x[9]+
cat_10[i]*x[10]+
cat_11[i]*x[11]+
cat_12[i]*x[12]+
x[13]))^2;
con c1: x[2]-x[1] >= .25;
con c2: x[3]-x[2] >= .25;
con c3: x[4]-x[3] >= .25;
con c4: x[5]-x[4] >= .25;
con c5: x[6]-x[5] >= .25;
con c6: x[7]-x[6] >= .25;
con c7: x[8]-x[7] >= .25;
con c8: x[9]-x[8] >= .25;
con c9: x[10]-x[9] >= .25;
con c10: x[11]-x[10] >= .25;
con c11: x[12]-x[11] >= .25;

con c12: 2 <= x[1] <= 8;
con c13: 2 <= x[2] <= 10;
con c14: 2 <= x[3] <= 10;
con c15: 2 <= x[4] <= 10;
con c16: 3 <= x[5] <= 14;
con c17: 3 <= x[6] <= 14;
con c18: 3 <= x[7] <= 15;
con c19: 3 <= x[8] <= 15;
con c20: 3 <= x[9] <= 16;
con c21: 3 <= x[10] <= 16;
con c22: 3 <= x[11] <= 16;
con c23: 3 <= x[12] <= 16;
read data work.work1 into [_n_] cat_1    /*reading in rows of observations from data returned from sampling with replacement*/
cat_2
cat_3
cat_4
cat_5
cat_6
cat_7
cat_8
cat_9
cat_10
cat_11
cat_12
dwpi_hours;
solve;
print x;
quit;

/*TRANSPOSING AND SAVING SOLUTION SET OF COEFFICIENTS FOR THIS RUN */
proc transpose data=exss
out=solns_t
prefix=cat_;
var x;
run;
/* DROPPING CLUTTER VARIABLE FROM SOLUTION OUTPUT*/
data soln_1;
set solns_t(drop=_name_);
run;

/* APPENDING CURRENT SOLUTION TO GROUP OF PREVIOUS SOLUTIONS*/
proc append base=storage data=soln_1;
run;
%END;
%MEND do_optmodel;
4 REPLIES 4
Mbs270
Obsidian | Level 7

Tried enclosing everything in a do but that did not work. All I want is something like

 

do i=1 to no_runs;

"run all the code above";

"append output to storage"

i=i+1;

end;

RobPratt
SAS Super FREQ

Please see this SAS Usage Note for an example of BY-group processing with PROC OPTMODEL.

Mbs270
Obsidian | Level 7

I edited the code with my current attempt. Is there anyway to make this simple macro work? It's intuitive and should work? I sandwiched the proc optmodel code between a macro call:

%macro do_optmodel;
%do i=1 %to &no_runs;

proc optmodel....

%end;
%mend do_optmodel;
RobPratt
SAS Super FREQ

Yes, that will work, with some modifications:

  1. Omit the BY statement, which is not directly supported in PROC OPTMODEL.
  2. Read from now_1 instead of work1.

You can also simplify the code by omitting the ODS OUTPUT and PRINT statements and instead doing this:

create data soln_1 from {j in 1..13} <col('cat_'||j)=x[j]>;

You can then omit the PROC TRANSPOSE and subsequent DATA step.

sas-innovate-white.png

Register Today!

Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9.

 

Early bird rate extended! Save $200 when you sign up by March 31.

Register now!

Discussion stats
  • 4 replies
  • 903 views
  • 0 likes
  • 2 in conversation