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.

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
Multiple Linear Regression in SAS

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.

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