#include "SolutionPoolManager.hpp" #include #include #include namespace solverlib { std::vector SolutionPoolManager::getTrackPlansFromSolution(SASolution& sol, bool withTrash) { std::vector trackPlans; trackPlans.reserve(STFMockInstance::tracks.size()); //id plan = id voie std::vector plans; plans.resize(STFMockInstance::tracks.size()); std::unordered_map>> decisionsOnMachines; std::vector> machineIdsFromTrackId(STFMockInstance::tracks.size()); for(auto& dec : sol.decisions) { if(!dec.second.excluded) { plans[dec.second.voie].isTrash = false; plans[dec.second.voie].track = dec.second.voie; plans[dec.second.voie].schedule[dec.first] = dec.second; decisionsOnMachines[dec.second.empV].push_back({dec.first, dec.second}); machineIdsFromTrackId[dec.second.voie].insert(dec.second.empV); } else if(withTrash) { TrackPlan trashTrack; trashTrack.source = sol.source; trashTrack.isTrash = true; trashTrack.mock = sol.mock; trashTrack.diagCost = 0; trashTrack.track = 0; trashTrack.schedule[dec.first] = { 0,CreneauHoraire(), 0, false, true,0,0,{0,0} }; trashTrack.cost = STFMockInstance::jobs[dec.first]->getPoidsRetard() * MAXIMUM_TIME_OFFSET; trackPlans.push_back(trashTrack); } } for(auto& plan : plans) { if(!plan.schedule.empty()) { bool feasible = true; if(!sol.penalty.isFeasible()) { for(auto& machine : machineIdsFromTrackId[plan.track]) { std::sort(decisionsOnMachines[machine].begin(), decisionsOnMachines[machine].end(), [&](auto& el, auto& el2){ return el.second.lastCreneau.first < el2.second.lastCreneau.first; }); feasible = checkSequence(decisionsOnMachines[machine], plan.track); if(!feasible) break; } } if(feasible) { plan.mock = sol.mock; plan.source = sol.source; plan.evaluate(); trackPlans.push_back(plan); } } } return trackPlans; } std::vector SolutionPoolManager::transformSolutionsIntoUniqueTrackPlans() { std::vector trackPlans; std::set uniqueSchedules; unsigned long countD = 0; trackPlans.reserve(STFMockInstance::tracks.size() * pool.size() + 1); while(!pool.empty()) { auto sol = pool.back(); //id plan = id voie std::vector plans; plans.resize(STFMockInstance::tracks.size()); std::unordered_map>> decisionsOnMachines; std::vector> machineIdsFromTrackId(STFMockInstance::tracks.size()); for(auto& dec : sol.decisions) { if(!dec.second.excluded) { plans[dec.second.voie].isTrash = false; plans[dec.second.voie].track = dec.second.voie; plans[dec.second.voie].schedule[dec.first] = dec.second; decisionsOnMachines[dec.second.empV].push_back({dec.first, dec.second}); machineIdsFromTrackId[dec.second.voie].insert(dec.second.empV); } } for(auto& plan : plans) { if(!plan.schedule.empty()) { bool feasible = true; if(!sol.penalty.isFeasible()) { for(auto& machine : machineIdsFromTrackId[plan.track]) { std::sort(decisionsOnMachines[machine].begin(), decisionsOnMachines[machine].end(), [&](auto& el, auto& el2){ return el.second.lastCreneau.first < el2.second.lastCreneau.first; }); feasible = checkSequence(decisionsOnMachines[machine], plan.track); if(!feasible) break; } } if(feasible) { plan.mock = sol.mock; plan.source = sol.source; plan.evaluate(); auto inserted = uniqueSchedules.insert(plan); if(!inserted.second) { countD++; } } else { countD++; } } } pool.pop_back(); } std::move(uniqueSchedules.begin(), uniqueSchedules.end(), std::back_inserter(trackPlans)); for(unsigned short job = 0; job < STFMockInstance::jobs.size(); ++job) { TrackPlan trashTrack; trashTrack.isTrash = true; trashTrack.diagCost = 0; trashTrack.track = 0; trashTrack.source = ESourceTrackPlan::Fake; trashTrack.schedule[job] = { 0,CreneauHoraire(), 0, false, true,0,0,{0,0} }; trashTrack.cost = STFMockInstance::jobs[job]->getPoidsRetard() * MAXIMUM_TIME_OFFSET; trackPlans.push_back(trashTrack); } auto nbplan = trackPlans.size(); loggerlib::Logger::systemNotify(loggerlib::LOGGER_PROGRESS, "Removed " + std::to_string(countD) + " non-unique or non-feasible track schedules"); loggerlib::Logger::systemNotify(loggerlib::LOGGER_PROGRESS, "Total track plans " + std::to_string(nbplan)); return trackPlans; } bool SolutionPoolManager::checkSequence(const std::vector>& jobsDec, unsigned int machine) { auto machineDisp = STFMockInstance::machines[machine]->getDispo(); unsigned short minBegin = machineDisp.getDebut().getRelativeDate(); std::vector> res; for(auto& jobDec : jobsDec) { auto matchWithMachine = CreneauHoraire::checkSlotsCompatibility(jobDec.second.timeslotGraphSplited, machineDisp).second; minBegin = std::max(minBegin, matchWithMachine.first); auto newJobDec = jobDec; unsigned int duration = !jobDec.second.rejected ? STFMockInstance::jobs[jobDec.first]->getDuree() : STFMockInstance::jobs[jobDec.first]->getDureeDiag(); newJobDec.second.lastCreneau = {minBegin, minBegin + duration}; if(minBegin + duration > matchWithMachine.first + matchWithMachine.second) return false; minBegin = minBegin + duration; } return true; } void SolutionPoolManager::provide(std::vector&& solutions) { std::move(solutions.begin(), solutions.end(), std::back_inserter(pool)); } }