Category: Chapter 8

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

Exercise 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.                                                                *
************************************************************************************/

* SAS macro for Analytical Hierarchy Process: solution to exercise 8.1.;
%let _title=’Analytical Hierarchy Process, solution to exercise 8.1′;
option nodate;
%let _dataC=’c:/sasor/Data8_1_C_exercise.txt’;
%let _dataA=’c:/sasor/Data8_1_A_exercise.txt’;
%let _nCriteria=4;
%let _nAlternative=3;
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/exercise-8-1

Exercise 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: solution to exercise 8.2.’;
%let _dataMCDM=’c:/sasor/Data8_2_exercise.txt’;
%let _nWareh=5;
%let _nCustomer=7;
%let _TotalCost=458000;
%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*****************************
****************************************************************************/

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

Chapter 8: Multiple-Criteria Decision Making

  • Multiple-Criteria Logistics Distribution Problem: Phase 1 (Analytic Hierarchy Process – AHP)
  • Multiple-Criteria Logistics Distribution Problem: Phase 2 (Goal Programming – GP)

Chapter 8 - Programs

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