Category: Chapter 5 – Programs

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

Exercise 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=’ A project network using PROC OPTMODEL, Assembly line balancing problem: solution to exercise 5.1′;
%let dataalb=’c:/sasor/Data5_1_exercise.txt’;
%let _activity=task;
%let _duration=time;
%let _earliest =Ei;
%let _latest =Li;
%let _nTask=8;
%let _nWork=4;
%let _CycleT=1.8;
%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} <EL[_N_,i]=col(‘W’||i)>;


* 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/exercise-5-1