#ifdef MPI #include "SA_MIRScheduler.h" #include "util_salib.h" //#include #include //#include #include #include int SA_MIRScheduler::Accept(float new_cost) { IterationNumber++; return SA_Scheduler::Accept(new_cost); } // \****************************************************** // true <=> iteration number on this temperature step as calculated // \****************************************************** int SA_MIRScheduler::Equilibrium() { return ( TimeExceeded() || GetNIter() >= rlakt || GetTotalIter() >= DesiredRunLength )? 1 : 0; } // \****************************************************** // true <=> total iteration number as requested // \****************************************************** int SA_MIRScheduler::Frozen() { return ( TimeExceeded() || GetTotalIter() >= DesiredRunLength )? 1 : 0; } // \****************************************************** // geometric update: T_n+1 = Alpha * T_n // \****************************************************** void SA_MIRScheduler::UpdateTemperature() { // if ( Temperature_Reset ) // { // if ( GetSigma() < (GetMean()/100000) ) // { ////std::cout << "Reset, weil: GetSigma() " << GetSigma() << " GetMean() " << GetMean() << std::endl; // Treset = maax(Treset/2,Tbest); // SetNewT(Treset); // } // else // { ////std::cout << "KEIN Reset, weil: GetSigma() " << GetSigma() << " GetMean() " << GetMean() << std::endl; // SetNewT(T*Alpha); // } // } // else // { // } SetNewT(T*Alpha); rlakt *= Run_Betta; } // \****************************************************** // requested total iteration number // setup the schedule for this number of iterations // \****************************************************** void SA_MIRScheduler::SetDesiredRunLength(int rl) { DesiredRunLength = rl; UpdateTsTf(); // start and end temperature calculation SetStartT(Ts); // important for class Scheduler if ( 0 < Alpha_user && Alpha_user < 1 ) { Tsteps = (log(Tf/Ts)/log(Alpha_user))+1; } else { Tsteps = FABS(Ts-Tf)+1; } if ( DesiredRunLength < Tsteps ) // change Alpha { Alpha = pow(Alpha_user,(Tsteps-1)/DesiredRunLength); rlakt = 1; Run_Betta = 1; } else { if ( (Betta == 1) || ((1-pow(Betta,Tsteps))/(1-Betta) > DesiredRunLength) ) { rlakt = DesiredRunLength/Tsteps; Run_Betta = 1; } else // perfect situation { rlakt = (DesiredRunLength*(1-Betta)) / (1-pow(Betta,Tsteps)); Run_Betta = Betta; } } Reset(); // Tbest = 0; } // \****************************************************** // parameter: // - in s: initial solution // returns: // - in b best seen solution // purposes: // - calculation of start and end temperature // - measuring SA-accept and SA-reset times // \****************************************************** void SA_MIRScheduler::WarmingUp(SA_Problem & P, SA_Solution &s, SA_Solution &b, MPI_Comm comm) { float NewCost, CostDiff; time_accept = time_reset = 0; double m_time=0; if ( myrank == 0 ) { std::cout << "SA_MIRScheduler: WarmingUp ..." << std::endl; } if ( initialT == 0 || endT == 0 ) { P.Copy(s,b); SetNewE(P.GetCost(s)); StartE = GetE(); float Step_Number = P.GetLocalN(); if ( myrank == 0 ) { std::cout << "P.GetLocalN() " << Step_Number << std::endl; } // a Step_Number-iteration run in the solution space // purposes: // - measuring accept-times in SA, // - start and end temperature calculation from cost differences for (int i=0; i < Step_Number; i++) { // measure accept times m_time = MPI_Wtime(); P.GetNeighbor(s,GetRelativeT()); NewCost = P.GetCost(s); CostDiff = FABS(NewCost - E); SetNewE(NewCost); P.UpdateSolution(s); time_accept +=MPI_Wtime() - m_time; UpdateEminEmax(CostDiff); // store CostDiff for T_start and T_end calculation if ( BestFound() ) P.Copy(s,b); // best solution must be always stored! } // a shorter run in the solution space // purpose: // - measuring reset-times in SA for (int j=0; j < Step_Number/10; j++) { // measure reset times m_time = MPI_Wtime(); P.GetNeighbor(s,GetRelativeT()); P.ResetSolution(s); time_reset +=MPI_Wtime() - m_time; } time_accept /= Step_Number; time_reset /= Step_Number/10; // communicate and compute mean time_accept and time_reset in MPI_COMM_WORLD int nproc=1,flag=0; MPI_Initialized(&flag); if ( flag ) { MPI_Comm_size(comm,&nproc); if( nproc > 1 ) { struct { double t_a,t_r; } in,out; in.t_a = time_accept; in.t_r = time_reset; MPI_Reduce(&in,&out,2,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD); if(myrank == 0) { time_accept = out.t_a/nproc; time_reset = out.t_r/nproc; std::cout << "time_accept " << time_accept << " time_reset " << time_reset << std::endl; } } } else { std::cout << "time_accept " << time_accept << " time_reset " << time_reset << std::endl; } // time_accept and time_reset are computed } UpdateTsTf(); // start and end temperature calculation SetStartT(Ts); // important for class Scheduler // Treset = Ts; // Tbest = 0; if ( myrank == 0 ) { std::cout << "SA_MIRScheduler: WarmingUp completed" << std::endl; ShowConfig(std::cout); } } // \****************************************************** // read configuration file (between '{' and '}' // \****************************************************** int SA_MIRScheduler::ReadConfig(std::istream & config) { char text[BUFLEN]; config >> text; if ( strcmp(text,"{") != 0) { std::cout << "In SA_MIRScheduler::ReadConfig: config file section does not begin with {!\n"; return FALSE; } while (config >> text && ( strcmp(text,"}") != 0 )) { if (strcmp(text, "SA_Scheduler") == 0) { if ( ! SA_Scheduler::ReadConfig(config) ) { std::cout <<"ReadConfing for Scheduler failed!\n"; return 0; } continue; } // variable initialtemperature may already by SA_Scheduler if StartT < INFINITY, // check this and set initialT if it was if (StartT != -1.0) { initialT = StartT; if ( initialT <= 0.01 ) { initialT = 0.01; } } else if (strcmp(text, "endtemperature") == 0) { config >> text; endT = atof(text); if ( endT <= 0.01 ) { endT = 0.01; } } else if (strcmp(text, "Alpha") == 0) { config >> text; Alpha = Alpha_user = atof(text); } else if (strcmp(text, "Betta") == 0) { config >> text; Betta = atof(text); } else if (strcmp(text, "Temperature_Reset") == 0) { config >> text; if (strcmp(text, "true") == 0) { Temperature_Reset = 1; } else if (strcmp(text, "false") == 0) { Temperature_Reset = 0; } else { Temperature_Reset = 0; if (myrank == 0) std::cout << "Unknown keyword "< dEmax ) dEmax = CostDiff; if ( CostDiff < dEmin && CostDiff > 0 ) dEmin = CostDiff; } // \****************************************************** // set start and end temperature as in configuration-file or after WarmingUp // \****************************************************** void SA_MIRScheduler::UpdateTsTf(void) { if ( initialT == 0 && endT != 0 ) { Ts = -dEmax/log(InitAccRatio); Tf = endT; } else if ( initialT != 0 && endT == 0 ) { Ts = initialT; Tf = -dEmin/log(InitAccRatio); } else if ( initialT == 0 && endT == 0 ) { Ts = -dEmax/log(InitAccRatio); Tf = -dEmin/log(InitAccRatio); } else { Ts = initialT; Tf = endT; } if ( Ts < 0.01 ) Ts = 0.01; if ( Tf < 0.01 ) Tf = 0.01; } // \****************************************************** // // \****************************************************** SA_MIRScheduler::SA_MIRScheduler(): SA_ParScheduler(), Tf(0.01), Ts(0), initialT(0), endT(0), Tbest(0), dEmax(0), dEmin(INFINITY), DesiredRunLength(0), IterationNumber(0), Temperature_Reset(0), rlakt(0), Alpha(0.9), Alpha_user(0.9), Betta(1), Run_Betta(1), Tsteps(0), time_reset(0), time_accept(0), samiroutput("SA_MIRScheduler","SA_Output.rsc") /// InitAccRatio(0.9) { samiroutput.EnableLevelNumbers(false); samiroutput.EnableIdentifier(true); samiroutput.SetOutputLevel(10); samiroutput.AddVariable(1,SA_FLOAT,&initialT); samiroutput.AddVariable(2,SA_FLOAT,&endT); samiroutput.AddVariable(3,SA_FLOAT,&Alpha_user); samiroutput.AddVariable(4,SA_FLOAT,&Betta); samiroutput.AddVariable(5,SA_FLOAT,&Ts); samiroutput.AddVariable(6,SA_FLOAT,&Tf); samiroutput.AddVariable(7,SA_FLOAT,&Tsteps); samiroutput.AddVariable(8,SA_FLOAT,&Alpha); samiroutput.AddVariable(9,SA_FLOAT,&Run_Betta); samiroutput.AddVariable(10,SA_FLOAT,&rlakt); samiroutput.AddVariable(11,SA_INT,&DesiredRunLength); samiroutput.AddVariable(12,SA_INT,&IterationNumber); samiroutput.AddVariable(13,SA_FLOAT,&dEmax); samiroutput.AddVariable(14,SA_FLOAT,&dEmin); samiroutput.AddVariable(15,SA_FLOAT,&Treset); samiroutput.AddVariable(16,SA_FLOAT,&Tbest); samiroutput.AddVariable(17,SA_FLOAT,&Temperature_Reset); samiroutput.AddVariable(18,SA_DOUBLE,&time_reset); samiroutput.AddVariable(19,SA_DOUBLE,&time_accept); samiroutput.SetPreviousOutput(SA_ParScheduler::GetSchedulerOutput()); } // \****************************************************** // // \****************************************************** SA_MIRScheduler::~SA_MIRScheduler() { } SA_Output * SA_MIRScheduler::GetSchedulerOutput() { return(&samiroutput); } #endif