Skip to content
Snippets Groups Projects
Commit 58ed359e authored by awenjb's avatar awenjb
Browse files

fix bug in time window constraint

- time window was doing a copy of an updated vector then update the vector doing two time a modification before evaluating the reach times
parent 8ccfd7b7
No related branches found
No related tags found
No related merge requests found
...@@ -64,5 +64,5 @@ public: ...@@ -64,5 +64,5 @@ public:
*/ */
void applyModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition, bool addPair); void applyModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition, bool addPair);
void print() const; void print() const override;
}; };
\ No newline at end of file
...@@ -99,4 +99,6 @@ public: ...@@ -99,4 +99,6 @@ public:
* Defaults to no op * Defaults to no op
*/ */
virtual void endOfDestructionCallback() {} virtual void endOfDestructionCallback() {}
virtual void print() const = 0;
}; };
\ No newline at end of file
...@@ -8,32 +8,33 @@ ...@@ -8,32 +8,33 @@
#include "lns/modification/route/remove_route.h" #include "lns/modification/route/remove_route.h"
#include "lns/solution/solution.h" #include "lns/solution/solution.h"
TimeWindowConstraint::TimeWindowConstraint(Solution const &solution) : Constraint(solution)
TimeWindowConstraint::TimeWindowConstraint(const Solution& solution) : Constraint(solution)
{ {
allRouteReachTimes.resize(getSolution().getRoutes().size()); allRouteReachTimes.resize(getSolution().getRoutes().size());
} }
TimeWindowConstraint::~TimeWindowConstraint()
TimeWindowConstraint::~TimeWindowConstraint()
{ {
allRouteReachTimes.clear(); allRouteReachTimes.clear();
} }
std::unique_ptr<Constraint> TimeWindowConstraint::clone(Solution const &newOwningSolution) const { std::unique_ptr<Constraint> TimeWindowConstraint::clone(Solution const &newOwningSolution) const
{
std::unique_ptr<TimeWindowConstraint> clonePtr = std::make_unique<TimeWindowConstraint>(newOwningSolution); std::unique_ptr<TimeWindowConstraint> clonePtr = std::make_unique<TimeWindowConstraint>(newOwningSolution);
clonePtr->allRouteReachTimes = allRouteReachTimes; clonePtr->allRouteReachTimes = allRouteReachTimes;
return clonePtr; return clonePtr;
} }
void TimeWindowConstraint::computeReachTimes(const PDPTWData& data, const std::vector<int> & routeIDs, ReachTimeVector & reachTimes) const void TimeWindowConstraint::computeReachTimes(PDPTWData const &data, std::vector<int> const &routeIDs,
ReachTimeVector &reachTimes) const
{ {
// Adjust the size of reachTimes vector // Adjust the size of reachTimes vector
reachTimes.resize(routeIDs.size(), 0); reachTimes.resize(routeIDs.size(), 0);
// Time to the first location // Time to the first location
reachTimes.at(0) = data.getDepot().getTimeWindow().getStart() + data::TravelTime(data, 0, routeIDs.at(0)); reachTimes.at(0) = data.getDepot().getTimeWindow().getStart() + data::TravelTime(data, 0, routeIDs.at(0));
// Compute other reachTimes (max between arrival and start of the time window + previous service time + travel time) // Compute other reachTimes (max between arrival and start of the time window + previous service time + travel time)
for (int i = 1; i < routeIDs.size(); ++i) { for (int i = 1; i < routeIDs.size(); ++i)
{
TimeInteger travelTime = data::TravelTime(data, routeIDs.at(i - 1), routeIDs.at(i)); TimeInteger travelTime = data::TravelTime(data, routeIDs.at(i - 1), routeIDs.at(i));
// locations are indexed from 0 to n-1, // locations are indexed from 0 to n-1,
TimeInteger serviceTime = data.getLocation(routeIDs.at(i - 1)).getServiceDuration(); TimeInteger serviceTime = data.getLocation(routeIDs.at(i - 1)).getServiceDuration();
...@@ -47,7 +48,7 @@ void TimeWindowConstraint::initReachTimes() ...@@ -47,7 +48,7 @@ void TimeWindowConstraint::initReachTimes()
{ {
allRouteReachTimes = std::vector<ReachTimeVector>(); allRouteReachTimes = std::vector<ReachTimeVector>();
int i = 0; int i = 0;
for (const Route& route : getSolution().getRoutes()) for (Route const &route: getSolution().getRoutes())
{ {
// init and calculate reach time value // init and calculate reach time value
allRouteReachTimes.emplace_back(); allRouteReachTimes.emplace_back();
...@@ -56,25 +57,24 @@ void TimeWindowConstraint::initReachTimes() ...@@ -56,25 +57,24 @@ void TimeWindowConstraint::initReachTimes()
} }
} }
// Copie le vecteur de reach time de la route concernée // Copie le vecteur de reach time de la route concernée
// Insère les positions pickup/delivery // Insère les positions pickup/delivery
// refait l'ordo sur le nouveau vecteur // refait l'ordo sur le nouveau vecteur
bool TimeWindowConstraint::checkInsertion(const PDPTWData& data, const Pair & pair, int routeIndex, int pickupPos, int deliveryPos) const bool TimeWindowConstraint::checkInsertion(PDPTWData const &data, Pair const &pair, int routeIndex, int pickupPos,
int deliveryPos) const
{ {
ReachTimeVector const &reachTimes = allRouteReachTimes.at(routeIndex); ReachTimeVector const &reachTimes = allRouteReachTimes.at(routeIndex);
// COPY route vector // COPY route vector
std::vector<int> route(getSolution().getRoute(routeIndex).getRoute().begin(), getSolution().getRoute(routeIndex).getRoute().end()) ; std::vector<int> route(getSolution().getRoute(routeIndex).getRoute().begin(),
getSolution().getRoute(routeIndex).getRoute().end());
// COPY reachTimes vector // COPY reachTimes vector
ReachTimeVector newReachTimes(reachTimes.begin(), reachTimes.end()); ReachTimeVector newReachTimes(reachTimes.begin(), reachTimes.end());
// Insert pickup and delivery // Insert pickup and delivery
route.insert(route.begin() + deliveryPos, pair.getDelivery().getId()); route.insert(route.begin() + deliveryPos, pair.getDelivery().getId());
route.insert(route.begin() + pickupPos, pair.getPickup().getId()); route.insert(route.begin() + pickupPos, pair.getPickup().getId());
// std::cout << "\n"; // std::cout << "\n";
// for (auto pos : route) // for (auto pos : route)
...@@ -94,89 +94,147 @@ bool TimeWindowConstraint::checkInsertion(const PDPTWData& data, const Pair & pa ...@@ -94,89 +94,147 @@ bool TimeWindowConstraint::checkInsertion(const PDPTWData& data, const Pair & pa
// std::cout << "\n"; // std::cout << "\n";
// Check Time Windows // Check Time Windows
for (int i = 0; i < newReachTimes.size(); ++i) for (int i = 0; i < newReachTimes.size(); ++i)
{ {
if (! data.getLocation(route.at(i)).getTimeWindow().isValid(newReachTimes.at(i)) ) if (!data.getLocation(route.at(i)).getTimeWindow().isValid(newReachTimes.at(i)))
{ {
return false; return false;
} }
} }
return true; return true;
} }
// A lot of check here because i had problems with this function
void TimeWindowConstraint::ApplyModif(PDPTWData const &data, Pair const &pair, int routeIndex, int pickupPos,
int deliveryPos, bool addPair)
{
// Check the routeIndex validity
if (routeIndex < 0 || routeIndex >= getSolution().getRoutes().size())
{
spdlog::error("Error: routeIndex out of bounds ({})", routeIndex);
return;
}
// Copy of the route vector (problem that cause a duplication of the TW)
std::vector<int> routeIDs = getSolution().getRoute(routeIndex).getRoute();
void TimeWindowConstraint::ApplyModif(const PDPTWData& data, const Pair & pair, int routeIndex, int pickupPos, int deliveryPos, bool addPair) // // Check Position validity
{ // if (pickupPos < 0 || pickupPos > routeIDs.size() ||
// COPY route vector // deliveryPos < 0 || deliveryPos > routeIDs.size()) {
std::vector<int> routeIDs(getSolution().getRoute(routeIndex).getRoute().begin(), getSolution().getRoute(routeIndex).getRoute().end()); // spdlog::error("Error: Indices pickupPos ({}) or deliveryPos ({}) are invalid for a route size of {}.",
// pickupPos, deliveryPos, routeIDs.size());
// Adjust pickup and delivery // return;
if (addPair) // }
// if (addPair) {
// routeIDs.insert(routeIDs.begin() + deliveryPos, pair.getDelivery().getId());
// routeIDs.insert(routeIDs.begin() + pickupPos, pair.getPickup().getId());
// }
// else {
// if (deliveryPos < routeIDs.size() && pickupPos < routeIDs.size() && pickupPos != deliveryPos) {
// if (deliveryPos > pickupPos) {
// routeIDs.erase(routeIDs.begin() + deliveryPos);
// routeIDs.erase(routeIDs.begin() + pickupPos);
// } else {
// routeIDs.erase(routeIDs.begin() + pickupPos);
// routeIDs.erase(routeIDs.begin() + deliveryPos);
// }
// } else {
// spdlog::error("Error: Invalid indices for removal (pickupPos: {}, deliveryPos: {}).", pickupPos, deliveryPos);
// return;
// }
// }
// the route is empty !
if (routeIDs.empty())
{ {
routeIDs.insert(routeIDs.begin() + deliveryPos, pair.getDelivery().getId()); allRouteReachTimes.at(routeIndex).clear();
routeIDs.insert(routeIDs.begin() + pickupPos, pair.getPickup().getId());
} }
else else
{ {
routeIDs.erase(routeIDs.begin() + deliveryPos); allRouteReachTimes.at(routeIndex).resize(routeIDs.size(), 0);
routeIDs.erase(routeIDs.begin() + pickupPos);
}
// Adjust the size of reachTimes vector allRouteReachTimes.at(routeIndex).at(0) =
allRouteReachTimes.at(routeIndex).resize(routeIDs.size(), 0); data.getDepot().getTimeWindow().getStart() + data::TravelTime(data, 0, routeIDs.at(0));
// Time to the first location
allRouteReachTimes.at(routeIndex).at(0) = data.getDepot().getTimeWindow().getStart() + data::TravelTime(data, 0, routeIDs.at(0)); // Compute reach times
// Compute other reachTimes (max between arrival and start of the time window) for (size_t i = 1; i < routeIDs.size(); ++i)
for (int i = 1; i < routeIDs.size(); ++i) { {
TimeInteger travelTime = data::TravelTime(data, routeIDs.at(i - 1), routeIDs.at(i)); if (i - 1 >= routeIDs.size() || i >= routeIDs.size())
TimeInteger serviceTime = data.getLocation(routeIDs.at(i - 1)).getServiceDuration(); {
TimeInteger startTW = data.getLocation(routeIDs.at(i - 1)).getTimeWindow().getStart(); spdlog::error("Error: Out-of-bounds access to routeIDs in the computation loop.");
allRouteReachTimes.at(routeIndex).at(i) = std::max(allRouteReachTimes.at(routeIndex).at(i - 1), startTW) + serviceTime + travelTime; return;
}
TimeInteger travelTime = data::TravelTime(data, routeIDs.at(i - 1), routeIDs.at(i));
TimeInteger serviceTime = data.getLocation(routeIDs.at(i - 1)).getServiceDuration();
TimeInteger startTW = data.getLocation(routeIDs.at(i - 1)).getTimeWindow().getStart();
allRouteReachTimes.at(routeIndex).at(i) =
std::max(allRouteReachTimes.at(routeIndex).at(i - 1), startTW) + serviceTime + travelTime;
}
} }
} }
bool TimeWindowConstraint::check(InsertPair const &op) const bool TimeWindowConstraint::check(InsertPair const &op) const
{ {
std::cout << " #TW Check"; std::cout << " #TW Check";
return checkInsertion(getSolution().getData(), op.getPair(), op.getRouteIndex(), op.getPickupInsertion(), op.getDeliveryInsertion()); return checkInsertion(getSolution().getData(),
op.getPair(),
op.getRouteIndex(),
op.getPickupInsertion(),
op.getDeliveryInsertion());
} }
void TimeWindowConstraint::apply(InsertPair const &op) void TimeWindowConstraint::apply(InsertPair const &op)
{ {
std::cout << "-> Apply Modification on Time Windows \n"; std::cout << "-> Apply Modification on Time Windows \n";
ApplyModif(getSolution().getData(), op.getPair(), op.getRouteIndex(), op.getPickupInsertion(), op.getDeliveryInsertion(), true); ApplyModif(getSolution().getData(),
op.getPair(),
op.getRouteIndex(),
op.getPickupInsertion(),
op.getDeliveryInsertion(),
true);
} }
bool TimeWindowConstraint::check(InsertRoute const &op) const bool TimeWindowConstraint::check(InsertRoute const &op) const
{ {
return true; return true;
} }
void TimeWindowConstraint::apply(InsertRoute const &op) void TimeWindowConstraint::apply(InsertRoute const &op)
{ {
allRouteReachTimes.emplace_back(); allRouteReachTimes.emplace_back();
} }
bool TimeWindowConstraint::check(RemovePair const &op) const bool TimeWindowConstraint::check(RemovePair const &op) const
{ {
return true; return true;
} }
void TimeWindowConstraint::apply(RemovePair const &op) void TimeWindowConstraint::apply(RemovePair const &op)
{ {
ApplyModif(getSolution().getData(), op.getPair(), op.getRouteIndex(), op.getPickupDeletion(), op.getDeliveryDeletion(), false); ApplyModif(getSolution().getData(),
op.getPair(),
op.getRouteIndex(),
op.getPickupDeletion(),
op.getDeliveryDeletion(),
false);
} }
bool TimeWindowConstraint::check(RemoveRoute const &op) const bool TimeWindowConstraint::check(RemoveRoute const &op) const
{ {
return true; return true;
} }
void TimeWindowConstraint::apply(RemoveRoute const &op) void TimeWindowConstraint::apply(RemoveRoute const &op)
{ {
allRouteReachTimes.erase(allRouteReachTimes.begin() + op.getRouteIndex()); allRouteReachTimes.erase(allRouteReachTimes.begin() + op.getRouteIndex());
} }
const std::vector<TimeWindowConstraint::ReachTimeVector>& TimeWindowConstraint::getallRouteReachTimes() const { std::vector<TimeWindowConstraint::ReachTimeVector> const &TimeWindowConstraint::getallRouteReachTimes() const
{
return allRouteReachTimes; return allRouteReachTimes;
} }
...@@ -184,17 +242,22 @@ void TimeWindowConstraint::print() const ...@@ -184,17 +242,22 @@ void TimeWindowConstraint::print() const
{ {
std::cout << "Reach Times : \n"; std::cout << "Reach Times : \n";
int i = 0; int i = 0;
for (const auto& reachTimes : getallRouteReachTimes()) for (auto const &reachTimes: getallRouteReachTimes())
{ {
//std::cout << reachTimes.size() << ", "; //std::cout << reachTimes.size() << ", ";
std::cout << "#" << i << " : "; std::cout << "#" << i << " : ";
for (const TimeInteger reachTime : reachTimes) for (const TimeInteger reachTime: reachTimes)
{ {
std::cout << reachTime << ", "; std::cout << reachTime << ", ";
} }
std::cout << "\n";
std::cout << "#" << i << " : ";
for (int locID: getSolution().getRoute(i).getRoute())
{
std::cout << locID << ", ";
}
std::cout << "\n "; std::cout << "\n ";
i++; i++;
} }
std::cout << "\n"; std::cout << "\n";
} }
...@@ -29,7 +29,7 @@ public: ...@@ -29,7 +29,7 @@ public:
const std::vector<ReachTimeVector> & getallRouteReachTimes() const; const std::vector<ReachTimeVector> & getallRouteReachTimes() const;
void print() const; void print() const override;
private: private:
/** /**
......
...@@ -105,5 +105,5 @@ Index InsertPair::getIndex() const ...@@ -105,5 +105,5 @@ Index InsertPair::getIndex() const
ModificationApplyVariant InsertPair::asApplyVariant() const ModificationApplyVariant InsertPair::asApplyVariant() const
{ {
return (*this); return *this;
} }
\ No newline at end of file
...@@ -91,5 +91,5 @@ Index RemovePair::getIndex() const ...@@ -91,5 +91,5 @@ Index RemovePair::getIndex() const
ModificationApplyVariant RemovePair::asApplyVariant() const ModificationApplyVariant RemovePair::asApplyVariant() const
{ {
return (*this); return *this;
} }
\ No newline at end of file
...@@ -9,53 +9,65 @@ ...@@ -9,53 +9,65 @@
void RandomDestroy::destroySolution(Solution &solution) const void RandomDestroy::destroySolution(Solution &solution) const
{ {
std::cout << " --- Random Destroy --- \n";
int nbRequests = solution.requestsFulFilledCount(); int nbRequests = solution.requestsFulFilledCount();
int actualNumberOfPairsToDestroy = std::min(nbRequests, numberOfPairsToDestroy); int actualNumberOfPairsToDestroy = std::min(nbRequests, numberOfPairsToDestroy);
int remainingPairToDelete = actualNumberOfPairsToDestroy; int remainingPairToDelete = actualNumberOfPairsToDestroy;
while (remainingPairToDelete < 0) while (remainingPairToDelete > 0)
{ {
// too complicated // too complicated
// Other (simpler) option -> choose random route then choose random pair ? // Other (simpler) option -> choose random route then choose random pair ?
// choose a random pair // choose a random location
int pairNumber = util::getRandomInt(0, remainingPairToDelete * 2 - 1); int locationNumber = util::getRandomInt(0, remainingPairToDelete * 2 - 1);
// test
// locationNumber = nbRequests * 2 - 1;
// std::cout << " " << locationNumber << " \n";
//
int pairID = 0; int pairID = 0;
int routeID = 0; int routeID = 0;
int count = 0; int position = 0;
Index index = std::make_tuple(0,0,0); Index index = std::make_tuple(0,0,0);
// retrieve index (route and position) // retrieve index (route and position)
for (const Route &route : solution.getRoutes()) for (const Route &route : solution.getRoutes())
{ {
count += route.getSize(); position += route.getSize();
if (pairNumber < count) if (locationNumber < position)
{ {
count = count - pairNumber; // calculate the location position
position = route.getSize() - (position - locationNumber);
std::get<0>(index) = routeID; // get location associated to the position
std::get<1>(index) = count; Location loc = solution.getData().getLocation(route.getRoute().at(position));
std::get<2>(index) = route.getPairLocationPosition(count, solution.getData());
// retrieve pickupID (= PairID) // retrieve pickupID (= PairID)
if (solution.getData().getLocation(route.getRoute().at(count)).getLocType() == LocType::PICKUP ) if (loc.getLocType() == LocType::PICKUP )
{ {
pairID = route.getRoute().at(count); pairID = route.getRoute().at(position);
std::get<1>(index) = position;
std::get<2>(index) = route.getPairLocationPosition(position, solution.getData());
} }
else else
{ {
pairID = route.getRoute().at(std::get<2>(index)); pairID = loc.getPair();
std::get<1>(index) = route.getPairLocationPosition(position, solution.getData());
std::get<2>(index) = position;
} }
std::get<0>(index) = routeID;
break; break;
} }
++routeID; ++routeID;
} }
RemovePair remPair = RemovePair(index, solution.getData().getPair(pairID)); RemovePair remPair = RemovePair(index, solution.getData().getPair(pairID));
// appliquer la modif (via solution method -> update correctement la solution)
solution.applyDestructSolution(remPair); solution.applyDestructSolution(remPair);
// update les compteurs // update les compteurs
......
...@@ -190,6 +190,8 @@ void Solution::applyRecreateSolution(AtomicRecreation &modification) ...@@ -190,6 +190,8 @@ void Solution::applyRecreateSolution(AtomicRecreation &modification)
} }
afterApplyModification(modification); afterApplyModification(modification);
std::cout << "\n --- \n";
this->print();
} }
void Solution::applyDestructSolution(AtomicDestruction &modification) void Solution::applyDestructSolution(AtomicDestruction &modification)
...@@ -204,6 +206,7 @@ void Solution::applyDestructSolution(AtomicDestruction &modification) ...@@ -204,6 +206,7 @@ void Solution::applyDestructSolution(AtomicDestruction &modification)
pairBank.insert(pairBank.end(), deletedPair.begin(), deletedPair.end()); pairBank.insert(pairBank.end(), deletedPair.begin(), deletedPair.end());
afterApplyModification(modification); afterApplyModification(modification);
this->print();
} }
void Solution::check() const void Solution::check() const
...@@ -227,5 +230,11 @@ void Solution::print() const ...@@ -227,5 +230,11 @@ void Solution::print() const
{ {
std::cout << id << ", "; std::cout << id << ", ";
} }
std::cout << "\nConstraints : \n";
for (const std::unique_ptr<Constraint> &constraint: constraints)
{
constraint->print();
}
std::cout << "\n"; std::cout << "\n";
} }
\ No newline at end of file
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "input/data.h" #include "input/data.h"
#include "lns/constraints/capacity/capacity_constraint.h" #include "lns/constraints/capacity/capacity_constraint.h"
#include "lns/constraints/time_window/time_window_constraint.h" #include "lns/constraints/time_window/time_window_constraint.h"
#include "lns/operators/destruction/random_destroy.h"
#include "lns/operators/reconstruction/list_heuristic_cost_oriented.h" #include "lns/operators/reconstruction/list_heuristic_cost_oriented.h"
#include "lns/solution/solution.h" #include "lns/solution/solution.h"
#include "lns/modification/pair/insert_pair.h" #include "lns/modification/pair/insert_pair.h"
...@@ -83,7 +84,20 @@ int main(int argc, char const *argv[]) ...@@ -83,7 +84,20 @@ int main(int argc, char const *argv[])
heuristic.reconstructSolution(solution, blinkRate, strategy, enumeration); heuristic.reconstructSolution(solution, blinkRate, strategy, enumeration);
solution.print(); solution.print();
solution.print();
std::cout << " --- supr !!! --- \n ";
RandomDestroy randomdestroy = RandomDestroy(5);
randomdestroy.destroySolution(solution);
//Index index = std::make_tuple(0,7,9);
//RemovePair remPair = RemovePair(index, solution.getData().getPair(2));
//solution.applyDestructSolution(remPair);
output::exportToJson(solution); //solution.print();
//output::exportToJson(solution);
return 0; return 0;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment