//#include //#include #include #include #include #include //#include #include #include #include //#include #include "SA_Solver.h" #include "util_salib.h" #include "SA_SeqEasyScheduler.h" const int MaxStringLength = 1024; // bound for the stringlength in the logfile // \****************************************************** // Konstruktor - Liest die Konfigurationsdatei mit Hilfe // der Methode ReadConfigFile. // \****************************************************** SA_Solver::SA_Solver(SA_Problem & prb): P(&prb), State(NULL), BestSolution(NULL), VerboseMode(FALSE), FileReadTime(0), InitialSolutionTime(0), SATime(0), PostprocTime(0), Algorithm(NULL), ConfigFileName(NULL), DataFileName(NULL), SolutionFileName(NULL), SolutionCostFileName(NULL), WriteFct(STREAM), OverwriteSolution(BETTER), OutputFileName(NULL), sasolvoutput("SA_Solver","SA_Output.rsc") { GetInitialSolution_fp = & SA_Problem::GetInitialSolution; strcpy(InitialSolutionStr, "Initial"); Algorithm = new char[8]; strcpy( Algorithm,"SeqAlg"); sasolvoutput.EnableLevelNumbers(false); sasolvoutput.EnableIdentifier(true); sasolvoutput.SetOutputLevel(10); // sasolvoutput.AddVariable(1,SA_STRING, ConfigFileName); // sasolvoutput.AddVariable(2,SA_STRING, DataFileName); // sasolvoutput.AddVariable(3,SA_STRING, OutputFileName); // sasolvoutput.AddVariable(4,SA_STRING, SolutionFileName); // sasolvoutput.AddVariable(5,SA_STRING, SolutionCostFileName); sasolvoutput.AddVariable(6,SA_INT, &WriteFct); sasolvoutput.AddVariable(7,SA_INT, &OverwriteSolution); strcpy(InitialSolutionStr,"Initial"); sasolvoutput.AddVariable(8,SA_STRING, InitialSolutionStr); sasolvoutput.AddVariable(9,SA_STRING, Algorithm); // ConfigFileName = new char[80]; // strcpy( ConfigFileName,"defname.cfg"); // DataFileName = new char[80]; // strcpy( DataFileName,"defname.in"); // OutputFileName = new char[80]; // strcpy( OutputFileName,"defname.out"); } // \****************************************************** // Destruktor // \****************************************************** SA_Solver::~SA_Solver() {//debug(SA_Solver::Destruktor , myrank); // delete Cooler; delete Algorithm; delete [] ConfigFileName; delete [] DataFileName; delete [] SolutionFileName; delete [] OutputFileName; } SA_Output *SA_Solver::GetSolverOutput() { if (Cooler != NULL) { sasolvoutput.SetPreviousOutput(Cooler->GetSchedulerOutput()); } return &sasolvoutput; } SA_Solution *SA_Solver::GetCurrentSolution() { return(State); } SA_Solution *SA_Solver::GetBestSolution() { return(BestSolution); } // \****************************************************** // Methode ShowConfig - Gibt die aktuelle Konfiguration // aus (nur zur Kontrolle). // \****************************************************** void SA_Solver::ShowConfig() { sasolvoutput.OutputInit(); // std::cout << "SA_Solver Konfiguration:" << std::endl // << "\tEingabedatei:\t\t" << DataFileName << std::endl // << "\tLoesungsdatei:\t\t" << SolutionFileName << std::endl // << "\tLogdatei:\t\t" << OutputFileName << std::endl // << "\tStartSolution:\t\t" << ( GetInitialSolution_fp == & SA_Problem::GetRandomSolution ? "Random":"Initial") <GetCost(*BestSolution); sasolvoutput.OutputFrozenYes(); // Ausgabe der Daten: F=Dateiname,T=Anfangstemperatur, C=Abkuehlungsfaktor, Z=Lese-/Rechenzeiten // output // << "Solv=Seq" // << " NPROC=1" // << " F=" << filename(DataFileName) // << " Z=" << FileReadTime << "/" << InitialSolutionTime << "/" << SATime << "/" << PostprocTime // << " StartSol=" << ( GetInitialSolution_fp == & SA_Problem::GetRandomSolution ? "Rnd":"Init") // <<" "; //// Cooler->OutputStatistics(output); // output << " PostE=" << BestPostE <GetCost(*BestSolution); // Ausgabe der Daten: F=Dateiname,T=Anfangstemperatur, C=Abkuehlungsfaktor, Z=Lese-/Rechenzeiten output << "Solv=Seq" << " NPROC=1" << " F=" << filename(DataFileName) << " Z=" << FileReadTime << "/" << InitialSolutionTime << "/" << SATime << "/" << PostprocTime << " StartSol=" << ( GetInitialSolution_fp == & SA_Problem::GetRandomSolution ? "Rnd":"Init") <<" "; Cooler->CreateLog(output); output << " PostE=" << BestPostE << std::endl; } // Controls the output of logging information. Uses the CreateLog methods of solver // and scheduler void SA_Solver::WriteLog(bool write) { if( write ) { char * log_buf = new char [MaxStringLength], * str=NULL; if (log_buf == NULL) { std::cout <<" memory exceeded in WriteLog\n"; exit(1); } std::ostrstream outstream(log_buf,MaxStringLength); CreateLog(outstream); // Cooler->CreateLog(outstream); // Cooler->OutputStatistics(); outstream<CreateLog(std::cout); // Cooler->OutputStatistics(); } } // Startloesungen erzeugen und ggf. ausgeben //void SA_Solver::InitStates() //{ // time_t starttime, endtime; // int things_done=0; //// Initialloesung erzeugen // if( State == NULL) // { // State = P->CreateSolution(); // things_done = 1; // } // if (BestSolution == NULL ) // BestSolution = P->CreateSolution(); // // InitialSolutionTime = time(NULL); // (*P.*GetInitialSolution_fp)(*State); // InitialSolutionTime = time(NULL)- InitialSolutionTime; // Cooler->SetStartE(P->GetCost(*State)); // // Cooler->ResetBestE(); // // P->Copy(*State,*BestSolution); // //if( things_done) //{ // if ( VerboseMode ) // { // std::cout << "Initial solution"<<":"<< "\n"; // std::cout << *State <GetCost(*State)< der Prozessor schreibt EIGENE Zeile in die Logdatei, //// in comm_masters von solchen Prozessoren steht der genau sie enthaltender Communicator. //// comm_slaves enthaelt jeweils alle Slaves zu einem Master. //// //// Bspl. : //// WriteLog(1,MPI_COMM_WORLD,MPI_COMM_SELF); (== WriteLog(1);) //// bedeutet : jeder Prozessor fuehrte eigenen Lauf durch, entsprechend muessen alle eine Zeile schreiben, //// wo nur von mir stammende Information zusammengefasst wird. //// WriteLog(myrank==0,MPI_COMM_SELF,MPI_COMM_WORLD); //// besagt dagegen : alle zusammen machten einen Lauf, es wird eine Zeile geschrieben, und darin //// steht Zusammenfassung von allen. //void SA_Solver::WriteLog(bool write) //{ // // if( write ) // { // char * log_buf = new char [MaxStringLength], // * str=NULL; // if (log_buf == NULL) // { // std::cout <<" memory exceeded in WriteLog\n"; // exit(1); // } // std::ostrstream outstream(log_buf,MaxStringLength); // OutputStatistics(outstream); // outstream<WarmingUp(*P,*State,*BestSolution); // ShowConfig(); // // time_t starttime, endtime; // //P->GetInitialSolution(*State); // // starttime = time(NULL); // do // { // do // { // P->GetNeighbor(*State,Cooler->GetRelativeT()); // // if ( Cooler->Accept( P->GetCost(*State) )) // { // P->UpdateSolution(*State); // if ( Cooler->BestFound() ) // P->Copy(*State,*BestSolution); // } // else // P->ResetSolution(*State); // // } while ( ! Cooler->Equilibrium()); // // if ( VerboseMode ) // { // Cooler->OutputSubchainStatistics(std::cout); std::cout <UpdateTemperature(); ////MPE_Log_event(4,0,"End UpdateTemperature"); // // // } while (! Cooler->Frozen()); // // endtime = time(NULL); // SATime = endtime - starttime; // // PostprocTime = time(NULL); // P->Postprocessing(*BestSolution); // PostprocTime = time(NULL) - PostprocTime; // // WriteLog(1); // WriteSolution(); // // return Cooler->GetBestE(); //} // \****************************************************** // Methode ReadConfig - Liest die Konfigurations- // daten ( geklammert mit '{' '}' ) aus dem istream // \****************************************************** int SA_Solver::ReadConfig(std::istream & config) { char text[BUFLEN]; config >> text; if ( strcmp(text,"{") != 0) { std::cout << "Config file section for SA_Solver does not begin with {!\n"; return FALSE; } while (config >> text && ( strcmp(text,"}") != 0 )) { if (strcmp(text, "datafilename") == 0) { config >> text; DataFileName = new char[strlen(text)+1]; strncpy(DataFileName, text, strlen(text)+1); std::cout << "Reading data file " << DataFileName << "... " << std::endl; // Einlesen der Problem-Daten FileReadTime = time(NULL); if (! P->ReadProblemData(DataFileName)) { std::cout << "Error reading data file!" << std::endl << std::flush; return 0; // exit(1); } std::cout << "finished!"<< std::endl; FileReadTime = time(NULL)- FileReadTime; } else if (strcmp(text, "outputfilename") == 0) { config >> text; OutputFileName = new char[strlen(text)+1]; strncpy(OutputFileName, text, strlen(text)+1); //std::cout << "file name " << OutputFileName << std::endl; } else if (strcmp(text, "solutionfilename") == 0) { config >> text; if (strcmp(text, "*") == 0) // Defaultname erwuenscht: setzt sich aus dem DataFileName und einem Praefix zusammen { char * SolutionSuffix = ".solution"; int dfn_len = strlen(DataFileName), sp_len = strlen(SolutionSuffix); SolutionFileName = new char[dfn_len+sp_len+1]; strncpy(SolutionFileName, DataFileName, dfn_len); strncpy(SolutionFileName+dfn_len, SolutionSuffix, sp_len+1); } else { SolutionFileName = new char[strlen(text)+1]; strncpy(SolutionFileName, text, strlen(text)+1); } char * CostSuffix = ".cost"; int f_ln = strlen(SolutionFileName), s_ln = strlen(CostSuffix); SolutionCostFileName = new char[f_ln+s_ln+1]; strncpy(SolutionCostFileName,SolutionFileName,f_ln); strncpy(SolutionCostFileName+f_ln,CostSuffix,s_ln+1); } else if (strcmp(text, "overwritesolution") == 0) { config >> text; if (strcmp(text, "never") == 0) { OverwriteSolution = NEVER; } else if (strcmp(text, "better") == 0) { OverwriteSolution = BETTER; } else if (strcmp(text, "always") == 0) { OverwriteSolution = ALWAYS; } else { OverwriteSolution = BETTER; std::cout << "Unknown keyword " << text << " for OverwriteSolution! Set to default \"better\""<> text; if (strcmp(text, "stream") == 0) { WriteFct = STREAM; } else if (strcmp(text, "path") == 0) { WriteFct = PATH; } else { WriteFct = STREAM; std::cout << "Unknown keyword "<> text; if (strcmp(text, "on") == 0) VerboseMode = TRUE; } else if (strcmp(text, "broadcastbest") == 0) { config >> text; // if (strcmp(text, "on") == 0) BroadcastBest = TRUE; } // else if (strcmp(text, "Scheduler") == 0) // { // // Instantiierung des Schedulers // delete Cooler; // // config >> text; // if (strcmp(text, "SeqEasyScheduler") == 0) // { // Cooler = new SeqEasyScheduler(); // } // // else if (strcmp(text, "FloodScheduler") == 0) // // { // // Cooler = new FloodScheduler(); // // } // //else if (strcmp(text, "OttenScheduler") == 0) // // { // // Cooler = new OttenScheduler(); // // } // else if (strcmp(text, "AartsScheduler") == 0) // { // // Cooler = new AartsScheduler(); // } // else // { // std::cout <<"Unknown Scheduler "<ReadConfig(config) ) // { // std::cout <<"ReadConfing for Scheduler failed!\n"; // return 0; // } // } // else if (strcmp(text, "algorithm") == 0) // { // config >> text; // delete Algorithm; // Algorithm = new char[strlen(text)+1]; // (strcpy(Algorithm, text) == 0); // } else if (strcmp(text, "verboselevel") == 0) { config >> text; sasolvoutput.SetOutputLevel(atoi(text)); } else if (strcmp(text, "StartSolution") == 0) { config >> text; if (strcmp(text, "Random") == 0) { strcpy(InitialSolutionStr,"Random "); GetInitialSolution_fp = & SA_Problem::GetRandomSolution; } } else { std::cout <<"In SA_Solver::ReadConfig unrecognized keyword \""<GetLocalN(); // if( Length <= 0 ) // { // std::cout << "Bad value "<GetNeighbor(*State,1); // std::cout<<"\tSingle GetNeighbor : done\n"; // P->UpdateSolution(*State); // std::cout<<"\tUpdateSolution : done\n"; // do // { // Cost = P->GetCost(*State); // P->Copy(*State,*BestSolution); // P->GetNeighbor(*State,1); // P->ResetSolution(*State); // if ( (Cost - P->GetCost(*State)) > EPSILON ) // { // status = 0; // std::cout<< "Error: the solution \n"<< (*BestSolution) <<" went after GetNeigbor and ResetSoltuion into\n" // << (*State) <<" and the costvalue has changed!\n"; // } // P->GetNeighbor(*State,1); // Cost = P->GetCost(*State); // P->UpdateSolution(*State); // if ( (Cost - P->GetCost(*State)) > EPSILON ) // { // status = 0; // std::cout<< "Error: the solution \n"<< (*State)<<"changed the costvalue after UpdateSolution!\n"; // } // } while (status && (i++)Copy(*BestSolution,*State); if(State == NULL) { State = new SA_Solution; P->GetInitialSolution(*State); } bestcost = P->GetCost(*State); while (failures < P->GetLocalN()) { P->GetNeighbor(*State,Cooler->GetRelativeT()); newcost = P->GetCost(*State); if (Cooler->Better(newcost,bestcost)) { bestcost = newcost; P->UpdateSolution(*State); failures = 0; std::cout << "Solution improved!" << std::endl; } else { P->ResetSolution(*State); failures++; std::cout << "."; } } P->Copy(*State,*BestSolution); WriteSolution(); } // \****************************************************** // Methode WriteSolution - Schreibt die beste Loesung entsprechen // der SolutionFileName und OverwriteSolution, // Bei VerboseMode wird diese auch ausgegeben. // // Format der Datei : in der ersten Zeile steht die Bewertung der Loesung gefolgt von dem Kommentar, // ab der zweiten Zeile kommt das Ergebnis von ostream << Solution; // // muss auf allen Prozessoren von comm aufgerufen werden // \****************************************************** void SA_Solver::WriteSolution() { if (VerboseMode) { std::cout << "Best solution found:\n"; std::cout << *BestSolution << std::endl; std::cout << "Value of best solutions cost function:\n"; std::cout << P->GetCost(*BestSolution) << std::endl; } else { std::cout << "Best found solution has the value of "<GetCost(*BestSolution)<> old_cost) ) { std::cout << "Read from "<Better( P->GetCost(*BestSolution),old_cost) ) { write = 1; if (VerboseMode) std::cout << "Solution better than known found. "; } else { if (VerboseMode) std::cout << "Best found solution is not better than known!\n"; } } } // SolutionCostFile.close(); } } if ( write ) { // write SolutionCost { std::ofstream SolutionCostFile(SolutionCostFileName,std::ios::out); if ( ! SolutionCostFile ) { std::cout << "Cannot open file " << SolutionCostFileName<<"!\n"; } else SolutionCostFile << P->GetCost(*BestSolution)<<" // Cost of the Solution in "<OutputSolution(SolutionFileName,*BestSolution) ) { std::cout <<"Write solution into "<