#ifdef MPI //#include //#include #include #include #include //#include #include #include "SA_ParScheduler.h" SA_ParScheduler::SA_ParScheduler(): saparoutput("SA_ParScheduler","SA_Output.rsc") // CoolingRatio(0.9), // subchainfactor(1.0), // StrictShort(true), // MinAccRatio(LOWER_ACCEPTANCE_RATIO), // MaxChainLength(UPPER_LOOP_BOUND), // MaxChainLength0(UPPER_LOOP_BOUND), // frozen_count(0), // frozen_limit(5), // pos(0),full(0),FrozenSum(0),Mean(0) { saparoutput.EnableLevelNumbers(false); saparoutput.EnableIdentifier(true); saparoutput.SetOutputLevel(10); saparoutput.AddVariable(1,SA_FLOAT,&out.tot_iter); saparoutput.AddVariable(2,SA_FLOAT,&out.tot_acc); saparoutput.AddVariable(3,SA_FLOAT,&out.StartE); saparoutput.AddVariable(4,SA_FLOAT,&out.E); saparoutput.SetPreviousOutput(SA_Scheduler::GetSchedulerOutput()); // // StartT = -1.0; // to indicate T0 was not set jet // MaxChainLength = MaxChainLength0 = 0; // -//- // // LastSolutions = new float[frozen_limit]; // for (int i=0; i < frozen_limit; i++) LastSolutions[i] = 0; } // \****************************************************** // Destruktor // \****************************************************** SA_ParScheduler::~SA_ParScheduler() {//debug(SA_ParScheduler::Destruktor , myrank); // delete [] LastSolutions; } SA_Output * SA_ParScheduler::GetSchedulerOutput() { return(&saparoutput); } // \****************************************************** // Methode ReadConfig - Liest die Konfigurations- // daten ( geklammert mit '{' '}' ) aus dem istream // \****************************************************** //int SA_ParScheduler::ReadConfig(std::istream & config) //{ ////debug(SA_ParScheduler::ReadConfig , myrank); // // char text[BUFLEN]; // config >> text; // if ( strcmp(text,"{") != 0) // { // std::cout << "In SA_ParScheduler::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; // } // } // // else if (strcmp(text, "coolingratio") == 0) // { // config >> text; // SetCoolingRatio( atof(text) ); // } // else if (strcmp(text, "frozenlimit") == 0) // { // config >> text; // SetFrozenLimit( atol(text) ); // } // else if (strcmp(text, "minaccratio") == 0) // { // config >> text; // MinAccRatio = atof(text); // if ( MinAccRatio < 0 || MinAccRatio >= 1) // { // std::cout <<"In SA_ParScheduler::ReadConfig: bad value "<< MinAccRatio<<" for minaccratio specified!\n"; // MinAccRatio = -1; // } // } // else if (strcmp(text, "subchainlength") == 0) // { // config >> text; // MaxChainLength = MaxChainLength0 = atol(text); // } // else if (strcmp(text, "subchainfactor") == 0) // { // config >> text; // subchainfactor = atof(text); // } // else if (strcmp(text, "strictshort") == 0) // { // config >> text; // if (strcmp(text, "no") == 0 || strcmp(text, "yes") == 0) { // if (strcmp(text, "no") == 0) { // StrictShort = false; // } // } else // { // std::cout <<"In SA_ParScheduler::ReadConfig: bad value "<< text<<" for strictshort specified! Leaving default yes\n"; // } // } // else // { // std::cout <<"In SA_ParScheduler::ReadConfig: unrecognized keyword \""<=0 ) // d.h. falls MPI initialisiert ist // { // // Beste gesehene Loesungsbewertung: // float BestBuff; // if ( OptType == Opt::MIN ) // MPI_Reduce(&BestE,&BestBuff,1,MPI_FLOAT,MPI_MIN,0,comm); // else // MPI_Reduce(&BestE,&BestBuff,1,MPI_FLOAT,MPI_MAX,0,comm); // // in.tot_iter = (float)total_iter; // in.tot_acc = (float)total_accepts; // in.StartE = StartE; // in.E = E; // MPI_Reduce(&in,&out,4,MPI_FLOAT,MPI_SUM,0,comm); // // int me,npr; // MPI_Comm_rank(comm,&me); // if ( me != 0 ) // return; // MPI_Comm_size(comm,&npr); // out.StartE = out.StartE/npr; // out.E = out.E/npr; //// output //// << " OT="<< ( OptType == Opt::MIN ? "MIN" : "MAX") //// << " T(0)=" << StartT //// << " T=" << T //// << " I=" << (unsigned long)out.tot_iter //// << " N_dT=" << n_dT // Anzahl der Temperaturstufen //// << " N_acc=" << (unsigned long)out.tot_acc //// << " N_upd=" << total_updates //// << " E(0)=" << out.StartE/npr //// << " E=" << out.E/npr //// << " BestE=" << BestBuff; // saparoutput.OutputFrozenYes(); // } // else { // SA_Scheduler::OutputStatistics(output); // } //} void SA_ParScheduler::CreateLog(std::ostream & output, MPI_Comm comm) {//debug(SA_ParScheduler::OutputStatistics , myrank); if ( myrank >=0 ) // d.h. falls MPI initialisiert ist { // Beste gesehene Loesungsbewertung: float BestBuff; if ( OptType == Opt::MIN ) MPI_Reduce(&BestE,&BestBuff,1,MPI_FLOAT,MPI_MIN,0,comm); else MPI_Reduce(&BestE,&BestBuff,1,MPI_FLOAT,MPI_MAX,0,comm); in.tot_iter = (float)total_iter; in.tot_acc = (float)total_accepts; in.StartE = StartE; in.E = E; MPI_Reduce(&in,&out,4,MPI_FLOAT,MPI_SUM,0,comm); int me,npr; MPI_Comm_rank(comm,&me); if ( me != 0 ) return; MPI_Comm_size(comm,&npr); out.StartE = out.StartE/npr; out.E = out.E/npr; output << " OT="<< ( OptType == Opt::MIN ? "MIN" : "MAX") << " T(0)=" << StartT << " T=" << T << " I=" << (unsigned long)out.tot_iter << " N_dT=" << n_dT // Anzahl der Temperaturstufen << " N_acc=" << (unsigned long)out.tot_acc << " N_upd=" << total_updates << " E(0)=" << out.StartE/npr << " E=" << out.E/npr << " BestE=" << BestBuff; } else { SA_Scheduler::CreateLog(output); } } // \****************************************************** // Methode UpdateTemperatureFixed - Aktualisiert die // Temperatur mit einem konstanten Faktor. // \****************************************************** //void SA_ParScheduler::UpdateTemperature() //{ // // // if( MinAccRatio < 0 ) // if MinAccRatio wasn't set in config file // { // Enqueue(); // // if ( FABS(E - Mean)/Mean < EPSILON) // frozen_count++; // else // frozen_count=0; // } // else // { // if ( GetAcceptRatio() < MinAccRatio ) //{ // frozen_count++; //} // else // frozen_count=0; // } // // SetNewT( T*CoolingRatio ); //} // // //// \****************************************************** //// Methode Equilibrium - Entscheidet, ob im gegebenen //// Schleifendurchlauf das Gleichgewicht erreicht wurde. //// \****************************************************** //int SA_ParScheduler::Equilibrium() //{//debug(SA_ParScheduler::Equilibrium, myrank); // //} // \****************************************************** // Methode Enqueue - Speichert die letzten frozen_limit // Kostenwerte. // \****************************************************** //void SA_ParScheduler::Enqueue() //{//debug(SA_ParScheduler::Enqueue, myrank); // // FrozenSum += E - LastSolutions[pos]; // LastSolutions[pos] = E; // pos = (pos+1)%frozen_limit; // if ( pos == 0) // full = TRUE; // // Mean = FrozenSum / (full?frozen_limit:pos); //} // // //// \****************************************************** //// Methode Frozen - Entscheidet, ob das System //// zum Stillstand gekommen ist. //// \****************************************************** //int SA_ParScheduler::Frozen() //{ //} // \****************************************************** // Method AartsWarmingUp // Implements Aart's warming up algorithm when several // processors are used // - the result of one processor is simply distributed // - may be improved (mean?) // \****************************************************** double SA_ParScheduler::AartsWarmingUp(SA_Problem & P, SA_Solution &s, SA_Solution &b, long length,MPI_Comm comm) {//debug(SA_ClusteringScheduler::AartsWarmingUp , myrank); if (InitAccRatio == -1.0) { InitAccRatio = 0.9; } float T0; // dummy, // NewCost, CostDiff, // MeandC,SumDeltaPlus = 0; // Summe aller uphill-Uebergaenge // SetNewE( P.GetCost(s) ); // StartE = GetE(); int nproc=1,me=0; if (myrank >= 0 ) { MPI_Comm_size(comm,&nproc); MPI_Comm_rank(comm,&me); } T0 = SA_Scheduler::AartsWarmingUp(P,s,b,length); // unsigned int m1,m2,i; // float m0; // m0 = Length/nproc + 1; // T0 = 1e-10; // for(m1=0,m2=0,i=0; i < m0; i++) // { // P.GetNeighbor(s,GetRelativeT()); // NewCost = P.GetCost(s); // CostDiff = abs(NewCost - E); // if ( Better(NewCost,E) ) // { // P.UpdateSolution(s); // SetNewE( NewCost ); // m1++; // counter for better moves // } // else // { // m2++; // counter for worther moves // SumDeltaPlus += CostDiff; // ? nich vielleicht NACH der Abfrage ? // if ( exp(-CostDiff/T) > rand_float() ) // { // P.UpdateSolution(s); // SetNewE( NewCost ); // } // else // { // P.ResetSolution(s); // SetNewE( E ); // } // } // if ( BestFound() ) // P.Copy(s,b); // dummy = m2*ksi0 - (1-ksi0)*m1 ; // if ( m2 > 0 && dummy != 0) // { // T0 = ( SumDeltaPlus/m2 ) / log( m2 / dummy ); // } // } if(nproc >1) { // MPI_Bcast(&T0,1,MPI_FLOAT,0,comm); std::cerr << "DBG: own value " << T0 << std::endl; float *rcvbuf = new float; MPI_Allreduce(&T0,rcvbuf,1,MPI_FLOAT,MPI_SUM,comm); *rcvbuf /= nproc; std::cerr << "DBG: reduced value " << *rcvbuf << std::endl; return ((double)*rcvbuf); } else { return((double)T0); } } // \************************************************ // Method WarmingUp // - Decision of warming up strategy is similar // to SA_Scheduler but the execution is // adapted to several processors // \************************************************ void SA_ParScheduler::WarmingUp(SA_Problem & P, SA_Solution &s, SA_Solution &b,MPI_Comm comm) { SA_Scheduler::WarmingUp(P,s,b); // } // if ( MaxChainLength == 0) // if subchainlength wasn't set in .cfg-file // { // MaxChainLength = MaxChainLength0 = (unsigned long)ceil(P.GetLocalN()); // } // //// use the subchainfactor (def. is 1) // MaxChainLength = MaxChainLength0 = (unsigned long)ceil(MaxChainLength*subchainfactor); // // if( StartT < 0.0) // if StartT wasn't set in .cfg-file // { // SetStartT( AartsWarmingUp(P,s,b,comm,MaxChainLength, InitAccRatio)); // } } #endif