00001
00002
00003
00004
00005 #include <fstream>
00006 #include "stdio.h"
00007 #include <cmath>
00008 #include <iostream>
00009 #include <sstream>
00010 #include <climits>
00011 #include <stack>
00012
00013 #include <string>
00014 #include <math.h>
00015
00016 #include <cstring>
00017 #include <cstdlib>
00018
00019 #define MAX(AA,BB) (((AA)>(BB))?(AA):(BB))
00020 #define MAXNODES 100
00021 #define MAXARCS 500
00022 #define MAXDESC 50 //Arc descriptor length
00023 #define MAXID 4 //Arc id length
00024 #define NAMELEN 8
00025 #define debug 0
00026
00027
00028 using namespace std;
00029
00030 struct activity{long num, dur; activity *next;};
00031 struct NODE {
00032 long nodenumber;
00033 char nodename[NAMELEN+1];
00034 long tasktime;
00035 long fstar;
00036 long bstar;
00037 long fcount;
00038 long bcount;
00039 long preds;
00040 long successors;
00041 long rank;
00042 long station;
00043 long label;
00044 long ES;
00045 long EF;
00046 long LS;
00047 long LF;
00048 long slack;
00049 long unsetpreds;
00050 long unsetsuccs;
00051 char nodeid[MAXID+1];
00052 char nodeDesc[MAXDESC+1];
00053 };
00054
00055 struct ARC {
00056 long arcnumber;
00057 long fromnode;
00058 long tonode;
00059 long fstar;
00060 long bstar;
00061 };
00062
00063 struct STATION {
00064 long stationtime;
00065 long numTasks;
00066 long stationNum;
00067 };
00068
00069 class project {
00070 public:
00071 project(){tMax = 0; numNodes=numArcs=0;}
00072 long min, n;
00073 void ReadProblem(const char *fname);
00074 void ReadProblem2(const char *fname);
00075 void AssignAllTasks(long,long);
00076 void AssignmentReport(long,long);
00077 long NodeNum(char*);
00078 long NewNodeNum(char*);
00079 long MakeStation(long,long);
00080 long IsTie(long,long);
00081 long FindTaskFit(long);
00082 void RankTasks(long);
00083 long Better(long,long,long);
00084 void PrintRanking(long);
00085 void CountPreds();
00086 void CountSuccessors();
00087 void AddPreds(long);
00088 void AddSuccessors(long);
00089 void ZeroNodeLabels();
00090 void ZeroNodePreds();
00091 void ZeroNodeSuccessors();
00092 void Printout();
00093 void NodeReport();
00094 void ArcReport();
00095 void Evaluate();
00096 void DoNode(long,string);
00097 void PutNode(long);
00098 void OutNodeLabel(long);
00099 void PutArc(long, string, long);
00100 void Driver(long,char**);
00101 void CPM();
00102 private:
00103 long tMax;
00104 long numNodes;
00105 long numArcs;
00106 long numStations;
00107 long numCritical;
00108 long root;
00109 long totaltime;
00110 long istart;
00111 long iend;
00112 NODE node[MAXNODES+1];
00113 ARC arc[MAXARCS+1];
00114 STATION station[MAXNODES+1];
00115 long tsort[MAXNODES+1];
00116 void SkipRestLine(ifstream &file);
00117 stack <long> nodestack;
00118 };
00119
00120
00121 void project::AssignmentReport(long ct,long rule) {
00122 long i,idle,calc;
00123 double e;
00124 cout << endl << " *** ASSEMBLY LINE SUMMARY ***" << endl << endl;
00125
00126 printf("Problem:\n");
00127 printf("--------\n");
00128 printf("Number of tasks %d\n",numNodes);
00129 printf("Total task time %d\n",totaltime);
00130 printf("Longest task time %d\n",tMax);
00131 printf("Target cycle time %d\n\n",ct);
00132
00133 printf("Assignment:\n");
00134 printf("-----------\n");
00135 printf("Rule %d\n",rule);
00136 for(i=1, calc=0; i <= numStations; ++i) {calc = MAX(calc,station[i].stationtime);}
00137 ct = calc;
00138 printf("Computed cycle time %d\n",ct);
00139 printf("Stations used, N %d\n",numStations);
00140 idle = 0;
00141 for(i=1; i <= numStations; ++i) {idle += (ct-station[i].stationtime);}
00142
00143 printf("Output per hour, N' %.2lf (if seconds)\n",3600.0/(double)ct);
00144 printf(" %.2lf (if minutes)\n",60.0/(double)ct);
00145 printf("Station time/cycle %d\n",numStations*ct);
00146 printf("Idle time/cycle %d\n",idle);
00147 e = (double)totaltime/((double) numStations*(double)ct);
00148 printf("Efficiency, E %lf\n",e);
00149 printf("Fraction idle, 1-E %lf\n",1.0-e);
00150 printf("Balance delay %lf\n",100.0*(1.0-e));
00151 }
00152
00153 void project::AssignAllTasks(long ct,long rule) {
00154 long i, tasksleft;
00155 cout << endl << " *** WORKSTATION ASSIGNMENTS ***" << endl << endl;
00156 cout << "For cycle time = " << ct << ", using rule " << rule << endl ;
00157 if (ct < tMax) {
00158 cout << "Infeasible cycle time, reset to " << tMax << ", the largest task time"<< endl;
00159 ct = tMax;
00160 }
00161 cout << endl;
00162
00163 for (i=1; i <= numNodes; ++i) node[i].label = node[i].bcount;
00164
00165 for (numStations=0,tasksleft=numNodes; numStations <= numNodes && tasksleft; ) {
00166 ++numStations;
00167 MakeStation(numStations,ct);
00168 tasksleft -= station[numStations].numTasks;
00169 }
00170 }
00171
00172 long project::MakeStation(long s, long cycletime) {
00173 long t,a,timeleft,cumtime;
00174 static STATION initstation = {0,0,0};
00175
00176 timeleft = cycletime;
00177 cumtime = 0;
00178 station[s] = initstation;
00179
00180
00181
00182
00183
00184
00185 cout << "Station " << s << " tasks:" ;
00186
00187 while ((timeleft > 0) && (t=FindTaskFit(timeleft)) > 0) {
00188 node[t].station = s;
00189 ++station[s].numTasks;
00190 station[s].stationtime += node[t].tasktime;
00191 timeleft -= node[t].tasktime;
00192
00193 cout << " " << node[t].nodename;
00194 a = node[t].fstar;
00195 while(a) { --node[arc[a].tonode].label; a = arc[a].fstar;}
00196 }
00197
00198 cout << " (time = " << station[s].stationtime << ")" << endl;
00199
00200 }
00201
00202 long project::FindTaskFit(long timeleft) {
00203 long i,t;
00204 for (i=1; i <= numNodes; ++i) {
00205 t = tsort[i];
00206 if (t <= 0) continue;
00207 if (node[t].label) continue;
00208 if (node[t].tasktime <= timeleft) {
00209 tsort[i] = -tsort[i];
00210 return t;
00211 }
00212 }
00213 return 0;
00214 }
00215
00216 void project::PrintRanking(long rule){
00217 long ties = 0;
00218 cout << "Tasks ranked by rule " << rule << ":" << endl;
00219 for (long i=1; i <= numNodes; ++i) {
00220 cout << " " << node[tsort[i]].nodename;
00221 if (IsTie(tsort[i],tsort[i-1])) {++ties; cout << "*"; }
00222
00223 }
00224 cout << endl;
00225 if (ties) cout << " (*task tied with prior task in ranking)" << endl;
00226 }
00227
00228 long project::IsTie(long i, long j) {
00229 if(i <1 || i > numNodes || j < 1 || j > numNodes) return 0;
00230 if (node[i].preds == node[j].preds && node[i].tasktime == node[j].tasktime) return 1;
00231 else return 0;
00232 }
00233
00234 void project::RankTasks(long rule) {
00235 long i,j,best,hold;
00236 for (i=1; i <= numNodes; ++i) tsort[i] = i;
00237 for (i=1; i < numNodes; ++i) {
00238 best = i;
00239 for (j=i+1; j <= numNodes; ++j) { if(Better(tsort[j],tsort[best],rule)) best = j; }
00240 if (best != i) {hold = tsort[i]; tsort[i]=tsort[best]; tsort[best] = hold;}
00241 }
00242 }
00243
00244 long project::Better(long j, long i, long rule) {
00245 switch (rule) {
00246 case 1: if (node[j].preds > node[i].preds) return 0;
00247 else if (node[j].preds < node[i].preds) return 1;
00248 break;
00249 case 2: if (node[j].successors < node[i].successors) return 0;
00250 else if (node[j].successors > node[i].successors) return 1;
00251 break;
00252 }
00253
00254 if (node[j].tasktime > node[i].tasktime) return 1;
00255 else return 0;
00256 }
00257
00258 void project::OutNodeLabel(long i){
00259 char buf[20];
00260
00261 cout << i;
00262 }
00263
00264 void project::PutArc(long a, string tab, long usetab)
00265
00266 {
00267 const char* cp;
00268 char buf[10];
00269
00270 cp = tab.c_str();
00271 return;
00272 }
00273
00274 void project::DoNode(long i, string tab1)
00275
00276 {
00277 long a,j,lvl,t;
00278 string postfix;
00279
00280 a = node[i].bstar;
00281 t = 0;
00282 while (a) {
00283 PutArc(a,tab1,t);
00284 DoNode(arc[a].tonode,postfix);
00285 a = arc[a].bstar;
00286 t = 1;
00287 }
00288 cout << tab1 << endl;
00289 return;
00290 }
00291
00292
00293 void project::SkipRestLine(ifstream &file)
00294 { char ch;
00295 do file.get(ch); while (!file.fail() && ch != '\n');
00296 }
00297
00298
00299 long project::NodeNum(char* s) {
00300 if (numNodes == 0) return NewNodeNum(s);
00301 for (long i=1; i <= numNodes; ++i) { if (!strncmp(s,node[i].nodename,NAMELEN)) return i; }
00302 return NewNodeNum(s);
00303 }
00304
00305 long project::NewNodeNum(char* s) {
00306 ++numNodes;
00307 memcpy(node[numNodes].nodename, s, sizeof(char)*(NAMELEN));
00308 node[numNodes].nodename[NAMELEN+1] = '\0';
00309 node[numNodes].ES = 0;
00310 node[numNodes].LS = LONG_MAX;
00311 return numNodes;
00312 }
00313
00314 void project::ReadProblem2(const char *fname)
00315 { long ifrom, jto, tasktime;
00316 int nstart, nend;
00317 char buf[256],save[256];
00318 char *token;
00319
00320 ifstream file;
00321 file.open(fname, ios_base::in);
00322 if (file.fail()) { cout << "Cannot open input file.\n"; exit(1); }
00323
00324 for (numArcs=0;;)
00325 {
00326 file.getline (buf,256);
00327 if (file.eof()) break;
00328 memcpy(save,buf,sizeof(char)*256);
00329
00330 token = strtok(buf," \t");
00331 jto = NodeNum(token);
00332
00333 token = strtok(NULL," \t");
00334 node[jto].tasktime = atoi(token);
00335 if (node[jto].tasktime > tMax) tMax = node[jto].tasktime;
00336 totaltime += node[jto].tasktime;
00337
00338 while (token = strtok(NULL," \t") ) {
00339 ifrom = NodeNum(token);
00340 ++numArcs;
00341 arc[numArcs].fromnode = ifrom;
00342 arc[numArcs].tonode = jto;
00343 arc[numArcs].bstar = node[jto].bstar;
00344 node[jto].bstar = numArcs;
00345 arc[numArcs].fstar = node[ifrom].fstar;
00346 node[ifrom].fstar = numArcs;
00347 ++node[ifrom].fcount;
00348 ++node[jto].bcount;
00349 }
00350 for (int i=1, nstart=nend=0; i <= numNodes; ++i) {
00351 if (node[i].preds == 0) { istart = i; ++nstart;}
00352 if (node[i].successors == 0) { iend = i; ++nend;}
00353 }
00354
00355 }
00356
00357 file.close();
00358 cout << numNodes << " task nodes, " << numArcs << " precedence arcs";
00359 cout << ", and " << totaltime << " time units for all tasks" << endl;
00360 if(istart != 1) { cout << "Exactly 1 start node (with no predecessors) is required.\n"; exit(1); }
00361 if(iend != 1) { cout << "Exactly 1 end node (with no successors) is required.\n"; exit(1); }
00362 }
00363
00364 void project::CountPreds(){
00365 long i;
00366 ZeroNodePreds();
00367 for (i=1; i <= numNodes; ++i) {
00368 ZeroNodeLabels();
00369 AddPreds(i);
00370 }
00371 return;
00372 }
00373
00374 void project::AddPreds(long i){
00375 long a;
00376 if (node[i].label) return;
00377 ++node[i].preds;
00378 node[i].label = 1;
00379 a = node[i].fstar;
00380 while(a) {
00381 AddPreds(arc[a].tonode);
00382 a = arc[a].fstar;
00383 }
00384 return;
00385 }
00386
00387 void project::ZeroNodeLabels(){
00388 for(long i=1; i<= numNodes; ++i) node[i].label = 0;
00389 }
00390
00391 void project::ZeroNodePreds(){
00392 for(long i=1; i<= numNodes; ++i) node[i].preds = -1;
00393 }
00394
00395
00396 void project::CountSuccessors(){
00397 long i;
00398 ZeroNodeSuccessors();
00399 for (i=1; i <= numNodes; ++i) {
00400 ZeroNodeLabels();
00401 AddSuccessors(i);
00402 }
00403 return;
00404 }
00405
00406 void project::AddSuccessors(long i){
00407 long a;
00408 if (node[i].label) return;
00409 ++node[i].successors;
00410 node[i].label = 1;
00411 a = node[i].bstar;
00412 while(a) {
00413 AddSuccessors(arc[a].fromnode);
00414 a = arc[a].bstar;
00415 }
00416 return;
00417 }
00418
00419 void project::ZeroNodeSuccessors(){
00420 for(long i=1; i<= numNodes; ++i) node[i].successors = -1;
00421 }
00422
00423 void project::Evaluate(){
00424 long i;
00425 long queue[MAXNODES+1];
00426 long qlen;
00427 long evnode;
00428 long evarc;
00429 long pred;
00430 long evcount;
00431
00432 qlen = 0;
00433 for(i = 1; i <=numNodes; ++i) {
00434 }
00435
00436 evcount = numNodes;
00437 while (qlen > 0) {
00438 evnode = queue[qlen--];
00439 --evcount;
00440 evarc = node[evnode].fstar;
00441 pred = node[evnode].bstar;
00442 --node[pred].label;
00443 if (debug) {cout << "Evaluating node " << evnode << " Q = {";
00444 for (i=1; i<= qlen; ++i) cout << queue[i] << " ";
00445 cout << "}" << endl;
00446 }
00447
00448 node[pred].bstar = evarc;
00449 if ((node[pred].label) <= 0) queue[++qlen] = pred;
00450 }
00451
00452 if (evcount) cout << "** There are " << evcount << " unevaluated nodes" << endl;
00453 root = evnode;
00454 }
00455
00456 void project::NodeReport(){
00457 long i;
00458 char buf[25];
00459
00460 cout <<endl<<" *** TASK SUMMARY ***"<< endl << endl ;
00461 cout << " Task Time Preds Succs";
00462 if (debug) cout << "Fstar Bstar Fcount Bcount Label";
00463 cout << endl;
00464 for(i=1;i<=numNodes; ++i) {
00465 printf("%8.8s %4d %5d %5d ",node[i].nodename,node[i].tasktime, node[i].preds, node[i].successors);
00466 if (debug) printf("% %5d %5d %5d",
00467 node[i].fstar, node[i].bstar, node[i].fcount, node[i].bcount, node[i].label);
00468 cout << endl;
00469 }
00470 cout << endl;
00471 }
00472
00473 void project::ArcReport(){
00474 long i;
00475
00476 cout << endl << " *** TASK PRECEDENCE REQUIREMENTS ***"<< endl << endl;
00477 printf(" Arc From To Fstar Bstar\n");
00478 printf("----- --------- ----- -----\n");
00479
00480 for(i=1;i<=numArcs; ++i) {
00481 printf("%3d %3d %3d %5d %5d\n",
00482 i, arc[i].fromnode, arc[i].tonode, arc[i].fstar, arc[i].bstar);
00483 }
00484 }
00485
00486 void project::Driver(long argc, char *argv[])
00487 {
00488 char *fname;
00489 long cycletm, irule;
00490
00491 if (argc != 2) {
00492 cout << "Usage: aon inputFilename \n";
00493 exit(1);
00494 }
00495 fname = argv[1];
00496 cout << "*** CPM-AON Critical Path Method, Activity-on-Node *** " << endl << endl;
00497 ReadProblem2(fname);
00498 CountPreds();
00499 CountSuccessors();
00500 NodeReport();
00501 RankTasks(irule);
00502 PrintRanking(irule);
00503 AssignAllTasks(cycletm,irule);
00504 AssignmentReport(cycletm,irule);
00505 }
00506
00507 void project::CPM ()
00508 {
00509
00510 long i,j,n,EFi,LSi;
00511
00512 for (i=1; i < numNodes; ++i) {
00513 node[i].unsetpreds = node[i].bcount;
00514 node[i].unsetsuccs = node[i].fcount;
00515 }
00516
00517 node[istart].ES = 0;
00518 nodestack.push(istart);
00519 do {
00520 i = nodestack.top();
00521 nodestack.pop();
00522 EFi = node[i].EF = node[i].ES + node[i].tasktime;
00523
00524 if ((n = node[i].fcount) > 0) {
00525 j = arc[node[i].fstar].tonode;
00526 for(; n >0; --n){
00527 if(EFi > node[j].EF) node[j].EF = EFi;
00528 if((--node[j].unsetpreds) == 0) nodestack.push(j);
00529 j = arc[node[j].fstar].tonode;
00530 }
00531 }
00532 } while(!nodestack.empty());
00533
00534
00535
00536 node[iend].LF = node[iend].EF;
00537 nodestack.push(iend);
00538 do {
00539 i = nodestack.top();
00540 nodestack.pop();
00541 LSi = node[i].LS = node[i].LF - node[i].tasktime;
00542 if((n = node[i].bcount) > 0) {
00543 j = arc[node[i].bstar].fromnode;
00544 for (; n > 0; --n) {
00545 if(LSi < node[j].LS) node[j].LS = LSi;
00546 if((--node[j].unsetsuccs) == 0) nodestack.push(j);
00547 j = arc[node[j].bstar].fromnode;
00548 }
00549 }
00550 } while(!nodestack.empty());
00551
00552
00553
00554 for(i=1,numCritical=0; i<numNodes; ++i) {
00555 node[i].slack = node[i].EF - node[i].ES;
00556 if(node[i].slack == 0) ++numCritical;
00557 }
00558 }
00559
00560 int main(int argc, char *argv[])
00561 { project g;
00562
00563 g.Driver(argc,argv);
00564 return 0;
00565 }
00566