28 static random_device rd;
 
   44                         if (mv1 == 
nullptr || mv2 == 
nullptr || duration < 0.0)
 
   45                                 throw InvalidArgument(caller(), 
"Attempt to pass the malicious constructor parameters!");
 
   46                         else if (mv1->minDuration()+mv2->minDuration() >= duration+2*
TIME_ERR || mv1->maxDuration()+mv2->maxDuration()+2*
TIME_ERR <= duration)
 
   47                                 throw InvalidArgument(caller(), 
"Invalid constructor parameters, the solution is infeasible!");
 
   49                         mFromX = max(duration-mv2->maxDuration(), mv1->minDuration());
 
   50                         mToX = min(duration-mv2->minDuration(), mv1->maxDuration());
 
   51                         mDirection = mToX-mFromX;
 
   52                         assert(mDirection > -
TIME_ERR && 
"A bug in the UnimodalFunctionHeuristic class, it should be positive!");
 
   71                 pair<double, double> 
durations(
const double& alpha)
 const {
 
   72                         if (alpha < 0.0 || alpha > 1.0)
 
   73                                 throw InvalidArgument(caller(), 
"Invalid function parameter, it must be in a range from 0.0 to 1.0!");
 
   75                         double d1 = mFromX+alpha*mDirection, d2 = mTotalDuration-d1;
 
   76                         assert(abs(d1+d2-mTotalDuration) < 5*
TIME_ERR && 
"Invalid golden search of the method, solution infeasible!");
 
   77                         assert(mMv1->minDuration() < d1+5*
TIME_ERR && d1 < mMv1->maxDuration()+5*
TIME_ERR && 
"Duration of movement 1 is out of bound!");
 
   78                         assert(mMv2->minDuration() < d2+5*
TIME_ERR && d2 < mMv2->maxDuration()+5*
TIME_ERR && 
"Duration of movement 2 is out of bound!");
 
   88                         const auto& durPair = durations(alpha);
 
   89                         return mMv1->energyConsumption(durPair.first)+mMv2->energyConsumption(durPair.second);
 
  108         const vector<Robot*>& robots = mLine.robots();
 
  109         uint32_t numberOfRobots = robots.size();
 
  110         if (ps.
locs.size() != numberOfRobots)
 
  114         bool writePwrms = ps.
pwrms.empty();
 
  115         vector<vector<Location*>> fixed(numberOfRobots);
 
  116         for (uint32_t r = 0; r < numberOfRobots; ++r)   {
 
  117                 vector<Movement*> mvs;
 
  118                 const vector<Location*>& locs = ps.
locs[r];
 
  119                 assert(locs.size() > 1 && 
"Circuits in the partial solution should be filled in!");
 
  120                 for (uint32_t l = 0; l+1 < locs.size(); ++l)    {
 
  121                         Location *from = locs[l], *to = locs[l+1];
 
  122                         Movement *mv = getValue(mMapping.locationsToMovement, {from, to}, caller());
 
  123                         assert(mv != 
nullptr && 
"Unexpected nullptr! Should be checked by setValue previously!");
 
  126                         if (mMapping.sptComp.count(from->parent()) > 0)
 
  127                                 fixed[r].push_back(from);
 
  130                 ps.
mvs.push_back(move(mvs));
 
  131                 if (writePwrms == 
true)
 
  132                         ps.
pwrms.emplace_back(locs.size(), robots[r]->fastestPowerSavingMode());
 
  141         bool collisionsFeasible = 
false;
 
  142         high_resolution_clock::time_point startInit = high_resolution_clock::now();
 
  144         double extraTime = duration_cast<duration<double>>(high_resolution_clock::now()-startInit).count();
 
  145         double minCriterion = F64_MAX, maxCriterion = F64_MIN;
 
  147         mKB.recordPartialProblemSolveCall();
 
  149         while (!collisionsFeasible)     {
 
  150                 high_resolution_clock::time_point startLP = high_resolution_clock::now();
 
  152                 mKB.recordLPCall(duration_cast<duration<double>>(high_resolution_clock::now()-startLP).count()+extraTime);
 
  153                 if (s.
status == OPTIMAL)        {
 
  158                         if (r.
a1 != 
nullptr && r.
a2 != 
nullptr)
 
  161                                 collisionsFeasible = 
true;
 
  166                                 case LP_INITIAL_PROBLEM:
 
  167                                         mKB.reportInfDueToLP();
 
  169                                 case POWER_MODE_HEURISTIC:
 
  170                                         mKB.reportInfDueToPwrmHeur();
 
  172                                 case LOCATION_CHANGE_HEURISTIC:
 
  173                                         mKB.reportInfDueToLocHeur();
 
  176                                         mKB.reportInfDueToPathChange();
 
  180                         mKB.recordInfeasibleLP();
 
  189                 throw SolverException(caller(), 
"A bug in solving the partial LP problem, the solution is infeasible!");
 
  193         if (minCriterion > 0.0)
 
  194                 mKB.recordLPFixDeterioration(maxCriterion/minCriterion-1.0);
 
  202         vector<double> startTimes, durations;
 
  203         uint32_t numberOfRobots = mLine.robots().size();
 
  204         for (uint32_t r = 0; r < numberOfRobots; ++r)   {
 
  205                 const vector<Location*>& locs = ps.
locs[r];
 
  207                         assert(loc != 
nullptr && loc->parent() != 
nullptr && 
"Unexpected null pointer!");
 
  209                         pair<double, double> val;
 
  216                         startTimes.push_back(val.first);
 
  217                         durations.push_back(val.second);
 
  222                 timing.
startLocs.push_back(move(startTimes));
 
  223                 timing.
durLocs.push_back(move(durations));
 
  224                 startTimes.clear(); durations.clear();
 
  226                 const vector<Movement*>& mvs = ps.
mvs[r];
 
  228                         assert(mv != 
nullptr && mv->parent() != 
nullptr && 
"Unexpected null pointer!");
 
  230                         pair<double, double> val;
 
  237                         startTimes.push_back(val.first);
 
  238                         durations.push_back(val.second);
 
  243                 timing.
startMvs.push_back(move(startTimes));
 
  244                 timing.
durMvs.push_back(move(durations));
 
  245                 startTimes.clear(); durations.clear();
 
  253         double cycleTime = mLine.productionCycleTime();
 
  254         double s1m = fmod(s1, cycleTime), s2m = fmod(s2, cycleTime);
 
  256                 swap(m1, m2); swap(s1, s2); swap(d1, d2); swap(s1m, s2m);
 
  259         double intersection1 = min(max(s1m+d1-s2m, 0.0), d2);
 
  260         double intersection2 = min(max(s2m+d2-(s1m+cycleTime), 0.0), d1);
 
  268                 if (s1m+0.5*d1 <= s2m+0.5*d2)   {
 
  269                         cl.
a1 = m1->baseParent();
 
  270                         cl.
a2 = m2->baseParent();
 
  271                         cl.
multiplier = (int32_t) round(((s2-s2m)/cycleTime)-((s1-s1m)/cycleTime));
 
  273                         cl.
a1 = m2->baseParent();
 
  274                         cl.
a2 = m1->baseParent();
 
  275                         cl.
multiplier = (int32_t) round(((s1-s1m)/cycleTime)-((s2-s2m)/cycleTime));
 
  286                 double s1 = mit1.second.first, d1 = mit1.second.second;
 
  287                 const auto& mit2 = mMapping.collisionSearch.find(m1);
 
  288                 if (mit2 != mMapping.collisionSearch.cend())    {
 
  292                                         double s2 = sit->second.first, d2 = sit->second.second;
 
  307         high_resolution_clock::time_point startLocHeur = high_resolution_clock::now();
 
  309         solutionChanged = 
false;
 
  310         double energyImprovement = 0.0;
 
  311         default_random_engine threadGenerator(rd());
 
  312         double cycleTime = mLine.productionCycleTime();
 
  313         uint32_t numberOfRobots = mLine.robots().size();
 
  314         double averageInputPower = ot.
totalEnergy/(numberOfRobots*cycleTime);
 
  315         for (uint32_t r = 0; r < numberOfRobots; ++r)   {
 
  316                 uint32_t numberOfLocations = ps.
locs[r].size();
 
  317                 uniform_int_distribution<uint32_t> randomOffset(0u, 1u);
 
  318                 for (uint32_t i = randomOffset(threadGenerator); i+1u < numberOfLocations; i += 2u)     {
 
  320                         assert(bestLoc != 
nullptr && bestLoc->parent() != 
nullptr && 
"Invalid initialization of the robotic cell!");
 
  321                         if (count(fixed[r].cbegin(), fixed[r].cend(), bestLoc) == 0)    {
 
  323                                 int64_t prevIdxMv = (i > 0 ? i-1 : ps.
mvs[r].size()-1);
 
  324                                 int64_t prevIdxLoc = (i > 0 ? i-1 : numberOfLocations-2);
 
  325                                 assert(prevIdxMv >= 0 && prevIdxLoc >= 0 && 
"Invalid index calculation, were the vectors initialized?!");
 
  326                                 Movement *bestEntering = ps.
mvs[r][prevIdxMv], *bestLeaving = ps.
mvs[r][i];
 
  330                                 double bestStart1 = ot.
startMvs[r][prevIdxMv], bestDur1 = ot.
durMvs[r][prevIdxMv];      
 
  332                                 double bestStart3 = ot.
startMvs[r][i], bestDur3 = ot.
durMvs[r][i];      
 
  333                                 double stationaryDuration = bestDur2, dynamicDuration = bestDur1+bestDur3;
 
  339                                 double initialEnergyConsumption = bestEntering->
energyConsumption(bestDur1), bestEnergyConsumption = F64_INF;
 
  340                                 initialEnergyConsumption += bestLoc->
energyConsumption(stationaryDuration, selectedPowerSavingMode);
 
  341                                 initialEnergyConsumption += bestLeaving->energyConsumption(bestDur3);
 
  343                                 for (
Location *loc : selLoc->parent()->locations())     {
 
  344                                         const auto& sit1 = mMapping.locationsToMovement.find({prevLoc, loc});
 
  345                                         const auto& sit2 = mMapping.locationsToMovement.find({loc, nextLoc});
 
  346                                         if (sit1 != mMapping.locationsToMovement.cend() && sit2 != mMapping.locationsToMovement.cend()) {
 
  347                                                 Movement *entering = sit1->second, *leaving = sit2->second;
 
  348                                                 bool callGoldenSearch = entering->minDuration()+leaving->minDuration() < dynamicDuration+
TIME_ERR;
 
  349                                                 callGoldenSearch = callGoldenSearch && entering->maxDuration()+leaving->maxDuration()+TIME_ERR > dynamicDuration;
 
  350                                                 if (callGoldenSearch == 
true)   {
 
  353                                                         const pair<double, double>& res = 
goldenSearch(unifFce);
 
  354                                                         double totalEnergy = res.second;
 
  355                                                         totalEnergy += loc->energyConsumption(stationaryDuration, selectedPowerSavingMode);
 
  357                                                         const pair<double, double>& mvsDurs = unifFce.
durations(res.first);
 
  358                                                         double s1 = ot.
startMvs[r][prevIdxMv], d1 = mvsDurs.first;
 
  359                                                         double s2 = s1+d1, d2 = stationaryDuration;
 
  360                                                         double s3 = s2+d2, d3 = mvsDurs.second;
 
  361                                                         if (loc->parent()->lastInCycle())
 
  364                                                         vector<ActivityModeInfo> partOfGantt = { { entering, s1, d1 }, { loc, s2, d2 }, { leaving, s3, d3 } };
 
  365                                                         double timePenalty = calculateBreakagePenalty(partOfGantt, ot);
 
  366                                                         totalEnergy += mPenaltyMultiplier*averageInputPower*timePenalty;
 
  368                                                         if (totalEnergy < bestEnergyConsumption)        {
 
  369                                                                 bestEnergyConsumption = totalEnergy;
 
  370                                                                 bestEntering = entering; bestLoc = loc; bestLeaving = leaving;
 
  371                                                                 bestStart1 = s1; bestDur1 = d1; bestStart2 = s2; bestDur2 = d2; bestStart3 = s3; bestDur3 = d3;
 
  377                                 if (bestEnergyConsumption < F64_INF)    {
 
  379                                         energyImprovement += initialEnergyConsumption-bestEnergyConsumption;
 
  381                                         ps.
mvs[r][prevIdxMv] = bestEntering;
 
  382                                         ot.
durMvs[r][prevIdxMv] = bestDur1;
 
  384                                         setValue(ot.
actToStartAndDur, bestEntering->parent(), {bestStart1, bestDur1}, caller());
 
  385                                         ps.
locs[r][i] = bestLoc;
 
  387                                                 ps.
locs[r].back() = ps.
locs[r].front();
 
  390                                         setValue(ot.
actToStartAndDur, bestLoc->parent(), {bestStart2, bestDur2}, caller());
 
  391                                         ps.
mvs[r][i] = bestLeaving;
 
  393                                         ot.
durMvs[r][i] = bestDur3;
 
  395                                         setValue(ot.
actToStartAndDur, bestLeaving->parent(), {bestStart3, bestDur3}, caller());
 
  396                                         if (bestLoc != selLoc)
 
  397                                                 solutionChanged = 
true;
 
  399                                         throw SolverException(caller(), 
"Cannot select a suitable location, either the heuristic bug or invalid partial solution!");
 
  405         mKB.recordLocHeurCall(duration_cast<duration<double>>(high_resolution_clock::now()-startLocHeur).count());
 
  407         return energyImprovement;
 
  412         high_resolution_clock::time_point startPwrmHeur = high_resolution_clock::now();
 
  414         solutionChanged = 
false;
 
  415         const vector<Robot*>& robots = mLine.robots();
 
  416         double cycleTime = mLine.productionCycleTime();
 
  417         uint32_t numberOfRobots = robots.size();
 
  418         vector<uint32_t> numberOfLocations(numberOfRobots);
 
  419         vector<vector<ActivityModeInfo>> info(numberOfRobots);
 
  420         vector<double> consumedEnergyPerRobot(numberOfRobots, 0.0);
 
  421         double averageInputPower = ot.
totalEnergy/(numberOfRobots*cycleTime);
 
  423         for (uint32_t r = 0; r < numberOfRobots; ++r)   {
 
  424                 numberOfLocations[r] = ps.
locs[r].size();
 
  425                 for (uint32_t l = 0; l+1 < numberOfLocations[r]; ++l)   {
 
  429                         info[r].push_back({loc, pwrm, energyLoc, startLoc, durLoc,
 
  430                                         max(pwrm->minimalDelay(), loc->parent()->minAbsDuration()), loc->parent()->maxAbsDuration()});
 
  431                         consumedEnergyPerRobot[r] += energyLoc;
 
  434                 for (uint32_t l = 0; l+1 < numberOfLocations[r]; ++l)   {
 
  437                         info[r].push_back({mv, 
nullptr, energyMv, startMv, durMv, mv->minDuration(), mv->maxDuration()});
 
  438                         consumedEnergyPerRobot[r] += energyMv;
 
  442         double originalEnergyConsumption = accumulate(consumedEnergyPerRobot.cbegin(), consumedEnergyPerRobot.cend(), 0.0);
 
  444         vector<ModeSwitchInfo> candidates;
 
  445         for (uint32_t r = 0; r < numberOfRobots; ++r)   {
 
  446                 for (uint32_t l = 0; l+1 < numberOfLocations[r]; ++l)   {
 
  451                                 if (pwrm != selMode && pwrm->minimalDelay() <= selAct->maxAbsDuration())        {
 
  452                                         vector<ActivityModeInfo> robotTiming = info[r];
 
  453                                         double minReqDur = max(selAct->minAbsDuration(), pwrm->minimalDelay());
 
  455                                         robotTiming[l].pwrm = pwrm;
 
  457                                         robotTiming[l].minDuration = robotTiming[l].curDuration = minReqDur;
 
  458                                         robotTiming[l].maxDuration = selAct->maxAbsDuration();
 
  460                                         double energyScaledRobot = scaleGanttToCycleTime(robotTiming);
 
  461                                         if (energyScaledRobot < F64_INF)        {
 
  462                                                 double timePenalty = calculateBreakagePenalty(robotTiming, ot);
 
  463                                                 double estimatedEnergy = originalEnergyConsumption-consumedEnergyPerRobot[r];
 
  464                                                 estimatedEnergy += energyScaledRobot+mPenaltyMultiplier*averageInputPower*timePenalty;
 
  465                                                 candidates.emplace_back(r, l, selLoc, selMode, pwrm, estimatedEnergy);
 
  472         double energyImprovement = 0.0;
 
  473         if (!candidates.empty())        {
 
  476                 sort(candidates.begin(), candidates.end());
 
  478                 const auto& sit = find_if(candidates.cbegin(), candidates.cend(), [&](
const ModeSwitchInfo& i) { 
return !tabuList.
isTabu(i.loc, i.from, i.to); });
 
  479                 if (sit != candidates.cend())   {
 
  485                         default_random_engine threadGenerator(rd());
 
  486                         uniform_int_distribution<uint32_t> randSel(0, candidates.size()-1);
 
  487                         uint32_t selIdx = randSel(threadGenerator);
 
  488                         selected = candidates[selIdx];
 
  496                 energyImprovement = originalEnergyConsumption-selected.
estimatedEnergy;
 
  497                 solutionChanged = 
true;
 
  500         mKB.recordPwrmHeurCall(duration_cast<duration<double>>(high_resolution_clock::now()-startPwrmHeur).count());
 
  502         return energyImprovement;
 
  506         double sumOfDur = 0.0;
 
  507         double robotEnergy = 0.0;
 
  508         double cycleTime = mLine.productionCycleTime();
 
  510                 sumOfDur += ami.curDuration;
 
  511                 robotEnergy += ami.energy;
 
  514         double durDiff = sumOfDur-cycleTime;
 
  515         vector<bool> changeAllowed(robotGantt.size(), 
false);
 
  516         bool shorten = durDiff > 0.0, prolong = durDiff < 0.0;
 
  519                 double maxFeasChange = F64_INF;
 
  520                 uint32_t numberOfModifiable = 0u;
 
  521                 for (uint32_t i = 0; i < robotGantt.size(); ++i)        {
 
  522                         if (shorten && robotGantt[i].curDuration > robotGantt[i].minDuration)   {
 
  523                                 maxFeasChange = min(maxFeasChange, robotGantt[i].curDuration-robotGantt[i].minDuration);
 
  524                                 changeAllowed[i] = 
true;
 
  525                                 ++numberOfModifiable;
 
  526                         } 
else if (prolong && robotGantt[i].curDuration < robotGantt[i].maxDuration)    {
 
  527                                 maxFeasChange = min(maxFeasChange, robotGantt[i].maxDuration-robotGantt[i].curDuration);
 
  528                                 changeAllowed[i] = 
true;
 
  529                                 ++numberOfModifiable;
 
  531                                 changeAllowed[i] = 
false;
 
  535                 if (numberOfModifiable > 0 && maxFeasChange < F64_INF)  {
 
  536                         maxFeasChange = min(abs(durDiff)/numberOfModifiable, maxFeasChange);
 
  538                                 maxFeasChange = -maxFeasChange;
 
  540                         for (uint32_t i = 0; i < robotGantt.size(); ++i)        {
 
  541                                 if (changeAllowed[i])   {
 
  542                                         double energyUpdated = F64_INF;
 
  544                                         double durationUpdated = robotGantt[i].curDuration + maxFeasChange;
 
  545                                         assert(robotGantt[i].minDuration <= durationUpdated+
TIME_ERR 
  546                                                         && durationUpdated <= robotGantt[i].maxDuration+
TIME_ERR && 
"Invalid scaling of the robot graph!");
 
  556                                         robotEnergy += energyUpdated-robotGantt[i].energy;
 
  558                                         robotGantt[i].energy = energyUpdated;
 
  559                                         robotGantt[i].curDuration = durationUpdated;
 
  564                         double minCycleTime = 0.0;
 
  566                                 minCycleTime += ami.minDuration;
 
  568                         if (minCycleTime+
TIME_TOL < cycleTime)
 
  569                                 throw SolverException(caller(), 
"A bug in the method, the gantt should be scalable!");
 
  576                 durDiff += numberOfModifiable*maxFeasChange;
 
  580         sort(robotGantt.begin(), robotGantt.end());
 
  581         for (uint32_t i = 0; i+1 < robotGantt.size(); ++i)
 
  582                 robotGantt[i+1].curStartTime = robotGantt[i].curStartTime+robotGantt[i].curDuration;
 
  585         double checkCycleTime = 0.0;
 
  587                 checkCycleTime += ami.curDuration;
 
  588                 if (ami.minDuration > ami.curDuration+
TIME_TOL || ami.maxDuration+
TIME_TOL < ami.curDuration)
 
  589                         throw SolverException(caller(), 
"Invalid update step of the algorithm.");
 
  592         if (abs(checkCycleTime-cycleTime) > 
TIME_TOL)
 
  593                 throw SolverException(caller(), 
"The robot gantt was not scaled to the desired cycle time, a bug in the algorithm!");
 
  601         double timePenalty = 0.0;
 
  602         double cycleTime = mLine.productionCycleTime();
 
  604         for (uint32_t i = 0; i < robotGantt.size(); ++i)        {
 
  606                 double s1 = robotGantt[i].curStartTime, d1 = robotGantt[i].curDuration;
 
  609                 const auto& sit = mMapping.collisionSearch.find(m1);
 
  610                 if (sit != mMapping.collisionSearch.cend())     {
 
  614                                         double s2 = mit->second.first, d2 = mit->second.second;
 
  623                 for (
const map<
Activity*, vector<TimeLag>>* mapPtr : { &mMapping.timeLagsFromAct, &mMapping.timeLagsToAct })    {
 
  624                         const auto& sit1 = mapPtr->find(m1->baseParent());
 
  625                         if (sit1 != mapPtr->cend())     {
 
  626                                 for (
const TimeLag& tl : sit1->second)  {
 
  627                                         Activity *relAct = (idx == 0 ? tl.to() : tl.from());
 
  630                                                 double s2 = mit->second.first;
 
  632                                                         timePenalty += max(s1-s2+tl.length()-tl.height()*cycleTime, 0.0);
 
  634                                                         timePenalty += max(s2-s1+tl.length()-tl.height()*cycleTime, 0.0);
 
  643         assert(timePenalty >= 0.0 && 
"Time penalty must be positive, a bug in the algorithm!");
 
The instance of the class corresponds to a robot movement between two coordinates. 
 
double mFromX
The minimal duration of the first movement. 
 
bool isTabu(Location *l, RobotPowerMode *from, RobotPowerMode *to) const 
It checks whether the modification of a partial solution is allowed, i.e. the move/modification is no...
 
std::vector< std::vector< double > > durLocs
Durations assigned to static activities' locations. 
 
void addTabu(Location *l, RobotPowerMode *from, RobotPowerMode *to)
It adds a performed modification into the tabu list. 
 
double totalEnergy
The amount of energy required per robot cycle. 
 
void addCollisionResolution(Activity *i, Activity *j, const int32_t &multipleOfCycleTime)
It adds a constraint  to resolve a collision where  and  are start time and duration of the activity ...
 
The base class incorporating common properties of robot operations and movements. ...
 
The structure representing a solution found by an algorithm. 
 
double scaleGanttToCycleTime(std::vector< ActivityModeInfo > &robotGantt) const 
It scales durations of activities in such a way that the robot cycle time is met. Updated start times...
 
CollisionResolution resolveTheWorstCollision(const PartialSolution &ps, const OptimalTiming &ot, const Solution &s) const 
It finds the worst collision, i.e. with the longest time of active collision, and returns how to reso...
 
std::vector< std::vector< double > > startMvs
Start times assigned to dynamic activities' movements. 
 
std::vector< std::vector< Location * > > locs
Selected locations for each robot, time ordered. 
 
std::vector< std::vector< Location * > > initializePartialSolution(PartialSolution &ps) const 
It appends the fixed movements (implied from fixed locations), and optionally fastest power saving mo...
 
std::vector< std::vector< RobotPowerMode * > > pwrms
Selected power saving modes of related locations. 
 
RobotPowerMode * to
The candidate power saving mode to switch to. 
 
Movement * mMv2
The second movement to be considered. 
 
An unimodal function for two movements and their fixed total time. 
 
State convert(const Status &ilpStatus)
Conversion between the ILP solver status and the solution state. 
 
Activity * a2
Second activity involved in the collision. 
 
An instance of this class is devoted to the solution checking. 
 
double estimatedEnergy
Estimated energy consumption after switching to the candidate power saving mode. 
 
A general exception of the program. 
 
The structure stores how to resolve one collision between robots. 
 
double mTotalDuration
The time needed for both the movements is equal to this fixed value. 
 
double heuristicPowerModeSelection(const OptimalTiming &ot, PartialSolution &ps, TabuList &tabuList, bool &solutionChanged) const 
The sub-heuristic tries to switch from one power saving mode to another one for a location in order t...
 
A short-term memory, containing a list of forbidden moves, that mitigates the risk of cycling...
 
double functionValue(const double &alpha) const 
Returns a function value, i.e. total energy consumption of both movements. 
 
CollisionResolution resolveCollision(ActivityMode *m1, double s1, double d1, ActivityMode *m2, double s2, double d2) const 
It checks whether there is a collision between two specified activities, and eventually returns how t...
 
double mDirection
A maximal possible difference in duration for both the movements. 
 
The optimization sub-heuristics and Linear Programming solver for partially fixed problems...
 
std::vector< std::vector< double > > startLocs
Start times assigned to static activities' locations. 
 
int32_t multiplier
Multiplier addressing the time shift in the number of cycles. 
 
bool checkAll()
It calls the private member methods to verify the solution. 
 
constexpr double TIME_ERR
Minimal recognizable difference in the time. 
 
constexpr double TIME_TOL
A minimal time difference that is considered significant for a solution. 
 
double totalEnergy
Energy consumption of a robotic cell for this timing. 
 
A partially fixed problem, i.e. tuple. 
 
Exception is thrown if a method is given invalid parameters or a user provides invalid program argume...
 
Thrown if no feasible solution is found by the heuristic. 
 
Collection of locations in which a robot operation (or waiting) can be performed. ...
 
State status
Enum specifying whether the solution is optimal, feasible, or infeasible... 
 
Structure encapsulates the time and energy properties of an activity with its selected mode (a moveme...
 
Fixed locations, power saving modes, and movements. 
 
Movement * mMv1
The first movement to be considered. 
 
It represents the power saving mode of the robot. 
 
Determines an optimal timing of a partially fixed problem. 
 
pair< double, double > durations(const double &alpha) const 
Calculates durations of the movements based on the relative step. 
 
std::pair< double, double > goldenSearch(const T &unimodalFce)
It finds the minimal function value of a unimodal convex function. 
 
Instance of TimeLag class defines a time relation between two different robots. 
 
Universal algorithms like Floyd-Warshall, Golden Search, etc. 
 
UnimodalFunctionHeuristic(Movement *mv1, Movement *mv2, double duration)
Constructor initializes the member variables. 
 
double heuristicLocationChanges(OptimalTiming &ot, PartialSolution &ps, const std::vector< std::vector< Location * >> &fixed, bool &solutionChanged) const 
The sub-heuristic locally optimizes the robot paths (change locations) to reduce energy consumption...
 
Algo
Defining constants for different states of the heuristic. 
 
Solution solve() const 
The energy optimal timing is determined by solving Linear Programming problem and the solution is ret...
 
double energyConsumption(const double &duration) const 
 
double mToX
The maximal duration of the first movement. 
 
double intersection
Duration of the collision between activities a1 and a2. 
 
uint32_t locationIdx
Index of the related location of the robot. 
 
OptimalTiming convert(const PartialSolution &ps, const Solution &s) const 
Auxiliary method that converts a general form of the solution to the timing of the robotic cell...
 
std::vector< std::vector< Movement * > > mvs
Selected movements, implied from the selected locations and their order. 
 
RobotPowerMode * from
The original power saving mode. 
 
Either a movement or location. 
 
The file declares a class responsible for checking of solutions. 
 
Records a potential energy impact if a power saving mode of a robot is switched to another one...
 
Location of the robot used either during work (welding) or waiting. 
 
std::map< Activity *, std::pair< double, double > > actToStartAndDur
Activity to the assigned start time and duration. 
 
Location * loc
A pointer to the considered location. 
 
double energyConsumption(const double &duration, RobotPowerMode *m) const 
 
std::map< ActivityMode *, std::pair< double, double > > modeToStartAndDur
Selected location/movement to the assigned start time and duration. 
 
std::vector< std::vector< double > > durMvs
Durations assigned to dynamic activities' movements. 
 
OptimalTiming solvePartialProblem(const PartialSolution &ps, const CircuitTuple &t, Algo algo)
Employs Linear Programming to obtain energy-efficient timing for a given tuple. 
 
Obtained timing for a partial problem. 
 
uint32_t robotIdx
Index of the robot. 
 
double calculateBreakagePenalty(const std::vector< ActivityModeInfo > &robotGantt, const OptimalTiming &ot) const 
It calculates the penalty for the violation of time lags and collisions. 
 
std::map< uint32_t, std::pair< double, double > > startTimeAndDuration
Mapping of the activity identification to its start time and duration. 
 
Activity * a1
First activity involved in the collision.