Category: Program

Program 4.2

/***********************************************************************************
* This program is taken from the following book. If using please cite it as:           *
* Emrouznejad, A. and W. Ho (2012). Applied Operations Research with SAS, *
* CRC Press: Taylor Francis Ltd, ISBN: 9781439841303.                                               *
* For details please visit: http://www.sas-or.com.                                                                *
************************************************************************************/

* A SAS procedure for Activity-on-Node representation of the project with uncertainty ;
option nodate;
%let _title=’Example 4.2. A project network: Activity-On-Node Format: employs three probabilistic time estimates for each activity’;
%let _data=’c:/sasor/Data4_2.txt’;
%let _activity=task;
%let _duration=days;

* The data handling macro;
%macro data;
* Import text tab delimited data file to SAS data file;
proc import
datafile=&_data
out=dpert
dbms=tab
replace;
getnames=yes;
run;

data dpert;
set dpert;
days=(Opti+4*most+pessi)/6;
variance=((Opti-pessi)/6)**2;
run;
%mend data;

* The model building macro;
%macro model;
proc cpm
out=pertout;
activity &_activity;
duration &_duration;
successor succ1 succ2 succ3;
run;
%put &_ORCPM_;
%mend model;

* The report writing macro;
%macro report;

data pertout1 ;
merge dpert pertout;
by task;
run;

data pertout2 (where=(T_float=0));
merge dpert pertout;
by task;
run;

title &_title;
proc print
data =pertout1 ;
run;

proc print
data =pertout2 ;
sum T_float;
sum days;
sum variance;
run;
%mend report;

%macro orpert;
%data;
%model;
%report;
%mend orpert;

%orpert;


/****************************************************************************
******************************END of the program*****************************
****************************************************************************/

Permanent link to this article: http://sas-or.com/book/program-4-2

Program 5.1

/***********************************************************************************
* This program is taken from the following book. If using please cite it as:           *
* Emrouznejad, A. and W. Ho (2012). Applied Operations Research with SAS, *
* CRC Press: Taylor Francis Ltd, ISBN: 9781439841303.                                               *
* For details please visit: http://www.sas-or.com.                                                                *
************************************************************************************/


* SAS macro for assembly line balancing problem;
%let _title=’Example 5.1. A project network using PROC OPTMODEL, Assembly line balancing problem’;
%let dataalb=’c:/sasor/Data5_1.txt’;
%let _activity=task;
%let _duration=time;
%let _earliest =Ei;
%let _latest =Li;
%let _nTask=8;
%let _nWork=5;
%let _CycleT=3.7;
%let _outdual=outdual ;
%let _outprimal=outprimal ;
%let _outtable=outtable;
option nodate;


* The data handling macro;
%macro data;
* Import text tab delimited data file to SAS data file;
proc import
datafile=&dataalb
out=dataalb
dbms=tab
replace;
getnames=yes;
run;


data dataalb2 (drop= i);
set dataalb;
array W(&_nWork);
do i=1 to &_nWork;
if Ei<=i<=Li then w(i)=1; else w(i)=0;
end;
run;
%mend data;


* The model building macro;
%macro model;
* Starting OPTMODEL Procedure;
proc optmodel;
* Define sets;
set TASKS=1..&_nTask;
set WORKS=1..&_nWork;


* Define variables;
var A{WORKS} binary >=0;
var x{TASKS,WORKS} binary >=0 ;
var z;


* Define parameters;
number Time{TASKS};
number EL{TASKS,WORKS};
number Succ1{TASKS};
number Succ2{TASKS};
number Succ3{TASKS};


* Load time (duration of each task);
read data dataalb2
into [_N_]
Time[_N_]=col(‘time’);


* Load EL (Earliest/Latest workstations to which the tasks can be assigned);
read data dataalb2
into [_N_]
{i in WORKS} ;


* Load Succ1 (First Immediate Successor);
read data dataalb2
into [_N_]
Succ1[_N_]=col(‘Succ1’);


* Load Succ2 (Second Immediate Successor);
read data dataalb2
into [_N_]
Succ2[_N_]=col(‘Succ2’);


* Load Succ3 (Third Immediate Successor);
read data dataalb2
into [_N_]
Succ3[_N_]=col(‘Succ3’);


* Define objective function ;
min obj = z;


* Define constrains;
con Objective: z= sum{i in WORKS} A[i];


con assignment_one_workstation {j in TASKS}: sum{i in WORKS} EL[j,i]*x[j,i]=1;


con cycle_time {i in WORKS}: sum{j in TASKS} EL[j,i]*Time[j]*x[j,i]<=&_CycleT;


con precedence1 {j in TASKS: succ1[j]>0}: sum{i in WORKS} i*EL[j,i]*x[j,i]-sum{i in WORKS} i*EL[succ1[j],i]*x[succ1[j],i]<=0;

con precedence2 {j in TASKS: succ2[j]>0}: sum{i in WORKS} i*EL[j,i]*x[j,i]-sum{i in WORKS} i*EL[succ2[j],i]*x[succ2[j],i]<=0;

con precedence3 {j in TASKS: succ3[j]>0}: sum{i in WORKS} i*EL[j,i]*x[j,i]-sum{i in WORKS} i*EL[succ3[j],i]*x[succ3[j],i]<=0;

con workstation {i in WORKS}: sum{j in TASKS} EL[j,i]*x[j,i]-sum{j in TASKS} EL[j,i]*A[i]<=0;

con utilize_earlier {i1 in WORKS, i2 in WORKS: i2>i1}: A[i2]-A[i1]<=0;

expand;
* Solve the model;
solve with MILP;

%put &_OROPTMODEL_;
* Create optimum values in a SAS dataset ‘optimout’;
create data optimout
from [TASKS WORKS]
={j in TASKS, i in WORKS}
amount=x;

*End of PROC OPTMODE;
quit;
%mend model;

* The report writing macro;
%macro report;
* report the results in a tabulated form;

proc tabulate data=optimout;
title &_title;
class TASKS WORKS ;
var amount;
table TASKS =” TASKS”,
WORKS*amount*sum
/ BOX=’Assigning Task to Workstation’ ;
run;
%mend report;

* Assembly line problem;
%macro oralbp;
%data;
%model;
%report;
%mend oralbp;

%oralbp;


/****************************************************************************
******************************END of the program*****************************
****************************************************************************/

Permanent link to this article: http://sas-or.com/book/program-5-1

Program 6.1

/***********************************************************************************
* This program is taken from the following book. If using please cite it as:           *
* Emrouznejad, A. and W. Ho (2012). Applied Operations Research with SAS, *
* CRC Press: Taylor Francis Ltd, ISBN: 9781439841303.                                               *
* For details please visit: http://www.sas-or.com.                                                                *
************************************************************************************/


* SAS procedure for traveling salesman problem;
%let _data=’c:/sasor/data6_1.txt’;
%let _travelP=city;
%let _title=’Example 6.1: Travelling salesman problem’;
option nodate;

* The data handling macro;
%macro data;
* Import text tab delimited data file to SAS data file;

proc import
datafile=&_data
out=dtsp1
dbms=tab
replace;
getnames=yes;
run;

data dtsp(drop=&_travelP);
set dtsp1;
run;
%mend data;

* The model building macro;
%macro model;

proc ga Matrix1 = dtsp;
call SetEncoding (‘S6’);
call SetObj(‘TSP’,0,’distances’,Matrix1);
call SetCross(‘Order’);
call Initialize(‘DEFAULT’, 6);
call ContinueFor(85);
run;
%mend model;

* The report writing macro;
%macro report;
title &_title;
proc print;
run;
%mend report;

* A SAS macro for traveling salesman problem;
%macro ortsp;
%data;
%model;
%report;
%mend ortsp;


%ortsp;


/****************************************************************************
******************************END of the program*****************************
****************************************************************************/

Permanent link to this article: http://sas-or.com/book/program-6-1

Program 7.1

/***********************************************************************************
* This program is taken from the following book. If using please cite it as:           *
* Emrouznejad, A. and W. Ho (2012). Applied Operations Research with SAS, *
* CRC Press: Taylor Francis Ltd, ISBN: 9781439841303.                                               *
* For details please visit: http://www.sas-or.com.                                                                *
************************************************************************************/


* Using PROC OPTMODEL for Printed Circuit Board (PCB) Assembly Line Assignment Problem;
option nodate ;
%let _title=’Example 7.1: A line assignment problem using PROC OPTMODEL’;
%let _dataC=’c:/sasor/Data7_1_C.txt’;
%let _dataT=’c:/sasor/Data7_1_T.txt’;
%let _nLine=4;
%let _nBoard=5;
%let _optimout=mysolution;

* The data handling macro;
%macro data;
* Import text tab delimited data file to SAS data file;

proc import
datafile=&_dataC
out=dataC
dbms=tab
replace;
getnames=yes;
run;

proc import
datafile=&_dataT
out=dataT
dbms=tab
replace;
getnames=yes;
run;
%mend data;

%macro model;
* Starting OPTMODEL Procedure;
proc optmodel;
* Define sets;
set LINES=1..&_nLine;
set BOARDS=1..&_nBoard;

* Define variables;
var X{LINES, BOARDS} integer >=0;

* Define parameters;
number cost{LINES, BOARDS};
number time{LINES, BOARDS};
number s{LINES};
number d{BOARDS};

* Load the time matrix;
read data dataT
into [_N_]
{j in BOARDS} <time[_N_,j]=col(‘board’||j)>;

* Load the cost matrix;
read data dataC (where =(line ne “demand”))
into [_N_]
{j in BOARDS} <cost[_N_,j]=col(‘board’||j)>;

* Load the demand array;
read data dataC (where =(line eq “demand”))
into
{j in BOARDS} <d[j]=col(‘board’||j)>;

* Load the supply array;
read data dataC (where= (line ne “demand”))
into [_N_] s[_N_]=col(“supply”);

* Define objective function;
min obj = sum{i in LINES, j in BOARDS} cost[i,j]*X[i,j];

* Define constrains;
con supply_line{i in LINES}:
sum{j in BOARDS} time[i,j]*X[i,j] <=s[i];

con demand_board{j in BOARDS}:
sum{i in LINES} X[i,j] =d[j];

* Solve the model;
solve with milp;
%put &_OROPTMODEL_;

* Exdpand the model;
expand;

* Create optimum values in a SAS dataset ‘optimout’;
create data &_optimout
from [LINES BOARDS]
={i in LINES, j in BOARDS: x[i,j]^=0}
amount=x ;

* Report the results in a tabulated form;
proc tabulate data=&_optimout;
title &_title;
class LINES BOARDS ;
var amount;
table LINES =” from City”,
BOARDS*amount*sum
/ BOX=’Assigning of Board to Line’;
run;

* End of OPTMODEL Procedure;
quit;
%mend model;

%macro report;
* Report the results in a tabulated form;

proc tabulate data=&_optimout;
title &_title;
class LINES BOARDS ;
var amount;
table LINES =” Line”,
BOARDS*amount*sum
/ BOX=’Assigning of Boards to Lines’ ;
run;
%mend report;

%macro orala;
%data;
%model;
%report;
%mend orala;

%orala;


/****************************************************************************
******************************END of the program*****************************
****************************************************************************/

Permanent link to this article: http://sas-or.com/book/program-7-1

Program 7.2

/***********************************************************************************
* This program is taken from the following book. If using please cite it as:           *
* Emrouznejad, A. and W. Ho (2012). Applied Operations Research with SAS, *
* CRC Press: Taylor Francis Ltd, ISBN: 9781439841303.                                               *
* For details please visit: http://www.sas-or.com.                                                                *
************************************************************************************/


* Using PROC OPTMODEL for Printed Circuit Board (PCB) Assembly Line Assignment Problem;
option nodate ;
%let _title=’Example 7.2: SMT placement machines or the component allocation problem using PROC OPTMODEL’;
%let _data=’c:/sasor/Data7_2.txt’;
%let _nMachine=3;
%let _nCompon=7;
%let _optimout=mysolution;

* The data handling macro;
%macro data;
* Import text tab delimited data file to SAS data file;
proc import
datafile=&_data
out=data12
dbms=tab
replace;
getnames=yes;
run;
%mend data;

%macro model;
* Starting OPTMODEL Procedure;
proc optmodel;
* Define sets;
set MACHINES=1..&_nMachine;
set COMPONENTS=1..&_nCompon;

* Define variables;
var X{MACHINES, COMPONENTS} integer >=0;
var T;

* Define parameters;
number time{MACHINES, COMPONENTS};
number s{MACHINES};
number c{COMPONENTS};

* Load the time matrix;
read data data12 (where =(machine ne “demand”))
into [_N_]
{j in COMPONENTS} ;

* Load the component array;
read data data12 (where =(machine eq “demand”))
into
{j in COMPONENTS} ;

print c;
* Load the setup-time array;
read data data12 (where= (machine ne “demand”))
into [_N_] s[_N_]=col(“setup”);

* Define objective function;
min obj = T;

* Define constrains;

con Total{i in MACHINES}:
T- s[i] – sum{j in COMPONENTS: time[i,j] ne 1E10} time[i,j]*X[i,j] >=0;

con compon{j in COMPONENTS: j ne 0}: sum{i in MACHINES} X[i,j] =c[j];

con zero{i in MACHINES, j in COMPONENTS : time[i,j]=1E10}: x[i,j]=0;

* Solve the model;
solve with milp;
%put &_OROPTMODEL_;

expand;
* Create optimum values in a SAS dataset ‘optimout’;
create data &_optimout
from [MACHINES COMPONENTS]
={i in MACHINES, j in COMPONENTS: x[i,j]^=0}
amount=x ;

* End of OPTMODEL Procedure;
quit;

%mend model;

%macro report;
* Report the results in a tabulated form;
proc tabulate data=&_optimout;
title &_title;
class MACHINES COMPONENTS ;
var amount;
table MACHINES =” Machine”,
COMPONENTS*amount*sum
/ BOX=’Machines or the Component Allocation Problem’;
run;
%mend report;

%macro orcap;
%data;
%model;
%report;
%mend orcap;

%orcap;


/****************************************************************************
******************************END of the program*****************************
****************************************************************************/

Permanent link to this article: http://sas-or.com/book/program-7-2

Program 7.3

/***********************************************************************************
* This program is taken from the following book. If using please cite it as:           *
* Emrouznejad, A. and W. Ho (2012). Applied Operations Research with SAS, *
* CRC Press: Taylor Francis Ltd, ISBN: 9781439841303.                                               *
* For details please visit: http://www.sas-or.com.                                                                *
************************************************************************************/

* A SAS procedure for SMT placement machines or the component sequencing problem;
%let _title=’Example 7.3: SMT placement machines or the component sequencing problem’;
%let _dataC=’c:/sasor/Data7_3_C.txt’;
%let _dataF=’c:/sasor/Data7_3_F.txt’;
%let _nFeeder=4;
%let _nCompon=4;
%let _outprimal= outprimal;
%let _outdual= outdual;
%let _outtable= outtable;
option nodate;

* The data handling macro;
%macro data;
* Import text tab delimited data file to SAS data file;

proc import
datafile=&_dataC
out=dataC
dbms=tab
replace;
getnames=yes;
run;

proc import
datafile=&_dataF
out=dataF
dbms=tab
replace;
getnames=yes;
run;
%mend data;

* The model building macro;
%macro model;
* Starting OPTMODEL Procedure;
proc optmodel;
* Define sets;
set COMP=0..&_nCompon;
set Feed=0..&_nFeeder;

* Define variables;
var u{COMP} integer >=0;
var x{COMP,COMP} binary >=0 ;
var z;

* Define parameters;
number d{COMP,COMP};
number cx {COMP};
number cy {COMP};
number type {COMP};
number fx {FEED};
number fy {FEED};
number randfeeder {FEED};
number d1;
number d2;
number Distance{COMP,FEED};
number ds2{COMP,FEED};

* Load component data;
read data Datac into [_N_] type[_N_]=col(‘type’);
read data Datac into [_N_] cx[_N_]=col(‘cx’);
read data Datac into [_N_] cy[_N_]=col(‘cy’);

* Load feeder data;
read data Dataf into [_N_] fx[_N_]=col(‘fx’);
read data Dataf into [_N_] fy[_N_]=col(‘fy’);
read data Dataf into [_N_] randfeeder[_N_]=col(‘randfeeder’);

cx[0]=0; cy[0]=0; fx[0]=0; fy[0]=0;

for {i in FEED, j in COMP}
do;
if (i ne 0 & j ne 0)
then do; d1=(cx[i]-fx[j])**2; d2=(cy[i]-fy[j])**2; end;
else if (i=0 & j=0)
then do; d1=0; d2=0; end;
else if (i=0)
then do; d1=(cx[j]**2); d2=(cy[j]**2); end;
else if (j=0)
then do; d1=(fx[i]**2); d2=(fy[i]**2); end;

Distance[i,j]=round(sqrt( d1+d2),0.000001);
end;
print Distance;

for {i in FEED, j in COMP}
do;
if (i=j) then ds2[i,j]=0;
else if i=0 then ds2[j,i]=Distance[randfeeder[j],0]+Distance[j,randfeeder[j]];
else if j=0 then ds2[j,i]=Distance[j,i];
else ds2[j,i]=Distance[j,randfeeder[j]]+Distance[i,randfeeder[j]];
end;

* Define objective function ;
min obj = z;

* Define constrains;
con Objective: z= sum{i in FEED, j in COMP} ds2[j,i]*x[i,j];

con component_immediately_before1 {i in FEED}: sum{j in COMP: i ne j} x[j,i]=1;

con component_immediately_before2 {j in COMP}: sum{i in FEED: i ne j} x[j,i]=1;

con subtour_elimination {i in FEED, j in COMP : i ne 0 & j ne 0 & i ne j}: u[i]-u[j] + &_nCompon * x[i,j]<=&_nCompon-1;

solve with MILP;

expand;

%put &_OROPTMODEL_;

* Create optimum values of x in a SAS dataset ‘optimout1’;
create data optimout1
from [COMP FEED]
={i in COMP, j in FEED: x[i,j] ne 0}
amount=x ;

* Create optimum values of u in a SAS dataset ‘optimout2’;
create data optimout2
from [COMP]
={i in COMP: u[i]}
amount=u ;
*End of PROC OPTMODE;

quit;
%mend model;
* The report writing macro;
%macro report;
title &_title;

proc tabulate data=optimout1;
title &_title;
class COMP FEED ;
var amount;
table COMP =”COMP”,
FEED*amount*sum
/ BOX=’Component sequencing’;
run;

proc tabulate data=optimout2;
title &_title;
class COMP ;
var amount;
table COMP =”COMP”,
amount*sum
/ BOX=’Component sequencing’;
run;

%mend report;


* A SAS macro for SMT placement machines or the component sequencing problem;
%macro orcsp;
%data;
%model;
%report;
%mend orcsp;


%orcsp;


/****************************************************************************
******************************END of the program*****************************
****************************************************************************/

Permanent link to this article: http://sas-or.com/book/program-7-3

Program 8.1

/***********************************************************************************
* This program is taken from the following book. If using please cite it as:           *
* Emrouznejad, A. and W. Ho (2012). Applied Operations Research with SAS, *
* CRC Press: Taylor Francis Ltd, ISBN: 9781439841303.                                               *
* For details please visit: http://www.sas-or.com.                                                                *
************************************************************************************/


* A SAS macro for analytic hierarchy process (AHP);
option nodate;
%let _Title=’Example 8.1. A SAS macro for analytic hierarchy process (AHP)’;
%let _dataC=’c:/sasor/data8_1_C.txt’;
%let _dataA=’c:/sasor/data8_1_A.txt’;
%let _nCriteria=5;
%let _nAlternative=4;
options linesize=100;

* A macro to import data;
%macro data;
* To import Criteria Pair;
proc import
datafile=&_dataC
out=dataC
dbms=tab
replace;
getnames=no;
run;

* To import Alternative Pair;
proc import
datafile=&_dataA
out=dataA
dbms=tab
replace;
getnames=no;
run;

data dataA(rename=(VAR1=Criteria VAR2=Alternative));
set dataA;
run;
%mend data;

*A macro for calculating AHP measures including Consistency;
%macro Consist(nDim, LamArray, AverageArray,PrArray, Lambda, CI, CR, RI,RIr);

do i1=1 to &nDim;
&LamArray(i1)=0;
do j1=1 to &nDim;
&LamArray(i1)=&LamArray(i1)+&AverageArray(j1)*&PrArray(i1,j1);
end;
end;

&Lambda=0;
do i1=1 to &nDim;
&Lambda=&Lambda+&LamArray(i1)/&AverageArray(i1);
end;

&Lambda=&Lambda/&nDim;
&CI=(&Lambda-&nDim)/(&nDim-1);
RI=&RIr(&nDim);
&CR=&CI/RI;
%mend Consist;

* A macro for calculating average priorities;
%macro Priority (MyMatrix,myDimension,AverageMyMatrix,DivideMyMatrix,SumMyMatrix);
do j=1 to &myDimension;
&SumMyMatrix(j)=0;
do i=1 to &myDimension;
&SumMyMatrix(j)=&SumMyMatrix(j)+&MyMatrix(i,j);
end;
end;

do i=1 to &myDimension;
do j=1 to &myDimension;
&DivideMyMatrix(i,j)=&MyMatrix(i,j)/&SumMyMatrix(j);
end;
end;

do i=1 to &myDimension;
&AverageMyMatrix(i)=0;
do j=1 to &myDimension;
&AverageMyMatrix(i)=&AverageMyMatrix(i)+&DivideMyMatrix(i,j);
end;
&AverageMyMatrix(i)=&AverageMyMatrix(i)/&myDimension;
end;
%mend Priority;

* A macro for writing priority matrix;
%macro report1 (Name,nDim,MyName,MyMatrix,AverageMyMatrix,Lambda, CI, CR, RI);
File Print;
title &_Title;
put // ” ” &Name @@;
do j1= 1 to &nDim;
c=9*j1+3;
put @c &MyName(j1) @@ ;
end;

c=c+9; put @c “Priori” @@ ;
c=c+9; put @c “LamMax” @@ ;
c=c+9; put @c “CI” @@ ;
c=c+9; put @c “RI” @@ ;
c=c+9; put @c “CR”;

do j1= 1 to &nDim+5;
c=9*j1+1; put @c ” ——– ” @@ ;
end;

do i1= 1 to &nDim;
put / ” ” &MyName(i1) @@;
do j1= 1 to &nDim;
c=9*j1+1; put @c &MyMatrix(i1,j1) 8.4 @@;
end;
c=c+10; put @c &AverageMyMatrix(i1) 8.4 @@;
end;

put;
do j1= 1 to &nDim+5;
c=9*j1+1; put @c ” ——– ” @@ ;
end;

put ; c=9*&nDim+10;put @c “Total ===>” @@;

c=&nDim*9+20; put @c Lambda 8.4 @@ ;
c=c+9; put @c CI 8.4 @@ ;
c=c+9; put @c RI 8.4 @@ ;
c=c+9; put @c CR 8.4 @@ ;
%mend report1;

* A macro for writing AHP resluts;
%macro report2 (nDimA,nDimC,RankAarray,AveragePAarray,AveragePCarray);
do j=1 to &nDimA;
RankAarray(j)=0;
do i=1 to &nDimC;
RankAarray(j)=RankAarray(j)+AveragePAarray(i,j)*AveragePCarray(i);
end;
end;

put // @10 “————————–” ;
put @10 “AHP Result “;
put @10 &_Title;
put @10 “————————–” ;
put @10 “Alternative” @25 “Priority” ;
put @10 “———–” @25 “———” ;

do j1= 1 to &nDimA;
put @10 NAarray(j1) @@ ;
put @25 RankAarray(j1) 8.4 ;
end;
put @10 “————————–” ;
%mend report2;

* A macro for AHP calculation;
%macro model;

data _NULL_;
array NCarray(&_nCriteria) $ NC1-NC&_nCriteria;
array NAarray(&_nAlternative) $ NA1-NA&_nAlternative;

array PCarray(&_nCriteria,&_nCriteria) ;
array PAarray(&_nCriteria,&_nAlternative,&_nAlternative) ;

array TempPAarray(&_nAlternative,&_nAlternative) ;
array TempAeragePAarray(&_nAlternative) ;

array AveragePAarray(&_nCriteria,&_nAlternative) ;
array AveragePCarray(&_nCriteria) ;

array DividePCarray(&_nCriteria,&_nCriteria) ;
array SumPCarray(&_nCriteria) ;

array DividePAarray(&_nAlternative,&_nAlternative) ;
array SumPAarray(&_nAlternative) ;

array RankAarray(&_nAlternative) ;
array LambdaCArray(&_nCriteria);
array LambdaAArray(&_nAlternative);

array RIr(10) RIr1-RIr10;
RIr3=0.58;
RIr4=0.90;
RIr5=1.12;
RIr6=1.24;
RIr7=1.32;
RIr8=1.41;

do i=1 to &_nCriteria;
Link ReaddataC;
NCarray(i)=VAR1;
%do j=2 %to &_nCriteria+1;
PCarray(i,&j-1)=VAR&j;
%end;
end;

do i=1 to &_nCriteria;
do j=1 to &_nAlternative;
Link ReaddataA;
NAarray(j)=Alternative;
%do k=3 %to &_nAlternative+2;
PAarray(i,j,&k-2)=VAR&k;
%end;
end;
end;

do i=1 to &_nCriteria;
do j=1 to &_nCriteria;
if PCarray(i,j)=. then PCarray(i,j)=1/PCarray(j,i);
end;
end;

do i=1 to &_nAlternative;
RankAarray(i)=0;
end;

do i=1 to &_nCriteria;
do j=1 to &_nAlternative;
do k=1 to &_nAlternative;
if PAarray(i,j,k)=. then PAarray(i,j,k)=1/PAarray(i,k,j);
end;
end;
end;

%Priority (PCarray,&_nCriteria,AveragePCarray,DividePCarray,SumPCarray);
%Consist (&_nCriteria,LambdaCArray,AveragePCarray,PCarray,Lambda, CI, CR, RI,RIr);
%report1 (“Criteria”, &_nCriteria,NCarray,PCarray,AveragePCarray,Lambda, CI, CR, RI);

do m=1 to &_nCriteria;
do j=1 to &_nAlternative;
do k=1 to &_nAlternative;
TempPAarray(j,k)=PAarray(m,j,k);
end;
end;
%Priority (TempPAarray,&_nAlternative,TempAeragePAarray,DividePAarray,SumPAarray);
do k=1 to &_nAlternative;
AveragePAarray(m,k)=TempAeragePAarray(k);
end;
%Consist (&_nAlternative,LambdaAArray,TempAeragePAarray,TempPAarray,Lambda, CI, CR, RI,RIr);
%report1 (NCarray (m),&_nAlternative,NAarray,TempPAarray,TempAeragePAarray,Lambda, CI, CR, RI);
end;

%report2 (&_nAlternative,&_nCriteria,RankAarray,AveragePAarray,AveragePCarray);

ReaddataC: set dataC; return;
ReaddataA: set dataA; return;
run;
%mend model;

* A SAS macro for analytic hierarchy process problem;
%macro orahp;
%data;
%model;
%mend orahp;

%orahp;


/****************************************************************************
******************************END of the program*****************************
****************************************************************************/

Permanent link to this article: http://sas-or.com/book/program-8-1

Program 8.2

/***********************************************************************************
* This program is taken from the following book. If using please cite it as:           *
* Emrouznejad, A. and W. Ho (2012). Applied Operations Research with SAS, *
* CRC Press: Taylor Francis Ltd, ISBN: 9781439841303.                                               *
* For details please visit: http://www.sas-or.com.                                                                *
************************************************************************************/


* A SAS procedure for MCDM;
options nodate;
%let _data=’c:\sasor\MCDM.txt’;
%let _title=’Example 8.2: An example of MCDM’;
%let _dataMCDM=’c:/sasor/Data8_2.txt’;
%let _nWareh=4;
%let _nCustomer=7;
%let _TotalCost=425000;
%let _outprimal=outprimal;
%let _outdual=outdual;
%let _outtable=outtable;
%let _myLarge=100000;

* The data handling macro;
%macro data;
* Import text tab delimited data file to SAS data file;
proc import
datafile=&_dataMCDM
out=dataC
dbms=tab
replace;
getnames=yes;
run;
%mend data;

* The model building macro;
%macro model (_stage);
* Starting OPTMODEL Procedure;
proc optmodel;

* Define sets;
set WAREHOUSE=1..&_nWareh;
set CUSTOMER=1..&_nCustomer;
set WAREHOUSE_CUSTOMER_TWO= 1..&_nCustomer+2*&_nWareh+2;
set Priority = 1..&_nWareh+3;
set stage ;
stage = {&_stage};

* Define variables;
var X{WAREHOUSE, CUSTOMER} integer >=0;
var u {WAREHOUSE} binary ;
var v {WAREHOUSE} binary ;
var w {WAREHOUSE} binary ;
var dPlus {WAREHOUSE_CUSTOMER_TWO} >=0 ;
var dNeg {WAREHOUSE_CUSTOMER_TWO} >=0 ;
var z{Priority} ;

* Define parameters;
number dc{WAREHOUSE, CUSTOMER};
number demand{CUSTOMER};
number QQ{WAREHOUSE};
number q{WAREHOUSE};
number hc{WAREHOUSE};
number fc{WAREHOUSE};
number pc{WAREHOUSE};
number WarehPriority{WAREHOUSE};
number P{Priority,Priority};

for {i in Priority , j in Priority: i ne j} P[i,j]=0;
for {i in Priority , j in Priority: i eq j} P[i,j]=1;

* Load the Unit delivery cost matrix;
read data Datac (where =(Wareh ne “demand”))
into [_N_]
{j in CUSTOMER} <dc[_N_,j]=col(‘Cust’||j)>;

* Load the demand array;
read data Datac (where =(Wareh eq “demand”))
into
{j in CUSTOMER} <demand[j]=col(‘Cust’||j)>;

* Load the Maximum throughput of warehouse array;
read data Datac (where =(Wareh ne “demand”))
into [_N_]
QQ[_N_]=col(‘QQi’);

* Load the Minimum throughput of warehouse array;
read data Datac (where =(Wareh ne “demand”))
into [_N_]
q[_N_]=col(‘qi’);

* Load the Unit holding cost array;
read data Datac (where =(Wareh ne “demand”))
into [_N_]
hc[_N_]=col(‘hci’);

* Load the Fixed cost array;
read data Datac (where =(Wareh ne “demand”))
into [_N_]
fc[_N_]=col(‘fci’);

* Load the Penalty cost array;
read data Datac (where =(Wareh ne “demand”))
into [_N_]
pc[_N_]=col(‘pci’);

* Load the Warehouse Priority that is obtained from AHP;
read data Datac (where =(Wareh ne “demand”))
into [_N_]
WarehPriority[_N_]=col(‘WarehPriority’);

* Define system constrains;
con sumV: sum{i in WAREHOUSE} v[i] <= &_nWareh;
con Mu {i in WAREHOUSE}: sum{j in CUSTOMER} x[i,j] + &_myLarge * u[i] <= q[i];
con Mv {i in WAREHOUSE}: sum{j in CUSTOMER} x[i,j] – &_myLarge * v[i] <= 0;
con wuv {i in WAREHOUSE}: w[i] – u[i] – v[i] = -1;
* Define Resource constraints;

* Priority 1 (P1);
con P1_1{ s in Priority, i in WAREHOUSE: s >= 1}: sum{j in CUSTOMER} x[i,j] – dPlus[i] + dNeg[i] <= QQ[i]; con P1_2{ s in Priority, j in CUSTOMER : s >= 1}: sum{i in WAREHOUSE} x[i,j] – dPlus[j+&_nWareh] + dNeg[j+&_nWareh] <= demand[j];

* Priority 2 (P2);
con P2{s in Priority : s >= 2}: sum{i in WAREHOUSE,j in CUSTOMER} (hc[i]+dc[i,j])*x[i,j] + sum{i in WAREHOUSE} fc[i]*v[i] – dPlus[&_nCustomer+&_nWareh+1] + dNeg[&_nCustomer+&_nWareh+1] <= &_TotalCost;

* Priority 3 (P3);
con P3{s in Priority : s >= 3}: sum{i in WAREHOUSE} pc[i]*w[i] – dPlus[&_nCustomer+&_nWareh+2] + dNeg[&_nCustomer+&_nWareh+2] = 0;

* Define AHP (P4) priority constraints;
con P4{s in Priority, i in WAREHOUSE: s >= i+3}: v[WarehPriority[i]]- dPlus[&_nCustomer+&_nWareh+i+2] + dNeg[&_nCustomer+&_nWareh+i+2]=1;

con z [1] = (sum {k in 1..&_nWareh} dPlus[k] + sum {k in &_nWareh+1..&_nWareh+&_nCustomer} (dPlus[k]+dNeg[k]));
con z [2] = (dPlus[&_nWareh+&_nCustomer+1]);
con z [3] = (dPlus[&_nWareh+&_nCustomer+2]);
con z [4] = (dPlus[&_nWareh+&_nCustomer+3]+ dNeg[&_nWareh+&_nCustomer+3]);
con z [5] = (dPlus[&_nWareh+&_nCustomer+4]+ dNeg[&_nWareh+&_nCustomer+4]);
con z [6] = (dPlus[&_nWareh+&_nCustomer+5]+ dNeg[&_nWareh+&_nCustomer+5]);
con z [7] = (dPlus[&_nWareh+&_nCustomer+6]+ dNeg[&_nWareh+&_nCustomer+6]);
* Define objective function;

* objective function;
min obj = sum {s1 in Priority, s in stage} P[s1 , s ]* z[s1];

solve with MILP; %put &_OROPTMODEL_; expand;

create data _optimout
from [WAREHOUSE CUSTOMER]
={i in WAREHOUSE, j in CUSTOMER}
amount=X ;

quit;
%mend;

* The report writing macro;
%macro report (_stage);
* Report the results in a tabulated form;
title &_title ‘(P=’ &_stage ‘)’;
proc tabulate data=_optimout;
title &_title;
class WAREHOUSE CUSTOMER ;
var amount;
table WAREHOUSE =” WAREHOUSE”,
CUSTOMER*amount*sum
/ BOX=’x[WAREHOUSE& CUSTOMER] ‘ ;
run;
%mend report;

* A SAS macro for multiple criteria decision making problem ;
%macro ormcdm;
%data;
%do i=1 %to &_nWareh+3;
%model(&i);
%report(&i);
%end;
%mend ormcdm;

%ormcdm;


/****************************************************************************
******************************END of the program*****************************
****************************************************************************/
_nCustomer+

Permanent link to this article: http://sas-or.com/book/program-8-2

Program 9.1

/***********************************************************************************
* This program is taken from the following book. If using please cite it as:           *
* Emrouznejad, A. and W. Ho (2012). Applied Operations Research with SAS, *
* CRC Press: Taylor Francis Ltd, ISBN: 9781439841303.                                               *
* For details please visit: http://www.sas-or.com.                                                                *
************************************************************************************/

*An example of OWA problem in SAS;
option nodate ;
%let _title=’Example 9.1: Ordered Weighted Averaging (OWA) Operators and Preference Ranking’;
%let _data=’c:/sasor/Data9_1.txt’;
%let _alpha=0.3;
%let _ncriteria=6;
%let _nalternative=10;
%let _owa1=’c:/sasor/owaOut1.txt’;
%let _owa2=’c:/sasor/owaOut2.txt’;
%let _owaOut1=owaOut1;
%let _owaOut2=owaOut2;

* Import text tab delimited data file to SAS data file;
%macro data;
proc import
datafile=&_data
out=alts
dbms=tab
replace;
getnames=yes;
run;
%mend data;

%macro model;
proc optmodel;
set CRITERIA = 1..&_ncriteria;
set CRITERIA1 = 1..&_ncriteria-1;
set ALTERNATIVE = 1..&_nalternative;
number c{ALTERNATIVE, CRITERIA};
number rankAE{ALTERNATIVE} ;
number rankMIN{ALTERNATIVE} ;
number rankMAX{ALTERNATIVE} ;
number rankMEAN{ALTERNATIVE} ;
number corder{ALTERNATIVE, CRITERIA};
number wMAX{ALTERNATIVE};
number wMIN{ALTERNATIVE};
number wMEAN{ALTERNATIVE};
number ctemp;
number altName{ALTERNATIVE};
number alpha=&_alpha;
number n=&_ncriteria;
var w{CRITERIA} ;
var delta;

read data alts
into [ALTERNATIVE]
{j in CRITERIA} ;

min obj =delta;

con orness: (1/(n-1))* sum{i in CRITERIA} (n-i)*w[i] = alpha;

con wji{i in 1..n, j in i+1..n }:
w[j]-w[i]+delta >= 0;

con wij{i in 1..n, j in i+1..n }:
w[i]-w[j]+delta >= 0;

con swumw:
sum{i in 1..n} w[i]= 1;

solve ;
%report;

quit;
%mend model;

%macro report;
* MAX-OWA;
for {i in CRITERIA}
if i=1 then wMAX[i]=1; else wMAX[i]=0;

* MIN-OWA;
for {i in CRITERIA}
if i=n then wMIN[i]=1; else wMIN[i]=0;

* MEAN-OWA;
for {i in CRITERIA}
wMEAN[i]=1/n;

*Order the criteria;
for {k in ALTERNATIVE}
do;
for {i in CRITERIA}
for {j in CRITERIA}
do;
if c[k,j] do;
ctemp=c[k,i]; c[k,i]=c[k,j];c[k,j]=ctemp;
end;
end;
end;

*Rank by AE-OWA model;
for {k in ALTERNATIVE}
do;
rankAE[k]=0;
for {i in CRITERIA}
rankAE[k]=rankAE[k]+c[k,i]*w[i];
end;

*Rank by MIN-OWA model;
for {k in ALTERNATIVE}
do;
rankMIN[k]=0;
for {i in CRITERIA}
rankMIN[k]=rankMIN[k]+c[k,i]*wMIN[i];
end;

*Rank by MIN-OWA model;
for {k in ALTERNATIVE}
do;
rankMAX[k]=0;
for {i in CRITERIA}
rankMAX[k]=rankMAX[k]+c[k,i]*wMAX[i];
end;

*Rank by MEAN-OWA model;
for {k in ALTERNATIVE}
do;
rankMEAN[k]=0;
for {i in CRITERIA}
rankMEAN[k]=rankMEAN[k]+c[k,i]*wMEAN[i];
end;

* To save the OWA weight in a text file;
file &_owa1;
put ‘Criteria,’ ‘w,’ ‘wMAX,’ ‘wMIN,’ ‘wMEAN’;
for {i in CRITERIA}
do;
put i ‘,’ w[i] ‘,’ wMAX[i] ‘,’ wMIN[i]’,’ wMEAN[i];
end;

* To save the Alternative ranks in a text file;
file &_owa2;
put ‘Alternative,’ ‘rankAE,’ ‘rankMAX,’ ‘rankMIN,’ ‘rankMEAN’;
for {k in ALTERNATIVE}
do;
put k ‘,’ rankAE[k] ‘,’ rankMAX[k] ‘,’ rankMIN[k]’,’ rankMEAN[k];
end;

closefile &_owa1;
closefile &_owa2;

* To save the OWA weight in a SAS dataset;
proc import
datafile=&_owa1
out=&_owaOut1
dbms=csv
replace;
getnames=yes;
run;

proc print; title &_title; run;


* To save the Alternative ranks in a SAS dataset;
proc import
datafile=&_owa2
out=&_owaOut2
dbms=csv
replace;
getnames=yes;
run;
proc print; title &_title; run;

%mend report;

%macro orowa;
%data;
%model;
%mend orwa;

%orowa;


/****************************************************************************
******************************END of the program*****************************
****************************************************************************/

Permanent link to this article: http://sas-or.com/book/program-9-1

Program 9.2

/***********************************************************************************
* This program is taken from the following book. If using please cite it as:           *
* Emrouznejad, A. and W. Ho (2012). Applied Operations Research with SAS, *
* CRC Press: Taylor Francis Ltd, ISBN: 9781439841303.                                               *
* For details please visit: http://www.sas-or.com.                                                                *
************************************************************************************/


* Using PROC OPTMODEL for Efficiency Measurement with Data Envelopment Analysis (DEA);
option nodate ;
%let _title=’Example 9.2: Efficiency Measurement Using Data Envelopment Analysis (DEA)’;
%let _InData=’C:\sasor\Data9_2_In.txt’;
%let _OutData=’C:\sasor\Data9_2_Out.txt’;
%let _nInput=2;
%let _nOutput=3;
%let _nUnits=10;
%let _Orienta=’OUTPUT’; *alternative option is ‘OUTPUT’ for output orientation;
%let _outdea1=EffOutOri;
%let _outdea2=EffInOri;

/*NOTE to Convexity constraints in both models for VRS;*/

* The data handling macro;
%macro data;
* Import text tab delimited input variables to SAS data file;
proc import
datafile=&_InData
out=data17_input
dbms=tab
replace;
getnames=yes;
run;

* Import text tab delimited output variables to SAS data file;
proc import
datafile=&_OutData
out=data17_output
dbms=tab
replace;
getnames=yes;
run;
%mend data;

* A DEA macro for CRS output orientation;
%macro model_outOri (j0);
* Starting OPTMODEL Procedure;
proc optmodel;
* Define sets;
set INPUTS=1..&_nInput;
set OUTPUTS=1..&_nOutput;
set UNITS=1..&_nUnits;

* Define variables;
var L{UNITS} >=0;
var Sin{INPUTS} >=0 ;
var Sout{OUTPUTS} >=0 ;
var h;

* Define parameters;
number Xin{UNITS, INPUTS};
number Yout{UNITS,OUTPUTS};
string DMUS{UNITS};
number eff;
string DMUj0;

* Load unit names;
read data data17_input
into [_N_]
DMUS[_N_]=col(‘dmu’);


* Load matrix of input variables;
read data data17_input
into [_N_]
{i in INPUTS} ;

* Load matrix of output variables;
read data data17_output
into [_N_]
{r in OUTPUTS} ;

* Define objective function ;
max obj = h;

* Define constrains;
con InpCon_outOri{i in INPUTS}:
sum{j in UNITS} L[j]*Xin[j,i] + Sin[i]=Xin[&j0,i];

con OutCon_outOri{r in OUTPUTS}:
sum{j in UNITS} L[j]*Yout[j,r] – Sout[r]=h*Yout[&j0,r];

* Define convexity constraints for VRS models;
con Convexity: sum{j in UNITS} L[j]=1;

* Solve the model;
solve ;

* Save the efficiency scores in a SAS dataset;
eff=1/h.sol;
DMUj0=DMUS[&j0];
create data solj0 from DMUj0 eff;

*End of PROC OPTMODE;
quit;
%mend model_outOri;

* A DEA macro for CRS input orientation;
%macro model_inOri (j0);
* Starting OPTMODEL Procedure;
proc optmodel;
* Define sets;
set INPUTS=1..&_nInput;
set OUTPUTS=1..&_nOutput;
set UNITS=1..&_nUnits;

* Define variables;
var L{UNITS} >=0;
var Sin{INPUTS} >=0 ;
var Sout{OUTPUTS} >=0 ;
var h;

* Define parameters;
number Xin{UNITS, INPUTS};
number Yout{UNITS,OUTPUTS};
string DMUS{UNITS};
number eff;
string DMUj0;

* Load unit names;
read data data17_input
into [_N_]
DMUS[_N_]=col(‘dmu’);

* Load matrix of input variables;
read data data17_input
into [_N_]
{i in INPUTS} ;

* Load matrix of output variables;
read data data17_output
into [_N_]
{r in OUTPUTS} ;

* Define objective function ;
min obj = h;

* Define constrains;
con InpCon_inOri{i in INPUTS}:
sum{j in UNITS} L[j]*Xin[j,i] + Sin[i]=h*Xin[&j0,i];

con OutCon_inOri{r in OUTPUTS}:
sum{j in UNITS} L[j]*Yout[j,r] – Sout[r]=Yout[&j0,r];

* Define convexity constraints for VRS models;
/*con Convexity: sum{j in UNITS} L[j]=1;*/

* Solve the model;
solve ;

* Save the efficiency scores in a SAS dataset;
eff=h.sol;
DMUj0=DMUS[&j0];
create data solj0 from DMUj0 eff ;

*End of PROC OPTMODE;
quit;
%mend model_inOri;

%macro report;
* Delete previusly created datasets;
proc datasets nolist;
delete &_outdea1 &_outdea2;
run;

* Select the model and execute it for each unit of assessment;
%do j0=1 %to &_nUnits;
%if &_Orienta=”INPUT”
%then %do;
%model_inOri (&j0);
* Save the efficiency scores in a SAS dataset;
proc datasets nolist;
append base=&_outdea2=solj0;
run;
%end;
%else %do;
%model_outOri (&j0);
proc datasets nolist;
append base=&_outdea1 data=solj0;
run;
%end;
%end;

%if &_Orienta=”INPUT”
%then %do;
* Sort and print the results by efficiency score;
proc sort data=&_outdea2;
by eff;
run;
proc print data=&_outdea2;
run;

* Sort and print the results by unit name;
proc sort data=&_outdea2;
by DMUj0;
run;
proc print data=&_outdea2;
run;
%end;
%else %do;
* Sort and print the results by efficiency score;
proc sort data=&_outdea1;
by eff;
run;
proc print data=&_outdea1; title &_title;
run;

* Sort and print the results by unit name;
proc sort data=&_outdea1;
by DMUj0;
run;
proc print data=&_outdea1; title &_title;
run;
%end;

%mend report;

%macro ordea;
%data;
%report;
%mend ordea;

%ordea;


/****************************************************************************
******************************END of the program*****************************
****************************************************************************/

Permanent link to this article: http://sas-or.com/book/program-9-2

Program 9.3

/***********************************************************************************
* This program is taken from the following book. If using please cite it as:           *
* Emrouznejad, A. and W. Ho (2012). Applied Operations Research with SAS, *
* CRC Press: Taylor Francis Ltd, ISBN: 9781439841303.                                               *
* For details please visit: http://www.sas-or.com.                                                                *
************************************************************************************/


* Using PROC OPTMODEL for Malmquist Productivity Index and its Components;
option nodate ;
%let _title=’Example 9.3. Malmquist Productivity Index and its Components’;
%let _InData_P1=’C:\sasor\Data9_3_In_P1.txt’;
%let _OutData_P1=’C:\sasor\Data9_3_Out_P1.txt’;
%let _InData_P2=’C:\sasor\Data9_3_In_P2.txt’;
%let _OutData_P2=’C:\sasor\Data9_3_Out_P2.txt’;
%let _nInput=2;
%let _nOutput=2;
%let _nUnits=6;
%let _outMalm1=outMalm1;
%let _outMalm2=outMalm2;
%let _Orienta=’INPUTMIN’; * Alternative selection is ‘OUTPUTMAX’;

%macro importdata (txtFile, sasFile);
proc import
datafile=&txtFile
out=&sasFile
dbms=tab
replace;
getnames=yes;
run;
%mend importdata;

* The data handling macro;
%macro data;
* Import text tab delimited input variables to SAS data file, period1;
%importdata(&_InData_P1,data9_3_input_P1);
* Import text tab delimited output variables to SAS data file, period1;
%importdata(&_OutData_P1,data9_3_output_P1);
* Import text tab delimited input variables to SAS data file, period2;
%importdata(&_InData_P2,data9_3_input_P2);
* Import text tab delimited output variables to SAS data file, period2;
%importdata(&_OutData_P2,data9_3_output_P2);
%mend data;

* A DEA macro for CRS output orientation;
%macro model_outOri ( per1, per2,j0);
* Starting OPTMODEL Procedure;
proc optmodel;
* Define sets;
set INPUTS=1..&_nInput;
set OUTPUTS=1..&_nOutput;
set UNITS=1..&_nUnits;
set PERIODS=1..2;

* Define variables;
var L{UNITS} >=0;
var Sin{INPUTS} >=0 ;
var Sout{OUTPUTS} >=0 ;
var h;

* Define parameters;
number Xin{PERIODS,UNITS, INPUTS};
number Yout{PERIODS,UNITS,OUTPUTS};
string DMUS{UNITS};
number eff;
string DMUj0;
number p1;
number p2;

* Load unit names;
read data data9_3_input_P1
into [_N_]
DMUS[_N_]=col(‘dmu’);

* Load matrix of input variables;
read data data9_3_input_P1
into [_N_]
{i in INPUTS} <Xin[1,_N_,i]=col(‘input’||i)>;

* Load matrix of input variables;
read data data9_3_input_P2
into [_N_]
{i in INPUTS} <Xin[2,_N_,i]=col(‘input’||i)>;

* Load matrix of input variables;
read data data9_3_output_P1
into [_N_]
{r in OUTPUTS} <Yout[1,_N_,r]=col(‘output’||r)>;

* Load matrix of input variables;
read data data9_3_output_P2
into [_N_]
{r in OUTPUTS} <Yout[2,_N_,r]=col(‘output’||r)>;

* Define objective function ;
max obj = h;

* Define constrains;
con InpCon_outOri{i in INPUTS}:
sum{j in UNITS} L[j]*Xin[&Per1,j,i] + Sin[i]=Xin[&Per2,&j0,i];

con OutCon_outOri{r in OUTPUTS}:
sum{j in UNITS} L[j]*Yout[&Per1,j,r] – Sout[r]=h*Yout[&Per2,&j0,r];
* Solve the model;
solve ;

* Save the efficiency scores in a SAS dataset;
eff=1/h.sol;
DMUj0=DMUS[&j0];
p1=&Per1;
p2=&Per2;
create data solj0 from DMUj0 p1 p2 eff;

*End of PROC OPTMODE;
quit;
%mend model_outOri;

%macro report(per1,per2);
* Select the model and execute it for each unit of assessment;
%do j0=1 %to &_nUnits;
%model_outOri (&per1,&per2,&j0);
* Save the results for report writing;
proc datasets nolist;
append base=&_outMalm1 data=solj0;
run;
%end;
%mend report;

%macro ormalm;
%data;
* Delete previously created datasets;
proc datasets nolist;
delete &_outMalm1;
run;

%report(1,1);
%report(2,2);
%report(1,2);
%report(2,1);

data &_outMalm2;
merge &_outMalm1(WHERE=(p1=1 and p2=1) RENAME=(eff=DEA11))
&_outMalm1(WHERE=(p1=1 and p2=2) RENAME=(eff=DEA12))
&_outMalm1(WHERE=(p1=2 and p2=1) RENAME=(eff=DEA21))
&_outMalm1(WHERE=(p1=2 and p2=2) RENAME=(eff=DEA22));
by dmuj0;
drop p1 p2;
run;

data &_outMalm2(drop=DEA21 DEA12 rename=(DEA11=EffPeriod1 DEA22=EffPeriod2));
set &_outMalm2;
EffChange=DEA22/DEA11;
TechChange=sqrt((DEA12*DEA11)/(DEA22*DEA21));
MalmIndex=EffChange*TechChange;
run;

proc print; run;

%mend ormalm;

%ormalm;


/****************************************************************************
******************************END of the program*****************************
****************************************************************************/

Permanent link to this article: http://sas-or.com/book/program-9-3

Exercise 2.1

/***********************************************************************************
* This program is taken from the following book. If using please cite it as:           *
* Emrouznejad, A. and W. Ho (2012). Applied Operations Research with SAS, *
* CRC Press: Taylor Francis Ltd, ISBN: 9781439841303.                                               *
* For details please visit: http://www.sas-or.com.                                                                *
************************************************************************************/

*Program 2.1_exercise: Using PROC OPTMODEL for Transportation problem;
option nodate ;
%let _title=’Example 2.1_exercise: Transportation problem for three suppliers and four customers.’;
%let _data=’c:\sasor\data2_1_exercise.txt’;

* The data handling macro;
%macro data;
* Import text tab delimited data file to SAS data file;
proc import
datafile=&_data
out=dcost
dbms=tab
replace;
getnames=yes;
run;
%mend data;

%macro model;
* Starting OPTMODEL Procedure;
proc optmodel;
* Define sets;
set SUPPLIERS;
set CUSTOMERS={1..4};

* Define parameters;
number demand{CUSTOMERS};
number supply{SUPPLIERS};
number cost{SUPPLIERS, CUSTOMERS};

* Define variables;
var X{SUPPLIERS, CUSTOMERS} >= 0;

* Load the supplier set and their amount of supply;
read data dcost (where= (supply ne .))
into SUPPLIERS=[Supplier] supply[Supplier]=col(“supply”);

* Load the customer set and their demand;
read data dcost (where= (supply eq .)) into
{c in CUSTOMERS} ;

* Load the cost of shipment from each supplier to each customer;
read data dcost (where= (supply ne .))
into SUPPLIERS=[Supplier]
{c in CUSTOMERS} ;

* Define objective function;
min obj = sum{s in SUPPLIERS, c in CUSTOMERS} cost[s,c]*x[s,c];

* Define constraints;
con req_supply{s in SUPPLIERS}:
sum{c in CUSTOMERS} x[s,c] <= supply[s]; con req_demand{c in CUSTOMERS}: sum{s in SUPPLIERS} x[s,c] >= demand[c];

con zero{c in CUSTOMERS, s in SUPPLIERS : cost[s,c]=1E10}: x[s,c]=0;

* Solve the model;
solve with lp/solver=primal;

* Create optimum values in a SAS dataset ‘optimout’;
create data optimout
from [SUPPLIERS CUSTOMERS]
={s in SUPPLIERS, c in CUSTOMERS: x[s,c]^=0}
amount=x;

* End of OPTMODEL Procedure;
quit;
%mend model;

* The report writing macro;
%macro report;
* report the results in a tabulated form;
proc tabulate data=optimout;
title &_title;
class SUPPLIERS CUSTOMERS ;
var amount;
table SUPPLIERS =” Suppliers”,
CUSTOMERS*amount*sum
/ BOX=’Amount of suppliers to customers’ ;
run;
%mend report;

* The ortrans macro for transportation problem;
%macro ortrans;
%data;
%model;
%report;
%mend ortrans;

%ortrans;


/****************************************************************************
******************************END of the program*****************************
****************************************************************************/

Permanent link to this article: http://sas-or.com/book/exercise-2-1