49 #include "../Algos/Algorithm.hpp"
50 #include "../Algos/EvcInterface.hpp"
51 #include "../Algos/Mads/SearchMethodBase.hpp"
52 #include "../Algos/SubproblemManager.hpp"
53 #include "../Cache/CacheBase.hpp"
54 #include "../Output/OutputQueue.hpp"
55 #include "../Math/RNG.hpp"
56 #include "../Util/fileutils.hpp"
59 #include "../Algos/Mads/MadsIteration.hpp"
60 #include "../Algos/Mads/Search.hpp"
61 #include "../Util/Clock.hpp"
65 omp_lock_t NOMAD::Algorithm::_algoCommentLock;
68 void NOMAD::Algorithm::init()
70 _name =
"AGenericAlgorithmHasNoName";
73 verifyParentNotNull();
75 if (
nullptr == _runParams)
77 throw NOMAD::StepException(__FILE__, __LINE__,
78 "A valid RunParameters must be provided to an Algorithm constructor.",
this);
81 if (
nullptr == _pbParams)
83 throw NOMAD::StepException(__FILE__, __LINE__,
84 "A valid PbParameters must be provided to the Algorithm constructor.",
this);
87 if (
nullptr == _stopReasons )
88 throw NOMAD::StepException(__FILE__, __LINE__,
89 "Valid stop reasons must be provided to the Algorithm constructor.",
this);
92 omp_init_lock(&_algoCommentLock);
96 _pbParams->checkAndComply();
99 _termination = std::make_unique<NOMAD::Termination>(
this );
102 NOMAD::Point fullFixedVariable = isRootAlgo() ? _pbParams->getAttributeValue<NOMAD::Point>(
"FIXED_VARIABLE")
103 : NOMAD::SubproblemManager::getSubFixedVariable(_parentStep);
105 NOMAD::Subproblem subproblem(_pbParams, fullFixedVariable);
106 NOMAD::SubproblemManager::addSubproblem(
this, subproblem);
107 _pbParams = subproblem.getPbParams();
108 _pbParams->checkAndComply();
114 signal(SIGINT, userInterrupt);
115 signal(SIGSEGV, debugSegFault);
120 NOMAD::Algorithm::~Algorithm()
122 NOMAD::SubproblemManager::removeSubproblem(
this);
124 omp_destroy_lock(&_algoCommentLock);
132 void NOMAD::Algorithm::setAlgoComment(
const std::string& algoComment,
const bool force)
136 auto rootAlgo =
const_cast<NOMAD::Algorithm*
>(getRootAlgorithm());
137 rootAlgo->setAlgoComment(algoComment, force);
142 omp_set_lock(&_algoCommentLock);
144 if (!_forceAlgoComment)
147 if (!_prevAlgoComment.empty() || !_algoComment.empty())
149 _prevAlgoComment.push_back(_algoComment);
151 _algoComment = algoComment;
155 _forceAlgoComment =
true;
158 omp_unset_lock(&_algoCommentLock);
165 void NOMAD::Algorithm::resetPreviousAlgoComment(
const bool force)
169 auto rootAlgo =
const_cast<NOMAD::Algorithm*
>(getRootAlgorithm());
170 rootAlgo->resetPreviousAlgoComment(force);
175 omp_set_lock(&_algoCommentLock);
177 if (!_forceAlgoComment || force)
179 if (_prevAlgoComment.empty())
186 _algoComment = std::move(_prevAlgoComment[_prevAlgoComment.size()-1]);
187 _prevAlgoComment.erase(_prevAlgoComment.end()-1);
189 if (_forceAlgoComment)
191 _forceAlgoComment =
false;
195 omp_unset_lock(&_algoCommentLock);
201 std::string NOMAD::Algorithm::getAlgoComment()
const
203 std::string algoComment;
206 algoComment = getRootAlgorithm()->getAlgoComment();
210 algoComment = _algoComment;
217 void NOMAD::Algorithm::startImp()
222 _startTime = NOMAD::Clock::getCPUTime();
230 _stopReasons->setStarted();
233 _algoSuccessful =
false;
234 _algoBestSuccess = NOMAD::SuccessType::NOT_EVALUATED;
239 readInformationForHotRestart();
240 NOMAD::CacheBase::getInstance()->setStopWaiting(
false);
244 NOMAD::EvcInterface::getEvaluatorControl()->resetLapBbEval();
245 NOMAD::EvcInterface::getEvaluatorControl()->setLapMaxBbEval(
NOMAD::INF_SIZE_T );
246 NOMAD::EvcInterface::getEvaluatorControl()->resetSgteEval();
248 if (
nullptr == _megaIteration)
258 NOMAD::CacheBase::resetNbCacheHits();
262 if (
nullptr != _initialization)
264 _initialization->start();
265 _initialization->run();
266 _initialization->end();
274 auto barrier = _megaIteration->getBarrier();
278 auto bestPoints = barrier->getAllPoints();
281 if (!bestPoints.empty())
283 std::transform(bestPoints.begin(), bestPoints.end(), std::back_inserter(x0s),
284 [](NOMAD::EvalPoint evalPoint) -> NOMAD::EvalPoint { return evalPoint; });
288 _pbParams->checkAndComply();
293 void NOMAD::Algorithm::endImp()
297 displayBestSolutions();
301 _totalRealAlgoTime = NOMAD::Clock::getTimeSinceStart();
302 _totalCPUAlgoTime += NOMAD::Clock::getCPUTime() - _startTime;
310 if ( _algoSuccessful )
313 auto searchMethodConst =
dynamic_cast<const NOMAD::SearchMethodBase*
>(_parentStep);
315 if (searchMethodConst !=
nullptr)
317 auto searchMethod =
const_cast<NOMAD::SearchMethodBase*
>(searchMethodConst);
318 searchMethod->setSuccessType(_algoBestSuccess);
324 NOMAD::EvcInterface::getEvaluatorControl()->resetLapBbEval();
325 NOMAD::EvcInterface::getEvaluatorControl()->setLapMaxBbEval(
NOMAD::INF_SIZE_T );
329 saveInformationForHotRestart();
330 NOMAD::CacheBase::getInstance()->setStopWaiting(
true);
334 resetPreviousAlgoComment();
338 void NOMAD::Algorithm::hotRestartOnUserInterrupt()
343 _totalCPUAlgoTime += NOMAD::Clock::getCPUTime() - _startTime;
346 hotRestartBeginHelper();
348 hotRestartEndHelper();
352 _startTime = NOMAD::Clock::getCPUTime();
358 void NOMAD::Algorithm::saveInformationForHotRestart()
const
370 std::string cacheFile = NOMAD::CacheBase::getInstance()->getFileName();
371 if (!cacheFile.empty())
373 NOMAD::CacheBase::getInstance()->write();
375 if ( _runParams->getAttributeValue<
bool>(
"HOT_RESTART_WRITE_FILES"))
377 std::cout <<
"Save information for hot restart." << std::endl;
378 std::cout <<
"Write hot restart file." << std::endl;
379 NOMAD::write(*
this, _runParams->getAttributeValue<std::string>(
"HOT_RESTART_FILE"));
384 void NOMAD::Algorithm::displayBestSolutions()
const
386 std::vector<NOMAD::EvalPoint> evalPointList;
392 : NOMAD::OutputLevel::LEVEL_VERY_HIGH;
393 NOMAD::OutputInfo displaySolFeas(_name, sFeas, outputLevel);
394 auto fixedVariable = NOMAD::SubproblemManager::getSubFixedVariable(
this);
396 sFeas =
"Best feasible solution";
397 auto barrier = getMegaIterationBarrier();
398 if (
nullptr != barrier)
400 evalPointList = barrier->getAllXFeas();
403 size_t nbBestFeas = evalPointList.size();
407 sFeas +=
": Undefined.";
408 displaySolFeas.addMsg(sFeas);
410 else if (1 == nbBestFeas)
413 displaySolFeas.addMsgAndSol(sFeas, *evalPointList.begin());
418 displaySolFeas.addMsgAndSol(sFeas, *evalPointList.begin());
422 const size_t maxSolCount = 8;
425 std::vector<NOMAD::EvalPoint>::const_iterator it;
427 for (it = evalPointList.begin(); it != evalPointList.end(); ++it)
430 if (evalPointList.begin() == it)
434 displaySolFeas.addMsgAndSol(
" ",*it);
435 if (solCount >= maxSolCount)
438 displaySolFeas.addMsg(
"... A total of " + std::to_string(evalPointList.size()) +
" feasible solutions were found.");
444 NOMAD::OutputQueue::Add(std::move(displaySolFeas));
446 evalPointList.clear();
451 NOMAD::OutputInfo displaySolInf(_name, sInf, outputLevel);
452 sInf =
"Best infeasible solution";
453 if (
nullptr != barrier)
455 evalPointList = barrier->getAllXInf();
458 size_t nbBestInf = evalPointList.size();
462 sInf +=
": Undefined.";
463 displaySolInf.addMsg(sInf);
465 else if (1 == nbBestInf)
468 displaySolInf.addMsgAndSol(sInf, *evalPointList.begin());
473 displaySolInf.addMsgAndSol(sInf, *evalPointList.begin());
479 std::vector<NOMAD::EvalPoint>::const_iterator it;
480 for (it = evalPointList.begin(); it != evalPointList.end(); ++it)
483 if (evalPointList.begin() == it)
487 displaySolInf.addMsgAndSol(
" ",(*it));
488 if (solCount >= maxSolCount)
491 displaySolInf.addMsg(
"... A total of " + std::to_string(evalPointList.size()) +
" infeasible solutions were found.");
497 NOMAD::OutputQueue::Add(std::move(displaySolInf));
501 void NOMAD::Algorithm::displayEvalCounts()
const
506 bool isSub = isSubAlgo();
509 size_t bbEval = NOMAD::EvcInterface::getEvaluatorControl()->getBbEval();
510 size_t lapBbEval = NOMAD::EvcInterface::getEvaluatorControl()->getLapBbEval();
511 size_t nbEval = NOMAD::EvcInterface::getEvaluatorControl()->getNbEval();
512 size_t sgteEval = NOMAD::EvcInterface::getEvaluatorControl()->getSgteEval();
513 size_t totalSgteEval = NOMAD::EvcInterface::getEvaluatorControl()->getTotalSgteEval();
514 size_t nbCacheHits = NOMAD::CacheBase::getNbCacheHits();
515 int nbEvalNoCount =
static_cast<int>(nbEval - bbEval - nbCacheHits);
518 bool showNbEvalNoCount = (nbEvalNoCount > 0);
519 bool showSgteEval = isSub && (sgteEval > 0);
520 bool showTotalSgteEval = (totalSgteEval > 0);
521 bool showNbCacheHits = (nbCacheHits > 0);
522 bool showNbEval = (nbEval > bbEval);
523 bool showLapBbEval = isSub && (bbEval > lapBbEval && lapBbEval > 0);
527 : NOMAD::OutputLevel::LEVEL_HIGH;
529 : NOMAD::OutputLevel::LEVEL_NORMAL;
532 std::string sFeedBbEval, sFeedLapBbEval, sFeedNbEvalNoCount, sFeedSgteEval,
533 sFeedTotalSgteEval, sFeedCacheHits, sFeedNbEval;
540 sFeedNbEvalNoCount +=
" ";
541 sFeedSgteEval +=
" ";
542 sFeedTotalSgteEval +=
" ";
543 sFeedCacheHits +=
" ";
546 else if (showNbEvalNoCount)
551 sFeedSgteEval +=
" ";
552 sFeedTotalSgteEval +=
" ";
553 sFeedCacheHits +=
" ";
561 sFeedSgteEval +=
" ";
562 sFeedTotalSgteEval +=
" ";
563 sFeedCacheHits +=
" ";
567 std::string sBbEval =
"Blackbox evaluations: " + sFeedBbEval +
NOMAD::itos(bbEval);
568 std::string sLapBbEval =
"Sub-optimization blackbox evaluations: " + sFeedLapBbEval +
NOMAD::itos(lapBbEval);
569 std::string sNbEvalNoCount =
"Blackbox evaluation (not counting): " + sFeedNbEvalNoCount +
NOMAD::itos(nbEvalNoCount);
570 std::string sSgteEval =
"Sgte evaluations: " + sFeedSgteEval +
NOMAD::itos(sgteEval);
571 std::string sTotalSgteEval =
"Total sgte evaluations: " + sFeedTotalSgteEval +
NOMAD::itos(totalSgteEval);
572 std::string sCacheHits =
"Cache hits: " + sFeedCacheHits +
NOMAD::itos(nbCacheHits);
573 std::string sNbEval =
"Total number of evaluations: " + sFeedNbEval +
NOMAD::itos(nbEval);
577 std::string sTotalRealTime =
"Total real time (round s): " + std::to_string(_totalRealAlgoTime);
578 std::string sTotalCPUTime =
"Total CPU time (s): " + std::to_string(_totalCPUAlgoTime);
581 AddOutputInfo(
"", outputLevelHigh);
583 AddOutputInfo(sBbEval, outputLevelHigh);
587 AddOutputInfo(sLapBbEval, outputLevelNormal);
589 if (showNbEvalNoCount)
591 AddOutputInfo(sNbEvalNoCount, outputLevelNormal);
595 AddOutputInfo(sSgteEval, outputLevelNormal);
597 if (showTotalSgteEval)
599 AddOutputInfo(sTotalSgteEval, outputLevelNormal);
603 AddOutputInfo(sCacheHits, outputLevelNormal);
607 AddOutputInfo(sNbEval, outputLevelNormal);
612 AddOutputInfo(sTotalRealTime, outputLevelNormal);
613 AddOutputInfo(sTotalCPUTime, outputLevelNormal);
619 bool NOMAD::Algorithm::isSubAlgo()
const
623 auto parentAlgo = getParentOfType<NOMAD::Algorithm*>();
624 if (
nullptr != parentAlgo)
633 bool NOMAD::Algorithm::terminate(
const size_t iteration)
635 return _termination->terminate(iteration);
639 void NOMAD::Algorithm::display ( std::ostream& os )
const
642 os <<
"MEGA_ITERATION " << std::endl;
643 os << *_megaIteration << std::endl;
644 os <<
"NB_EVAL " << NOMAD::EvcInterface::getEvaluatorControl()->getNbEval() << std::endl;
645 os <<
"NB_BB_EVAL " << NOMAD::EvcInterface::getEvaluatorControl()->getBbEval() << std::endl;
647 NOMAD::RNG::getPrivateSeed(x, y, z);
648 os <<
"RNG " << x <<
" " << y <<
" " << z << std::endl;
665 int nbEval = 0, nbBbEval = 0;
668 while (is >> name && is.good() && !is.eof())
670 if (
"MEGA_ITERATION" == name)
672 is >> *_megaIteration;
674 else if (
"NB_EVAL" == name)
678 else if (
"NB_BB_EVAL" == name)
682 else if (
"RNG" == name)
685 NOMAD::RNG::setPrivateSeed(x, y, z);
690 for (
unsigned i = 0; i < name.size(); i++)
698 NOMAD::EvcInterface::getEvaluatorControl()->setBbEval(nbBbEval);
699 NOMAD::EvcInterface::getEvaluatorControl()->setNbEval(nbEval);