• Main Page
  • Modules
  • Classes
  • Files
  • File List

D:/Projekt/ECF_trunk/examples/iprojekt/fitnes.cpp

00001 /*
00002 Radi za:
00003 SINGLE okruzenje:
00004 - staticke i dinamicke dolaske poslova
00005 - sa i bez ogranicenja u rasporedu
00006 - trajanja postavljanja za staticki i dinamicki slucaj
00007 UNIFORM okruzenje:
00008 - staticke i dinamicke dolaske poslova
00009 - trajanja postavljanja za staticki i dinamicki slucaj
00010 treba napraviti:
00011 - promijeniti racunanje SPr ! (otkomentirati)
00012 UNRELATED okruzenje:
00013 - dinamicki uvjeti rada (simulacija online schedulinga)
00014 JOBSHOP okruzenje:
00015 - staticki dolasci poslova
00016 - sa ili bez idle time
00017 */
00018 
00019 #include <ecf/ECF.h>
00020 #include "fitnes.hpp"
00021 #include <cmath>
00022 
00023 // globalna varijabla - koriste je svi zivi...
00024 node Nodes[TOTAL_NODES];
00025 
00026 // makroi za uvjetnu provjeru
00027 #define CHECKMSG(condition, text) \
00028 if(!(condition)) {fprintf(stderr,"file: " __FILE__ "\nline: %d\nmsg:  " text "\n",__LINE__); exit(1);}
00029 #define CHECK(condition) \
00030 if(!(condition)) {fprintf(stderr,"Nesto ne valja!\nfile: " __FILE__ "\nline: %d\n" ,__LINE__); exit(1);}
00031 // fja max{x,0}
00032 #define POS(x)      (x>0 ? x : 0)
00033 #define MIN(x,y)    (x<y ? x : y)
00034 #define MAX(x,y)    (x>y ? x : y)
00035 
00036 
00037 // fja za uporabu qsort-a
00038 double *pVal;
00039 int Before(const void *arg1, const void *arg2)
00040 {
00041     if(pVal[*(uint*)arg1] < pVal[*(uint*)arg2])
00042         return -1;
00043     else if(pVal[*(uint*)arg1] > pVal[*(uint*)arg2])
00044         return 1;
00045     return 0;
00046 }
00047 
00048 
00049 // definira imena terminala i funkcija; takodjer postavlja aktivne funkcije
00050 SchedulingEvalOp::SchedulingEvalOp()
00051 {
00052     for(int i=0; i<TERMINALS+OFFSET; i++)
00053     {   Nodes[i].active = false;
00054     }
00055     for(int i=TERMINALS+OFFSET; i<TOTAL_NODES; i++)
00056     {   Nodes[i].active = true;
00057     }
00058     // definiramo imena mogucih funkcija i terminala
00059     Nodes[NUL].name = "0";
00060     Nodes[NUL].value = 0;
00061     Nodes[ONE].name = "1";
00062     Nodes[ONE].value = 1;
00063     Nodes[T_N].name = "N";
00064     Nodes[T_SP].name = "SP";
00065     Nodes[T_SD].name = "SD";
00066     Nodes[T_pt].name = "pt";
00067     Nodes[T_dd].name = "dd";
00068     Nodes[T_w].name = "w";
00069     Nodes[T_Nr].name = "Nr";
00070     Nodes[T_SPr].name = "SPr";
00071     Nodes[T_SL].name = "SL";
00072     Nodes[T_AR].name = "AR";
00073     Nodes[T_SC].name = "SC";
00074     Nodes[T_LVL].name = "LVL";
00075     Nodes[T_STP].name = "STP";
00076     Nodes[T_Sav].name = "Sav";
00077     Nodes[T_SLs].name = "SLs";
00078     Nodes[T_SPD].name = "SPD";
00079     Nodes[T_Msm].name = "Msm";
00080     Nodes[T_pmin].name = "pmin";
00081     Nodes[T_pavg].name = "pavg";
00082     Nodes[T_PAT].name = "PAT";
00083     Nodes[T_MR].name = "MR";
00084     Nodes[T_age].name = "age";
00085     Nodes[T_L].name = "L";
00086     Nodes[T_SLr].name = "SLr";
00087     Nodes[T_CLK].name = "CLK";
00088     Nodes[T_NOPr].name = "NOPr";
00089     Nodes[T_TWK].name = "TWK";
00090     Nodes[T_TWKr].name = "TWKR";
00091     Nodes[T_PTav].name = "PTav";
00092     Nodes[T_HTR].name = "HTR";
00093     Nodes[T_TF].name = "TF";
00094     // terminali za strojeve
00095     Nodes[T_MNOPr].name = "MNOPr";
00096     Nodes[T_MNOPw].name = "MNOPw";
00097     Nodes[T_MTWK].name = "MTWK";
00098     Nodes[T_MTWKr].name = "MTWKr";
00099     Nodes[T_MTWKav].name = "MTWKav";
00100     Nodes[T_MUTL].name = "MUTL";
00101     // funkcije
00102     Nodes[ADD].name = "+";
00103     Nodes[SUB].name = "-";
00104     Nodes[MUL].name = "*";
00105     Nodes[DIV].name = "/";
00106     Nodes[POS].name = "pos";
00107     Nodes[SQR].name = "sqr";
00108     Nodes[IFGT].name = "ifgt";
00109     // default parametri
00110     m_Idleness = false;     // po defaultu ne cekamo u job shop okruzenju
00111     m_TermUsage = false;    // iskljucena statistika koristenja terminala
00112     m_BestSubset = 100;     // po defaultu gledamo 100 najboljih
00113     m_LEF = 0;  // nema rezanja fitnesa po defaultu
00114     m_editing = false;  // niti editiranja
00115     m_Evaluation = false;   // pisanje detaljnih rezultata u fajl je iskljuceno
00116     Evaluator.SetExprSize(2000);    // postavimo max velicinu izraza... :)
00117     edited = 0; // koliko cvorova je editirano
00118     total = 0;  // koliko cvorova je ukupno bilo
00119 }
00120 
00121 
00122 SchedulingEvalOp::~SchedulingEvalOp()
00123 {
00124     delete [] pRasporedjen;
00125     delete [] pVrijednosti;
00126     delete [] pIndex;
00127     delete [] pUsed;
00128     delete [] pArray;
00129     delete [] pSlack;
00130     delete [] pSlackSpeed;
00131     delete [] pSamples;
00132     delete [] pArrival;
00133     delete [] pLevel;
00134     delete [] pSetupAvg;
00135     delete [] pLastJob;
00136     delete [] pMachineScheduled;
00137     delete [] pOperationReady;
00138     delete [] pJobReady;
00139     delete [] pOperationsScheduled;
00140     delete [] pTotalWorkRemaining;
00141     delete [] pTotalWorkDone;
00142     delete [] pTotalMachineWork;
00143     delete [] pMachineWorkRemaining;
00144     delete [] pOperationsWaiting;
00145     delete [] pMachineValues;
00146 }
00147 
00148 
00149 void SchedulingEvalOp::registerParameters(StateP state)
00150 {
00151     state->getRegistry()->registerEntry("test_cases", (voidP) (new std::string), ECF::STRING);
00152     state->getRegistry()->registerEntry("normalized", (voidP) (new uint(1)), ECF::UINT);
00153 }
00154 
00155 
00156 // inicijalizacija
00157 // zove se nakon ucitavanja GP parametara, prije pocetka evolucije
00158 bool SchedulingEvalOp::initialize(StateP state)
00159 {
00160     std::string configFile;
00161 
00162     // check if the parameters are defined in the conf. file
00163     if(!state->getRegistry()->isModified("test_cases"))
00164         return false;
00165 
00166     voidP sptr = state->getRegistry()->getEntry("test_cases"); // get parameter value
00167     configFile = *((std::string*) sptr.get()); // convert from voidP to user defined type
00168     in_file = configFile;
00169 
00170     sptr = state->getRegistry()->getEntry("normalized"); // get parameter value
00171     m_Normalized = (bool) *((uint*) sptr.get()); // convert from voidP to user defined type
00172 
00173     // procitaj terminale iz registrija
00174     ReadTerminals(state);
00175 
00176 // originalni dio iz BEAGLE implementacije:
00177     std::string input,sp,duration,deadline,weightT,weightF,weightE,weightN,term,ready,cons,speed;
00178     char pom[256];
00179     ReadPar p;
00180     unsigned int i,j;
00181     double d_niz[2][1000];
00182 
00185     //IntegerVector::Handle hPopSize;
00186     //hPopSize = castHandleT<IntegerVector>(ioSystem.getRegister().getEntry("ec.pop.size"));
00187     //unsigned int nDemes = (unsigned int) (*hPopSize).size();
00188     //m_PopSize = 0;
00189     //for(i=0; i<nDemes; i++)
00190     //  m_PopSize += (*hPopSize)[i];
00193     //m_SubsetSize = (uint) (0.1 * (float)m_PopSize) + 1;
00194 
00195     // inicijalizacija default vrijednosti
00196     input = configFile; // glavni ulazni fajl, mora ga biti
00197 
00198     // ucitavanje parametara
00199     p.OpenFile(input.c_str());
00200     if(p.ReadParameter("single",ReadPar::INTEGER,&i))
00201         m_Environment = SINGLE;
00202     else if(p.ReadParameter("uniform",ReadPar::INTEGER,&i))
00203         m_Environment = UNIFORM;
00204     else if(p.ReadParameter("unrelated",ReadPar::INTEGER,&i))
00205         m_Environment = UNRELATED;
00206     else if(p.ReadParameter("jobshop",ReadPar::INTEGER,&i))
00207         m_Environment = JOBSHOP;
00208     p.ReadParameter("sets",ReadPar::INTEGER,&sets);
00209     p.ReadParameter("max_jobs",ReadPar::INTEGER,&max_jobs);
00210     if(!p.ReadParameter("max_machines",ReadPar::INTEGER,&max_machines))
00211         max_machines = 1;
00212     p.ReadParameter("max_length",ReadPar::INTEGER,&max_length);
00213     p.ReadParameter("duration",ReadPar::STRING,pom); duration = pom;
00214     p.ReadParameter("deadline",ReadPar::STRING,pom); deadline = pom;
00215     p.ReadParameter("weight_T",ReadPar::STRING,pom); weightT = pom;
00216     p.ReadParameter("weight_F",ReadPar::STRING,pom); weightF = pom;
00217     p.ReadParameter("weight_E",ReadPar::STRING,pom); weightE = pom;
00218     p.ReadParameter("weight_N",ReadPar::STRING,pom); weightN = pom;
00219     p.ReadParameter("SP",ReadPar::STRING,pom); sp = pom;
00220     p.ReadParameter("machine_file",ReadPar::STRING,pom); speed = pom;
00221     // dinamicki dolasci poslova
00222     if(p.ReadParameter("ready",ReadPar::STRING,pom))
00223     {   ready = pom;
00224         m_dynamic = true;
00225     }
00226     else
00227         m_dynamic = false;
00228     // limited error fitness izracunavanje
00229     if(p.ReadParameter("LEF",ReadPar::INTEGER,&i))
00230     {   if(i==1)
00231         {   m_LEF = true;
00232             if(!p.ReadParameter("LEF_value",ReadPar::DOUBLE,&m_LEFVal))
00233                 CHECKMSG(0,"LEF vrijednost nije zadana!");
00234         }
00235     }
00236     // evaluacija - ispis rjesenja za svaku jedinku
00237     if(p.ReadParameter("evaluation",ReadPar::INTEGER,&i))
00238         if(i==1) m_Evaluation = true;
00239     // fitness - mora biti definiran
00240     if(p.ReadParameter("fitness",ReadPar::STRING,pom))
00241     {   input = pom;
00242         if(input == "Twt")
00243             m_fitness = Twt;
00244         else if(input == "Nwt")
00245             m_fitness = Nwt;
00246         else if(input == "FTwt")
00247             m_fitness = FTwt;
00248         else if(input == "ETwt")
00249             m_fitness = ETwt;
00250         else if(input == "Cmax")
00251             m_fitness = Cmax;
00252         else if(input == "Fwt")
00253             m_fitness = Fwt;
00254         else
00255             CHECKMSG(0,"Nepoznata fitnes funkcija!");
00256     }
00257     else CHECKMSG(0,"Nije definirana fitnes funkcija!");
00258     // editiranje jedinke
00259     if(p.ReadParameter("editing",ReadPar::INTEGER,&i))
00260         if(i==1) m_editing = true;
00261     // stochastic sampling, koliko
00262     if(p.ReadParameter("stsampling",ReadPar::DOUBLE,&m_sampling))
00263         m_stsampling = true;
00264     else
00265         m_stsampling = false;
00266     // ogranicenja u rasporedu
00267     if(p.ReadParameter("constraints",ReadPar::STRING,pom))
00268     {   cons = pom;
00269         m_constrained = true;
00270     }
00271     else
00272         m_constrained = false;
00273     // trajanja postavljanja
00274     if(p.ReadParameter("setup",ReadPar::DOUBLE,&m_setup_faktor))
00275         m_setup = true;
00276     else
00277         m_setup = false;
00278     // eventualno definiranje podskupa jedinki za brojanje terminala
00279     p.ReadParameter("bestsubset",ReadPar::INTEGER,&m_BestSubset);
00280     if(p.ReadParameter("idleness",ReadPar::INTEGER, &i))
00281         if(i == 1)  m_Idleness = true;
00282 
00283     N.Init(sets);
00284     SP.Init(sets);
00285     SD.Init(sets);
00286     Machines.Init(sets);
00287     MachineReady.Init(max_machines);
00288     Speed.Init(sets,max_jobs);
00289     Duration.Init(sets,max_jobs);
00290     Deadline.Init(sets,max_jobs);
00291     Durations.Init(max_jobs, max_machines);
00292     MachineIndex.Init(max_jobs, max_machines);
00293     WeightT.Init(sets,max_jobs);
00294     WeightF.Init(sets,max_jobs);
00295     WeightE.Init(sets,max_jobs);
00296     WeightN.Init(sets,max_jobs);
00297     Fitness.Init(sets+1,FUNCTIONS);
00298     Values.Init(max_machines,max_jobs);
00299     Precedence.Reset(max_jobs,max_jobs);    // prazna matrica znaci da nema ogranicenja!
00300     Setup.Init(max_jobs+1,max_jobs);
00301     if(m_Environment == JOBSHOP)
00302     {   Schedule.Init(sets, max_machines*max_jobs);
00303         PTimeAvg.Reset(sets, max_machines);
00304     }
00305     else
00306     {   Schedule.Init(sets,max_jobs);
00307         PTimeAvg.Init(sets,max_jobs);
00308         PTimeMinMachine.Init(sets,max_jobs);
00309     }
00310     SortedReady.Init(sets,max_jobs);
00311 
00312     pVrijednosti = new double[max_jobs];
00313     pRasporedjen = new bool[max_jobs];
00314     pIndex = new unsigned int[max_jobs];
00315     pUsed = new unsigned int[max_jobs];
00316     pArray = new double[max_jobs];
00317     pSlack = new double[max_jobs];
00318     pSlackSpeed = new double[max_jobs];
00319     pArrival = new double[max_jobs];
00320     pLevel = new double[max_jobs];
00321     pSetupAvg = new double[max_jobs + 1];
00322     pSamples = new bool[sets];
00323     pLastJob = new unsigned int[max_machines];
00324     pMachineScheduled = new unsigned int[max_machines];
00325     pOperationReady = new double[max_machines];
00326     pJobReady = new double[max_jobs];
00327     pOperationsScheduled = new unsigned int[max_jobs];
00328     pTotalWorkRemaining = new double[max_jobs];
00329     pTotalWorkDone = new double[max_jobs];
00330     pTotalMachineWork = new double[max_machines];
00331     pOperationsWaiting = new unsigned int[max_machines];
00332     pMachineWorkRemaining = new double[max_machines];
00333     pMachineValues = new double[max_machines];
00334     p.ReadParameter("jobs",ReadPar::DOUBLE,&d_niz[0][0],sets);
00335     p.ReadParameter("machines",ReadPar::DOUBLE,&d_niz[1][0],sets);
00336     total_jobs = 0;
00337     for(i=0; i<sets; i++)
00338     {   N[i][0] = d_niz[0][i];
00339         total_jobs += (int) d_niz[0][i];
00340         Machines[i][0] = d_niz[1][i];
00341     }
00342     Duration.Load(duration.c_str());
00343     Deadline.Load(deadline.c_str());
00344     if(m_Environment==UNIFORM)
00345     {   Speed.Load(speed.c_str());
00346     }
00347     WeightT.Load(weightT.c_str());
00348     WeightF.Load(weightF.c_str());
00349     WeightE.Load(weightE.c_str());
00350     WeightN.Load(weightN.c_str());
00351     SP.Load(sp.c_str());
00352     if(m_dynamic) Ready.Load(ready.c_str());
00353     else Ready.Reset(sets,max_jobs);
00354     if(m_constrained) Constraints.Load(cons.c_str());
00355     // racunamo sumu deadline-a
00356     Level.Init(sets,max_jobs);
00357     for(i=0; i<sets; i++)
00358     {   SD.Set(i,0);
00359         for(j=0; j<(unsigned int)N.Get(i); j++)
00360         {   SD.data[i][0] += Deadline.data[i][j];
00361             Level[i][j] = -1;   // oznacimo da je neizracunato
00362         }
00363     }
00364     // racunamo level cvorova u grafu ovisnosti
00365     for(i=0; i<sets; i++)
00366     {   if(m_constrained)
00367             ReadConstraints(Constraints,i,(unsigned int)N.Get(i),Precedence);
00368         for(j=0; j<(unsigned int)N.Get(i); j++)
00369             Level[i][j] = NodeLevel(i,j);
00370     }
00371     // racunamo prosjek i minimalno trajanje izvodjenja za UNRELATED
00372     if(m_Environment == UNRELATED)
00373     {   for(uint set=0; set<sets; set++)
00374         {   uint jobs = (uint) N[set][0];
00375             uint machines = (uint) Machines[set][0];
00376             for(j=0; j<jobs; j++)
00377             {   PTimeAvg[set][j] = 0;
00378                 uint min_machine = 0;
00379                 for(uint machine=0; machine<machines; machine++)
00380                 {   PTimeAvg[set][j] += Duration[set][j*machines + machine];
00381                     if(Duration[set][j*machines + machine] < Duration[set][j*machines + min_machine])
00382                         min_machine = machine;
00383                 }
00384                 PTimeAvg[set][j] /= machines;
00385                 PTimeMinMachine[set][j] = min_machine;
00386             }
00387         }
00388     }
00389     if(m_Environment == JOBSHOP)    // prosjek trajanja operacija po strojevima
00390     {   for(uint set=0; set<sets; set++)
00391         {   uint jobs = (uint) N[set][0];
00392             uint machines = (uint) Machines[set][0];
00393             for(j=0; j<jobs; j++)
00394             {   uint operations = machines;
00395                 for(uint op=0; op<operations; op++)
00396                 {   double dur = Duration[set][j*operations + op];
00397                     uint machine = (uint) dur / 1000;
00398                     dur = (int)dur % 1000;  // dobijemo trajanje
00399                     PTimeAvg[set][machine] += dur;
00400                 }
00401             }
00402             for(uint m=0; m<machines; m++)
00403                 PTimeAvg[set][m] /= jobs;
00404         }
00405     }
00406 
00407     // sortiramo indekse poslova po dolascima - treba za ubrzano izracunavanje
00408     for(i=0; i<sets; i++)
00409     {   ::pVal = Ready[i];
00410         uint jobs = (uint) N[i][0];
00411         for(j=0; j<jobs; j++)
00412             pIndex[j] = j;
00413         qsort(pIndex,jobs,sizeof(unsigned int),::Before);
00414         for(j=0; j<jobs; j++)
00415             SortedReady[i][j] = pIndex[j];
00416     }
00417                 
00418     p.CloseFile();
00419 
00420     return true;
00421 }
00422 
00423 
00424 
00425 // zove se iz main() prije inicijalizacije populacije
00426 void SchedulingEvalOp::DefineNodeNames(void)
00427 {
00428 }
00429 
00430 
00431 // citanje terminala iz konf. datoteke
00432 // radi se prije inicijalizacije populacije; poziva se iz main()
00433 void SchedulingEvalOp::ReadTerminals(TreeP tree)
00434 {
00435     int i,dummy;
00436     ReadPar p;
00437     std::string term;
00438     p.OpenFile(in_file.c_str());
00439 
00440     // citanje aktivnih terminala
00441     for(i = OFFSET; i < TERMINALS + OFFSET; i++)
00442     {   term = "T_" + Nodes[i].name;
00443         if(p.ReadParameter(term.c_str(),ReadPar::INTEGER,&dummy))
00444         {   Nodes[i].active = true;
00445 
00446             // zadavanje terminala ECF-u
00447             Tree::PrimitiveP newTerm = (Tree::PrimitiveP) new Tree::Primitives::Terminal;
00448             newTerm->setName(Nodes[i].name);
00449             tree->addTerminal(newTerm);
00450         }
00451     }
00452     p.CloseFile();
00453 }
00454 
00455 
00456 // citanje terminala iz ECF parametra 'tree.terminalset'
00457 // poziva se iz initialize()
00458 void SchedulingEvalOp::ReadTerminals(StateP state)
00459 {
00460     int i;
00461     std::string term;
00462 
00463     GenotypeP gen = (GenotypeP) (state->getGenotypes()[0]);
00464     TreeP tree = boost::dynamic_pointer_cast<Tree::Tree> (gen);
00465     voidP val = tree->getParameterValue(state, "terminalset");
00466     std::string terminals = *((std::string*) val.get());
00467     terminals = " " + terminals + " ";
00468 
00469     // citanje aktivnih terminala
00470     for(i = OFFSET; i < TERMINALS + OFFSET; i++)
00471     {   if(terminals.find(" " + Nodes[i].name + " ") != string::npos)
00472         {   Nodes[i].active = true;
00473         }
00474     }
00475 }
00476 
00477 
00478 FitnessP SchedulingEvalOp::evaluate(IndividualP individual)
00479 { 
00480 /*  double dClock, dRawFitness=0, dFitness, dRez, dSetFitness, dAvgWeights;
00481     double dLateness, dTotalLateness=0, dTardiness, dTotalTardiness=0;
00482     double dNwt, dTotalNwt=0, dBest, dSPr, dMsum, dSetupTime, dFwt;
00483     Double DResult, DBest;
00484     unsigned int nPoslova,nNiz,nJob,i,j,k,index,nLateJobs,nTotalLateJobs=0,nNr;
00485     unsigned int nLastJob,nMachines,nOdabrani,nMachine;
00486 */
00487     // stvaranje zeljenog Fintess objekta:
00488     FitnessP fitness = static_cast<FitnessP> (new FitnessMin);
00489 
00490     // dohvat genotipa jedinke
00491     TreeP tree = boost::dynamic_pointer_cast<Tree::Tree> (individual->getGenotype());
00492 
00493 // oroginalni kod iz BEAGLE implementacije
00494     unsigned int i;
00495     double dRawFitness, dFitness;
00496     ReadIndividual(individual); // procitaj i zapisi jedinku
00497 
00498     // stochastic sampling?
00499     if(m_stsampling)
00500     {   int koliko = (int) (m_sampling*sets);
00501         int razmak = sets / koliko;
00502         int pocetni = rand()%razmak;
00503         for(i=0; i<sets; i++)
00504             pSamples[i] = false;
00505         for(i=pocetni; i<sets; i+=razmak)
00506             pSamples[i] = true;
00507     }
00508 
00509     switch(m_Environment)
00510     {   case SINGLE:
00511             EvaluateSingle(dRawFitness);
00512         break;
00513         case UNIFORM:
00514             EvaluateUniform(dRawFitness);
00515         break;
00516         case UNRELATED:
00517             EvaluateUnrelated(dRawFitness);
00518         break;
00519         case JOBSHOP:
00520             EvaluateJobShop(dRawFitness);
00521         break;
00522     }
00523 
00524     //dFitness = dRawFitness /= nJobS*SETS; // prosjek
00525     //double lRMSE = sqrt(sqrt(dRawFitness));       // irelevantno za turnir selekciju
00526     //dFitness = (1.0 / (lRMSE + 1.0)); 
00527     dFitness = dRawFitness; // (trazimo minimum)
00528 
00529     if(m_Evaluation)    // samo za usporedbu heuristika! pise rezultate svih skupova u fajl
00530     {   Fitness.Save("rezultat_GP.txt");
00531         std::ostream *file = new std::ofstream("rezultat_GP.txt", std::ios_base::app);
00532         Evaluator.write();
00533         *file << std::endl << "-- infix: " << Evaluator.m_output << " --" << std::endl;
00534         *file << "Editirano: " << edited << ", ukupno: " << total << std::endl;
00535         *file << std::flush;
00536         delete file;
00537         Schedule.Save("raspored_GP.txt");
00538     }
00539 
00540     // pogledamo je li ukljuceno brojanje terminala
00541 //  if(m_TermUsage)
00542 //      UpdateTerminalStatistic(dFitness);
00543                 
00544     fitness->setValue(dFitness);
00545 
00546     return fitness;
00547 }
00548 
00549 
00550 void SchedulingEvalOp::write(std::string &output)
00551 {
00552 }
00553 
00554 
00555 // dekodira matricu Constraints i definira matricu Precedence
00556 void SchedulingEvalOp::ReadConstraints(Matrica &Constraints, int set, int jobs, Matrica &Precedence)
00557 {
00558     int i,j,prethodnika,prethodnik,pom;
00559     unsigned int podatak;
00560     //Precedence.Init(jobs,jobs);
00561     // prvo ocistimo prva dva stupca! gdje su brojevi prethodnika i sljedbenika
00562     for(i=0; i<jobs; i++)
00563         for(j=0; j<2; j++)
00564             Precedence[i][j] = 0;
00565     for(i=0; i<jobs; i++)
00566     {   podatak = (unsigned int) Constraints[set][i];
00567         prethodnik = 1; // koji po redu posao iza mene
00568         prethodnika = 0;
00569         while(podatak != 0)
00570         {   if(podatak%2 != 0)
00571             {   prethodnika++;  // povecam broj svojih prethodnika
00572                 pom = (int) Precedence[i-prethodnik][1] + 1;
00573                 Precedence[i-prethodnik][pom+1] = i;
00574                 Precedence[i-prethodnik][1] = pom;  // i broj sljedbenika od moga prethodnika
00575             }
00576             prethodnik++;
00577             podatak /= 2;
00578         }
00579         Precedence[i][0] = prethodnika;
00580     }
00581 }
00582 
00583 
00584 // generira matricu sequence dependant setup trajanja
00585 // i polje prosjecnih trajanja postavljanja za svaki posao prema ostalima
00586 void SchedulingEvalOp::MakeSetup(Matrica &Duration, int set, int jobs, double faktor, Matrica &Setup)
00587 {
00588     int i,j;
00589     pSetupAvg[jobs] = 0;
00590     if(m_Environment == JOBSHOP)
00591     {   srand(set);
00592         for(i=0; i<jobs; i++)
00593         {   Setup[jobs][i] = (int) ((rand()%max_length+1) * faktor);    // polazno trajanje postavljanja
00594             pSetupAvg[jobs] += Setup[jobs][i];
00595             for(j=0; j<=i; j++)
00596             {   Setup[i][j] = (int) ((rand()%max_length+1) * faktor);
00597                 Setup[j][i] = (int) ((rand()%max_length+1) * faktor);
00598                 pSetupAvg[i] += Setup[i][j];
00599                 pSetupAvg[j] += Setup[j][i];
00600             }
00601         }
00602     }
00603     else
00604         for(i=0; i<jobs; i++)
00605         {   pSetupAvg[i] = 0;
00606             Setup[jobs][i] = Duration[set][(i+1) % jobs];   // polazno trajanje postavljanja
00607             pSetupAvg[jobs] += Setup[jobs][i];
00608             for(j=0; j<=i; j++)
00609             {   Setup[i][j] = ceil( fabs( Duration[set][i] - Duration[set][j] ) * faktor);
00610                 Setup[j][i] = ceil( fabs( Duration[set][(i+1) % jobs] - Duration[set][(j+1) % jobs] ) * faktor);
00611                 pSetupAvg[i] += Setup[i][j];
00612                 pSetupAvg[j] += Setup[j][i];
00613             }
00614         }
00615     pSetupAvg[jobs] /= jobs;
00616     for(i=0; i<jobs; i++)
00617         pSetupAvg[i] /= (jobs-1);
00618 }
00619 
00620 
00621 // procita jedinku i zapise u RPN; takodjer editira i prebroji terminale
00622 void SchedulingEvalOp::ReadIndividual(IndividualP individual)
00623 {
00624     TreeP tree = boost::dynamic_pointer_cast<Tree::Tree> (individual->getGenotype());
00625     static std::string strTerminal;
00626     unsigned int nTreeSize,i,j,nTree;
00627     uint nTrees = (uint) individual->size();
00628     for(nTree = 0; nTree<nTrees; nTree++)   // vrtimo kroz stabla
00629     {   TreeP pTree = boost::dynamic_pointer_cast<Tree::Tree> (individual->getGenotype(nTree)); // pokazivac na tree
00630         nTreeSize = (uint) pTree->size();
00631         if(nTreeSize > Evaluator.m_iExprSize)   // jel imamo dovoljno mjesta za cvorove
00632             Evaluator.SetExprSize(nTreeSize);
00633 
00634         // procitamo cijelo stablo i zapisemo u rpn
00635         for(i=0; i<nTreeSize; i++)
00636         {   //strTerminal = (*pTree)[i].mPrimitive->getName();
00637             strTerminal = (*pTree)[i]->primitive_->getName();
00638             for(j=OFFSET; j<TOTAL_NODES; j++)
00639             {   if(!Nodes[j].active)
00640                     continue;
00641                 if(strTerminal == Nodes[j].name)
00642                 {   Evaluator.m_pExpression[nTree][i] = j;
00643                     break;
00644                 }
00645             }
00646             assert(j<TOTAL_NODES);
00647         }
00648         // editiranje?
00649         if(m_editing)
00650         {   Evaluator.m_nTree = nTree;  // zadamo na kojem se stablu radi
00651             Evaluator.m_iPosition = Evaluator.m_iEditedPos = -1;
00652             Evaluator.edit();
00653             Evaluator.copy();   // automatski prebrojava terminale i funkcije
00654             total += Evaluator.m_iPosition;
00655             edited += Evaluator.m_iPosition - Evaluator.m_iEditedPos;
00656         }
00657     }
00658 
00659 }
00660 
00661 
00662 // rekurzivno racunanje 'level' vrijednosti svakog posla
00663 // ima smisla samo u problemima s ogranicenjima
00664 // promjena 27.07: level cvora ukljucuje i trajanje cvora
00665 double SchedulingEvalOp::NodeLevel(int set, int node)
00666 {   double value,level;
00667     int succ,i,next;
00668     if(Level[set][node] > -1)   // ako je vec izracunato
00669         return Level[set][node];
00670     if(Precedence[node][1] == 0)    // ako nema sljedbenika
00671         return Duration[set][node];
00672     succ = (int)Precedence[node][1];    // koliko sljedbenika
00673     next = (int)Precedence[node][2];    // prvi sljedbenik
00674     level = NodeLevel(set,next) + Duration[set][node];  // level zbog prvog sljedbenika
00675     for(i=1; i<succ; i++)
00676     {   next = (int)Precedence[node][i+2];
00677         value = NodeLevel(set,next) + Duration[set][node];
00678         if(value > level)
00679             level = value;
00680     }
00681     return level;
00682 }
00683 
00684 
00685 // racuna vremenski i drugacije ovisne terminale
00686 void SchedulingEvalOp::CalcTimedTerminals(uint &nNiz, uint &nPoslova, uint &nJob, double &dClock, \
00687                                     uint nMachine, uint nMachines)
00688 {   uint i,j;
00689     for(i=nJob; i<nPoslova; i++)    // racunamo vrem. ovisne terminale, samo za nerasporedjene poslove
00690     {   j = pIndex[i];  // 'pravi' indeks posla
00691         if(m_Environment == UNIFORM)
00692         {   Evaluator.m_dTermValuesArray[T_SPD][j] = Speed[nNiz][nMachine]; // brzina stroja (neovisna o poslu)
00693             pSlack[j] = Deadline[nNiz][j] - (dClock + Duration[nNiz][j]);
00694             pSlackSpeed[j] = Deadline[nNiz][j] - (dClock + Duration[nNiz][j] * Speed[nNiz][nMachine]);
00695             Evaluator.m_dTermValuesArray[T_L][j] = POS(dClock + Duration[nNiz][j]*Speed[nNiz][nMachine]- Deadline[nNiz][j]);    // kasnjenje
00696         }
00697         if(m_Environment == UNRELATED)
00698         {   Evaluator.m_dTermValuesArray[T_PAT][j] = POS(MachineReady[(uint)PTimeMinMachine[nNiz][j]][0] - dClock);
00699             Evaluator.m_dTermValuesArray[T_MR][j] = POS(MachineReady[nMachine][0] - dClock);
00700             Evaluator.m_dTermValuesArray[T_pt][j] = Duration[nNiz][j*nMachines + nMachine];
00701             Evaluator.m_dTermValuesArray[T_age][j] = POS(dClock - Ready[nNiz][j]);
00702             pSlack[j] = Deadline[nNiz][j] - (dClock + Duration[nNiz][j*nMachines + nMachine]);
00703             Evaluator.m_dTermValuesArray[T_L][j] = POS(dClock + Duration[nNiz][j*nMachines + nMachine]- Deadline[nNiz][j]); // kasnjenje
00704         }
00705         if(m_Environment == SINGLE)
00706         {   pSlack[j] = Deadline[nNiz][j] - (dClock + Duration[nNiz][j]);
00707             Evaluator.m_dTermValuesArray[T_L][j] = POS(dClock + Duration[nNiz][j]- Deadline[nNiz][j]);  // kasnjenje
00708             //Evaluator.m_dTermValuesArray[T_L][j] = POS(dClock - Deadline[nNiz][j]);   // kasnjenje
00709         }
00710 
00711         // 'zajednicki' terminali
00712         Evaluator.m_dTermValuesArray[T_CLK][j] = dClock;
00713         pArrival[j] = POS(Ready[nNiz][j] - dClock); // pozitivna vrijednost dolaska
00714         Evaluator.m_dTermValuesArray[T_AR][j] = pArrival[j];    // za koliko dolazi
00715         if(pSlack[j]<0) pSlack[j] = 0;  // uzimamo samo pozitivni slack?
00716         if(pSlackSpeed[j]<0) pSlackSpeed[j] = 0;    // uzimamo samo pozitivni slack?
00717         // pokazalo se malo boljim!
00718         Evaluator.m_dTermValuesArray[T_SL][j] = pSlack[j];  // slack
00719         Evaluator.m_dTermValuesArray[T_SLs][j] = pSlackSpeed[j];    // slack sa brzinom
00720 
00721         if(m_Environment != SINGLE) // za SINGLE se racunaju u glavnoj funkciji
00722         {   // trajanje postavljanja u odnosu na zadnji posao na zadanom stroju
00723             Evaluator.m_dTermValuesArray[T_STP][j] = Setup[pLastJob[nMachine]][j];
00724             Evaluator.m_dTermValuesArray[T_Sav][j] = pSetupAvg[pLastJob[nMachine]]; // prosjecno t.p.
00725         }
00726     }
00727 }
00728 
00729 
00730 // obrada za SINGLE okruzenje
00731 void SchedulingEvalOp::EvaluateSingle(double &dRawFitness)
00732 {
00733     double dClock, dRez, dSetFitness, dAvgWeights, dAvgDuration, dAvgDueDate;
00734     double dLateness, dTotalLateness=0, dTardiness, dTotalTardiness=0;
00735     double dNwt, dTotalNwt=0, dBest, dSPr, dSDr;
00736     unsigned int nPoslova,nNiz,nJob,i,j,k,index,nLateJobs,nTotalLateJobs=0,nNr;
00737     unsigned int nLastJob,nOdabrani;
00738 
00739     dRawFitness=0;
00740 
00741 // vrtimo sve skupove
00742     for(nNiz=0; nNiz<sets; nNiz++)
00743     {   nNr = nPoslova = (int) N.Get(nNiz);
00744     // preliminarna ispitivanja
00745         // radimo li stochastic sampling
00746         if(m_stsampling)
00747             if(pSamples[nNiz] == false)
00748                 continue;   // jednostavno preskocimo taj test case
00749         // gleda li se limited error fitness
00750         if(m_LEF)
00751         {   if(dRawFitness > m_LEFVal)
00752                 break;  // prekid ispitivanja
00753         }
00754         if(m_constrained)   // ima li ogranicenja
00755             ReadConstraints(Constraints,nNiz,nPoslova,Precedence);
00756         if(m_setup) // trajanja postavljanja
00757             MakeSetup(Duration,nNiz,nPoslova,m_setup_faktor,Setup);
00758     // postavljanje pocetnih vrijednosti za pojedini skup
00759         nLateJobs = 0;
00760         dLateness = 0;
00761         dTardiness = 0;
00762         dNwt = 0;
00763         dClock = 0; dSetFitness = 0;
00764         nLastJob = nPoslova;
00765         dAvgDueDate = 0;
00766         for(i=0; i<nPoslova; i++)
00767         {   dAvgDueDate += Deadline[nNiz][i];
00768             pRasporedjen[i] = false;    // svi nerasporedjeni
00769             pIndex[i] = i;  // inicijalni poredak
00770         }
00771         dAvgDueDate /= nPoslova;
00772     // postavljanje pocetnih vrijednosti terminala
00773         Evaluator.m_pTermValues[T_N] = N.Get(nNiz);
00774         dSPr = Evaluator.m_pTermValues[T_SP] = SP.Get(nNiz);
00775         dSDr = Evaluator.m_pTermValues[T_SD] = SD.Get(nNiz);
00776         Evaluator.SetTermArraySize(nPoslova);   // koliko poslova u skupu - za vektorsku evaluaciju
00777         Evaluator.pIndex = pIndex;  // polje indeksa poslova
00778         Evaluator.m_iOffset = 0;        // indeks prvog nerasporedjenog
00779         for(i=0; i<nPoslova; i++)
00780         {   Evaluator.m_dTermValuesArray[T_N][i] = N.data[nNiz][0];
00781             Evaluator.m_dTermValuesArray[T_SP][i] = SP.data[nNiz][0];
00782             Evaluator.m_dTermValuesArray[T_SD][i] = SD.data[nNiz][0];
00783             Evaluator.m_dTermValuesArray[T_SC][i] = Precedence[i][1];   // broj sljedbenika
00784             Evaluator.m_dTermValuesArray[T_TF][i] = 1 - dAvgDueDate / SP[nNiz][0];
00785         }
00786         memcpy(Evaluator.m_dTermValuesArray[T_pt], Duration.data[nNiz], nPoslova*sizeof(double));
00787         memcpy(Evaluator.m_dTermValuesArray[T_dd], Deadline.data[nNiz], nPoslova*sizeof(double));
00788         memcpy(Evaluator.m_dTermValuesArray[T_w],  WeightT.data[nNiz], nPoslova*sizeof(double));
00789         memcpy(Evaluator.m_dTermValuesArray[T_LVL], Level[nNiz], nPoslova*sizeof(double));
00790 
00792 // ako u terminalima ima vremenski ovisnih, moramo raditi posao po posao
00793 // vektorska evaluacija!
00794         for(nJob=0; nJob<nPoslova; nJob++)  // rasporedjujemo svaki posao unutar skupa
00795         {   for(i=nJob; i<nPoslova; i++)    // racunamo vrem. ovisne terminale, samo za nerasporedjene poslove
00796             {   j = pIndex[i];
00797                 Evaluator.m_dTermValuesArray[T_SPr][j] = dSPr;  // suma trajanja preostalih
00798                 Evaluator.m_dTermValuesArray[T_Nr][j] = nNr;    // broj preostalih
00799                 Evaluator.m_dTermValuesArray[T_STP][j] = Setup[nLastJob][j];    // trajanje postavljanja
00800                 Evaluator.m_dTermValuesArray[T_Sav][j] = pSetupAvg[nLastJob];   // prosjecno t.p.
00801                 //Evaluator.m_dTermValuesArray[T_SD][j] = dSDr; // proba
00802             }
00803             Evaluator.m_iPosition = -1;
00804             Evaluator.m_iOffset = nJob; // od kojeg posla pocinjemo - prethodni su vec rasporedjeni!
00805 
00806             if(m_dynamic)   // dinamicka okolina; + uzeta u obzir eventualna ogranicenja
00807             {   unsigned int raspolozivi = nJob, prvi = nJob;
00808                 unsigned int najkraci;  // najkraci raspolozivi
00809                 // trebamo pronaci prvog raspolozivog bez nezavrsenih prethodnika
00810                 for(; Precedence[pIndex[raspolozivi]][0] > 0; raspolozivi++)    NULL;
00811                 double kada = Ready[nNiz][pIndex[raspolozivi]]; // pocetno vrijeme
00812                 double najdulje = 0, najkrace = 0;
00813                 for( ; raspolozivi < nPoslova; raspolozivi++)   // koji je 'najstariji'?
00814                 {   k = pIndex[raspolozivi];
00815                     if(Ready.data[nNiz][k] < kada && Precedence[k][0] == 0) // gledamo najblize vrijeme dolaska
00816                     {   kada = Ready.data[nNiz][k];
00817                         prvi = raspolozivi;
00818                     }
00819                 }
00820                 if(kada > dClock)   // nema raspolozivih 
00821                 {   dClock = kada;  // sat postavimo na najblize vrijeme dolaska
00822                 }
00823                 // trebamo izracunati nove vrijednosti vremenski ovisnih terminala!
00824                 CalcTimedTerminals(nNiz,nPoslova,nJob,dClock);
00825                 // pronadjimo najduljeg i najkraceg raspolozivog
00826                 najdulje = najkrace = Duration[nNiz][pIndex[prvi]];
00827                 najkraci = prvi;
00828                 for(i=nJob; i<nPoslova; i++)
00829                 {   k = pIndex[i];
00830                     if(dClock < Ready[nNiz][k] || Precedence[k][0] > 0)
00831                         continue;
00832                     if(Duration[nNiz][k] < najkrace)    // najkrace
00833                     {   najkrace = Duration[nNiz][k];
00834                         najkraci = i;
00835                     }
00836                 }
00837                 // sad pogledamo najduljega koji pocinje <= zavrsetka najkraceg raspolozivog
00838                 for(i=nJob; i<nPoslova; i++)
00839                 {   k = pIndex[i];
00840                     if(Precedence[k][0] > 0)
00841                         continue;
00842                     if(Duration[nNiz][k] > najdulje && Ready[nNiz][k] <= (dClock+najkrace)) // gledamo najdulje trajanje
00843                         najdulje = Duration[nNiz][k];
00844                 }
00845                 // sada je (dClock + najkrace + najdulje) limit za gledanje u buducnost!
00846 
00847                 Evaluator.evaluate_array(pVrijednosti); // ocijenimo sve
00848                 // prva verzija (kompliciranija)
00849                 // gledat cemo sve cije vrijeme dolaska je prije zavrsetka najduljeg trenutno raspolozivog
00850                     // MODIFIKACIJA (09.09.): gledamo sve koji mogu poceti prije zavrsetka najkraceg + trajanje do tada spremnog najduljeg!
00851                     // (pronadjemo najduljeg koji moze poceti prije zavrsetka najkraceg)
00852                 // tada: ako se prije odabranoga moze ugurati neki kraci, odaberemo najboljeg kraceg
00853                 //kada = najdulje + 1;  // poc. vrijednost za dolazak trenutno odabranog
00854                 kada = najkrace + najdulje;
00855                 dBest = pVrijednosti[pIndex[najkraci]]; // poc. vrijednost za usporedbu
00856                 nOdabrani = najkraci;
00857                 for(i=nJob; i<nPoslova; i++)    // trazimo najbolju vrijednost unutar < (dClock + kada)
00858                 {   k = pIndex[i];
00859                     if(Precedence[k][0] == 0 && (pVrijednosti[k] < dBest) && (Ready[nNiz][k] < dClock + kada))
00860                     {   dBest = pVrijednosti[k];
00861                         nOdabrani = i;
00862                     }
00863                 }
00864                 kada = Ready[nNiz][pIndex[nOdabrani]] - dClock; // za koliko pocinje odabrani?
00865                 if(kada >= najkrace)    // ako stane jos barem jedan, odaberimo najbolji koji ce zavrsiti prije pocetka odabranog
00866                 {   dBest = pVrijednosti[pIndex[najkraci]]; // poc. vrijednost za usporedbu
00867                     nOdabrani = najkraci;
00868                     for(i=nJob; i<nPoslova; i++)
00869                     {   k = pIndex[i];
00870                         if(Precedence[k][0] == 0 && (Ready[nNiz][k] + Duration[nNiz][k] <= dClock + kada) \
00871                             && pVrijednosti[k] < dBest \
00872                             && Ready[nNiz][k] - dClock < najkrace)  // pocinje prije zavrsetka najkraceg!
00873                         {   dBest = pVrijednosti[k];
00874                             nOdabrani = i;
00875                         }
00876                     }
00877                     kada = Ready[nNiz][pIndex[nOdabrani]] - dClock; // novi odabrani
00878                 }
00879 
00880 /*              // druga verzija (jednostavnija)
00881                 // samo gledamo najboljega koji moze poceti prije zavrsetka najkraceg raspolozivog
00882                 dBest = pVrijednosti[pIndex[najkraci]]; // poc. vrijednost za usporedbu
00883                 nOdabrani = najkraci;
00884                 for(i=nJob; i<nPoslova; i++)    // trazimo najbolju vrijednost unutar < (dClock + najkrace)
00885                 {   if((pVrijednosti[pIndex[i]] < dBest) && (Ready[nNiz][pIndex[i]] < dClock + najkrace) \
00886                         && Precedence[pIndex[i]][0] == 0)
00887                     {   dBest = pVrijednosti[pIndex[i]];
00888                         nOdabrani = i;
00889                     }
00890                 }
00891                 kada = Ready[nNiz][pIndex[nOdabrani]] - dClock; // za koliko pocinje odabrani?
00892 */
00893                 // redovni nastavak (iza 1. i 2. verzije)
00894                 if(kada > 0)    // odabrali smo cekati
00895                     dClock += kada; // ili: dClock = Ready[nNiz][pIndex[nOdabrani]];
00896             }   // endif - m_dynamic
00897 
00898             else    // staticki
00899             {   CalcTimedTerminals(nNiz,nPoslova,nJob,dClock);
00900                 nOdabrani = nJob;
00901                 if(m_constrained)   // trazimo prvi bez prethodnika
00902                     for(; Precedence[pIndex[nOdabrani]][0] > 0; nOdabrani++)    NULL;
00903                 Evaluator.evaluate_array(pVrijednosti); // ocijenimo sve
00904                 dBest = pVrijednosti[pIndex[nOdabrani]];    // pretpostavimo da je neki najbolji
00905                 for(i=nJob; i<nPoslova; i++)    // pa pogledamo ostale
00906                 {   // trazimo najmanju vrijednost
00907                     if(pVrijednosti[pIndex[i]] < dBest && Precedence[pIndex[i]][0] == 0)    // je li to najbolja vrijednost?
00908                     {   dBest = pVrijednosti[pIndex[i]];
00909                         nOdabrani = i;
00910                     }
00911                 }
00912             }
00913 
00914             // vrijednost pIndex[nOdabrani] je indeks posla koji ide sljedeci
00915             // gledamo nOdabrani kao rezultat; zamijenimo nJob-ti i odabrani u polju indeksa
00916             i = pIndex[nJob];
00917             pIndex[nJob] = pIndex[nOdabrani];
00918             pIndex[nOdabrani] = i;
00919             pRasporedjen[pIndex[nJob]] = true;
00920             dClock += Duration[nNiz][pIndex[nJob]]; // update vremena
00921             dSPr -= Duration[nNiz][pIndex[nJob]];       // update trajanja preostalih
00922             dSDr -= Deadline[nNiz][pIndex[nJob]];       // update deadlinea
00923             nNr--;                                          // update broja preostalih
00924             if(m_constrained)   // smanjimo broj prethodnika svim sljedbenicima odabranog posla
00925                 for(i=0; i<Precedence[pIndex[nJob]][1]; i++)
00926                 {   j = (int) Precedence[pIndex[nJob]][i+2];
00927                     Precedence[j][0] -= 1;
00928                 }
00929             if(m_setup) // trajanje postavljanja
00930             {   dClock += Setup[nLastJob][pIndex[nJob]];
00931                 nLastJob = pIndex[nJob];    // sljedeci prethodni posao
00932             }
00933             Schedule[nNiz][nJob] = pIndex[nJob];    // zapisemo u raspored
00934         } // kraj petlje koja vrti poslove u skupu
00935 
00936         // racunanje raznih kriterija za trenutni skup
00937         {   if(m_Evaluation)
00938             {   for(nJob=nPoslova ; nJob < this->max_jobs; nJob++)
00939                     Schedule[nNiz][nJob] = 0;                   // ostalo nule
00940             }
00941             // odredimo fitnes kriterij - sve moguce funkcije
00942             dClock = 0; nLastJob = nPoslova; dAvgWeights = dAvgDuration = 0;
00943             for(nJob = 0; nJob<nPoslova; nJob++)
00944             {   index = pIndex[nJob];
00945                 dAvgWeights += WeightT[nNiz][index];
00946                 dAvgDuration += Duration[nNiz][index];
00947                 if(m_dynamic && dClock < Ready[nNiz][index])    // ako jos nije raspoloziv
00948                     dClock = Ready[nNiz][index];
00949                 if(m_setup)
00950                     dClock += Setup[nLastJob][index];
00951                 nLastJob = index;
00952                 dClock += Duration.data[nNiz][index];   // update vremena
00953                 dRez = dClock - Deadline.Get(nNiz,index);   // kasnjenje
00954                 dLateness += dRez*WeightT.data[nNiz][index];    // tezinsko kasnjenje
00955                 if(dRez > 0) dTardiness += dRez*WeightT.data[nNiz][index];  // tezinska zakasnjelost
00956                 if(dRez > 0) nLateJobs ++;  // kao broj zakasnjelih poslova
00957                 if(dRez > 0) dNwt += WeightN.data[nNiz][index]; // tezinski broj zakasnjelih
00958             }
00959             // normiranje fitnesa ovisno o broju poslova - dodano 27.07.
00960             // promijenjeno (valjda konacno) 04.09.
00961             dAvgWeights /= nPoslova;    // prosjecni tezinski faktor skupa
00962             dAvgDuration /= nPoslova;
00963             dTardiness /= (nPoslova * dAvgWeights * dAvgDuration);
00964             dNwt /= (nPoslova * dAvgWeights);
00965             switch(m_fitness)   // sto uzimamo kao fitnes?
00966             {   case Twt: dRawFitness += dTardiness; break;
00967                 case Nwt: dRawFitness += dNwt; break;
00968                 default: exit(1);
00969             }
00970             nTotalLateJobs += nLateJobs;
00971             dTotalNwt += dNwt;
00972             dTotalLateness += dLateness;
00973             dTotalTardiness += dTardiness;
00974             Fitness[nNiz][Twt] = dTardiness;
00975             Fitness[nNiz][Nwt] = dNwt;
00976             Fitness[nNiz][FTwt] = 0;    // zasada
00977             Fitness[nNiz][ETwt] = 0;
00978         }
00979     }
00980 // kraj petlje koja vrti skupove poslova
00981     Fitness.data[sets][Twt] = dTotalTardiness;
00982     Fitness.data[sets][Nwt] = dTotalNwt;
00983 }
00984 
00985 
00986 
00987 // obrada za UNIFORM okruzenje
00988 // implementirani terminali: pt,w,dd,SPD,SL,Sls,Msm,STP,Sav,Nr,SP
00989 void SchedulingEvalOp::EvaluateUniform(double &dRawFitness)
00990 {
00991     double dClock, dRez, dSetFitness, dAvgWeights, dAvgDuration;
00992     double dLateness, dTotalLateness=0, dTardiness, dTotalTardiness=0, dTotalFwt=0;
00993     double dNwt, dTotalNwt=0, dBest, dSPr, dMsum, dSetupTime, dFwt, dCmax, dTotalCmax=0;
00994     unsigned int nPoslova,nNiz,nJob,i,j,k,index,nLateJobs,nTotalLateJobs=0,nNr;
00995     unsigned int nLastJob,nMachines,nOdabrani,nMachine;
00996 
00997     dRawFitness=0;
00998 
00999 // vrtimo sve skupove
01000     for(nNiz=0; nNiz<sets; nNiz++)
01001     {   nNr = nPoslova = (int) N.Get(nNiz);
01002     // preliminarna ispitivanja
01003         // radimo li stochastic sampling
01004         if(m_stsampling)
01005             if(pSamples[nNiz] == false)
01006                 continue;   // jednostavno preskocimo taj test case
01007         // gleda li se limited error fitness
01008         if(m_LEF)
01009         {   if(dRawFitness > m_LEFVal)
01010                 break;  // prekid ispitivanja
01011         }
01012         if(m_constrained)   // ima li ogranicenja
01013             ReadConstraints(Constraints,nNiz,nPoslova,Precedence);
01014         if(m_setup) // trajanja postavljanja
01015             MakeSetup(Duration,nNiz,nPoslova,m_setup_faktor,Setup);
01016     // postavljanje pocetnih vrijednosti za pojedini skup
01017         nLateJobs = 0;
01018         dLateness = 0;
01019         dTardiness = 0;
01020         dNwt = 0;
01021         dFwt = 0;
01022         dClock = 0; dSetFitness = 0;
01023         nLastJob = nPoslova;
01024         for(i=0; i<nPoslova; i++)
01025         {   pRasporedjen[i] = false;    // svi nerasporedjeni
01026             pIndex[i] = i;  // inicijalni poredak
01027         }
01028         nMachines = (uint) Machines[nNiz][0];
01029         dMsum = 0;
01030         for(j=0; j<nMachines; j++)
01031         {   MachineReady[j][0] = 0;     // pocetno vrijeme raspolozivosti strojeva
01032             dMsum += 1/Speed[nNiz][j];  // suma brzina svih strojeva
01033             pLastJob[j] = nPoslova;     // pocetni prethodni posao
01034         }
01035     // postavljanje pocetnih vrijednosti terminala
01036         Evaluator.m_pTermValues[T_N] = N.Get(nNiz);
01037         dSPr = Evaluator.m_pTermValues[T_SP] = SP.Get(nNiz);
01038         Evaluator.m_pTermValues[T_SD] = SD.Get(nNiz);
01039         Evaluator.SetTermArraySize(nPoslova);   // koliko poslova u skupu - za vektorsku evaluaciju
01040         Evaluator.pIndex = pIndex;  // polje indeksa poslova
01041         Evaluator.m_iOffset = 0;        // indeks prvog nerasporedjenog
01042         for(i=0; i<nPoslova; i++)
01043         {   Evaluator.m_dTermValuesArray[T_N][i] = N.data[nNiz][0];
01044             Evaluator.m_dTermValuesArray[T_SP][i] = SP.data[nNiz][0];
01045             Evaluator.m_dTermValuesArray[T_SD][i] = SD.data[nNiz][0];
01046             Evaluator.m_dTermValuesArray[T_SC][i] = Precedence[i][1];   // broj sljedbenika
01047         }
01048         memcpy(Evaluator.m_dTermValuesArray[T_pt], Duration.data[nNiz], nPoslova*sizeof(double));
01049         memcpy(Evaluator.m_dTermValuesArray[T_dd], Deadline.data[nNiz], nPoslova*sizeof(double));
01050         memcpy(Evaluator.m_dTermValuesArray[T_w],  WeightT.data[nNiz], nPoslova*sizeof(double));
01051         memcpy(Evaluator.m_dTermValuesArray[T_LVL], Level[nNiz], nPoslova*sizeof(double));
01052 
01054 // ako u terminalima ima vremenski ovisnih, moramo raditi posao po posao
01055 // vektorska evaluacija!
01056         for(nJob=0; nJob<nPoslova; nJob++)  // rasporedjujemo svaki posao unutar skupa
01057         {   for(i=nJob; i<nPoslova; i++)    // racunamo nove terminale samo za nerasporedjene
01058             {   j = pIndex[i];
01059                 Evaluator.m_dTermValuesArray[T_SPr][j] = dSPr;  // suma trajanja preostalih
01060                 Evaluator.m_dTermValuesArray[T_Nr][j] = nNr;    // broj preostalih
01061             }
01062             Evaluator.m_iPosition = -1;
01063             Evaluator.m_iOffset = nJob; // od kojeg posla pocinjemo - prethodni su vec rasporedjeni!
01064 
01065             if(m_dynamic)   // dinamicka okolina;
01066             {   // trebamo naci prvi raspolozivi stroj i prvi raspolozivi posao
01067                 unsigned int raspolozivi = nJob, prvi = nJob;
01068                 // trebamo pronaci prvog raspolozivog bez nezavrsenih prethodnika
01069                 for(; Precedence[pIndex[raspolozivi]][0] > 0; raspolozivi++)    NULL;
01070                 double kada = Ready[nNiz][pIndex[raspolozivi]]; // pocetno vrijeme
01071                 for( ; raspolozivi < nPoslova; raspolozivi++)   // koji je 'najstariji'?
01072                 {   k = pIndex[raspolozivi];
01073                     if(Ready.data[nNiz][k] < kada && Precedence[k][0] == 0) // gledamo najblize vrijeme dolaska
01074                     {   kada = Ready.data[nNiz][k];
01075                         prvi = raspolozivi;
01076                     }
01077                 }   // sada je pIndex[prvi] prvi raspolozivi posao
01078                 nMachine = 0;
01079                 for(i=0; i<nMachines; i++)
01080                     if(MachineReady[i][0] < MachineReady[nMachine][0])
01081                         nMachine = i;
01082                 // nMachine je prvi raspolozivi stroj
01083                 if(kada < MachineReady[nMachine][0])
01084                     kada = MachineReady[nMachine][0];
01085                 if(kada > dClock)   // prvo vrijeme kad imamo raspoloziv i stroj i posao
01086                     dClock = kada;  // sat postavimo na najblize vrijeme raspolozivosti
01087                 // trebamo izracunati nove vrijednosti vremenski ovisnih terminala!
01088                 CalcTimedTerminals(nNiz,nPoslova,nJob,dClock,nMachine);
01089 
01090                 Evaluator.evaluate_array(pVrijednosti); // ocijenimo sve
01091                 // samo gledamo najboljega koji moze poceti 
01092                 dBest = pVrijednosti[pIndex[prvi]]; // poc. vrijednost za usporedbu
01093                 nOdabrani = prvi;
01094                 for(i=nJob; i<nPoslova; i++)
01095                 {   if((pVrijednosti[pIndex[i]] < dBest) && Precedence[pIndex[i]][0] == 0 \
01096                         && Ready[nNiz][pIndex[i]] <= dClock)
01097                     {   dBest = pVrijednosti[pIndex[i]];
01098                         nOdabrani = i;
01099                     }
01100                 }
01101             }   // endif - m_dynamic
01102             else    // staticki
01103             {   // pronadjemo prvi raspolozivi stroj
01104                 nMachine = 0;
01105                 for(i=1; i<nMachines; i++)
01106                     if(MachineReady[i][0] < MachineReady[nMachine][0])
01107                         nMachine = i;
01108                 dClock = MachineReady[nMachine][0]; // to je trenutno vrijeme
01109                 CalcTimedTerminals(nNiz,nPoslova,nJob,dClock,nMachine);
01110                 nOdabrani = nJob;
01111                 if(m_constrained)   // trazimo prvi bez prethodnika
01112                     for(; Precedence[pIndex[nOdabrani]][0] > 0; nOdabrani++)    NULL;
01113                 Evaluator.evaluate_array(pVrijednosti); // ocijenimo sve
01114                 dBest = pVrijednosti[pIndex[nOdabrani]];    // pretpostavimo da je neki najbolji
01115                 for(i=nJob; i<nPoslova; i++)    // pa pogledamo ostale
01116                 {   // trazimo najmanju vrijednost
01117                     if(pVrijednosti[pIndex[i]] < dBest && Precedence[pIndex[i]][0] == 0)    // je li to najbolja vrijednost?
01118                     {   dBest = pVrijednosti[pIndex[i]];
01119                         nOdabrani = i;
01120                     }
01121                 }
01122             }
01123 
01124             // vrijednost pIndex[nOdabrani] je indeks posla koji ide sljedeci, na stroju nMachine
01125             // gledamo nOdabrani kao rezultat; zamijenimo nJob-ti i odabrani u polju indeksa
01126             i = pIndex[nJob];
01127             pIndex[nJob] = pIndex[nOdabrani];
01128             pIndex[nOdabrani] = i;
01129             pRasporedjen[pIndex[nJob]] = true;
01130 
01131             //dSPr -= Duration.data[nNiz][pIndex[nJob]];        // update trajanja preostalih
01132             dSPr -= Duration.data[nNiz][pIndex[nJob]]*dMsum;    // zapravo bi trebalo ovako!
01133             nNr--;                                          // update broja preostalih
01134             if(m_setup) // trajanje postavljanja
01135             {   dSetupTime = Setup[pLastJob[nMachine]][pIndex[nJob]];
01136                 pLastJob[nMachine] = pIndex[nJob];  // sljedeci prethodni posao
01137             }
01138             else dSetupTime = 0;
01139             if(m_constrained)   // smanjimo broj prethodnika svim sljedbenicima odabranog posla
01140                 for(i=0; i<Precedence[pIndex[nJob]][1]; i++)
01141                 {   j = (int) Precedence[pIndex[nJob]][i+2];
01142                     Precedence[j][0] -= 1;
01143                 }
01144             MachineReady[nMachine][0] = dClock + dSetupTime + \
01145                 Duration[nNiz][pIndex[nJob]] * Speed[nNiz][nMachine];
01146             // odredimo sljedeci element u matrici rasporeda (indeks stroja je tisucica)
01147             Schedule[nNiz][nJob] = pIndex[nJob] + nMachine * 1000;
01148         } // kraj petlje koja vrti poslove u skupu
01149         // racunanje raznih kriterija za trenutni skup
01150         {   if(m_Evaluation)
01151             {   for(nJob=nPoslova ; nJob < this->max_jobs; nJob++)
01152                     Schedule[nNiz][nJob] = 0;                   // ostalo nule
01153             }
01154             // odredimo fitnes kriterij - sve moguce funkcije
01155             dClock = 0; nLastJob = nPoslova; dAvgWeights = 0;
01156             for(i=0; i<nMachines; i++)
01157             {   MachineReady[i][0] = 0;
01158                 pLastJob[i] = nPoslova;
01159             }
01160             for(nJob = 0; nJob<nPoslova; nJob++)
01161             {   index = (int) Schedule[nNiz][nJob];
01162                 nMachine = index / 1000;    // na kojem stroju
01163                 index = index % 1000;       // koji posao
01164                 dAvgWeights += WeightT[nNiz][index];
01165                 if(m_dynamic && MachineReady[nMachine][0] < Ready[nNiz][index]) // ako posao jos nije raspoloziv
01166                     MachineReady[nMachine][0] = Ready[nNiz][index];
01167                 MachineReady[nMachine][0] += Duration[nNiz][index] * Speed[nNiz][nMachine];
01168                 if(m_setup)
01169                     MachineReady[nMachine][0] += Setup[pLastJob[nMachine]][index];
01170                 pLastJob[nMachine] = index;
01171                 dRez = MachineReady[nMachine][0] - Deadline.Get(nNiz,index);    // kasnjenje
01172                 dLateness += dRez*WeightT.data[nNiz][index];    // tezinsko kasnjenje
01173                 if(dRez > 0) dTardiness += dRez*WeightT.data[nNiz][index];  // tezinska zakasnjelost
01174                 if(dRez > 0) nLateJobs ++;  // kao broj zakasnjelih poslova
01175                 if(dRez > 0) dNwt += WeightN.data[nNiz][index]; // tezinski broj zakasnjelih
01176                 dFwt = (MachineReady[nMachine][0] - Ready[nNiz][index]) * WeightT[nNiz][index]; // tezinsko protjecanje
01177             }
01178             dCmax = 0;  // odredjivanje Cmax
01179             for(i=0; i<nMachines; i++)
01180                 if(MachineReady[i][0] > dCmax)
01181                     dCmax = MachineReady[i][0];
01182             // normiranje fitnesa ovisno o broju poslova - dodano 27.07.
01183             // i o prosjecnom trajanju - dodano 15.09.
01184             dAvgDuration = SP[nNiz][0] / nPoslova;  // prosjecno trajanje posla
01185             dAvgWeights /= nPoslova;    // prosjecni tezinski faktor skupa
01186             dTardiness /= (nPoslova * dAvgWeights * dAvgDuration);
01187             dNwt /= (nPoslova * dAvgWeights);
01188             dFwt /= (nPoslova * dAvgWeights * dAvgDuration);
01189             dCmax /= (nPoslova * dAvgDuration);
01190             switch(m_fitness)   // sto uzimamo kao fitnes?
01191             {   case Twt: dRawFitness += dTardiness; break;
01192                 case Nwt: dRawFitness += dNwt; break;
01193                 case Fwt: dRawFitness += dFwt; break;
01194                 case Cmax: dRawFitness += dCmax; break;
01195                 default: throw;
01196             }
01197             nTotalLateJobs += nLateJobs;
01198             dTotalNwt += dNwt;
01199             dTotalFwt += dFwt;
01200             dTotalLateness += dLateness;
01201             dTotalTardiness += dTardiness;
01202             dTotalCmax += dCmax;
01203             Fitness[nNiz][Twt] = dTardiness;
01204             Fitness[nNiz][Nwt] = dNwt;
01205             Fitness[nNiz][FTwt] = 0;    // zasada
01206             Fitness[nNiz][ETwt] = 0;
01207             Fitness[nNiz][Fwt] = dFwt;
01208             Fitness[nNiz][Cmax] = dCmax;
01209         }
01210 
01211     } // kraj petlje koja vrti skupove poslova
01212     Fitness[sets][Twt] = dTotalTardiness;
01213     Fitness[sets][Nwt] = dTotalNwt;
01214     Fitness[sets][FTwt] = 0;
01215     Fitness[sets][ETwt] = 0;
01216     Fitness[sets][Fwt] = dTotalFwt;
01217     Fitness[sets][Cmax] = dTotalCmax;
01218 }
01219 
01220 
01221 
01222 
01223 // obrada za UNRELATED okruzenje
01224 // implementirani terminali: w, dd, pt, SL, pmin, pavg, PAT, MR, age
01225 // ne koristimo u dinamickom: N, Nr, SP, SPr, SD
01226 void SchedulingEvalOp::EvaluateUnrelated(double &dRawFitness)
01227 {
01228     double dClock, dRez, dSetFitness, dAvgWeights, dCmax, dTotalCmax=0;
01229     double dLateness, dTotalLateness=0, dTardiness, dTotalTardiness=0;
01230     double dNwt, dTotalNwt=0, dBest, dSPr, dSetupTime, dFwt, dTotalFwt=0;
01231     unsigned int nPoslova,nNiz,nJob,i,j,k,index,nLateJobs,nTotalLateJobs=0,nNr;
01232     unsigned int nLastJob,nMachines,nOdabrani,nMachine;
01233 
01234     dRawFitness=0;
01235 
01236 // vrtimo sve skupove
01237     for(nNiz=0; nNiz<sets; nNiz++)
01238     {   nNr = nPoslova = (int) N.Get(nNiz);
01239     // preliminarna ispitivanja
01240         // radimo li stochastic sampling
01241         if(m_stsampling)
01242             if(pSamples[nNiz] == false)
01243                 continue;   // jednostavno preskocimo taj test case
01244         // gleda li se limited error fitness
01245         if(m_LEF)
01246         {   if(dRawFitness > m_LEFVal)
01247                 break;  // prekid ispitivanja
01248         }
01249         if(m_constrained)   // ima li ogranicenja
01250             ReadConstraints(Constraints,nNiz,nPoslova,Precedence);
01251         if(m_setup) // trajanja postavljanja
01252             MakeSetup(Duration,nNiz,nPoslova,m_setup_faktor,Setup);
01253     // postavljanje pocetnih vrijednosti za pojedini skup
01254         nLateJobs = 0;
01255         dLateness = 0;
01256         dTardiness = 0;
01257         dNwt = 0;
01258         dFwt = 0;
01259         dClock = 0; dSetFitness = 0;
01260         nLastJob = nPoslova;
01261         for(i=0; i<nPoslova; i++)
01262         {   pRasporedjen[i] = false;    // svi nerasporedjeni
01263             // procitamo niz indeksa poslova sortiran po dolasku
01264             pIndex[i] = (uint) SortedReady[nNiz][i];    // inicijalni poredak
01265         }
01266 
01267         nMachines = (uint) Machines[nNiz][0];
01268         for(j=0; j<nMachines; j++)
01269         {   MachineReady[j][0] = 0;     // pocetno vrijeme raspolozivosti strojeva
01270             pLastJob[j] = nPoslova;     // pocetni prethodni posao
01271         }
01272 
01273         // postavljanje pocetnih vrijednosti terminala
01274         dSPr = SP.Get(nNiz);
01275         Evaluator.SetTermArraySize(nPoslova);   // koliko poslova u skupu - za vektorsku evaluaciju
01276         Evaluator.pIndex = pIndex;  // polje indeksa poslova
01277         Evaluator.m_iOffset = 0;        // indeks prvog nerasporedjenog
01278         Evaluator.m_iEnd = 1;   // pocetna vrijednost zadnjeg posla koji se uzima u o obzir
01279         for(i=0; i<nPoslova; i++)
01280         {   Evaluator.m_dTermValuesArray[T_N][i] = N.data[nNiz][0];
01281             Evaluator.m_dTermValuesArray[T_SP][i] = SP.data[nNiz][0];
01282             Evaluator.m_dTermValuesArray[T_SD][i] = SD.data[nNiz][0];
01283             Evaluator.m_dTermValuesArray[T_SC][i] = Precedence[i][1];   // broj sljedbenika
01284             // najkrace trajanje izvodjenja posla
01285             Evaluator.m_dTermValuesArray[T_pmin][i] = Duration[nNiz][i*nMachines + (uint)PTimeMinMachine[nNiz][i]];
01286         }
01287         memcpy(Evaluator.m_dTermValuesArray[T_dd], Deadline.data[nNiz], nPoslova*sizeof(double));
01288         memcpy(Evaluator.m_dTermValuesArray[T_w],  WeightT.data[nNiz], nPoslova*sizeof(double));
01289         memcpy(Evaluator.m_dTermValuesArray[T_LVL], Level[nNiz], nPoslova*sizeof(double));
01290         memcpy(Evaluator.m_dTermValuesArray[T_pavg], PTimeAvg[nNiz], nPoslova*sizeof(double));
01291 
01293 // ako u terminalima ima vremenski ovisnih, moramo raditi posao po posao
01294 // vektorska evaluacija!
01295         for(nJob=0; nJob<nPoslova; nJob++)  // rasporedjujemo svaki posao unutar skupa
01296         {   for(i=nJob; i<nPoslova; i++)    // racunamo nove terminale samo za nerasporedjene
01297             {   j = pIndex[i];
01298                 Evaluator.m_dTermValuesArray[T_SPr][j] = dSPr;  // suma trajanja preostalih
01299                 Evaluator.m_dTermValuesArray[T_Nr][j] = nNr;    // broj preostalih
01300             }
01301             Evaluator.m_iPosition = -1;
01302             Evaluator.m_iOffset = nJob; // od kojeg posla pocinjemo - prethodni su vec rasporedjeni!
01303 
01304             if(m_dynamic)   // dinamicka okolina; zapravo simulacija online rasporedjivanja
01305 //
01306 // daklem ovako: 
01307 // - gledamo prvo vrijeme kad je raspoloziv i posao i stroj (barem jedan)
01308 // - ocijenimo sve poslove za sve strojeve
01309 // - gledamo najbolju vrijednost:
01310 //  - ako je za raspolozivi stroj, rasporedi
01311 //  - ako je za neraspolozivi stroj, gledaj sljedece vrijednosti (od drugih poslova)
01312 // - ako svi poslovi imaju svoje najbolje vrijednosti za neraspolozive strojeve, NE RASPOREDI nego 
01313 // pomakni vrijeme na prvi sljedeci raspolozivi stroj i ponovi ispocetka (za sve pristigle poslove!)
01314 // 
01315             {   // trebamo naci prvi raspolozivi stroj i prvi raspolozivi posao
01316                 unsigned int raspolozivi = nJob, prvi = nJob;
01317                 // trebamo pronaci prvog raspolozivog bez nezavrsenih prethodnika
01318                 for(; Precedence[pIndex[raspolozivi]][0] > 0; raspolozivi++)    NULL;
01319                 double kada = Ready[nNiz][pIndex[raspolozivi]]; // pocetno vrijeme
01320                 for( ; raspolozivi < nPoslova; raspolozivi++)   // koji je 'najstariji'?
01321                 {   k = pIndex[raspolozivi];
01322                     if(Ready.data[nNiz][k] < kada && Precedence[k][0] == 0) // gledamo najblize vrijeme dolaska
01323                     {   kada = Ready.data[nNiz][k];
01324                         prvi = raspolozivi;
01325                     }
01326                 }   // sada je pIndex[prvi] prvi raspolozivi posao
01327                 nMachine = 0;
01328                 for(i=0; i<nMachines; i++)
01329                     if(MachineReady[i][0] < MachineReady[nMachine][0])
01330                         nMachine = i;
01331                 // nMachine je prvi raspolozivi stroj
01332                 if(kada < MachineReady[nMachine][0])
01333                     kada = MachineReady[nMachine][0];
01334                 dClock = kada;  // sat postavimo na najblize vrijeme raspolozivosti
01335                 // sad odredimo koji zadnji posao gledamo iz polja indeksa
01336                 for(i=Evaluator.m_iEnd; i<nPoslova && Ready[nNiz][pIndex[i]]<=dClock; i++) NULL;
01337                 Evaluator.m_iEnd = i;
01338 
01339                 // probajmo ovako: pronaci najbolju kombinaciju svih pristiglih poslova i raspolozivih strojeva
01340                 // varijacija: gledamo sve strojeve (i one trenutno zauzete)
01341                 for(nMachine=0; nMachine<nMachines; nMachine++)
01342                 {   //if(MachineReady[nMachine][0] > dClock)    // varijanta samo sa slobodnim strojevima
01343                     //  continue;
01344                     // trebamo izracunati nove vrijednosti vremenski ovisnih terminala!
01345                     CalcTimedTerminals(nNiz,nPoslova,nJob,dClock,nMachine,nMachines);
01346                     Evaluator.m_iPosition = -1;
01347                     Evaluator.evaluate_array(pVrijednosti); // ocijenimo sve
01348                     memcpy(Values[nMachine],pVrijednosti,nPoslova*sizeof(double));  // pohranimo vrijednosti za taj stroj
01349                 }
01350                 bool BestSet = false;
01351                 uint nBestMachine, nBestJobMachine;
01352                 for(i=nJob; i<nPoslova; i++)
01353                 {   if(Precedence[pIndex[i]][0] != 0 || Ready[nNiz][pIndex[i]] > dClock)
01354                         continue;
01355                     // je li posao odabrao neraspolozivi stroj?
01356                     nBestJobMachine = 0;
01357                     for(nMachine=1; nMachine<nMachines; nMachine++)
01358                         if(Values[nBestJobMachine][pIndex[i]] < Values[nMachine][pIndex[i]])
01359                             nBestJobMachine = nMachine;
01360                     if(MachineReady[nBestJobMachine][0] > dClock)
01361                         continue;   // tebe necemo sada rasporediti...
01362                     if(!BestSet)    // ako je to prvi posao koji je odabrao raspolozivi stroj
01363                     {   nBestMachine = nBestJobMachine;
01364                         dBest = Values[nBestMachine][pIndex[i]];
01365                         nOdabrani = i;
01366                         BestSet = true;
01367                     }
01368                     else    // inace vidi kolika je vrijednost
01369                     {   if(Values[nBestJobMachine][pIndex[i]] < dBest)
01370                         {   nBestMachine = nBestJobMachine;
01371                             dBest = Values[nBestJobMachine][pIndex[i]];
01372                             nOdabrani = i;
01373                         }
01374                     }
01375                 }
01376                 // ako nijedan posao nije za raspolozivi stroj, prekidamo iteraciju petlje koja vrti poslove
01377                 if(!BestSet)
01378                 {   nJob--;
01379                     // vremena svih raspolozivih strojeva prebaci na prvi sljedeci zavrsetak
01380                     // prvo pronadji najblize sljedece vrijeme raspolozivosti stroja
01381                     for(i=0; i<nMachines && MachineReady[i][0] <= dClock; i++)  NULL;
01382                     nMachine = i;
01383                     for( ; i<nMachines; i++)
01384                         if(MachineReady[i][0] > dClock && MachineReady[i][0] < MachineReady[nMachine][0])
01385                             nMachine = i;
01386                     // a onda sve raspolozive stavi na to vrijeme
01387                     dClock = MachineReady[nMachine][0];
01388                     for(i=0; i<nMachines; i++)
01389                         if(MachineReady[i][0] < dClock)
01390                             MachineReady[i][0] = dClock;
01391                     continue;
01392                 }
01393                 // inace, rasporedi posao na raspolozivom stroju
01394                 nMachine = nBestMachine;
01395             }   // endif - m_dynamic
01396             else    // staticki
01397             {   // pronadjemo prvi raspolozivi stroj
01398                 nMachine = 0;
01399                 for(i=1; i<nMachines; i++)
01400                     if(MachineReady[i][0] < MachineReady[nMachine][0])
01401                         nMachine = i;
01402                 dClock = MachineReady[nMachine][0]; // to je trenutno vrijeme
01403                 CalcTimedTerminals(nNiz,nPoslova,nJob,dClock,nMachine,nMachines);
01404                 nOdabrani = nJob;
01405                 if(m_constrained)   // trazimo prvi bez prethodnika
01406                     for(; Precedence[pIndex[nOdabrani]][0] > 0; nOdabrani++)    NULL;
01407                 Evaluator.evaluate_array(pVrijednosti); // ocijenimo sve
01408                 dBest = pVrijednosti[pIndex[nOdabrani]];    // pretpostavimo da je neki najbolji
01409                 for(i=nJob; i<nPoslova; i++)    // pa pogledamo ostale
01410                 {   // trazimo najmanju vrijednost
01411                     if(pVrijednosti[pIndex[i]] < dBest && Precedence[pIndex[i]][0] == 0)    // je li to najbolja vrijednost?
01412                     {   dBest = pVrijednosti[pIndex[i]];
01413                         nOdabrani = i;
01414                     }
01415                 }
01416             }   // zavrsen odabir posla
01417 
01418             // vrijednost pIndex[nOdabrani] je indeks posla koji ide sljedeci, na stroju nMachine
01419             // gledamo nOdabrani kao rezultat; zamijenimo nJob-ti i odabrani u polju indeksa
01420             i = pIndex[nJob];
01421             pIndex[nJob] = pIndex[nOdabrani];
01422             pIndex[nOdabrani] = i;
01423             pRasporedjen[pIndex[nJob]] = true;
01424             nOdabrani = pIndex[nJob];   // nOdabrani je pravi indeks posla
01425 
01426             // update trajanja preostalih - jos treba definirati
01427             //dSPr -= Duration.data[nNiz][nOdabrani]*dMsum; 
01428             nNr--;      // update broja preostalih
01429             if(m_setup) // trajanje postavljanja
01430             {   dSetupTime = Setup[pLastJob[nMachine]][nOdabrani];
01431                 pLastJob[nMachine] = nOdabrani; // sljedeci prethodni posao
01432             }
01433             else dSetupTime = 0;
01434             if(m_constrained)   // smanjimo broj prethodnika svim sljedbenicima odabranog posla
01435                 for(i=0; i<Precedence[nOdabrani][1]; i++)
01436                 {   j = (int) Precedence[nOdabrani][i+2];
01437                     Precedence[j][0] -= 1;
01438                 }
01439             MachineReady[nMachine][0] = dClock + dSetupTime + \
01440                 Duration[nNiz][nOdabrani*nMachines + nMachine];
01441             // odredimo sljedeci element u matrici rasporeda (indeks stroja je tisucica)
01442             Schedule[nNiz][nJob] = nOdabrani + nMachine * 1000;
01443         } // kraj petlje koja vrti poslove u skupu
01444         // racunanje raznih kriterija za trenutni skup
01445         {   if(m_Evaluation)
01446             {   for(nJob=nPoslova ; nJob < this->max_jobs; nJob++)
01447                     Schedule[nNiz][nJob] = 0;                   // ostalo nule
01448             }
01449             // odredimo fitnes kriterij - sve moguce funkcije
01450             dClock = 0; nLastJob = nPoslova; dAvgWeights = 0; dCmax = 0;
01451             for(i=0; i<nMachines; i++)
01452             {   MachineReady[i][0] = 0;
01453                 pLastJob[i] = nPoslova;
01454             }
01455             for(nJob = 0; nJob<nPoslova; nJob++)
01456             {   index = (int) Schedule[nNiz][nJob];
01457                 nMachine = index / 1000;    // na kojem stroju
01458                 index = index % 1000;       // koji posao
01459                 dAvgWeights += WeightT[nNiz][index];
01460                 if(m_dynamic && MachineReady[nMachine][0] < Ready[nNiz][index]) // ako posao jos nije raspoloziv
01461                     MachineReady[nMachine][0] = Ready[nNiz][index];
01462                 MachineReady[nMachine][0] += Duration[nNiz][index*nMachines + nMachine];
01463                 if(m_setup)
01464                     MachineReady[nMachine][0] += Setup[pLastJob[nMachine]][index];
01465                 pLastJob[nMachine] = index;
01466                 dRez = MachineReady[nMachine][0] - Deadline.Get(nNiz,index);    // kasnjenje
01467                 dLateness += dRez*WeightT.data[nNiz][index];    // tezinsko kasnjenje
01468                 if(dRez > 0) dTardiness += dRez*WeightT.data[nNiz][index];  // tezinska zakasnjelost
01469                 if(dRez > 0) nLateJobs ++;  // kao broj zakasnjelih poslova
01470                 if(dRez > 0) dNwt += WeightN.data[nNiz][index]; // tezinski broj zakasnjelih
01471                 if(m_dynamic)
01472                     dFwt += MachineReady[nMachine][0] - Ready[nNiz][index]; // protjecanje, NIJE TEZINSKO
01473                 else
01474                     dFwt += MachineReady[nMachine][0];
01475             }
01476             for(i=0; i<nMachines; i++)
01477                 if(MachineReady[i][0] > dCmax)
01478                     dCmax = MachineReady[i][0];
01479             // normiranje fitnesa ovisno o broju poslova - dodano 27.07.
01480             dAvgWeights /= nPoslova;    // prosjecni tezinski faktor skupa
01481             dTardiness /= (nPoslova * dAvgWeights);
01482             dNwt /= (nPoslova * dAvgWeights);
01483             dFwt /= nPoslova;
01484             dCmax /= nPoslova;
01485             switch(m_fitness)   // sto uzimamo kao fitnes?
01486             {   case Twt: dRawFitness += dTardiness; break;
01487                 case Nwt: dRawFitness += dNwt; break;
01488                 case Fwt: dRawFitness += dFwt; break;
01489                 case Cmax: dRawFitness += dCmax; break;
01490                 default: CHECK(0);
01491             }
01492             nTotalLateJobs += nLateJobs;
01493             dTotalNwt += dNwt;
01494             dTotalFwt += dFwt;
01495             dTotalLateness += dLateness;
01496             dTotalTardiness += dTardiness;
01497             dTotalCmax += dCmax;
01498             Fitness[nNiz][Twt] = dTardiness;
01499             Fitness[nNiz][Nwt] = dNwt;
01500             Fitness[nNiz][FTwt] = 0;    // zasada
01501             Fitness[nNiz][ETwt] = 0;
01502             Fitness[nNiz][Fwt] = dFwt;
01503             Fitness[nNiz][Cmax] = dCmax;
01504         }
01505 
01506     } // kraj petlje koja vrti skupove poslova
01507     Fitness[sets][Twt] = dTotalTardiness;
01508     Fitness[sets][Nwt] = dTotalNwt;
01509     Fitness[sets][Fwt] = dTotalFwt;
01510     Fitness[sets][Cmax] = dTotalCmax;
01511 }
01512 
01513 
01514 
01515 
01516 void SchedulingEvalOp::EvaluateJobShop(double &dRawFitness)
01517 {
01518     double dL, dT, dTwt, dF, dFwt, dN, dNwt, dCmax;
01519     double dTotalT, dTotalTwt, dTotalF, dTotalFwt, dTotalN, dTotalNwt, dTotalCmax;
01520     double dClock, dAvgWeights, dTotalAvgLoad, dBestMachineValue, dAvgDuration;
01521     double dBest, dSetupTime, m1, m2, dNajkrace, dBegin;
01522     unsigned int nPoslova, nNiz, nJob, i, j, k, nNr, nOperations, nOperation, nNextOperation;
01523     unsigned int nMachines, nMachine, nSchedule, nMachineIndex, nJobsToEval, nBestJob, nNextMachine;
01524     unsigned int nBottleneck;
01525 
01526     dRawFitness=0;
01527     dTotalT = dTotalTwt = dTotalF = dTotalFwt = dTotalN = dTotalNwt = dTotalCmax = 0;
01528 
01529 // vrtimo sve skupove
01530     for(nNiz=0; nNiz<sets; nNiz++)
01531     {   nNr = nPoslova = (int) N.Get(nNiz);
01532     // preliminarna ispitivanja
01533         // radimo li stochastic sampling
01534         if(m_stsampling)
01535             if(pSamples[nNiz] == false)
01536                 continue;   // jednostavno preskocimo taj test case
01537         // gleda li se limited error fitness
01538         if(m_LEF)
01539         {   if(dRawFitness > m_LEFVal)
01540                 break;  // prekid ispitivanja
01541         }
01542         if(m_setup) // trajanja postavljanja
01543             MakeSetup(Duration,nNiz,nPoslova,m_setup_faktor,Setup);
01544     // postavljanje pocetnih vrijednosti za pojedini skup
01545         dClock = 0;
01546         dTotalAvgLoad = 0;  // prosjecno opterecenje svih strojeva
01547         nOperations = nMachines = (uint) Machines[nNiz][0];
01548         dBestMachineValue = 0;
01549         nBottleneck = nMachines;    // nijedan nije bottleneck na pocetku
01550         for(j=0; j<nMachines; j++)
01551         {   MachineReady[j][0] = 0;     // pocetno vrijeme raspolozivosti strojeva
01552             pLastJob[j] = nPoslova;     // pocetni prethodni posao
01553             pMachineScheduled[j] = 0;   // broj rasporedjenih operacija na stroju
01554             pOperationReady[j] = -1;    // raspolozivost operacija za strojeve tek treba odrediti
01555             pTotalMachineWork[j] = 0;   // ukupno opterecenje stroja
01556             pOperationsWaiting[j] = 0;  // broj operacija na cekanju
01557             pMachineValues[j] = 0;      // vrijednosti strojeva - racunaju se stablom odluke
01558         }
01559         for(i=0; i<nPoslova; i++)
01560         {   pTotalWorkRemaining[i] = 0;
01561             pTotalWorkDone[i] = 0;
01562             pIndex[i] = i;  // inicijalni poredak
01563             pJobReady[i] = Ready[nNiz][i];  // Ready su nule u statickom slucaju
01564             pOperationsScheduled[i] = 0;    // broj rasporedjenih operacija posla
01565             for(j=0; j<nOperations; j++)
01566             {   k = (int) Duration[nNiz][i*nOperations + j];
01567                 nMachine = k / 1000;    // indeks stroja
01568                 if(j == 0)  // za prvu operaciju
01569                     pOperationsWaiting[nMachine]++;
01570                 k = k % 1000;       // trajanje operacije
01571                 pTotalWorkRemaining[i] += k;
01572                 Durations[i][j] = k;
01573                 dTotalAvgLoad += k;
01574                 MachineIndex[i][j] = nMachine;
01575                 pTotalMachineWork[nMachine] += k;
01576             }
01577             // pogledamo na kojem je stroju prva operacija posla
01578             nMachine = (int) MachineIndex[i][0];
01579             pOperationReady[nMachine] = pJobReady[i];
01580             // znaci taj stroj je trazen u trenutku dolaska posla (0 u statickom slucaju)
01581         }
01582         dAvgDuration = dTotalAvgLoad / nPoslova;    // prosjecno trajanje poslova
01583         dTotalAvgLoad /= nMachines;
01584         Evaluator.SetTermArraySize(nPoslova);   // koliko poslova u skupu - za vektorsku evaluaciju
01585         Evaluator.pIndex = pIndex;  // polje indeksa poslova
01586         Evaluator.m_iOffset = 0;        // indeks prvog nerasporedjenog
01587         //Evaluator.m_iEnd = 1; // pocetna vrijednost zadnjeg posla koji se uzima u o obzir
01588         // postavljanje pocetnih vrijednosti terminala - nepromjenjivi
01589         memcpy(Evaluator.m_dTermValuesArray[T_dd], Deadline.data[nNiz], nPoslova*sizeof(double));
01590         memcpy(Evaluator.m_dTermValuesArray[T_w],  WeightT.data[nNiz], nPoslova*sizeof(double));
01591         memcpy(Evaluator.m_dTermValuesArray[T_TWK], pTotalWorkRemaining, nPoslova*sizeof(double));
01592         // nepromjenjivi terminali za strojeve
01593         for(i=0; i<nMachines; i++)
01594         {   Evaluator.m_dTermValuesArray[T_MTWKav][i] = dTotalAvgLoad;
01595             Evaluator.m_dTermValuesArray[T_MTWK][i] = pTotalMachineWork[i];
01596             pMachineWorkRemaining[i] = pTotalMachineWork[i];
01597         }
01598         memcpy(Evaluator.m_dTermValuesArray[T_MTWK], pTotalMachineWork, nMachines*sizeof(double));
01599 
01600         for(nSchedule = 0; nSchedule < nPoslova*nMachines; nSchedule++)
01601         {   // treba pronaci stroj koji ima najranije vrijeme raspolozivosti i sebe i operacije za njega
01602             for(nMachine = 0; nMachine<nMachines; nMachine++)
01603                 if(pOperationReady[nMachine] >= 0)  // je li stroj uopce trazen
01604                     break;
01605             for(i = nMachine; i < nMachines; i++)
01606             {   if(pOperationReady[i] < 0)  // jos se nije pojavila potreba za tim strojem
01607                     continue;
01608                 m1 = MAX(MachineReady[i][0],pOperationReady[i]);
01609                 m2 = MAX(MachineReady[nMachine][0],pOperationReady[nMachine]);
01610                 if(m1 < m2) // ima neki stroj koji je prije raspoloziv za rasporediti
01611                     nMachine = i;
01612             }
01613             dClock = MAX(MachineReady[nMachine][0], pOperationReady[nMachine]);
01614             // pronadjemo kada bilo koja operacija moze najprije zavrsiti
01615             dNajkrace = -1;
01616             for(nJob=0; nJob<nPoslova; nJob++)
01617             {   nOperation = pOperationsScheduled[nJob];
01618                 if(nOperation == nMachines) continue;       // ovaj posao je zavrsio
01619                 nMachineIndex = (int) MachineIndex[nJob][nOperation];
01620                 if(nMachineIndex != nMachine) continue; // ovaj posao ne ceka na taj stroj
01621                 if(dNajkrace < 0)
01622                     dNajkrace = MAX(dClock, pJobReady[nJob]) + Durations[nJob][nOperation];
01623                 else
01624                 {   dBegin = MAX(dClock, pJobReady[nJob]);
01625                     if(dNajkrace > dBegin + Durations[nJob][nOperation])
01626                         dNajkrace = dBegin + Durations[nJob][nOperation];
01627                 }
01628             }
01629             // sada treba pronaci operaciju najveceg prioriteta koja ceka na taj stroj
01630             // radimo tako da poslove cije operacije treba ocijeniti stavimo na pocetak pIndex
01631             // prije evaluacije odredimo koliko ih ima (kao m_iEnd u Evaluatoru)
01632             nJobsToEval = 0;
01633             for(nJob=0; nJob<nPoslova; nJob++)
01634             {   nOperation = pOperationsScheduled[nJob];
01635                 if(nOperation == nMachines) continue;       // ovaj posao je zavrsio
01636                 nMachineIndex = (int) MachineIndex[nJob][nOperation];
01637                 if(nMachineIndex != nMachine) continue; // ovaj posao ne ceka na taj stroj
01638                 // mozemo uzeti u obzir samo one koji su vec spremni:
01639                 if(!m_Idleness)
01640                     if(pJobReady[nJob] > dClock) continue;  // jos nije zavrsila prethodna operacija
01641                 // ili mozemo uzeti u obzir i one koji ce tek zavrsiti, ali ne kasnije od moguceg zavrsetka najkrace spremne operacije
01642                 dBegin = MAX(pJobReady[nJob],dClock);
01643                 if(dBegin > dNajkrace)  // nema smisla gledati ako pocinje iza najkraceg zavrsetka
01644                     continue;
01645                 // ako smo dosli ovdje, uzet cemo u obzir operaciju nOper. posla nJob na stroju nMachine
01646                 pIndex[nJobsToEval] = nJob;
01647                 nJobsToEval++;
01648             }
01649 #ifdef TREES
01650             // pomocu prvog stabla odlucimo koja od dva preostala koristimo za prioritete
01651 *
01652 MNOPr[nMachine] = nOperations - pMachineScheduled[nMachine]
01653 MTWKav = dTotalAvgLoad;
01654 MTWK[nMachine] = pTotalMachineWork[nMachine];
01655 MNOPw[nMachine] = pOperationsWaiting[nMachine];
01656 MTWKr[nMachine] = pMachineWorkRemaining[nMachine];
01657 MUTL[nMachine] = (pTotalMachineWork[nMachine] - pMachineWorkRemaining[nMachine]) / dClock;
01658 */
01659             Evaluator.m_nTree = 0;
01660             // prvo stablo racunamo samo za nMachine - pa za taj stroj racunamo terminale
01661             Evaluator.m_dTermValuesArray[T_MNOPr][nMachine] = nOperations - pMachineScheduled[nMachine];
01662             Evaluator.m_dTermValuesArray[T_MNOPw][nMachine] = pOperationsWaiting[nMachine];
01663             Evaluator.m_dTermValuesArray[T_MTWKr][nMachine] = pMachineWorkRemaining[nMachine];
01664             if(dClock == 0)
01665                 Evaluator.m_dTermValuesArray[T_MUTL][nMachine] = 1;
01666             else
01667                 Evaluator.m_dTermValuesArray[T_MUTL][nMachine] = (pTotalMachineWork[nMachine] - pMachineWorkRemaining[nMachine]) / dClock;
01668 
01669             Evaluator.m_iPosition = -1;
01670             nSavedIndex = pIndex[nMachine]; // pohranimo indeks posla koji se tu nalazi
01671             pIndex[nMachine] = nMachine;
01672             Evaluator.m_iOffset = nMachine;
01673             Evaluator.m_iEnd = nMachine + 1;
01674             Evaluator.evaluate_array(pVrijednosti); // ocijenimo stroj u stablu odluke
01675             pMachineValues[nMachine] = pVrijednosti[nMachine];
01676             // MODIFIKACIJA 15.09.: uvijek pronadjemo novi dBestMachineValue kao Bottleneck
01677 *           dBestMachineValue = pMachineValues[0];
01678             nBottleneck = 0;
01679             for(i=0; i<nMachine; i++)
01680                 if(pMachineValues[i] > dBestMachineValue)
01681                 {   dBestMachineValue = pMachineValues[i];
01682                     nBottleneck = i;
01683                 }
01684 */
01685             // MODIFIKACIJA 13.09.: uvijek pamtimo stroj koji je postigao najvecu vrijednost
01686             // (dok se ne postigne veca)
01687             if(pMachineValues[nMachine] >= dBestMachineValue)   // je li nova najveca vrijednost?
01688             {   dBestMachineValue = pMachineValues[nMachine];
01689                 nBottleneck = nMachine;
01690             }
01691 
01692             if(nMachine == nBottleneck) // jesam li ja bottleneck?
01693                 Evaluator.m_nTree = 2;  // za najoptereceniji stroj
01694             else
01695                 Evaluator.m_nTree = 1;  // za sve ostale
01696             pIndex[nMachine] = nSavedIndex; // vratimo indeks posla
01697 #else   // samo jedno stablo
01698             Evaluator.m_nTree = 0;  // vratimo na obicno stablo
01699 #endif
01700             // vektorska evaluacija!
01701             // trebamo definirati vrijednosti terminala za trenutne operacije odabranih poslova
01702             for(i=0; i<nJobsToEval; i++)
01703             {   nJob = pIndex[i];
01704                 nOperation = pOperationsScheduled[nJob];
01705                 Evaluator.m_dTermValuesArray[T_pt][nJob] = Durations[nJob][nOperation];
01706                 Evaluator.m_dTermValuesArray[T_CLK][nJob] = dClock;
01707                 Evaluator.m_dTermValuesArray[T_AR][nJob] = POS(pJobReady[nJob] - dClock); 
01708                 Evaluator.m_dTermValuesArray[T_STP][nJob] = Setup[pLastJob[nMachine]][nJob];
01709                 Evaluator.m_dTermValuesArray[T_Sav][nJob] = pSetupAvg[pLastJob[nMachine]];
01710                 Evaluator.m_dTermValuesArray[T_age][nJob] = POS(dClock - Ready[nNiz][nJob]);
01711                 Evaluator.m_dTermValuesArray[T_NOPr][nJob] = nOperations - pOperationsScheduled[nJob];
01712                 Evaluator.m_dTermValuesArray[T_PTav][nJob] = PTimeAvg[nNiz][nMachine];
01713                 Evaluator.m_dTermValuesArray[T_TWKr][nJob] = pTotalWorkRemaining[nJob];
01714                 if(pTotalWorkDone[nJob] == 0)
01715                     Evaluator.m_dTermValuesArray[T_HTR][nJob] = 1;
01716                 else
01717                     Evaluator.m_dTermValuesArray[T_HTR][nJob] = POS(dClock - Ready[nNiz][nJob]) / pTotalWorkDone[nJob];
01718             }
01719             Evaluator.m_iPosition = -1;
01720             Evaluator.m_iOffset = 0;
01721             Evaluator.m_iEnd = nJobsToEval; // toliko ih ima za ocijeniti
01722             Evaluator.evaluate_array(pVrijednosti); // ocijenimo sve u odabranom stablu
01723             dBest = pVrijednosti[pIndex[0]]; // poc. vrijednost za usporedbu
01724             nBestJob = pIndex[0];
01725             for(i=1; i<nJobsToEval; i++)
01726             {   if(pVrijednosti[pIndex[i]] < dBest)
01727                 {   dBest = pVrijednosti[pIndex[i]];
01728                     nBestJob = pIndex[i];
01729                 }
01730             }
01731 
01732             // nBestJob na nMachine
01733             nOperation = pOperationsScheduled[nBestJob];    // sadasnja operacija (koja ce se izvesti)
01734             pOperationsScheduled[nBestJob] += 1;    // novi broj rasporedjenih operacija posla
01735             pTotalWorkRemaining[nBestJob] -= Durations[nBestJob][nOperation];
01736             pMachineWorkRemaining[nMachine] -= Durations[nBestJob][nOperation];
01737             pTotalWorkDone[nBestJob] += Durations[nBestJob][nOperation];
01738             if(m_setup)
01739             {   dSetupTime = Setup[pLastJob[nMachine]][nBestJob];
01740                 pLastJob[nMachine] = nBestJob;
01741             }
01742             else
01743                 dSetupTime = 0;
01744             dClock = MAX(dClock, pJobReady[nBestJob]);  // ako smo odlucili pricekati
01745             MachineReady[nMachine][0] = dClock + dSetupTime + Durations[nBestJob][nOperation];
01746             pJobReady[nBestJob] = MachineReady[nMachine][0];    // kada ce sljedeca operacija biti raspoloziva
01747             if(nOperation < nOperations-1)  // ako posao ima jos operacija
01748             {   nNextMachine = (int) MachineIndex[nBestJob][pOperationsScheduled[nBestJob]];
01749                 if(pOperationReady[nNextMachine] < 0)   // ako stroj trenutno nije trazen...
01750                     pOperationReady[nNextMachine] = pJobReady[nBestJob];    // ... bit ce tada
01751                 else    // provjeri dolazi li moja sljedeca operacija prije trenutno najblize za taj stroj
01752                     if(pOperationReady[nNextMachine] > pJobReady[nBestJob])
01753                         pOperationReady[nNextMachine] = pJobReady[nBestJob];
01754             }
01755             // kada cu ja (stroj) opet biti trazen?
01756             pOperationReady[nMachine] = -1;
01757             pOperationsWaiting[nMachine] = 0;
01758             for(j=0; j<nPoslova; j++)
01759             {   nNextOperation = pOperationsScheduled[j];
01760                 if(nNextOperation == nMachines) continue;   // ovaj nema vise operacija
01761                 nNextMachine = (int) MachineIndex[j][nNextOperation];
01762                 if(nNextMachine != nMachine) continue;
01763                 pOperationsWaiting[nMachine]++;
01764                 if(pOperationReady[nMachine] < 0)
01765                     pOperationReady[nMachine] = pJobReady[j];
01766                 else
01767                     if(pOperationReady[nMachine] > pJobReady[j])
01768                         pOperationReady[nMachine] = pJobReady[j];
01769             }
01770             nOperation = (int) pMachineScheduled[nMachine];
01771             pMachineScheduled[nMachine] += 1;
01772             Schedule[nNiz][nMachine * nPoslova + nOperation] = nBestJob;
01773         }   // kraj rasporedjivanja skupa
01774 
01775         // racunanje raznih kriterija za trenutni skup
01776         {   if(m_Evaluation)
01777             {   for(i=nPoslova*nMachines ; i < (uint)Schedule.GetCol(); i++)
01778                     Schedule[nNiz][i] = 0;          // ostalo nule
01779             }
01780             // odredimo fitnes kriterij - sve moguce funkcije
01781             dAvgWeights = 0;
01782             dCmax = dF = dFwt = dT = dTwt = dN = dNwt = 0;
01783             for(j=0; j<nPoslova; j++)
01784             {   dAvgWeights += WeightT[nNiz][j];
01785                 if(dCmax < pJobReady[j])
01786                     dCmax = pJobReady[j];
01787                 dF += pJobReady[j] - Ready[nNiz][j];
01788                 dFwt += (pJobReady[j] - Ready[nNiz][j]) * WeightT[nNiz][j];
01789                 if(pJobReady[j] > Deadline[nNiz][j])
01790                 {   dN += 1;
01791                     dNwt += WeightT[nNiz][j];
01792                     dL = pJobReady[j] - Deadline[nNiz][j];
01793                     dT += dL;
01794                     dTwt += WeightT[nNiz][j] * dL;
01795                 }
01796             }
01797             dAvgWeights /= nPoslova;
01798             dCmax /= nPoslova*dAvgDuration;
01799             dF /= nPoslova;
01800             dFwt /= nPoslova*dAvgWeights*dAvgDuration;
01801             dT /= nPoslova;
01802             dTwt /= nPoslova*dAvgWeights*dAvgDuration;
01803             dN /= nPoslova;
01804             dNwt /= nPoslova*dAvgWeights;
01805             dTotalCmax += dCmax;
01806             dTotalF += dF;
01807             dTotalFwt += dFwt;
01808             dTotalT += dT;
01809             dTotalTwt += dTwt;
01810             dTotalN += dN;
01811             dTotalNwt += dNwt;
01812 
01813             switch(m_fitness)   // sto uzimamo kao fitnes?
01814             {   case Twt: dRawFitness += dTwt; break;
01815                 case Nwt: dRawFitness += dNwt; break;
01816                 case Fwt: dRawFitness += dFwt; break;
01817                 case Cmax: dRawFitness += dCmax; break;
01818                 default: CHECK(0);
01819             }
01820             Fitness[nNiz][Twt] = dTwt;
01821             Fitness[nNiz][Nwt] = dNwt;
01822             Fitness[nNiz][FTwt] = 0;    // zasada
01823             Fitness[nNiz][ETwt] = 0;
01824             Fitness[nNiz][Fwt] = dFwt;
01825             Fitness[nNiz][Cmax] = dCmax;
01826         }
01827 
01828     } // kraj petlje koja vrti skupove poslova
01829     Fitness.data[sets][Twt] = dTotalTwt;
01830     Fitness.data[sets][Nwt] = dTotalNwt;
01831 }

Generated on Wed Sep 21 2011 13:46:53 for ECF by  doxygen 1.7.1