Syntax Examples (omods01)


/***************************************************************/
/*                                                             */
/*          S A S   S A M P L E   L I B R A R Y                */
/*                                                             */
/*    NAME: omods01                                            */
/*   TITLE: Syntax Examples (omods01)                          */
/* PRODUCT: OR                                                 */
/*  SYSTEM: ALL                                                */
/*    KEYS: OR                                                 */
/*   PROCS: OPTMODEL                                           */
/*    DATA:                                                    */
/*                                                             */
/* SUPPORT:                             UPDATE:                */
/*     REF:                                                    */
/*    MISC: Examples from the Syntax section of the            */
/*          OPTMODEL chapter of Mathematical Programming.      */
/*                                                             */
/***************************************************************/


/****************************************************************
 *                                                              *
 *  Declaration Statements                                      *
 *                                                              *
 ****************************************************************/


/*  NUMBER, STRING, and SET Parameters  */
proc optmodel;
   num a{i in 1..2} init i**2;
   a[1] = 2;
   put a[*]=;
quit;



/*  NUMBER, STRING, and SET Parameters: Initializing Arrays  */
proc optmodel;
   number a{1..3} = [5 4 7];
   number b{1..3} INIT [5 4 7];
   put a[*]=;
   b[1] = 1;
   put b[*]=;
quit;



/*  PROBLEM Declaration: Adding Model Components */
proc optmodel;
   problem prob1;
   use problem prob1;
   var x >= 0;             /* included in prob1 */
   min z1 = (x-1)**2;      /* included in prob1 */
   expand;                 /* prob1 contains x, z1 */

   problem prob2 from prob1;
   use problem prob2;      /* includes x, z1 */
   min z2 = (x-2)**2;      /* included in prob2 */
   expand;                 /* prob2 contains x, z1, z2 */
                           /* note z1 is not expanded */

   use problem _start_;    /* don't modify prob2 */
   min z3 = (x-3)**2;
   problem prob3 include x z3;
   use problem prob3;
   expand;                 /* prob3 contains x, z3 */
quit;

/****************************************************************
 *                                                              *
 *  Programming Statements                                      *
 *                                                              *
 ****************************************************************/


/*  CALL Statement: Updating OPTMODEL Parameters  */
proc optmodel;
   number a{i in 1..4} init i;
   number seed init -1;
   call ranperm(seed, a[1], a[2], a[3], a[4]);
   print a;
quit;

/*  CLOSEFILE Statement  */
filename greet 'hello.txt';
proc optmodel;
   file greet;
   put 'Hi!';
   closefile greet;
quit;

/*  COFOR Statement: A Simple Loop  */
proc optmodel printlevel=0;
   var x {1..6} >= 0;

   minimize z = sum {j in 1..6} x[j];

   con a1: x[1] + x[2] + x[3]                      <= 4;
   con a2:                      x[4] + x[5] + x[6] <= 6;
   con a3: x[1] +               x[4]               >= 5;
   con a4:        x[2] +               x[5]        >= 2;
   con a5:               x[3] +               x[6] >= 3;

   cofor{i in 3..5} do;
      fix x[1]=i;
      solve;
      put i= x[1]= _solution_status_=;
   end;
quit;

/* Monte Carlo MINLP Portfolio Optimization */

/* Expected Return For Assets */
data means;
   input return;
   datalines;
0.000065763
0.002604107
0.000753611
0.000082178
-.000380250
0.000399003
0.002421262
0.002412429
0.000773394
0.000403047
0.001361435
;

/* Asset Return Covariance */
data covdata;
   input cov asset1 asset2;
   datalines;
0.001353751 1 1
0.000468578 1 2
0.001280990 1 3
-.000032003 1 4
0.000731890 1 5
0.000660113 1 6
0.000641176 1 7
0.000466734 1 8
0.000683927 1 9
0.000658789 1 10
0.000606616 1 11
0.000307035 2 2
0.000534959 2 3
-.000006434 2 4
0.000310362 2 5
0.000304408 2 6
0.000348148 2 7
0.000243561 2 8
0.000311989 2 9
0.000301229 2 10
0.000282500 2 11
0.001448759 3 3
-.000031943 3 4
0.000772008 3 5
0.000745441 3 6
0.000782744 3 7
0.000554453 3 8
0.000762838 3 9
0.000745559 3 10
0.000719599 3 11
0.000026314 4 4
-.000027629 4 5
-.000025069 4 6
-.000016775 4 7
-.000016202 4 8
-.000026060 4 9
-.000026031 4 10
-.000019917 4 11
0.000510235 5 5
0.000463580 5 6
0.000471570 5 7
0.000346507 5 8
0.000479810 5 9
0.000463526 5 10
0.000424889 5 11
0.000455959 6 6
0.000471924 6 7
0.000332697 6 8
0.000462159 6 9
0.000455080 6 10
0.000421059 6 11
0.000572171 7 7
0.000371153 7 8
0.000473532 7 9
0.000470686 7 10
0.000449428 7 11
0.000316483 8 8
0.000337295 8 9
0.000331312 8 10
0.000328404 8 11
0.000482038 9 9
0.000462024 9 10
0.000429875 9 11
0.000456097 10 10
0.000420613 10 11
0.000460050 11 11
;

/*  COFOR Statement: Optimization With a Fixed Number Of Trials  */
proc optmodel printlevel=0 nthreads=4;
   /* assets and related parameters */
   set ASSETS;
   num return {ASSETS};
   num cov {ASSETS, ASSETS} init 0;
   read data means into ASSETS=[_n_] return;
   read data covdata into [asset1 asset2] cov cov[asset2,asset1]=cov;
   num riskLimit init 0.00025;
   num minThreshold init 0.1;
   num numTrials = 10;

   /* number of random trials */
   set TRIALS = 1..numTrials;

   /* declare NLP problem for fixed set of assets */
   set ASSETS_THIS;
   var AssetPropVar {ASSETS} >= minThreshold <= 1;
   max ExpectedReturn = sum {i in ASSETS} return[i] * AssetPropVar[i];
   con RiskBound:
      sum {i in ASSETS_THIS, j in ASSETS_THIS}
          cov[i,j] * AssetPropVar[i] * AssetPropVar[j] <= riskLimit;
   con TotalPortfolio:
      sum {asset in ASSETS} AssetPropVar[asset] = 1;

   /* parameters to track best solution */
   num infinity = constant('BIG');
   num best_objective init -infinity;
   set INCUMBENT;

   /* iterate over trials */
   num start  {TRIALS};
   num finish {TRIALS};
   num overall_start;
   overall_start = time();
   call streaminit(1);
   cofor {trial in TRIALS} do;
      start[trial] = time() - overall_start;
      put;
      put trial=;
      ASSETS_THIS = {i in ASSETS: rand('UNIFORM') < 0.5};
      put ASSETS_THIS=;
      for {i in ASSETS diff ASSETS_THIS}
         fix AssetPropVar[i] = 0;
      solve with NLP / logfreq=0;
      put _solution_status_=;
      if _solution_status_ ne 'INFEASIBLE' then do;
         if best_objective < ExpectedReturn then do;
            best_objective = ExpectedReturn;
            INCUMBENT = ASSETS_THIS;
         end;
      end;
      finish[trial] = time() - overall_start;
   end;

   put best_objective= INCUMBENT=;
   create data plotdata from [trial] start finish;
quit;

proc sgplot data=plotdata;
   highlow y=trial low=start high=finish / type=bar x2axis;
   yaxis reverse;
   x2axis label="seconds";
run;

/*  COFOR Statement: Optimization With a Time Limit Using LEAVE  */
proc optmodel printlevel=0;
   set ASSETS;
   num return {ASSETS};
   num cov {ASSETS, ASSETS} init 0;
   read data means into ASSETS=[_n_] return;
   read data covdata into [asset1 asset2] cov cov[asset2,asset1]=cov;
   num riskLimit init 0.00025;
   num minThreshold init 0.1;

   /* declare NLP problem for fixed set of assets */
   set ASSETS_THIS;
   var AssetPropVar {ASSETS} >= minThreshold <= 1;
   max ExpectedReturn = sum {i in ASSETS} return[i] * AssetPropVar[i];
   con RiskBound:
      sum {i in ASSETS_THIS, j in ASSETS_THIS}
          cov[i,j] * AssetPropVar[i] * AssetPropVar[j] <= riskLimit;
   con TotalPortfolio:
      sum {asset in ASSETS} AssetPropVar[asset] = 1;

   num infinity = constant('BIG');
   num best_objective init -infinity;
   set INCUMBENT;

   /* run for 30 seconds */
   num last_time;
   last_time = time() + 30;
   num n_trials init 0;
   call streaminit(1);
   cofor {trial in 1..1e9} do;
      put;
      put trial=;
      ASSETS_THIS = {i in ASSETS: rand('UNIFORM') < 0.5};
      put ASSETS_THIS=;
      for {i in ASSETS diff ASSETS_THIS} fix AssetPropVar[i] = 0;
      solve with NLP / logfreq=0;
      put _solution_status_=;
      if _solution_status_ ne 'INFEASIBLE' then do;
         if best_objective < ExpectedReturn then do;
            best_objective = ExpectedReturn;
            INCUMBENT = ASSETS_THIS;
         end;
      end;
      n_trials = n_trials + 1;
      if time() >= last_time then leave;
   end;

   put n_trials=;
   put best_objective= INCUMBENT=;
quit;

/*  CREATE DATA Statement: Output of Parameters  */
proc optmodel;
   number m = 7, n = 5;
   create data example from m n;
quit;

/*  CREATE DATA Statement: Output of an Expression  */
proc optmodel;
   number m = 7, n = 5;
   create data example from ratio=(m/n);
quit;

/*  CREATE DATA Statement: Using a COL Expression  */
proc optmodel;
   number m = 7, n = 5;
   create data example from col("s"||n)=(m+n);
quit;

/*  CREATE DATA Statement: Columns  */
proc optmodel;
   set<string> alph = {'a', 'b', 'c'};
   var x{1..3, alph} init 2;
   create data example from [i]=(1..3)
      {j in alph}<col("x"||j)=x[i,j]>;
quit;



/*  CREATE DATA Statement: Creating a Single Observation  */
proc optmodel;
   number m = 7, n = 5;
   create data example from m n ratio=(m/n) col("s"||n)=(m+n);
quit;

proc print;
run;



/*  CREATE DATA Statement: Column Options  */
proc optmodel;
   num sq{i in 1..10} = i*i;
   create data squares from [i/format=hex2./length=3] sq/format=6.2;
quit;

proc print;
run;



/*  CREATE DATA Statement: Key Columns  */
proc optmodel;
   number m{1..5, 1..3} = [[1 1] 1 [4 1] 1 [*] 0];
   set ISET = setof{i in 1..2} i**2;
   create data example
      from [i j] = {i in ISET, {1, 2}} m;
quit;

proc print data=example noobs;
run;



/*  CREATE DATA Statement: Unspecified Key-Set  */
proc optmodel;
   number x{1..2} init 2;
   var y{2..3} init 3;
   create data exdata from [keycol] x y;
quit;

proc print;
run;



/*  CREATE DATA Statement: Iterated Columns  */
proc optmodel;
   num m = 3;  /* number of rows/observations */
   num n = 4;  /* number of columns in a */
   num a{i in 1..m, j in 1..n} = i*j;  /* compute a */
   num b{i in 1..m} = i**2;  /* compute b */
   set<num> subset = 2..m;  /* used to omit first row */
   create data out
          from [i]=subset {j in 1..n}<col("a"||j)=a[i,j]> b;
quit;


/*  DO Statement: DO Statement, Iterative  */
proc optmodel;
   number i;
   do i=1,3,5;
      put i;
   end;
quit;



/*  DO Statement: Iterating Over a Range  */
proc optmodel;
   number i;
   do i=1 to 5 by 2;
      put 'value of i assigned by the DO loop = ' i;
      i=i**2;
      put 'value of i assigned in the body of the loop = ' i;
   end;
quit;



/*  DO Statement: Iterating Over a Set  */
proc optmodel;
   set s = {1,3,5};
   number i;
   do i = s;
      put i;
   end;
quit;



/*  DO Statement: Iterating With a WHILE Clause  */
proc optmodel;
   set s = {1,2,3,4,5};
   number i;
   do i = s while(i NE 4);
      put i;
   end;
quit;



/*  DO UNTIL Statement  */
proc optmodel;
   number i;
   i = 1;
   do until (i=3);
      put i;
      i=i+1;
   end;
quit;



/*  DO WHILE Statement  */
proc optmodel;
   number i;
   i = 1;
   do while (i<3);
      put i;
      i=i+1;
   end;
quit;



/*  DROP Statement  */
proc optmodel;
   var x{1..10};
   con c1: x[1] + x[2] <= 3;
   con disp{i in 1..9}: x[i+1] >= x[i] + 0.1;

   expand /con;
   drop c1;        /* drops the c1 constraint */
   expand /con;
   drop disp[5];   /* drops just disp[5] */
   expand /con;
   drop {i in 1..3} disp;  /* drop disp[1] disp[2] disp[3] */
   expand /con;
   drop disp;      /* drops all disp constraints */
   expand /con;

   restore c1 disp;
   drop c1 disp[5];
   expand /con;
quit;

/*  EXPAND Statement  */
proc optmodel;
   number n=2;
   var x{1..n};
   min z1=sum{i in 1..n}(x[i]-i)**2;
   max z2=sum{i in 1..n}(i-x[i])**3;
   con c{i in 1..n}: x[i]>=0;
   fix x[2]=3;
   expand;
quit;



/*  EXPAND Statement: SOLVE Option  */
proc optmodel;
   number n=2;
   var x{1..n};
   min z1=sum{i in 1..n}(x[i]-i)**2;
   max z2=sum{i in 1..n}(i-x[i])**3;
   con c{i in 1..n}: x[i]>=0;
   fix x[2]=3;
   expand / solve;
quit;



/*  FILE Statement: Multiple Files  */
proc optmodel;
   file 'file.txt' lrecl=80;   /* opens file.txt     */
   put 'This is line 1 of file.txt.';
   file print;                  /* selects the listing */
   put 'This goes to the listing.';
   file 'file.txt';            /* reselects file.txt */
   put 'This is line 2 of file.txt.';
   closefile 'file.txt';       /* closes file.txt    */
   file log;                    /* selects the SAS log */
   put 'This goes to the log.';

   /* using expression to open and write a collection of files */
   str ofile;
   num i;
   num l = 40;
   do i = 1 to 3;
      ofile = ('file' || i || '.txt');
      file (ofile) lrecl=(l*i);
      put ('This goes to ' || ofile);
      closefile (ofile);
   end;
quit;

/*  FILE Statement: Logical File Names  */
proc optmodel;
   /* assigns a logical name to file.txt */
   /* see FILENAME statement in        */
   /* SAS Global Statements: Reference */
   filename myfile 'file.txt' mod;

   file myfile;
   put 'This is line 3 of file.txt.';
   closefile myfile;
   file myfile;
   put 'This is line 4 of file.txt.';
   closefile myfile;
quit;

/* FIX Statement */
proc optmodel;
   var x, y;
   num a = 2;
   fix x y=a+1;
   expand;
quit;

proc optmodel;
   var x{1..10};
   fix x = 0;
   fix x[10] = 1;
   expand;
   unfix x;

   fix {i in 1..10} x[i] = if i eq 10 then 1 else 0;
   expand;
quit;

/*  FOR Statement  */
proc optmodel;
   for {i in 1..2, j in {'a', 'b'}} put i= j=;
quit;



proc optmodel;
   var x{1..10};
   for {i in 1..10}
      x[i] = ranuni(-1);
   print x;
quit;

/*  LEAVE Statement  */
proc optmodel;
   number i, j;
   do i = 1..5;
      do j = 1..4;
         if i >= 3 and j = 2 then leave;
      end;
      print i j;
   end;
quit;



/*  PRINT Statement  */
proc optmodel;
   num x = 4.3;
   var y{j in 1..4} init j*3.68;
   print y; /* identifier-expression */
   print (x * .265) dollar6.2; /* (expression) [format] */
   print {i in 2..4} y; /* {index-set} identifier-expression */
   print {i in 1..3}(i + i*.2345692) best7.;
                               /* {index-set} (expression) [format] */
   print "Line 1"; /* string */
quit;



proc optmodel;
   num a{i in 1..3} = i*i;
   num b{i in 3..5} = 4*i;
   print a b;
quit;



/*  PRINT Statement: Matrix Output  */
proc optmodel;
   print {i in 1..6, j in i..6} (i*10+j);
quit;



/*  PRINT Statement: PMATRIX= Option  */
proc optmodel;
   num a{i in 1..6, i..i} = i;
   num b{i in 1..3, j in 1..3} = i*j;
   print a;
   print b;
   reset options pmatrix=3;
   print a;
   reset options pmatrix=0.5;
   print b;
quit;



/*  READ DATA Statement: Key Columns  */

data invdata;
   input item $ invcount;
   datalines;
table 100
sofa  250
chair 80
;

proc optmodel;
   set<string> Items;
   number invcount{Items};
   read data invdata into Items=[item] invcount;
   print invcount;
quit;



/*  READ DATA Statement: Columns  */

data exdata;
   input column1 column2;
   datalines;
1 2
3 4
;

proc optmodel;
   number n init 2;
   set<num> indx;
   number p{indx}, q{indx};
   read data exdata into
      indx=[_N_] p=column1 q=col("column"||n);
   print p q;



/*  READ DATA Statement: Iterated Columns  */
data dmnd;
   input loc $ day1 day2 day3 day4 day5;
   datalines;
East 1.1 2.3 1.3 3.6 4.7
West 7.0 2.1 6.1 5.8 3.2
;

proc optmodel;
   set DOW = 1..5;  /* days of week, 1=Monday, 5=Friday */
   set<string> LOCS; /* locations */
   number demand{LOCS, DOW};
   read data dmnd
        into LOCS=[loc]
        {d in DOW} < demand[loc, d]=col("day"||d) >;
   print demand;
quit;



/*  RESTORE Statement  */
proc optmodel;
   var x{1..4}, y{1..4};
   con c{i in 1..4}: x[i] + y[i] <=1;
   drop c;
   expand;

   restore c[1];
   expand;

   restore {i in 2..3} c[i]; /* like "restore c[2] c[3];" */
   expand;

   restore c;
   expand;
quit;

/*  SAVE MPS Statement  */
proc optmodel;
   var x >= 0, y >= 0;
   con c: x >= y;
   con bx: x <= 2;
   con by: y <= 1;
   min obj=0.5*x-y;
   save mps MPSData;
quit;

proc optlp data=MPSData pout=PrimalOut dout=DualOut;
run;



/*  SAVE QPS Statement  */
proc optmodel;
   var x{1..2} >= 0;
   min z = 2*x[1] + 3 * x[2] + x[1]**2 + 10*x[2]**2
                  + 2.5*x[1]*x[2];
   con c1: x[1] - x[2] <= 1;
   con c2: x[1] + 2*x[2] >= 100;
   save qps QPSData;
quit;

proc optqp data=QPSData pout=PrimalOut dout=DualOut;
run;



/*  STOP Statement  */
proc optmodel;
   number i, j;
   do i = 1..5;
      do j = 1..4;
         if i = 3 and j = 2 then stop;
      end;
   end;
   print i j;
quit;



/* SUBMIT Statement */
proc optmodel;
   set<str> NODES;
   num priority{NODES};

   /* set up priority data... */
   call streaminit(12345);
   NODES = setof{i in 1..26} substr('ABCDEFGHIJKLMNOPQRSTUVWXYZ',i,1);
   for {id in NODES} priority[id] = 100*rand('UNIFORM');

   /* sort nodes by descending priority */
   create data temppri from [id] priority;
   submit;
      proc sort;
         by descending priority;
      run;
   endsubmit;

   /* load nodes by priority */
   str nodesByPri{i in 1..card(NODES)};
   read data temppri into [_n_] nodesByPri=id;

   /* use the sorted list... */
   print nodesByPri {i in 1..card(NODES)} priority[nodesByPri[i]];
quit;

/*  SUBMIT Statement: Passing a Macro Variable Value  */
proc optmodel;
   for {i in 1..5} do;
      submit a=i;
         %put Value of a is &a..;
      endsubmit;
   end;
quit;

/* SUBMIT Statement Error Handling */
proc optmodel;
   num success, syscc;
   submit / OK = success out syscc;
      data example;
         set notfound;
         j = i*i;
      run;
   endsubmit;
   print success syscc;
quit;

/* UNFIX Statement */
proc optmodel;
   var x{1..3};
   fix x;       /* fixes entire array to 0 */
   expand;
   unfix x[1];  /* x[1] can now be varied again */
   expand;
   unfix x[2] = 2;  /* x[2] is given an initial value 2 */
                  /* and can be varied now */
   expand;
   print x;
   unfix x;  /* all x indices can now be varied */
   expand;
quit;

proc optmodel;
   var x{1..3} init 2;
   num a = 1;
   fix x;
   unfix x[1] x[2]=a+3;
   expand;
   print x;
   fix x;
   unfix {1..2} x = a+3;  /* equivalent to prior UNFIX statement */
   expand;
   print x;
quit;