Resources

Introduction to Optimization examples (intmplp0)

/***************************************************************/
/*                                                             */
/*          S A S   S A M P L E   L I B R A R Y                */
/*                                                             */
/*    NAME: intmplp0                                           */
/*   TITLE: Introduction to Optimization examples (intmplp0)   */
/* PRODUCT: OR, GRAPH                                          */
/*  SYSTEM: ALL                                                */
/*    KEYS: OR                                                 */
/*   PROCS: LP, NETFLOW, GCHART                                */
/*    DATA:                                                    */
/*                                                             */
/* SUPPORT:                             UPDATE:                */
/*     REF:                                                    */
/*    MISC: Examples from the Introduction to Optimization     */
/*          chapter of Mathematical Programming Legacy         */
/*          Procedures.                                        */
/*                                                             */
/***************************************************************/

data factory;
   input _id_ $ CHOCO TOFFEE _type_ $ _rhs_;
   datalines;
object      0.25    0.75   MAX     .
process1   15.00   40.00   LE  27000
process2    0.00   56.25   LE  27000
process3   18.75    0.00   LE  27000
process4   12.00   50.00   LE  27000
;

proc lp data=factory;
run;

/***************************************************************

                Model Building: PROC LP

 ***************************************************************/

data sp_factory;
   format _type_ $8. _row_ $10. _col_ $10.;
   input _type_ $_row_ $ _col_ $ _coef_;
   datalines;
max      object     .            .
.        object     chocolate    .25
.        object     toffee       .75
le       process1   .            .
.        process1   chocolate    15
.        process1   toffee       40
.        process1   _RHS_        27000
le       process2   .            .
.        process2   toffee       56.25
.        process2   _RHS_        27000
le       process3   .            .
.        process3   chocolate    18.75
.        process3   _RHS_        27000
le       process4   .            .
.        process4   chocolate    12
.        process4   toffee       50
.        process4   _RHS_        27000
;

proc lp data=sp_factory sparsedata;
run;

data manfg;
   format product $12.;
   input product $ object process1 - process4 ;
   datalines;
chocolate        .25    15  0.00 18.75    12
toffee           .75    40 56.25  0.00    50
licorice        1.00    29 30.00 20.00    20
jelly_beans      .85    10  0.00 30.00    10
_RHS_            .   27000 27000 27000 27000
;

data model;
   array process {5} object process1-process4;
   format _type_ $8. _row_ $12. _col_ $12. ;
   keep _type_ _row_ _col_ _coef_;

   set manfg;         /* read the manufacturing data */

   /* build the object function */

   if _n_=1 then do;
      _type_='max'; _row_='object'; _col_=' '; _coef_=.;
      output;
   end;

   /* build the constraints */

   do i=1 to 5;
      if i>1 then do;
         _type_='le'; _row_='process'||put(_i_-1,1.);
      end;
      else            _row_='object';
      _col_=product; _coef_=process[i];
      output;
   end;
run;

proc print data=model;
run;

/***************************************************************

                  Model Building:  PROC NETFLOW

 ***************************************************************/

data nodes;
   format node $10. ;
   input node $ supdem;
   datalines;
customer_1   -100
customer_2   -200
customer_3    -50
factory_1     500
factory_2     500
;

data network;
   format from $12. to $12.;
   input from $ to $ cost ;
   datalines;
factory_1     warehouse_1  10
factory_2     warehouse_1   5
factory_1     warehouse_2   7
factory_2     warehouse_2   9
warehouse_1   customer_1    3
warehouse_1   customer_2    4
warehouse_1   customer_3    4
warehouse_2   customer_1    5
warehouse_2   customer_2    5
warehouse_2   customer_3    6
;

proc netflow arcout=arc_sav
             arcdata=network nodedata=nodes;
   node node;      /* node data set information */
   supdem supdem;
   tail from;      /* arc data set information */
   head to;
   cost cost;
run;

proc print;
   var from to cost _capac_ _lo_ _supply_ _demand_
       _flow_ _fcost_ _rcost_;
   sum _fcost_;
run;

/***************************************************************

                  Matrix Generation

 ***************************************************************/

data material;
   format descpt $20.;
   input descpt $ cost supply;
   datalines;
silk_material             .21   25.8
polyester_material        .6    22.0
cotton_material           .9    13.6
;

data tie;
   format descpt $20.;
   input descpt $ price contract demand;
   datalines;
all_silk                  6.70    6.0    7.00
all_polyester             3.55   10.0   14.00
poly_cotton_blend         4.31   13.0   16.00
cotton_poly_blend         4.81    6.0    8.50
;

data manfg;
   format descpt $20.;
   input descpt $ silk poly cotton;
   datalines;
all_silk                   100     0      0
all_polyester                0   100      0
poly_cotton_blend            0    50     50
cotton_poly_blend            0    30     70
;

data model;
   array  raw_mat {3} $ 20 ;
   array  raw_comp {3} silk poly cotton;
   length _type_ $ 8  _col_ $ 20  _row_ $ 20 _coef_ 8 ;
   keep   _type_      _col_       _row_      _coef_ ;

   /* define the objective, lower, and upper bound rows */

   _row_='profit'; _type_='max';     output;
   _row_='lower';  _type_='lowerbd'; output;
   _row_='upper';  _type_='upperbd'; output;
   _type_=' ';

   /* the object and upper rows for the raw materials */

   do i=1 to 3;
      set material;
      raw_mat[i]=descpt;  _col_=descpt;
      _row_='profit';    _coef_=-cost;  output;
      _row_='upper';     _coef_=supply; output;
   end;

   /* the object, upper, and lower rows for the products */

   do i=1 to 4;
      set tie;
      _col_=descpt;
      _row_='profit'; _coef_=price;    output;
      _row_='lower';  _coef_=contract; output;
      _row_='upper';  _coef_=demand;   output;
   end;

   /* the coefficient matrix for manufacturing */

   _type_='eq';
   do i=1 to 4;          /* loop for each raw material */
      set manfg;
      do j=1 to 3;       /* loop for each product      */

         _col_=descpt;   /* % of material in product   */
         _row_  = raw_mat[j];
         _coef_ = raw_comp[j]/100;
         output;

         _col_  = raw_mat[j];  _coef_ = -1;
         output;

         /* the right-hand side */

         if i=1 then do;
            _col_='_RHS_';
            _coef_=0;
            output;
         end;
      end;
      _type_='  ';
   end;
   stop;
run;

proc lp sparsedata primalout=solution;

proc print;
      id _var_;
      var _lbound_--_r_cost_;
run;


/***************************************************************

                  Exploiting Model Structure

 ***************************************************************/

data network;
   format from $12. to $12.;
   input  from $ to $ cost ;
   datalines;
factory_1    warehouse_1  10
factory_2    warehouse_1   5
factory_1    warehouse_2   7
factory_2    warehouse_2   9
warehouse_1  customer_1   3
warehouse_1  customer_2   4
warehouse_1  customer_3   4
warehouse_2  customer_1   5
warehouse_2  customer_2   5
warehouse_2  customer_3   6
;

data nodes;
   format node $12. ;
   input node $  supdem;
   datalines;
customer_1   -100
customer_2   -200
customer_3    -50
factory_1     500
factory_2     500
;

data side_con;
   format _type_ $8. _row_ $8. _col_ $21. ;
   input  _type_  _row_  _col_  _coef_ ;
   datalines;
eq       balance   .                         .
.        balance  factory_1_warehouse_1      1
.        balance  factory_1_warehouse_2      1
.        balance  factory_2_warehouse_1     -1
.        balance  factory_2_warehouse_2     -1
.        balance  diff                      -1
lo       lowerbd  diff                    -100
up       upperbd  diff                     100
;

proc netflow
   conout=con_sav
   arcdata=network nodedata=nodes condata=side_con
   sparsecondata ;
   node node;
   supdem supdem;
   tail from;
   head to;
   cost cost;
run;

proc print;
   var from to _name_ cost _capac_ _lo_ _supply_ _demand_
       _flow_ _fcost_ _rcost_;
   sum _fcost_;
run;

/***************************************************************

                  Report Writing: The DATA Step

 ***************************************************************/

data product(keep= _var_ _value_ _price_ revenue)
     material(keep=_var_ _value_ _price_ cost);
   set solution;
   if _price_>0 then do;
      revenue=_price_*_value_; output product;
   end;
   else if _price_<0 then do;
      _price_=-_price_;
      cost = _price_*_value_; output material;
   end;
run;

/* display the product report */

proc print data=product;
   id _var_;
   var _value_ _price_ revenue ;
   sum revenue;
   title 'Revenue Generated from Tie Sales';
run;

/* display the materials report */

proc print data=material;
   id _var_;
   var _value_ _price_ cost;
   sum cost;
   title 'Cost of Raw Materials';
run;

/***************************************************************

          Report Writing: Other Reporting Procedures

 ***************************************************************/

title;
proc gchart data=con_sav;
   hbar from / sumvar=_flow_;
run;

proc gchart data=product;
   pie _var_ / sumvar=revenue;
title h=2.5 'Projected Tie Sales Revenue';
run;