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