Modifs de SimAnn pour multistart
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
namespace solverlib {
|
||||
using namespace random;
|
||||
|
||||
bool StatSimulatedAnnealing::activate = true;
|
||||
bool StatSimulatedAnnealing::activate = false;
|
||||
bool SimulatedAnnealing::withDynProg = false;
|
||||
bool SimulatedAnnealing::authorizeInfeasible = true;
|
||||
|
||||
@@ -39,7 +39,17 @@ namespace solverlib {
|
||||
};
|
||||
|
||||
|
||||
SimulatedAnnealing::SimulatedAnnealing(std::unordered_map<unsigned short, Decision>& decs, std::shared_ptr<modellib::STFMockInstance> mock, ESourceTrackPlan source)
|
||||
/*SimulatedAnnealing::SimulatedAnnealing(std::unordered_map<unsigned short, Decision>& decs, std::shared_ptr<modellib::STFMockInstance> mock, ESourceTrackPlan source)
|
||||
{
|
||||
randomEngine = solverlib::random::makeEngine();
|
||||
maxCostOfJob = (*std::max_element(STFMockInstance::jobs.begin(), STFMockInstance::jobs.end(), [&](auto op1, auto op2){return op1->getPoidsRetard() < op2->getPoidsRetard();}))->getPoidsRetard();
|
||||
setPenaltyWeights();
|
||||
addSolutionToPool(decs, mock, source);
|
||||
for (unsigned int i = 0; i< STFMockInstance::machines.size(); ++i)
|
||||
solutions[0].penaltyPerMachine[i] = Penalty{};
|
||||
}*/
|
||||
|
||||
SimulatedAnnealing::SimulatedAnnealing(std::vector<std::optional<Decision>>& decs, std::shared_ptr<modellib::STFMockInstance> mock, ESourceTrackPlan source)
|
||||
{
|
||||
randomEngine = solverlib::random::makeEngine();
|
||||
maxCostOfJob = (*std::max_element(STFMockInstance::jobs.begin(), STFMockInstance::jobs.end(), [&](auto op1, auto op2){return op1->getPoidsRetard() < op2->getPoidsRetard();}))->getPoidsRetard();
|
||||
@@ -49,7 +59,19 @@ namespace solverlib {
|
||||
solutions[0].penaltyPerMachine[i] = Penalty{};
|
||||
}
|
||||
|
||||
void SimulatedAnnealing::addSolutionToPool(std::unordered_map<unsigned short, Decision>& decs, std::shared_ptr<modellib::STFMockInstance> mock, ESourceTrackPlan source, bool isPutFirst)
|
||||
|
||||
/*void SimulatedAnnealing::addSolutionToPool(std::unordered_map<unsigned short, Decision>& decs, std::shared_ptr<modellib::STFMockInstance> mock, ESourceTrackPlan source, bool isPutFirst)
|
||||
{
|
||||
auto costs = evaluate(decs);
|
||||
if(!isPutFirst)
|
||||
solutions.push_back({source, mock, decs, costs.first, costs.second});
|
||||
else
|
||||
{
|
||||
solutions.insert(solutions.begin(), {source, mock, decs, costs.first, costs.second});
|
||||
}
|
||||
}*/
|
||||
|
||||
void SimulatedAnnealing::addSolutionToPool(std::vector<std::optional<Decision>>& decs, std::shared_ptr<modellib::STFMockInstance> mock, ESourceTrackPlan source, bool isPutFirst)
|
||||
{
|
||||
auto costs = evaluate(decs);
|
||||
if(!isPutFirst)
|
||||
@@ -61,7 +83,7 @@ namespace solverlib {
|
||||
}
|
||||
|
||||
|
||||
std::pair<unsigned int, unsigned int> SimulatedAnnealing::evaluate(const std::unordered_map<unsigned short, Decision>& decs)
|
||||
/*std::pair<unsigned int, unsigned int> SimulatedAnnealing::evaluate(const std::unordered_map<unsigned short, Decision>& decs)
|
||||
{
|
||||
unsigned int cost = 0;
|
||||
unsigned int diagCost = 0;
|
||||
@@ -80,6 +102,29 @@ namespace solverlib {
|
||||
}
|
||||
}
|
||||
return {cost, diagCost};
|
||||
}*/
|
||||
|
||||
std::pair<unsigned int, unsigned int> SimulatedAnnealing::evaluate(const std::vector<std::optional<Decision>>& decs)
|
||||
{
|
||||
unsigned int cost = 0;
|
||||
unsigned int diagCost = 0;
|
||||
unsigned short id = 0;
|
||||
for(auto& dec : decs)
|
||||
{
|
||||
if((*dec).excluded)
|
||||
{
|
||||
cost += MAXIMUM_TIME_OFFSET * modellib::STFMockInstance::jobs[id]->getPoidsRetard();
|
||||
}
|
||||
else
|
||||
cost += modellib::STFMockInstance::jobs[id]->getPoidsRetard() * (*dec).lastCreneau.first;
|
||||
|
||||
if((*dec).rejected)
|
||||
{
|
||||
diagCost += modellib::STFMockInstance::jobs[id]->getPoidsRejet();
|
||||
}
|
||||
++id;
|
||||
}
|
||||
return {cost, diagCost};
|
||||
}
|
||||
|
||||
EMovingOperators SimulatedAnnealing::pick_operator() {
|
||||
@@ -136,6 +181,9 @@ namespace solverlib {
|
||||
rate = cooling_rate;
|
||||
std::uniform_real_distribution<double> uniform(0.0, 1.0);
|
||||
|
||||
auto bestPlansBeg = pool.getTrackPlansFromSolution(best, false);
|
||||
for (auto& tp : bestPlansBeg) pool.addTrackPlan(std::move(tp));
|
||||
|
||||
while (T > Tmin + 10e-6)
|
||||
{
|
||||
for (int i = 0; i < iterations_per_temp; ++i)
|
||||
@@ -167,7 +215,6 @@ namespace solverlib {
|
||||
{
|
||||
stats.addFailInfo(op, getP(delta, op), diff, delta, T, neighbor->penalty.isFeasible());
|
||||
}
|
||||
//TODO AJOUTER AUTORISER AVEC PENALITE LES INFEASABLES => NECESSITE DE METTRE À JOUR LA GENERATION TRACK PLAN POUR LE ILP ET IGNORER LES TRACKPLANS INF
|
||||
|
||||
if (delta < 0 || uniform(randomEngine) < getP(delta, op))
|
||||
{
|
||||
@@ -179,7 +226,12 @@ namespace solverlib {
|
||||
cost_best = cost_cur;
|
||||
}
|
||||
|
||||
solutions.push_back(current);
|
||||
if (current.penalty.isFeasible()) {
|
||||
auto tps = pool.getTrackPlansFromSolution(current, false);
|
||||
for (auto& tp : tps)
|
||||
pool.addTrackPlan(std::move(tp)); // dédup inline
|
||||
}
|
||||
//solutions.push_back(current);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,19 +239,70 @@ namespace solverlib {
|
||||
//loggerlib::Logger::systemNotify(loggerlib::LOGGER_PROGRESS, "Temperature : " + std::to_string(T));
|
||||
//loggerlib::Logger::systemNotify(loggerlib::LOGGER_PROGRESS, "Solution pool : " + std::to_string(solutions.size()));
|
||||
}
|
||||
|
||||
auto bestPlansFin = pool.getTrackPlansFromSolution(best, false);
|
||||
for (auto& tp : bestPlansFin) pool.addTrackPlan(std::move(tp));
|
||||
//loggerlib::Logger::systemNotify(loggerlib::LOGGER_PROGRESS, "Best solution : " + std::to_string(best.cost));
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
SASolution SimulatedAnnealing::solveMultiStart(
|
||||
double T_max, double T_min, double cooling_rate,
|
||||
int iterations_per_temp, int n_restarts)
|
||||
{
|
||||
SASolution globalBest = solve(T_max, T_min, cooling_rate, iterations_per_temp);
|
||||
loggerlib::Logger::systemNotify(loggerlib::LOGGER_PROGRESS, "Best solution is " + std::string((globalBest.penalty.isFeasible() ? "feasible" : "not feasible")));
|
||||
loggerlib::Logger::systemNotify(loggerlib::LOGGER_PROGRESS, "Best solution : " + std::to_string(globalBest.cost));
|
||||
|
||||
for (int r = 0; r < n_restarts; ++r)
|
||||
{
|
||||
loggerlib::Logger::systemNotify(loggerlib::LOGGER_PROGRESS, "Restart :" + std::to_string(r));
|
||||
|
||||
// Perturbation : repartir du meilleur mais bruité
|
||||
SASolution perturbed = perturbSolution(globalBest);
|
||||
solutions[0] = perturbed;
|
||||
|
||||
// Re-run avec température réduite (exploitation locale)
|
||||
double t_restart = T_max * std::pow(0.5, r % 4); // alterne les températures
|
||||
SASolution localBest = solve(t_restart, T_min, cooling_rate, iterations_per_temp);
|
||||
|
||||
if (localBest.penalty.isFeasible() && localBest.cost < globalBest.cost)
|
||||
globalBest = localBest;
|
||||
|
||||
loggerlib::Logger::systemNotify(loggerlib::LOGGER_PROGRESS, "Best solution restart is " + std::string((localBest.penalty.isFeasible() ? "feasible" : "not feasible")));
|
||||
loggerlib::Logger::systemNotify(loggerlib::LOGGER_PROGRESS, "Best solution restart : " + std::to_string(localBest.cost));
|
||||
}
|
||||
|
||||
loggerlib::Logger::systemNotify(loggerlib::LOGGER_PROGRESS, "Best solution restart : " + std::to_string(globalBest.cost));
|
||||
|
||||
return globalBest;
|
||||
}
|
||||
|
||||
SASolution SimulatedAnnealing::perturbSolution(const SASolution& sol) {
|
||||
SASolution perturbed = sol;
|
||||
// Forcer N opérateurs aléatoires pour s'éloigner du bassin d'attraction
|
||||
int n_kicks = 3 + randomEngine() % 5;
|
||||
for (int k = 0; k < n_kicks; ++k) {
|
||||
auto op = pick_operator();
|
||||
auto neighbor = apply_operator(perturbed, op);
|
||||
if (neighbor.has_value())
|
||||
perturbed = std::move(*neighbor);
|
||||
}
|
||||
return perturbed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
double SimulatedAnnealing::effectiveCost(const SASolution& s) const {
|
||||
return s.fictiveCost + s.penalty.weighted(effectiveLambdas());
|
||||
}
|
||||
|
||||
std::unordered_map<EPenaltyType, double> SimulatedAnnealing::effectiveLambdas() const {
|
||||
ArrayLambda SimulatedAnnealing::effectiveLambdas() const {
|
||||
double p = progress();
|
||||
return {
|
||||
{EPenaltyType::TIME_WINDOW_OVERRUN, std::exp(8*(p-0.2))-0.8},
|
||||
{std::exp(18*(p-0.3))},//(int)EPenaltyType::TIME_WINDOW_OVERRUN,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -226,7 +329,7 @@ namespace solverlib {
|
||||
case EMovingOperators::DYN_PROG:
|
||||
break;
|
||||
}
|
||||
return std::exp(-delta/T);
|
||||
return std::exp(-delta/(T));
|
||||
}
|
||||
|
||||
//OPERATEURS
|
||||
@@ -246,19 +349,24 @@ namespace solverlib {
|
||||
if (!mock) return std::nullopt;
|
||||
|
||||
std::vector<unsigned short> active_ops;
|
||||
for (auto& [op_id, dec] : sol.decisions)
|
||||
if (!dec.excluded) active_ops.push_back(op_id);
|
||||
unsigned int id = 0;
|
||||
for (auto& dec : sol.decisions)
|
||||
{
|
||||
if (!(*dec).excluded)
|
||||
active_ops.push_back(id);
|
||||
++id;
|
||||
}
|
||||
if (active_ops.size() < 2) return std::nullopt;
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, (int)active_ops.size() - 1);
|
||||
unsigned short op_a = active_ops[dist(randomEngine)];
|
||||
const Decision& dec_a = sol.decisions.at(op_a);
|
||||
const Decision& dec_a = *sol.decisions[op_a];
|
||||
|
||||
std::vector<unsigned short> seq_swap(1, op_a);
|
||||
|
||||
for (auto& op_id : active_ops) {
|
||||
if (op_id == op_a) continue;
|
||||
const Decision& dec_b = sol.decisions.at(op_id);
|
||||
const Decision& dec_b = *sol.decisions[op_id];
|
||||
if (dec_b.empV != dec_a.empV) continue;
|
||||
|
||||
seq_swap.push_back({
|
||||
@@ -268,8 +376,8 @@ namespace solverlib {
|
||||
if (seq_swap.size() == 1) return std::nullopt;
|
||||
|
||||
std::sort(seq_swap.begin(), seq_swap.end(), [&](auto job1, auto job2){
|
||||
const Decision& dec_a = sol.decisions.at(job1);
|
||||
const Decision& dec_b = sol.decisions.at(job2);
|
||||
const Decision& dec_a = *sol.decisions[job1];
|
||||
const Decision& dec_b = *sol.decisions[job2];
|
||||
|
||||
return dec_a.lastCreneau.first < dec_b.lastCreneau.first;
|
||||
});
|
||||
@@ -292,16 +400,14 @@ namespace solverlib {
|
||||
std::vector<std::pair<unsigned short, Decision>> jobsSeq;
|
||||
jobsSeq.reserve(seqCop.size());
|
||||
for (auto& job_id : seqCop)
|
||||
jobsSeq.push_back({job_id, sol.decisions.at(job_id)});
|
||||
jobsSeq.push_back({job_id, *sol.decisions[job_id]});
|
||||
|
||||
Penalty oldPen = sol.penaltyPerMachine.count(dec_a.empV)
|
||||
? sol.penaltyPerMachine.at(dec_a.empV)
|
||||
: Penalty{};
|
||||
Penalty oldPen = sol.penaltyPerMachine[dec_a.empV];
|
||||
|
||||
unsigned int oldCost = 0;
|
||||
for (auto& job_id : seq_swap)
|
||||
oldCost += STFMockInstance::jobs[job_id]->getPoidsRetard()
|
||||
* sol.decisions.at(job_id).lastCreneau.first;
|
||||
* (*sol.decisions[job_id]).lastCreneau.first;
|
||||
|
||||
Penalty newPen; bool feasible = true;
|
||||
auto res = checkSequence(jobsSeq, dec_a.empV, newPen, feasible);
|
||||
@@ -327,13 +433,18 @@ namespace solverlib {
|
||||
if (!mock) return std::nullopt;
|
||||
|
||||
std::vector<unsigned short> active_ops;
|
||||
for (auto& [op_id, dec] : sol.decisions)
|
||||
if (!dec.excluded) active_ops.push_back(op_id);
|
||||
unsigned int id = 0;
|
||||
for (auto& dec : sol.decisions)
|
||||
{
|
||||
if (!(*dec).excluded)
|
||||
active_ops.push_back(id);
|
||||
++id;
|
||||
}
|
||||
if (active_ops.size() < 2) return std::nullopt;
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, (int)active_ops.size() - 1);
|
||||
unsigned short op_a = active_ops[dist(randomEngine)];
|
||||
const Decision& dec_a = sol.decisions.at(op_a);
|
||||
const Decision& dec_a = *sol.decisions[op_a];
|
||||
|
||||
struct SwapCandidate {
|
||||
unsigned short op_a;
|
||||
@@ -347,7 +458,7 @@ namespace solverlib {
|
||||
//pair < op, empR post swap>
|
||||
for (auto& op_id : active_ops) {
|
||||
if (op_id == op_a) continue;
|
||||
const Decision& dec_b = sol.decisions.at(op_id);
|
||||
const Decision& dec_b = *sol.decisions[op_id];
|
||||
if (dec_b.empV == dec_a.empV) continue;
|
||||
|
||||
// Vérifier compatibilité infrastructure
|
||||
@@ -378,12 +489,12 @@ namespace solverlib {
|
||||
// Tirer deuxième op parmi les candidats
|
||||
std::uniform_int_distribution<int> cand_dist(0, (int)swap_candidates.size() - 1);
|
||||
auto swap = swap_candidates[cand_dist(randomEngine)];
|
||||
const Decision& dec_b = sol.decisions.at(swap.op_b);
|
||||
const Decision& dec_b = *sol.decisions[swap.op_b];
|
||||
|
||||
// échanger tracks et slots
|
||||
SASolution neighbor = sol;
|
||||
Decision& new_dec_a = neighbor.decisions[op_a];
|
||||
Decision& new_dec_b = neighbor.decisions[swap.op_b];
|
||||
Decision& new_dec_a = *neighbor.decisions[op_a];
|
||||
Decision& new_dec_b = *neighbor.decisions[swap.op_b];
|
||||
|
||||
new_dec_a.voie = dec_b.voie;
|
||||
new_dec_a.site = dec_b.site;
|
||||
@@ -403,29 +514,29 @@ namespace solverlib {
|
||||
auto oldCrenB = dec_b.lastCreneau;
|
||||
|
||||
// Pénalités anciennes O(1)
|
||||
Penalty oldPenA = sol.penaltyPerMachine.count(dec_a.empV)
|
||||
? sol.penaltyPerMachine.at(dec_a.empV) : Penalty{};
|
||||
Penalty oldPenB = sol.penaltyPerMachine.count(dec_b.empV)
|
||||
? sol.penaltyPerMachine.at(dec_b.empV) : Penalty{};
|
||||
Penalty oldPenA = sol.penaltyPerMachine[dec_a.empV];
|
||||
Penalty oldPenB = sol.penaltyPerMachine[dec_b.empV];
|
||||
|
||||
std::vector<std::pair<unsigned short, decision>> jobsEmpVA;
|
||||
std::vector<std::pair<unsigned short, decision>> jobsEmpVB;
|
||||
unsigned int oldCost = dec_a.lastCreneau.first * STFMockInstance::jobs[op_a]->getPoidsRetard() + dec_b.lastCreneau.first * STFMockInstance::jobs[swap.op_b]->getPoidsRetard();
|
||||
unsigned int op_id = 0;
|
||||
for(auto& dec : neighbor.decisions)
|
||||
{
|
||||
if(!dec.second.excluded)
|
||||
if(!(*dec).excluded)
|
||||
{
|
||||
if(dec.second.empV == new_dec_a.empV)
|
||||
if((*dec).empV == new_dec_a.empV)
|
||||
{
|
||||
jobsEmpVA.push_back({dec.first, dec.second});
|
||||
oldCost += dec.second.lastCreneau.first * STFMockInstance::jobs[dec.first]->getPoidsRetard();
|
||||
jobsEmpVA.push_back({op_id, (*dec)});
|
||||
oldCost += (*dec).lastCreneau.first * STFMockInstance::jobs[op_id]->getPoidsRetard();
|
||||
}
|
||||
if(dec.second.empV == new_dec_b.empV)
|
||||
if((*dec).empV == new_dec_b.empV)
|
||||
{
|
||||
jobsEmpVB.push_back({dec.first, dec.second});
|
||||
oldCost += dec.second.lastCreneau.first * STFMockInstance::jobs[dec.first]->getPoidsRetard();
|
||||
jobsEmpVB.push_back({op_id, (*dec)});
|
||||
oldCost += (*dec).lastCreneau.first * STFMockInstance::jobs[op_id]->getPoidsRetard();
|
||||
}
|
||||
}
|
||||
++op_id;
|
||||
}
|
||||
std::sort(jobsEmpVA.begin(), jobsEmpVA.end(), [&](auto& el1, auto& el2){
|
||||
auto cren1 = el1.second.lastCreneau;
|
||||
@@ -481,8 +592,13 @@ namespace solverlib {
|
||||
if (!mock) return std::nullopt;
|
||||
|
||||
std::vector<unsigned short> inactive_ops;
|
||||
for (auto& [op_id, dec] : sol.decisions)
|
||||
if (dec.excluded) inactive_ops.push_back(op_id);
|
||||
unsigned int id = 0;
|
||||
for (auto& dec : sol.decisions)
|
||||
{
|
||||
if ((*dec).excluded)
|
||||
inactive_ops.push_back(id);
|
||||
++id;
|
||||
}
|
||||
if (inactive_ops.empty()) return std::nullopt;
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, (int)inactive_ops.size() - 1);
|
||||
@@ -508,7 +624,7 @@ namespace solverlib {
|
||||
|
||||
//Construire le voisin - try insert
|
||||
SASolution neighbor = sol;
|
||||
Decision& new_dec_a = neighbor.decisions[op_a];
|
||||
Decision& new_dec_a = *neighbor.decisions[op_a];
|
||||
auto dur = mock->dispoVoiesRames[disp].match.second - mock->dispoVoiesRames[disp].match.first;
|
||||
|
||||
new_dec_a.rejected = dur >= STFMockInstance::jobs[op_a]->getDuree() ? false : true,
|
||||
@@ -521,23 +637,24 @@ namespace solverlib {
|
||||
new_dec_a.lastCreneau = {0,0};
|
||||
|
||||
// Pénalité ancienne O(1) — séquence sans op_a
|
||||
Penalty oldPen = sol.penaltyPerMachine.count(new_dec_a.empV)
|
||||
? sol.penaltyPerMachine.at(new_dec_a.empV) : Penalty{};
|
||||
Penalty oldPen = sol.penaltyPerMachine[new_dec_a.empV];
|
||||
|
||||
unsigned int oldDiagCost = 0;
|
||||
unsigned int oldCostScheduled = 0;
|
||||
unsigned int newDiagCost = new_dec_a.rejected ? STFMockInstance::jobs[op_a]->getPoidsRejet() : 0;
|
||||
std::vector<std::pair<unsigned short, decision>> jobsEmpVA;
|
||||
unsigned int op_id = 0;
|
||||
for(auto& dec : neighbor.decisions)
|
||||
{
|
||||
if(!dec.second.excluded && dec.first != op_a)
|
||||
if(!(*dec).excluded && op_id != op_a)
|
||||
{
|
||||
if(dec.second.empV == new_dec_a.empV)
|
||||
if((*dec).empV == new_dec_a.empV)
|
||||
{
|
||||
jobsEmpVA.push_back({dec.first, dec.second});
|
||||
oldCostScheduled += dec.second.lastCreneau.first * STFMockInstance::jobs[dec.first]->getPoidsRetard();
|
||||
jobsEmpVA.push_back({op_id, (*dec)});
|
||||
oldCostScheduled += (*dec).lastCreneau.first * STFMockInstance::jobs[op_id]->getPoidsRetard();
|
||||
}
|
||||
}
|
||||
++op_id;
|
||||
}
|
||||
|
||||
std::sort(jobsEmpVA.begin(), jobsEmpVA.end(), [&](auto& el1, auto& el2){
|
||||
@@ -566,8 +683,7 @@ namespace solverlib {
|
||||
|
||||
applySequenceResult(neighbor, seq, *res, newCost, penA, feasA);
|
||||
|
||||
double oldFictive = sol.fictiveExcludedCosts.count(op_a)
|
||||
? fictiveCostExcluded(op_a)
|
||||
double oldFictive = neighbor.fictiveExcludedCosts[op_a] > 0.0 ? fictiveCostExcluded(op_a)
|
||||
: MAXIMUM_TIME_OFFSET * STFMockInstance::jobs[op_a]->getPoidsRetard();
|
||||
|
||||
unsigned int oldCostExcluded = MAXIMUM_TIME_OFFSET * STFMockInstance::jobs[op_a]->getPoidsRetard();
|
||||
@@ -576,7 +692,7 @@ namespace solverlib {
|
||||
neighbor.penaltyPerMachine[new_dec_a.empV] = penA;
|
||||
neighbor.isFeasible = neighbor.penalty.isFeasible();
|
||||
neighbor.fictiveCost = (neighbor.fictiveCost - oldFictive - oldCostScheduled) + newCost;
|
||||
neighbor.fictiveExcludedCosts.erase(op_a);
|
||||
neighbor.fictiveExcludedCosts[op_a] = 0.0;
|
||||
neighbor.diagCost = (neighbor.diagCost - oldDiagCost) + newDiagCost;
|
||||
neighbor.cost = (neighbor.cost - oldCostExcluded - oldCostScheduled) + newCost;
|
||||
neighbor.source = ESourceTrackPlan::SimAn;
|
||||
@@ -590,15 +706,21 @@ namespace solverlib {
|
||||
if (!mock) return std::nullopt;
|
||||
|
||||
std::vector<unsigned short> active_ops;
|
||||
for (auto& [op_id, dec] : sol.decisions)
|
||||
if (!dec.excluded) active_ops.push_back(op_id);
|
||||
unsigned int id = 0;
|
||||
for (auto& dec : sol.decisions)
|
||||
{
|
||||
if (!(*dec).excluded)
|
||||
active_ops.push_back(id);
|
||||
++id;
|
||||
|
||||
}
|
||||
if (active_ops.empty()) return std::nullopt;
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, (int)active_ops.size() - 1);
|
||||
unsigned short op_a = active_ops[dist(randomEngine)];
|
||||
|
||||
std::vector<unsigned int> dispCandidate;
|
||||
const Decision& dec_a = sol.decisions.at(op_a);
|
||||
const Decision& dec_a = *sol.decisions[op_a];
|
||||
|
||||
for (auto& disp : mock->jobDispoVoiesRames[op_a]) {
|
||||
if(dec_a.empV == mock->dispoVoiesRames[disp].dispoVoie)
|
||||
@@ -621,7 +743,7 @@ namespace solverlib {
|
||||
|
||||
//Construire le voisin - try insert
|
||||
SASolution neighbor = sol;
|
||||
Decision& new_dec_a = neighbor.decisions[op_a];
|
||||
Decision& new_dec_a = *neighbor.decisions[op_a];
|
||||
auto dur = mock->dispoVoiesRames[disp].match.second - mock->dispoVoiesRames[disp].match.first;
|
||||
|
||||
new_dec_a.rejected = dur >= STFMockInstance::jobs[op_a]->getDuree() ? false : true,
|
||||
@@ -633,10 +755,8 @@ namespace solverlib {
|
||||
new_dec_a.lastCreneau = {0,0};
|
||||
|
||||
// Pénalités anciennes O(1) — machine de départ et machine d'arrivée
|
||||
Penalty oldPenSrc = sol.penaltyPerMachine.count(dec_a.empV)
|
||||
? sol.penaltyPerMachine.at(dec_a.empV) : Penalty{};
|
||||
Penalty oldPenDst = sol.penaltyPerMachine.count(new_dec_a.empV)
|
||||
? sol.penaltyPerMachine.at(new_dec_a.empV) : Penalty{};
|
||||
Penalty oldPenSrc = sol.penaltyPerMachine[dec_a.empV];
|
||||
Penalty oldPenDst = sol.penaltyPerMachine[new_dec_a.empV];
|
||||
|
||||
unsigned int oldCost = dec_a.lastCreneau.first*STFMockInstance::jobs[op_a]->getPoidsRetard();
|
||||
unsigned int oldDiagCost = dec_a.rejected ? STFMockInstance::jobs[op_a]->getPoidsRejet() : 0;
|
||||
@@ -644,25 +764,26 @@ namespace solverlib {
|
||||
|
||||
std::vector<std::pair<unsigned short, decision>> jobsEmpVA;
|
||||
std::vector<std::pair<unsigned short, decision>> jobsEmpVB;
|
||||
|
||||
unsigned int op_id = 0;
|
||||
for(auto& dec : neighbor.decisions)
|
||||
{
|
||||
if(!dec.second.excluded && dec.first != op_a)
|
||||
if(!(*dec).excluded && op_id != op_a)
|
||||
{
|
||||
if(dec.second.empV == new_dec_a.empV)
|
||||
if((*dec).empV == new_dec_a.empV)
|
||||
{
|
||||
jobsEmpVA.push_back({dec.first, dec.second});
|
||||
oldCost += dec.second.lastCreneau.first * STFMockInstance::jobs[dec.first]->getPoidsRetard();
|
||||
jobsEmpVA.push_back({op_id, (*dec)});
|
||||
oldCost += (*dec).lastCreneau.first * STFMockInstance::jobs[op_id]->getPoidsRetard();
|
||||
}
|
||||
}
|
||||
if(!dec.second.excluded)
|
||||
if(!(*dec).excluded)
|
||||
{
|
||||
if(dec.second.empV == dec_a.empV)
|
||||
if((*dec).empV == dec_a.empV)
|
||||
{
|
||||
jobsEmpVB.push_back({dec.first, dec.second});
|
||||
oldCost += dec.second.lastCreneau.first * STFMockInstance::jobs[dec.first]->getPoidsRetard();
|
||||
jobsEmpVB.push_back({op_id, (*dec)});
|
||||
oldCost += (*dec).lastCreneau.first * STFMockInstance::jobs[op_id]->getPoidsRetard();
|
||||
}
|
||||
}
|
||||
++op_id;
|
||||
}
|
||||
|
||||
std::sort(jobsEmpVA.begin(), jobsEmpVA.end(), [&](auto& el1, auto& el2){
|
||||
@@ -719,8 +840,13 @@ namespace solverlib {
|
||||
if (!mock) return std::nullopt;
|
||||
|
||||
std::vector<unsigned short> active_ops;
|
||||
for (auto& [op_id, dec] : sol.decisions)
|
||||
if (!dec.excluded) active_ops.push_back(op_id);
|
||||
unsigned int id = 0;
|
||||
for (auto& dec : sol.decisions)
|
||||
{
|
||||
if (!(*dec).excluded)
|
||||
active_ops.push_back(id);
|
||||
++id;
|
||||
}
|
||||
if (active_ops.empty()) return std::nullopt;
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, (int)active_ops.size() - 1);
|
||||
@@ -729,8 +855,8 @@ namespace solverlib {
|
||||
|
||||
//Construire le voisin - exclure a
|
||||
SASolution neighbor = sol;
|
||||
const Decision& dec_a = sol.decisions.at(op_a);
|
||||
Decision& new_dec_a = neighbor.decisions[op_a];
|
||||
const Decision& dec_a = *sol.decisions[op_a];
|
||||
Decision& new_dec_a = *neighbor.decisions[op_a];
|
||||
|
||||
new_dec_a.rejected = false,
|
||||
new_dec_a.excluded = true;
|
||||
@@ -742,23 +868,24 @@ namespace solverlib {
|
||||
new_dec_a.lastCreneau = {0,0};
|
||||
|
||||
// Pénalité ancienne O(1) — inclut la contribution de op_a
|
||||
Penalty oldPen = sol.penaltyPerMachine.count(dec_a.empV)
|
||||
? sol.penaltyPerMachine.at(dec_a.empV) : Penalty{};
|
||||
Penalty oldPen = sol.penaltyPerMachine[dec_a.empV];
|
||||
|
||||
unsigned int oldCost = dec_a.lastCreneau.first * STFMockInstance::jobs[op_a]->getPoidsRetard();
|
||||
unsigned int oldDiagCost = dec_a.rejected ? STFMockInstance::jobs[op_a]->getPoidsRejet() : 0;
|
||||
|
||||
std::vector<std::pair<unsigned short, decision>> jobsEmpVA;
|
||||
unsigned int op_id = 0;
|
||||
for(auto& dec : neighbor.decisions)
|
||||
{
|
||||
if(!dec.second.excluded)
|
||||
if(!(*dec).excluded)
|
||||
{
|
||||
if(dec.second.empV == dec_a.empV)
|
||||
if((*dec).empV == dec_a.empV)
|
||||
{
|
||||
jobsEmpVA.push_back({dec.first, dec.second});
|
||||
oldCost += dec.second.lastCreneau.first * STFMockInstance::jobs[dec.first]->getPoidsRetard();
|
||||
jobsEmpVA.push_back({op_id, (*dec)});
|
||||
oldCost += (*dec).lastCreneau.first * STFMockInstance::jobs[op_id]->getPoidsRetard();
|
||||
}
|
||||
}
|
||||
++op_id;
|
||||
}
|
||||
|
||||
unsigned int remaining = 0.0;
|
||||
@@ -796,16 +923,21 @@ namespace solverlib {
|
||||
if (!mock) return std::nullopt;
|
||||
|
||||
std::vector<unsigned short> active_ops;
|
||||
for (auto& [op_id, dec] : sol.decisions)
|
||||
if (!dec.excluded) active_ops.push_back(op_id);
|
||||
unsigned int id = 0;
|
||||
for (auto& dec : sol.decisions)
|
||||
{
|
||||
if (!(*dec).excluded)
|
||||
active_ops.push_back(id);
|
||||
++id;
|
||||
}
|
||||
if (active_ops.empty()) return std::nullopt;
|
||||
|
||||
std::uniform_int_distribution<int> dist(0, (int)active_ops.size() - 1);
|
||||
unsigned short op_a = active_ops[dist(randomEngine)];
|
||||
const Decision& dec_a = sol.decisions.at(op_a);
|
||||
const Decision& dec_a = *sol.decisions[op_a];
|
||||
|
||||
SASolution neighbor = sol;
|
||||
Decision& new_dec_a = neighbor.decisions[op_a];
|
||||
Decision& new_dec_a = *neighbor.decisions[op_a];
|
||||
|
||||
|
||||
unsigned int oldDiagCost = dec_a.rejected ? STFMockInstance::jobs[op_a]->getPoidsRejet() : 0;
|
||||
@@ -825,21 +957,22 @@ namespace solverlib {
|
||||
}
|
||||
|
||||
// Pénalité ancienne O(1)
|
||||
Penalty oldPen = sol.penaltyPerMachine.count(dec_a.empV)
|
||||
? sol.penaltyPerMachine.at(dec_a.empV) : Penalty{};
|
||||
Penalty oldPen = sol.penaltyPerMachine[dec_a.empV];
|
||||
|
||||
unsigned int oldCost = 0;
|
||||
std::vector<std::pair<unsigned short, decision>> jobsEmpVA;
|
||||
unsigned int op_id = 0;
|
||||
for(auto& dec : neighbor.decisions)
|
||||
{
|
||||
if(!dec.second.excluded)
|
||||
if(!(*dec).excluded)
|
||||
{
|
||||
if(dec.second.empV == dec_a.empV)
|
||||
if((*dec).empV == dec_a.empV)
|
||||
{
|
||||
jobsEmpVA.push_back({dec.first, dec.second});
|
||||
oldCost += dec.second.lastCreneau.first * STFMockInstance::jobs[dec.first]->getPoidsRetard();
|
||||
jobsEmpVA.push_back({op_id, (*dec)});
|
||||
oldCost += (*dec).lastCreneau.first * STFMockInstance::jobs[op_id]->getPoidsRetard();
|
||||
}
|
||||
}
|
||||
++op_id;
|
||||
}
|
||||
|
||||
std::sort(jobsEmpVA.begin(), jobsEmpVA.end(), [&](auto& el1, auto& el2){
|
||||
|
||||
Reference in New Issue
Block a user