3#include "SchedulingEvalOp.h"
19#define CHECKMSG(condition, text) \
20if(!(condition)) {fprintf(stderr,"file: " __FILE__ "\nline: %d\nmsg: " text "\n",__LINE__); exit(1);}
21#define CHECK(condition) \
22if(!(condition)) {fprintf(stderr,"Nesto ne valja!\nfile: " __FILE__ "\nline: %d\n" ,__LINE__); exit(1);}
24#define POS(x) (x>0 ? x : 0)
25#define MIN(x,y) (x<y ? x : y)
26#define MAX(x,y) (x>y ? x : y)
35const int FUNCTIONS = 6;
40 state->getRegistry()->registerEntry(
"test_cases", (voidP) (
new std::string), ECF::STRING);
41 state->getRegistry()->registerEntry(
"normalized", (voidP) (
new uint(1)), ECF::UINT);
47 std::string configFile;
50 if(!state->getRegistry()->isModified(
"test_cases"))
53 voidP sptr = state->getRegistry()->getEntry(
"test_cases");
54 configFile = *((std::string*) sptr.get());
56 sptr = state->getRegistry()->getEntry(
"normalized");
57 m_Normalized = (bool) *((uint*) sptr.get());
60 std::string input,sp,duration,deadline,weightT,weightF,weightE,weightN,term,ready,cons,speed;
64 double d_niz[2][1000];
70 p.OpenFile(input.c_str());
71 if(p.ReadParameter(
"single",ReadPar::INTEGER,&i))
72 m_Environment = SINGLE;
73 else if(p.ReadParameter(
"uniform",ReadPar::INTEGER,&i))
74 m_Environment = UNIFORM;
75 else if(p.ReadParameter(
"unrelated",ReadPar::INTEGER,&i))
76 m_Environment = UNRELATED;
77 else if(p.ReadParameter(
"jobshop",ReadPar::INTEGER,&i))
78 m_Environment = JOBSHOP;
79 p.ReadParameter(
"sets",ReadPar::INTEGER,&sets);
80 p.ReadParameter(
"max_jobs",ReadPar::INTEGER,&max_jobs);
81 if(!p.ReadParameter(
"max_machines",ReadPar::INTEGER,&max_machines))
83 p.ReadParameter(
"max_length",ReadPar::INTEGER,&max_length);
84 p.ReadParameter(
"duration",ReadPar::STRING,pom); duration = pom;
85 p.ReadParameter(
"deadline",ReadPar::STRING,pom); deadline = pom;
86 p.ReadParameter(
"weight_T",ReadPar::STRING,pom); weightT = pom;
87 p.ReadParameter(
"weight_F",ReadPar::STRING,pom); weightF = pom;
88 p.ReadParameter(
"weight_E",ReadPar::STRING,pom); weightE = pom;
89 p.ReadParameter(
"weight_N",ReadPar::STRING,pom); weightN = pom;
90 p.ReadParameter(
"SP",ReadPar::STRING,pom); sp = pom;
91 p.ReadParameter(
"machine_file",ReadPar::STRING,pom); speed = pom;
93 if(p.ReadParameter(
"ready",ReadPar::STRING,pom))
100 if(p.ReadParameter(
"LEF",ReadPar::INTEGER,&i))
103 if(!p.ReadParameter(
"LEF_value",ReadPar::DOUBLE,&m_LEFVal))
104 CHECKMSG(0,
"LEF vrijednost nije zadana!");
110 if(p.ReadParameter(
"evaluation",ReadPar::INTEGER,&i))
111 if(i==1) m_Evaluation =
true;
112 else m_Evaluation =
false;
114 if(p.ReadParameter(
"fitness",ReadPar::STRING,pom))
118 else if(input ==
"Nwt")
120 else if(input ==
"FTwt")
122 else if(input ==
"ETwt")
124 else if(input ==
"Cmax")
126 else if(input ==
"Fwt")
129 CHECKMSG(0,
"Nepoznata fitnes funkcija!");
131 else CHECKMSG(0,
"Nije definirana fitnes funkcija!");
133 if(p.ReadParameter(
"editing",ReadPar::INTEGER,&i))
134 if(i==1) m_editing =
true;
136 if(p.ReadParameter(
"stsampling",ReadPar::DOUBLE,&m_sampling))
139 m_stsampling =
false;
141 if(p.ReadParameter(
"constraints",ReadPar::STRING,pom))
143 m_constrained =
true;
146 m_constrained =
false;
148 if(p.ReadParameter(
"setup",ReadPar::DOUBLE,&m_setup_faktor))
153 if(p.ReadParameter(
"idleness",ReadPar::INTEGER, &i))
154 if(i == 1) m_Idleness =
true;
168 MachineReady.Init(max_machines);
169 Speed.Init(sets,max_jobs);
170 Duration.Init(sets,max_jobs);
171 Deadline.Init(sets,max_jobs);
172 Durations.Init(max_jobs, max_machines);
173 MachineIndex.Init(max_jobs, max_machines);
174 WeightT.Init(sets,max_jobs);
175 WeightF.Init(sets,max_jobs);
176 WeightE.Init(sets,max_jobs);
177 WeightN.Init(sets,max_jobs);
178 Fitness.Init(sets+1,FUNCTIONS);
179 Values.Init(max_machines,max_jobs);
180 Precedence.Reset(max_jobs,max_jobs);
181 Setup.Init(max_jobs+1,max_jobs);
182 if(m_Environment == JOBSHOP)
183 { Schedule.Init(sets, max_machines*max_jobs);
184 PTimeAvg.Reset(sets, max_machines);
187 { Schedule.Init(sets,max_jobs);
188 PTimeAvg.Init(sets,max_jobs);
189 PTimeMinMachine.Init(sets,max_jobs);
191 SortedReady.Init(sets,max_jobs);
193 pVrijednosti =
new double[max_jobs];
194 pRasporedjen =
new bool[max_jobs];
195 pIndex =
new unsigned int[max_jobs];
196 pUsed =
new unsigned int[max_jobs];
197 pArray =
new double[max_jobs];
198 pSlack =
new double[max_jobs];
199 pSlackSpeed =
new double[max_jobs];
200 pArrival =
new double[max_jobs];
201 pLevel =
new double[max_jobs];
202 pSetupAvg =
new double[max_jobs + 1];
203 pSamples =
new bool[sets];
204 pLastJob =
new unsigned int[max_machines];
205 pMachineScheduled =
new unsigned int[max_machines];
206 pOperationReady =
new double[max_machines];
207 pJobReady =
new double[max_jobs];
208 pOperationsScheduled =
new unsigned int[max_jobs];
209 pTotalWorkRemaining =
new double[max_jobs];
210 pTotalWorkDone =
new double[max_jobs];
211 pTotalMachineWork =
new double[max_machines];
212 pOperationsWaiting =
new unsigned int[max_machines];
213 pMachineWorkRemaining =
new double[max_machines];
214 pMachineValues =
new double[max_machines];
215 p.ReadParameter(
"jobs",ReadPar::DOUBLE,&d_niz[0][0],sets);
216 p.ReadParameter(
"machines",ReadPar::DOUBLE,&d_niz[1][0],sets);
218 for(i=0; i<sets; i++)
219 { N[i][0] = d_niz[0][i];
220 total_jobs += (int) d_niz[0][i];
221 Machines[i][0] = d_niz[1][i];
223 Duration.Load(duration.c_str());
224 Deadline.Load(deadline.c_str());
225 if(m_Environment==UNIFORM)
226 { Speed.Load(speed.c_str());
228 WeightT.Load(weightT.c_str());
229 WeightF.Load(weightF.c_str());
230 WeightE.Load(weightE.c_str());
231 WeightN.Load(weightN.c_str());
233 if(m_dynamic) Ready.Load(ready.c_str());
234 else Ready.Reset(sets,max_jobs);
235 if(m_constrained) Constraints.Load(cons.c_str());
237 Level.Init(sets,max_jobs);
238 for(i=0; i<sets; i++)
240 for(j=0; j<(
unsigned int)N.Get(i); j++)
241 { SD.data[i][0] += Deadline.data[i][j];
246 for(i=0; i<sets; i++)
248 ReadConstraints(Constraints,i,(
unsigned int)N.Get(i),Precedence);
249 for(j=0; j<(
unsigned int)N.Get(i); j++)
250 Level[i][j] = NodeLevel(i,j);
253 if(m_Environment == UNRELATED)
254 {
for(uint set=0; set<sets; set++)
255 { uint jobs = (uint) N[set][0];
256 uint machines = (uint) Machines[set][0];
257 for(j=0; j<jobs; j++)
258 { PTimeAvg[set][j] = 0;
259 uint min_machine = 0;
260 for(uint machine=0; machine<machines; machine++)
261 { PTimeAvg[set][j] += Duration[set][j*machines + machine];
262 if(Duration[set][j*machines + machine] < Duration[set][j*machines + min_machine])
263 min_machine = machine;
265 PTimeAvg[set][j] /= machines;
266 PTimeMinMachine[set][j] = min_machine;
270 if(m_Environment == JOBSHOP)
271 {
for(uint set=0; set<sets; set++)
272 { uint jobs = (uint) N[set][0];
273 uint machines = (uint) Machines[set][0];
274 for(j=0; j<jobs; j++)
275 { uint operations = machines;
276 for(uint op=0; op<operations; op++)
277 {
double dur = Duration[set][j*operations + op];
278 uint machine = (uint) dur / 1000;
279 dur = (int)dur % 1000;
280 PTimeAvg[set][machine] += dur;
283 for(uint m=0; m<machines; m++)
284 PTimeAvg[set][m] /= jobs;
308double SchedulingEvalOp::NodeLevel(
int set,
int node)
311 if(Level[set][
node] > -1)
312 return Level[set][
node];
313 if(Precedence[
node][1] == 0)
314 return Duration[set][
node];
315 succ = (int)Precedence[
node][1];
316 next = (int)Precedence[
node][2];
317 level = NodeLevel(set,next) + Duration[set][
node];
318 for(i=1; i<succ; i++)
319 { next = (int)Precedence[
node][i+2];
320 value = NodeLevel(set,next) + Duration[set][
node];
330SchedulingEvalOp::~SchedulingEvalOp()
332 delete [] pRasporedjen;
333 delete [] pVrijednosti;
338 delete [] pSlackSpeed;
344 delete [] pMachineScheduled;
345 delete [] pOperationReady;
347 delete [] pOperationsScheduled;
348 delete [] pTotalWorkRemaining;
349 delete [] pTotalWorkDone;
350 delete [] pTotalMachineWork;
351 delete [] pMachineWorkRemaining;
352 delete [] pOperationsWaiting;
353 delete [] pMachineValues;
358void SchedulingEvalOp::ReadConstraints(
Matrica &Constraints,
int set,
int jobs,
Matrica &Precedence)
360 int i,j,prethodnika,prethodnik,pom;
361 unsigned int podatak;
364 for(i=0; i<jobs; i++)
366 Precedence[i][j] = 0;
367 for(i=0; i<jobs; i++)
368 { podatak = (
unsigned int) Constraints[set][i];
374 pom = (int) Precedence[i-prethodnik][1] + 1;
375 Precedence[i-prethodnik][pom+1] = i;
376 Precedence[i-prethodnik][1] = pom;
381 Precedence[i][0] = prethodnika;
388void SchedulingEvalOp::MakeSetup(
Matrica &Duration,
int set,
int jobs,
double faktor,
Matrica &Setup)
392 if(m_Environment == JOBSHOP)
394 for(i=0; i<jobs; i++)
395 { Setup[jobs][i] = (int) ((rand()%max_length+1) * faktor);
396 pSetupAvg[jobs] += Setup[jobs][i];
398 { Setup[i][j] = (int) ((rand()%max_length+1) * faktor);
399 Setup[j][i] = (int) ((rand()%max_length+1) * faktor);
400 pSetupAvg[i] += Setup[i][j];
401 pSetupAvg[j] += Setup[j][i];
406 for(i=0; i<jobs; i++)
408 Setup[jobs][i] = Duration[set][(i+1) % jobs];
409 pSetupAvg[jobs] += Setup[jobs][i];
411 { Setup[i][j] = ceil( fabs( Duration[set][i] - Duration[set][j] ) * faktor);
412 Setup[j][i] = ceil( fabs( Duration[set][(i+1) % jobs] - Duration[set][(j+1) % jobs] ) * faktor);
413 pSetupAvg[i] += Setup[i][j];
414 pSetupAvg[j] += Setup[j][i];
417 pSetupAvg[jobs] /= jobs;
418 for(i=0; i<jobs; i++)
419 pSetupAvg[i] /= (jobs-1);
426 FitnessP fitness =
static_cast<FitnessP
> (
new FitnessMin);
429 TreeP tree = boost::dynamic_pointer_cast<Tree::Tree> (individual->getGenotype());
433 double dRawFitness, dFitness;
437 {
int koliko = (int) (m_sampling*sets);
438 int razmak = sets / koliko;
439 int pocetni = rand()%razmak;
440 for(i=0; i<sets; i++)
442 for(i=pocetni; i<sets; i+=razmak)
446 switch(m_Environment)
448 dRawFitness = EvaluateSingle(tree);
465 dFitness = dRawFitness;
478 fitness->setValue(dFitness);
485double SchedulingEvalOp::EvaluateSingle(TreeP tree)
487 double dClock, dRez, dSetFitness, dAvgWeights, dAvgDuration, dAvgDueDate;
488 double dLateness, dTotalLateness=0, dTardiness, dTotalTardiness=0;
489 double dNwt, dTotalNwt=0, dBest, dSPr, dSDr;
490 unsigned int nPoslova,nNiz,nJob,i,j,index,nLateJobs,nTotalLateJobs=0,nNr;
491 unsigned int nLastJob,nOdabrani;
493 double dRawFitness=0;
496 for(nNiz = 0; nNiz < sets; nNiz++)
497 { nNr = nPoslova = (int) N.Get(nNiz);
501 if(pSamples[nNiz] ==
false)
505 {
if(dRawFitness > m_LEFVal)
509 ReadConstraints(Constraints,nNiz,nPoslova,Precedence);
511 MakeSetup(Duration,nNiz,nPoslova,m_setup_faktor,Setup);
518 dClock = 0; dSetFitness = 0;
521 for(i=0; i<nPoslova; i++)
522 { dAvgDueDate += Deadline[nNiz][i];
523 pRasporedjen[i] =
false;
526 dAvgDueDate /= nPoslova;
550 for(nJob=0; nJob<nPoslova; nJob++)
553 tree->setTerminalValue(
"SPr", &dSPr);
554 tree->setTerminalValue(
"Nr", &nNr);
558 {
unsigned int raspolozivi = nJob, prvi = nJob;
559 unsigned int najkraci;
561 for(; Precedence[pIndex[raspolozivi]][0] > 0; raspolozivi++) NULL;
562 double kada = Ready[nNiz][pIndex[raspolozivi]];
563 double najdulje = 0, najkrace = 0;
564 for( ; raspolozivi < nPoslova; raspolozivi++)
565 {
int job = pIndex[raspolozivi];
566 if(Ready.data[nNiz][job] < kada && Precedence[job][0] == 0)
567 { kada = Ready.data[nNiz][job];
575 najdulje = najkrace = Duration[nNiz][pIndex[prvi]];
577 for(i = nJob; i < nPoslova; i++)
578 {
int job = pIndex[i];
579 if(dClock < Ready[nNiz][job] || Precedence[job][0] > 0)
581 if(Duration[nNiz][job] < najkrace)
582 { najkrace = Duration[nNiz][job];
587 for(i = nJob; i < nPoslova; i++)
588 {
int job = pIndex[i];
589 if(Precedence[job][0] > 0)
591 if(Duration[nNiz][job] > najdulje && Ready[nNiz][job] <= (dClock+najkrace))
592 najdulje = Duration[nNiz][job];
598 for(i = nJob; i<nPoslova; i++)
601 pSlack[j] = POS(Deadline[nNiz][j] - (dClock + Duration[nNiz][j]));
602 tree->setTerminalValue(
"SL", &pSlack[j]);
603 tree->setTerminalValue(
"pt", &Duration[nNiz][j]);
604 tree->setTerminalValue(
"w", &WeightT[nNiz][j]);
605 tree->setTerminalValue(
"dd", &Deadline[nNiz][j]);
609 tree->setTerminalValue(
"STP", &Setup[nLastJob][j]);
610 tree->setTerminalValue(
"Sav", &pSetupAvg[nLastJob]);
615 tree->setTerminalValue(
"SC", &Precedence[j][1]);
616 tree->setTerminalValue(
"LVL", &Level[nNiz][j]);
619 tree->execute(&dCurrent);
620 pVrijednosti[j] = dCurrent;
625 dBest = pVrijednosti[pIndex[najkraci]];
626 nOdabrani = najkraci;
627 for(i=nJob; i<nPoslova; i++)
628 {
if((pVrijednosti[pIndex[i]] < dBest) && (Ready[nNiz][pIndex[i]] < dClock + najkrace) \
629 && Precedence[pIndex[i]][0] == 0)
630 { dBest = pVrijednosti[pIndex[i]];
634 kada = Ready[nNiz][pIndex[nOdabrani]] - dClock;
648 for(i = nJob; i<nPoslova; i++)
651 pSlack[j] = POS(Deadline[nNiz][j] - (dClock + Duration[nNiz][j]));
652 tree->setTerminalValue(
"SL", &pSlack[j]);
653 tree->setTerminalValue(
"pt", &Duration[nNiz][j]);
654 tree->setTerminalValue(
"w", &WeightT[nNiz][j]);
655 tree->setTerminalValue(
"dd", &Deadline[nNiz][j]);
659 tree->setTerminalValue(
"STP", &Setup[nLastJob][j]);
660 tree->setTerminalValue(
"Sav", &pSetupAvg[nLastJob]);
665 tree->setTerminalValue(
"SC", &Precedence[j][1]);
666 tree->setTerminalValue(
"LVL", &Level[nNiz][j]);
669 tree->execute(&dCurrent);
671 pVrijednosti[j] = dCurrent;
674 dBest = pVrijednosti[pIndex[nJob]];
678 for(; Precedence[pIndex[nOdabrani]][0] > 0; nOdabrani++) NULL;
680 for(i = nJob; i<nPoslova; i++)
682 int index = pIndex[i];
683 if(pVrijednosti[index] < dBest && Precedence[index][0] == 0)
684 { dBest = pVrijednosti[index];
693 pIndex[nJob] = pIndex[nOdabrani];
694 pIndex[nOdabrani] = i;
695 pRasporedjen[pIndex[nJob]] =
true;
698 dClock += Duration[nNiz][pIndex[nJob]];
699 dSPr -= Duration[nNiz][pIndex[nJob]];
700 dSDr -= Deadline[nNiz][pIndex[nJob]];
703 for(i=0; i<Precedence[pIndex[nJob]][1]; i++)
704 { j = (int) Precedence[pIndex[nJob]][i+2];
705 Precedence[j][0] -= 1;
708 { dClock += Setup[nLastJob][pIndex[nJob]];
709 nLastJob = pIndex[nJob];
711 Schedule[nNiz][nJob] = pIndex[nJob];
717 {
for(nJob=nPoslova ; nJob < this->max_jobs; nJob++)
718 Schedule[nNiz][nJob] = 0;
721 dClock = 0; nLastJob = nPoslova; dAvgWeights = dAvgDuration = 0;
722 for(nJob = 0; nJob<nPoslova; nJob++)
723 { index = pIndex[nJob];
724 dAvgWeights += WeightT[nNiz][index];
725 dAvgDuration += Duration[nNiz][index];
726 if(m_dynamic && dClock < Ready[nNiz][index])
727 dClock = Ready[nNiz][index];
729 dClock += Setup[nLastJob][index];
731 dClock += Duration.data[nNiz][index];
732 dRez = dClock - Deadline.Get(nNiz,index);
733 dLateness += dRez*WeightT.data[nNiz][index];
734 if(dRez > 0) dTardiness += dRez*WeightT.data[nNiz][index];
735 if(dRez > 0) nLateJobs ++;
736 if(dRez > 0) dNwt += WeightN.data[nNiz][index];
741 dAvgWeights /= nPoslova;
742 dAvgDuration /= nPoslova;
743 dTardiness /= (nPoslova * dAvgWeights * dAvgDuration);
744 dNwt /= (nPoslova * dAvgWeights);
747 {
case Twt: dRawFitness += dTardiness;
break;
748 case Nwt: dRawFitness += dNwt;
break;
751 nTotalLateJobs += nLateJobs;
753 dTotalLateness += dLateness;
754 dTotalTardiness += dTardiness;
755 Fitness[nNiz][Twt] = dTardiness;
763 Fitness[sets][Twt] = dTotalTardiness;
764 Fitness[sets][Nwt] = dTotalNwt;
Fitness for minimization problems.
bool initialize(StateP)
Initialize the evaluator. Called before first evaluation occurs.
FitnessP evaluate(IndividualP individual)
Evaluate a single individual. Method must create and return a Fitness object.
void registerParameters(StateP)
Register evaluator parameters. Called before EvaluateOp::initialize method.