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.