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:
*/
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:
* Defaults to no op
*/
virtual void endOfDestructionCallback() {}
virtual void print() const = 0;
};
\ No newline at end of file
......@@ -8,32 +8,33 @@
#include "lns/modification/route/remove_route.h"
#include "lns/solution/solution.h"
TimeWindowConstraint::TimeWindowConstraint(const Solution& solution) : Constraint(solution)
TimeWindowConstraint::TimeWindowConstraint(Solution const &solution) : Constraint(solution)
{
allRouteReachTimes.resize(getSolution().getRoutes().size());
}
TimeWindowConstraint::~TimeWindowConstraint()
TimeWindowConstraint::~TimeWindowConstraint()
{
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);
clonePtr->allRouteReachTimes = allRouteReachTimes;
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
reachTimes.resize(routeIDs.size(), 0);
// Time to the first location
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)
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));
// locations are indexed from 0 to n-1,
TimeInteger serviceTime = data.getLocation(routeIDs.at(i - 1)).getServiceDuration();
......@@ -47,7 +48,7 @@ void TimeWindowConstraint::initReachTimes()
{
allRouteReachTimes = std::vector<ReachTimeVector>();
int i = 0;
for (const Route& route : getSolution().getRoutes())
for (Route const &route: getSolution().getRoutes())
{
// init and calculate reach time value
allRouteReachTimes.emplace_back();
......@@ -56,25 +57,24 @@ void TimeWindowConstraint::initReachTimes()
}
}
// Copie le vecteur de reach time de la route concernée
// Insère les positions pickup/delivery
// 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);
// 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
ReachTimeVector newReachTimes(reachTimes.begin(), reachTimes.end());
// Insert pickup and delivery
route.insert(route.begin() + deliveryPos, pair.getDelivery().getId());
route.insert(route.begin() + pickupPos, pair.getPickup().getId());
// std::cout << "\n";
// for (auto pos : route)
......@@ -94,89 +94,147 @@ bool TimeWindowConstraint::checkInsertion(const PDPTWData& data, const Pair & pa
// std::cout << "\n";
// 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 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)
{
// COPY route vector
std::vector<int> routeIDs(getSolution().getRoute(routeIndex).getRoute().begin(), getSolution().getRoute(routeIndex).getRoute().end());
// Adjust pickup and delivery
if (addPair)
// // Check Position validity
// if (pickupPos < 0 || pickupPos > routeIDs.size() ||
// deliveryPos < 0 || deliveryPos > routeIDs.size()) {
// spdlog::error("Error: Indices pickupPos ({}) or deliveryPos ({}) are invalid for a route size of {}.",
// pickupPos, deliveryPos, routeIDs.size());
// return;
// }
// 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());
routeIDs.insert(routeIDs.begin() + pickupPos, pair.getPickup().getId());
allRouteReachTimes.at(routeIndex).clear();
}
else
{
routeIDs.erase(routeIDs.begin() + deliveryPos);
routeIDs.erase(routeIDs.begin() + pickupPos);
}
allRouteReachTimes.at(routeIndex).resize(routeIDs.size(), 0);
// Adjust the size of reachTimes vector
allRouteReachTimes.at(routeIndex).resize(routeIDs.size(), 0);
// Time to the first location
allRouteReachTimes.at(routeIndex).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)
for (int i = 1; i < routeIDs.size(); ++i) {
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;
allRouteReachTimes.at(routeIndex).at(0) =
data.getDepot().getTimeWindow().getStart() + data::TravelTime(data, 0, routeIDs.at(0));
// Compute reach times
for (size_t i = 1; i < routeIDs.size(); ++i)
{
if (i - 1 >= routeIDs.size() || i >= routeIDs.size())
{
spdlog::error("Error: Out-of-bounds access to routeIDs in the computation loop.");
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
{
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)
{
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
{
return true;
}
void TimeWindowConstraint::apply(InsertRoute const &op)
{
allRouteReachTimes.emplace_back();
}
bool TimeWindowConstraint::check(RemovePair const &op) const
{
return true;
}
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
{
return true;
}
void TimeWindowConstraint::apply(RemoveRoute const &op)
{
allRouteReachTimes.erase(allRouteReachTimes.begin() + op.getRouteIndex());
}
const std::vector<TimeWindowConstraint::ReachTimeVector>& TimeWindowConstraint::getallRouteReachTimes() const {
std::vector<TimeWindowConstraint::ReachTimeVector> const &TimeWindowConstraint::getallRouteReachTimes() const
{
return allRouteReachTimes;
}
......@@ -184,17 +242,22 @@ void TimeWindowConstraint::print() const
{
std::cout << "Reach Times : \n";
int i = 0;
for (const auto& reachTimes : getallRouteReachTimes())
for (auto const &reachTimes: getallRouteReachTimes())
{
//std::cout << reachTimes.size() << ", ";
std::cout << "#" << i << " : ";
for (const TimeInteger reachTime : reachTimes)
for (const TimeInteger reachTime: reachTimes)
{
std::cout << reachTime << ", ";
}
std::cout << "\n";
std::cout << "#" << i << " : ";
for (int locID: getSolution().getRoute(i).getRoute())
{
std::cout << locID << ", ";
}
std::cout << "\n ";
i++;
}
std::cout << "\n";
}
......@@ -29,7 +29,7 @@ public:
const std::vector<ReachTimeVector> & getallRouteReachTimes() const;
void print() const;
void print() const override;
private:
/**
......
......@@ -105,5 +105,5 @@ Index InsertPair::getIndex() const
ModificationApplyVariant InsertPair::asApplyVariant() const
{
return (*this);
return *this;
}
\ No newline at end of file
......@@ -91,5 +91,5 @@ Index RemovePair::getIndex() const
ModificationApplyVariant RemovePair::asApplyVariant() const
{
return (*this);
return *this;
}
\ No newline at end of file
......@@ -9,53 +9,65 @@
void RandomDestroy::destroySolution(Solution &solution) const
{
std::cout << " --- Random Destroy --- \n";
int nbRequests = solution.requestsFulFilledCount();
int actualNumberOfPairsToDestroy = std::min(nbRequests, numberOfPairsToDestroy);
int remainingPairToDelete = actualNumberOfPairsToDestroy;
while (remainingPairToDelete < 0)
while (remainingPairToDelete > 0)
{
// too complicated
// Other (simpler) option -> choose random route then choose random pair ?
// choose a random pair
int pairNumber = util::getRandomInt(0, remainingPairToDelete * 2 - 1);
// choose a random location
int locationNumber = util::getRandomInt(0, remainingPairToDelete * 2 - 1);
// test
// locationNumber = nbRequests * 2 - 1;
// std::cout << " " << locationNumber << " \n";
//
int pairID = 0;
int routeID = 0;
int count = 0;
int position = 0;
Index index = std::make_tuple(0,0,0);
// retrieve index (route and position)
for (const Route &route : solution.getRoutes())
{
count += route.getSize();
if (pairNumber < count)
position += route.getSize();
if (locationNumber < position)
{
count = count - pairNumber;
// calculate the location position
position = route.getSize() - (position - locationNumber);
std::get<0>(index) = routeID;
std::get<1>(index) = count;
std::get<2>(index) = route.getPairLocationPosition(count, solution.getData());
// get location associated to the position
Location loc = solution.getData().getLocation(route.getRoute().at(position));
// 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
{
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;
}
++routeID;
}
RemovePair remPair = RemovePair(index, solution.getData().getPair(pairID));
// appliquer la modif (via solution method -> update correctement la solution)
solution.applyDestructSolution(remPair);
// update les compteurs
......
......@@ -190,6 +190,8 @@ void Solution::applyRecreateSolution(AtomicRecreation &modification)
}
afterApplyModification(modification);
std::cout << "\n --- \n";
this->print();
}
void Solution::applyDestructSolution(AtomicDestruction &modification)
......@@ -204,6 +206,7 @@ void Solution::applyDestructSolution(AtomicDestruction &modification)
pairBank.insert(pairBank.end(), deletedPair.begin(), deletedPair.end());
afterApplyModification(modification);
this->print();
}
void Solution::check() const
......@@ -227,5 +230,11 @@ void Solution::print() const
{
std::cout << id << ", ";
}
std::cout << "\nConstraints : \n";
for (const std::unique_ptr<Constraint> &constraint: constraints)
{
constraint->print();
}
std::cout << "\n";
}
\ No newline at end of file
......@@ -14,6 +14,7 @@
#include "input/data.h"
#include "lns/constraints/capacity/capacity_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/solution/solution.h"
#include "lns/modification/pair/insert_pair.h"
......@@ -83,7 +84,20 @@ int main(int argc, char const *argv[])
heuristic.reconstructSolution(solution, blinkRate, strategy, enumeration);
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;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment