Skip to content
Snippets Groups Projects
Commit 0a8185f2 authored by awenjb's avatar awenjb
Browse files

add Constraint

- Add TimeWIndow constraint
- add Capacity constraint
 TODO
- constraint check in O(1)
- consrtaint tests
- use constraints in solution
- full solution checker
parent 9829a4b0
Branches
No related tags found
No related merge requests found
Showing
with 701 additions and 46 deletions
......@@ -8,7 +8,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
# link time optimisation (LTO) for release and release with debug info builds
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Finding dependencies
find_package(CLI11 REQUIRED)
......@@ -22,11 +22,15 @@ find_package(spdlog REQUIRED)
add_executable(pdptw src/main.cpp
src/input/data.cpp
src/input/location.cpp
src/input/pair.cpp
src/input/pdptw_data.cpp
src/input/time_window.cpp
src/input/json_parser.cpp
src/lns/solution/route.cpp
src/lns/solution/solution.cpp
src/lns/constraints/constraint.cpp
src/lns/constraints/capacity/capacity_constraint.cpp
src/lns/constraints/time_window/time_window_constraint.cpp
src/lns/modification/pair/insert_pair.cpp
src/lns/modification/pair/remove_pair.cpp
src/lns/modification/route/insert_route_with_pair.cpp
......@@ -35,3 +39,5 @@ add_executable(pdptw src/main.cpp
)
target_link_libraries(pdptw PRIVATE CLI11::CLI11 nlohmann_json::nlohmann_json spdlog::spdlog)
target_include_directories(pdptw PUBLIC ${CMAKE_SOURCE_DIR}/src)
......@@ -46,6 +46,12 @@ double data::TravelCost(PDPTWData const &data, int index1, int index2)
return data.getMatrix()[index1][index2];
}
double data::TravelTime(PDPTWData const &data, int from, int to)
{
return data.getMatrix()[from][to];
}
double data::SegmentCost(PDPTWData const &data, Route const &route, int start, int end)
{
// TO DO
......
......@@ -39,4 +39,10 @@ namespace data
* (take location id in parameters)
*/
double TravelCost(PDPTWData const &data, int index1, int index2);
/**
* Return the travel time between two location
* (take location id in parameters)
*/
double TravelTime(PDPTWData const &data, int from, int to);
}
\ No newline at end of file
#include "pair.h"
Pair::Pair(const Location& pickupLoc, const Location& deliveryLoc)
: pickup(pickupLoc), delivery(deliveryLoc) {}
const Location& Pair::getPickup() const
{
return pickup.get();
}
const Location& Pair::getDelivery() const
{
return delivery.get();
}
\ No newline at end of file
#pragma once
#include "location.h"
// Represent a pair pickup/delivery of location
class Pair
{
private:
std::reference_wrapper<Location const> pickup;
std::reference_wrapper<Location const> delivery;
public:
Pair(const Location& pickupLoc, const Location& deliveryLoc);
const Location& getPickup() const;
const Location& getDelivery() const;
};
\ No newline at end of file
......@@ -12,7 +12,7 @@ unsigned int PDPTWData::getSize()
return size;
}
int PDPTWData::getCapacity()
int PDPTWData::getCapacity() const
{
return capacity;
}
......
......@@ -57,7 +57,7 @@ public:
Matrix const &getMatrix() const;
unsigned int getSize();
int getCapacity();
int getCapacity() const;
void print() const;
};
#include "capacity_constraint.h"
CapacityConstraint::CapacityConstraint(Solution const &solution) : Constraint(solution)
{
// Init an empty vector of reach time for all routes
//std::vector<CapacityVector> routeCapacities(getSolution().getRoutes().size(), CapacityVector());
routeCapacities.resize(getSolution().getRoutes().size());
}
std::unique_ptr<Constraint> CapacityConstraint::clone(Solution const &newOwningSolution) const {
std::unique_ptr<CapacityConstraint> clonePtr = std::make_unique<CapacityConstraint>(newOwningSolution);
clonePtr->routeCapacities = routeCapacities;
return clonePtr;
}
void CapacityConstraint::initCapacities()
{
routeCapacities = std::vector<CapacityVector>();
for (const Route& route : getSolution().getRoutes())
{
CapacityVector capacities;
int currentCapacity = 0;
for (int locationID : route.getRoute())
{
currentCapacity += getSolution().getData().getLocation(locationID).getDemand();
capacities.push_back(currentCapacity);
}
routeCapacities.push_back(capacities);
}
}
std::vector<int> const & CapacityConstraint::getRouteCapacities(int routeIndex) const
{
return routeCapacities[routeIndex];
}
// check for every location between the pickupPosition and the deliveryPosition
// not ideal
bool CapacityConstraint::checkModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition) const
{
std::cout << "\n";
int max_capacity = getSolution().getData().getCapacity();
// guardrail
if (pair.getPickup().getDemand() > max_capacity)
{
return false;
}
// check if the disponible capacity is enough are not
for (int i = PickupPosition; i <= DeliveryPosition; ++i) {
if ((i!=0) && (getRouteCapacities(routeIndex).at(i-1) + pair.getPickup().getDemand() >= max_capacity))
{
return false;
}
}
return true;
}
// update the route and the weight
// not ideal
void CapacityConstraint::applyModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition, bool addPair)
{
std::cout << "ok \n";
if (addPair)
{
// Insert new values
routeCapacities[routeIndex].insert(routeCapacities[routeIndex].begin()+DeliveryPosition, 0);
if (DeliveryPosition != 0)
{
routeCapacities[routeIndex][DeliveryPosition] += routeCapacities[routeIndex][DeliveryPosition-1];
}
routeCapacities[routeIndex].insert(routeCapacities[routeIndex].begin()+PickupPosition, pair.getPickup().getDemand());
if (PickupPosition != 0)
{
routeCapacities[routeIndex][PickupPosition] += routeCapacities[routeIndex][PickupPosition-1];
}
// Update value
for (int i = PickupPosition + 1; i < DeliveryPosition + 1; ++i)
{
routeCapacities[routeIndex][i] += pair.getPickup().getDemand();
}
}
else
{
for (int i = PickupPosition + 1; i < DeliveryPosition; ++i)
{
routeCapacities[routeIndex][i] += pair.getDelivery().getDemand();
}
// remove pair
routeCapacities[routeIndex].erase(routeCapacities[routeIndex].begin() + DeliveryPosition);
routeCapacities[routeIndex].erase(routeCapacities[routeIndex].begin() + PickupPosition);
}
}
bool CapacityConstraint::check(InsertPair const &op) const
{
return checkModif(op.getPair(), op.getRouteIndex(), op.getPickupInsertion(), op.getDeliveryInsertion());
}
void CapacityConstraint::apply(InsertPair const &op)
{
applyModif(op.getPair(), op.getRouteIndex(), op.getPickupInsertion(), op.getDeliveryInsertion(), true);
}
bool CapacityConstraint::check(InsertRoute const &op) const
{
return true;
}
void CapacityConstraint::apply(InsertRoute const &op)
{
// add new empty route
routeCapacities.emplace_back();
}
bool CapacityConstraint::check(RemovePair const &op) const
{
// Remove a pair (always true)
return true;
}
void CapacityConstraint::apply(RemovePair const &op)
{
applyModif(op.getPair(), op.getRouteIndex(), op.getPickupDeletion(), op.getDeliveryDeletion(), false);
}
bool CapacityConstraint::check(RemoveRoute const &op) const
{
return true;
}
void CapacityConstraint::apply(RemoveRoute const &op)
{
// add new empty route
routeCapacities.erase(routeCapacities.begin() + op.getRouteIndex());
}
void CapacityConstraint::print() const
{
std::cout << "Used capacity : \n";
int i = 0;
for (const auto& capaVector : routeCapacities)
{
std::cout << "#" << i << " : ";
for (const int capa : capaVector)
{
std::cout << capa << ", ";
}
std::cout << "\n ";
i++;
}
std::cout << "\n";
}
#pragma once
#include "./../constraint.h"
#include "./../../../input/pair.h"
/**
* Capacity constraint.
* To check this, we keep track of the sum of all requests and check it against the max capacity.
* TO DO, verification in O(1) by storing a matrix !
*/
class CapacityConstraint : public Constraint
{
public:
using CapacityVector = std::vector<int>;
private:
std::vector<CapacityVector> routeCapacities;
void apply(InsertPair const &op) override;
void apply(InsertRoute const &op) override;
void apply(RemovePair const &op) override;
void apply(RemoveRoute const &op) override;
bool check(InsertPair const &op) const override;
bool check(InsertRoute const &op) const override;
bool check(RemovePair const &op) const override;
bool check(RemoveRoute const &op) const override;
public:
explicit CapacityConstraint(Solution const &);
CapacityConstraint(CapacityConstraint const &) = default;
std::unique_ptr<Constraint> clone(Solution const &newOwningSolution) const override;
/*
* Given the solution, calculate the capacities when leaving each location
* Modify the routeCapacities vector !
*/
void initCapacities();
/*
* Return capacity vector of a route
*/
CapacityVector const &getRouteCapacities(int routeIndex) const;
/*
* Check if a modification is valid or not
* (for now, check only the position of the pickup)
* TO DO (1 or 2)
* 1) check if every index on the path can take the new capacity
* 2) store a matrix / Segment Tree ?? to evaluate the maximum load between two part of the route
* -> a matrix but check in O(1) (update in O(n))
*/
bool checkModif(Pair const &pair, int routeIndex, int position, int DeliveryPosition) const;
/*
* Update the weight
*/
void applyModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition, bool addPair);
void print() const;
};
\ No newline at end of file
#include "constraint.h"
Constraint::Constraint(Solution const &solution) : solution(solution) {}
Solution const &Constraint::getSolution() const
{
return solution.get();
}
PDPTWData const &Constraint::data() const
{
return getSolution().getData();
}
void Constraint::setSolution(Solution const &newSolutionOwner)
{
solution = newSolutionOwner;
}
void ModificationVisitor::applyVariant(ModificationApplyVariant const &applyModificationVariant)
{
// lambda auto&& + std::visit combo
// allows to split the variant to each strongly typed function for each modification (see the protected pure virtual functions apply)
// If compilation breaks here, it is likely that a type T in the ModificationApplyVariant has no function ModificationVisitor::apply(T const &) associated
std::visit([this](auto &&op) { this->apply(op); }, applyModificationVariant);
}
bool ConstraintVisitor::checkVariant(ModificationCheckVariant const &checkModificationVariant)
{
// lambda auto&& + std::visit combo
// allows to split the variant to each strongly typed function for each modification (see the protected pure virtual functions apply)
// If compilation breaks here, it is likely that a type T in the ModificationCheckVariant has no function ConstraintVisitor::apply(T const &) associated
return std::visit([this](auto &&op) { return this->check(op); }, checkModificationVariant);
}
#pragma once
#include <variant>
#include "./../solution/solution.h"
// all modifications
#include "./../modification/pair/insert_pair.h"
#include "./../modification/pair/remove_pair.h"
#include "./../modification/route/insert_route.h"
#include "./../modification/route/remove_route.h"
using ModificationApplyVariant =
std::variant<std::reference_wrapper<InsertPair const>, std::reference_wrapper<InsertRoute const>,
std::reference_wrapper<RemovePair const>, std::reference_wrapper<RemoveRoute const>>;
// defines the variant that can store all the modifications that can be checked (recreation modifications)
using ModificationCheckVariant =
std::variant<std::reference_wrapper<InsertPair const>, std::reference_wrapper<InsertRoute const>,
std::reference_wrapper<RemovePair const>, std::reference_wrapper<RemoveRoute const>>;
/**
* Visitor pattern for the modifications.
* It splits the variant into separate apply functions for each Modification.
*/
class ModificationVisitor
{
protected:
// A child class must handle all the modification types ie. implement all these functions
virtual void apply(InsertPair const &op) = 0;
virtual void apply(InsertRoute const &op) = 0;
virtual void apply(RemovePair const &op) = 0;
virtual void apply(RemoveRoute const &op) = 0;
public:
/**
* A modification has been applied to the solution,
* the constraint can use information from the modification to update its state.
*/
void applyVariant(ModificationApplyVariant const &applyModificationVariant);
};
/**
* Visitor pattern for the constraint. Adds the check part that constraints must implement
* It splits the variant into separate check/apply functions for each Modification.
*/
class ConstraintVisitor : public ModificationVisitor
{
protected:
// A child class must handle all the modification types ie. implement all these functions
virtual bool check(InsertPair const &op) const = 0;
virtual bool check(InsertRoute const &op) const = 0;
virtual bool check(RemovePair const &op) const = 0;
virtual bool check(RemoveRoute const &op) const = 0;
public:
virtual ~ConstraintVisitor() = default;
/**
* Checks that a modification is valid for the solution
* If a check fails it must return false.
*/
bool checkVariant(ModificationCheckVariant const &checkModificationVariant);
};
/**
* Base class for a constraint.
* It has to define all checks (from ConstraintVisitor),
* and can modify its state with the apply (from ModificationVisitor), it looks like a listener pattern
*/
class Constraint : public ConstraintVisitor
{
std::reference_wrapper<Solution const> solution;
protected:
explicit Constraint(Solution const &);
PDPTWData const &data() const;
public:
/**
* It is expected that the new Solution is in valid state regarding precedence graph and times when cloning
*/
virtual std::unique_ptr<Constraint> clone(Solution const &newOwningSolution) const = 0;
Solution const &getSolution() const;
// used when a solution is moved, we must update the owner
void setSolution(Solution const &newSolutionOwner);
~Constraint() override = default;
/**
* Callback when many destruction are done. It is expected that checks work after a call to this.
* Defaults to no op
*/
virtual void endOfDestructionCallback() {}
};
\ No newline at end of file
#include "time_window_constraint.h"
#include "input/data.h"
#include "input/pdptw_data.h"
#include "input/time_window.h"
#include "lns/solution/solution.h"
TimeWindowConstraint::TimeWindowConstraint(Solution const &solution) : Constraint(solution)
{
// Empty
}
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;
}
// 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
{
ReachTimeVector const &reachTimes = allRouteReachTimes.at(routeIndex);
// COPY route vector
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() + pickupPos, pair.getPickup().getId());
route.insert(route.begin() + deliveryPos, pair.getDelivery().getId());
// Compute new reach time
computeReachTimes(data, route, newReachTimes);
// Check Time Windows
for (int i = 0; i < reachTimes.size(); ++i)
{
if (! data.getLocation(route[i]).getTimeWindow().isValid(newReachTimes.at(i)) )
{
return false;
}
}
return true;
}
void TimeWindowConstraint::computeReachTimes(const PDPTWData& data, const std::vector<int> & routeIDs, ReachTimeVector & reachTimes) const
{
// Adjust the size of reachTimes vector
reachTimes.resize(routeIDs.size(), 0);
// Time to the first location
reachTimes[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[i - 1], routeIDs[i]);
TimeInteger serviceTime = data.getLocation(routeIDs[i - 1]).getServiceDuration();
TimeInteger startTW = data.getLocation(routeIDs[i]).getTimeWindow().getStart();
reachTimes[i] = std::max(reachTimes[i - 1] + serviceTime + travelTime, startTW);
}
}
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)
{
routeIDs.insert(routeIDs.begin() + pickupPos, pair.getPickup().getId());
routeIDs.insert(routeIDs.begin() + deliveryPos, pair.getDelivery().getId());
}
else
{
routeIDs.erase(routeIDs.begin() + deliveryPos);
routeIDs.erase(routeIDs.begin() + pickupPos);
}
// Adjust the size of reachTimes vector
allRouteReachTimes[routeIndex].resize(routeIDs.size(), 0);
// Time to the first location
allRouteReachTimes[routeIndex][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[i - 1], routeIDs[i]);
TimeInteger serviceTime = data.getLocation(routeIDs[i - 1]).getServiceDuration();
TimeInteger startTW = data.getLocation(routeIDs[i]).getTimeWindow().getStart();
allRouteReachTimes[routeIndex][i] = std::max(allRouteReachTimes[routeIndex][i - 1] + serviceTime + travelTime, startTW);
}
}
bool TimeWindowConstraint::check(InsertPair const &op) const
{
return checkInsertion(getSolution().getData(), op.getPair(), op.getRouteIndex(), op.getPickupInsertion(), op.getDeliveryInsertion());
}
void TimeWindowConstraint::apply(InsertPair const &op)
{
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);
}
bool TimeWindowConstraint::check(RemoveRoute const &op) const
{
return true;
}
void TimeWindowConstraint::apply(RemoveRoute const &op)
{
allRouteReachTimes.erase(allRouteReachTimes.begin() + op.getRouteIndex());
}
#pragma once
#include "lns/constraints/constraint.h"
#include "input/pair.h"
#include "input/time_window.h"
#include <vector>
/**
* Time Window Constraint
* Check that the time windows are respected.
* For now, compute all time window in a route
* TO DO FTS
*/
class TimeWindowConstraint : public Constraint
{
public:
explicit TimeWindowConstraint(Solution const &);
TimeWindowConstraint(TimeWindowConstraint const &) = default;
std::unique_ptr<Constraint> clone(Solution const &newOwningSolution) const override;
private:
using ReachTimeVector = std::vector<TimeInteger>;
/**
* For each route, store the reach time of each location
*/
std::vector<ReachTimeVector> allRouteReachTimes;
// Recalcul tous les reachTimes pour une route
ReachTimeVector computeReachTimes(const Route& route) const;
bool updateReachTimes(const PDPTWData& data, Pair & pair,int routeIndex, int pickupPos, int deliveryPos);
/**
* Check if the insertion of a pair pickup/delivery is valid or not.
* COPY the route where we insert the pair !
*/
bool checkInsertion(const PDPTWData& data, const Pair & pair, int routeIndex, int pickupPos, int deliveryPos) const;
/**
* Given route IDs, compute the reachTimes of the route.
* If a vehicule is in advance, set the reach time to start of the timeWindow.
* Modify reachTimes vector !
*/
void computeReachTimes(const PDPTWData& data, const std::vector<int> & routeIDs, ReachTimeVector & reachTimes) const;
/**
* Given route IDs, modify the reachTimes
*/
void ApplyModif(const PDPTWData& data, const Pair & pair, int routeIndex, int pickupPos, int deliveryPos, bool addPair);
void apply(InsertPair const &op) override;
void apply(InsertRoute const &op) override;
void apply(RemovePair const &op) override;
void apply(RemoveRoute const &op) override;
bool check(InsertPair const &op) const override;
bool check(InsertRoute const &op) const override;
bool check(RemovePair const &op) const override;
bool check(RemoveRoute const &op) const override;
public:
};
\ No newline at end of file
......@@ -8,7 +8,17 @@ InsertPair::InsertPair(int routeIndex, int pickupInsertion, int deliveryInsertio
pickupInsertion(pickupInsertion),
deliveryInsertion(deliveryInsertion),
pickupLocation(pickupLocation),
deliveryLocation(deliveryLocation) {}
deliveryLocation(deliveryLocation),
pair(Pair(pickupLocation, deliveryLocation)) {}
InsertPair::InsertPair(int routeIndex, int pickupInsertion, int deliveryInsertion,
Pair const &pair)
: routeIndex(routeIndex),
pickupInsertion(pickupInsertion),
deliveryInsertion(deliveryInsertion),
pickupLocation(pair.getPickup()),
deliveryLocation(pair.getDelivery()),
pair(pair) {}
void InsertPair::modifySolution(Solution &solution)
......@@ -79,3 +89,9 @@ const Location *InsertPair::getAddedLocation() const
return &pickupLocation;
}
const Pair &InsertPair::getPair() const
{
return pair;
}
......@@ -3,6 +3,7 @@
#include "./../atomic_recreation.h"
#include "./../../solution/solution.h"
#include "./../../../input/location.h"
#include "./../../../input/pair.h"
#include <functional>
class Route;
......@@ -37,8 +38,11 @@ class InsertPair : public AtomicRecreation
*/
Location const & deliveryLocation;
Pair const & pair;
public:
InsertPair(int routeIndex, int pickupInsertion, int deliveryInsertion, Location const &pickupLocation, Location const &deliveryLocation);
InsertPair(int routeIndex, int pickupInsertion, int deliveryInsertion, Pair const &pair);
void modifySolution(Solution &solution) override;
double evaluate(Solution const &solution) const override;
......@@ -48,6 +52,7 @@ public:
int getRouteIndex() const;
Location const &getPickupLocation() const;
Location const &getDeliveryLocation() const;
Pair const &getPair() const;
Location const *getAddedLocation() const override;
......
......@@ -8,7 +8,17 @@ RemovePair::RemovePair(int routeIndex, int pickupDeletion, int deliveryDeletion,
pickupDeletion(pickupDeletion),
deliveryDeletion(deliveryDeletion),
pickupLocation(pickupLocation),
deliveryLocation(deliveryLocation) {}
deliveryLocation(deliveryLocation),
pair(Pair(pickupLocation, deliveryLocation)) {}
RemovePair::RemovePair(int routeIndex, int pickupDeletion, int deliveryDeletion,
Pair const &pair) :
routeIndex(routeIndex),
pickupDeletion(pickupDeletion),
deliveryDeletion(deliveryDeletion),
pickupLocation(pair.getPickup()),
deliveryLocation(pair.getDelivery()),
pair(pair) {}
void RemovePair::modifySolution(Solution &solution)
{
......@@ -79,3 +89,8 @@ std::vector<int> const & RemovePair::getDeletedRequests() const
{
return removedLocationID;
}
Pair const &RemovePair::getPair() const
{
return pair;
}
\ No newline at end of file
......@@ -3,6 +3,7 @@
#include "./../atomic_destruction.h"
#include "./../../solution/solution.h"
#include "./../../../input/location.h"
#include "./../../../input/pair.h"
#include <functional>
class Route;
......@@ -35,6 +36,7 @@ class RemovePair : public AtomicDestruction
*/
Location const & deliveryLocation;
Pair const & pair;
/**
* Removed Location ID (empty before ModifySolution is called)
......@@ -44,6 +46,7 @@ class RemovePair : public AtomicDestruction
public:
RemovePair(int routeIndex, int pickupDeletion, int deliveryDeletion, Location const &pickupLocation, Location const &deliveryLocation);
RemovePair(int routeIndex, int pickupDeletion, int deliveryDeletion, Pair const &pair);
void modifySolution(Solution &solution) override;
double evaluate(Solution const &solution) const override;
......@@ -54,6 +57,8 @@ public:
Location const &getPickupLocation() const;
Location const &getDeliveryLocation() const;
Pair const &getPair() const;
/**
* Return the location ID of location that has been deleted
*/
......
......@@ -11,8 +11,9 @@ class Route
{
private:
int cost;
std::vector<int> route;
int cost;
/* Stocké dans les contraintes
......
......@@ -13,6 +13,8 @@
#include "input/time_window.h"
#include "input/json_parser.h"
#include "input/data.h"
#include "lns/constraints/capacity/capacity_constraint.h"
#include "lns/constraints/time_window/time_window_constraint.h"
#include "lns/solution/solution.h"
#include "lns/modification/pair/insert_pair.h"
#include "lns/modification/route/insert_route.h"
......@@ -24,10 +26,9 @@ using json = nlohmann::json;
int main(int argc, char const *argv[])
{
/* code */
//std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/test_inst.json";
std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/n100/bar-n100-1.json";
//std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/n100/bar-n100-1.json";
std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/Nantes_1.json";
//std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/n5000/bar-n5000-1.json";
std::cout << filepath << "\n";
......@@ -38,58 +39,58 @@ int main(int argc, char const *argv[])
/*
* test
*/
Solution emptySol = Solution(data);
// SOLUTION 1-6-2-7 (time ; 104)
Solution::RequestBank bank {3,4,5,8,9,10};
// Empty Solution
Solution sol = Solution(data);
std::vector<int> path {1,2,6,7};
Route route = Route(path, 0);
std::vector<Route> routes;
routes.push_back(route);
InsertRoute op1 = InsertRoute();
int totalCost = 0;
Solution sol = Solution(data, bank, routes, totalCost);
sol.print();
// Ajoute une route vide
op1.modifySolution(sol);
Location r1P = data.getLocations()[0];
Location r1D = data.getLocations()[50];
// Couple pickup/delivery
Location r2P = data.getLocations()[1];
Location r2D = data.getLocations()[51];
Location r2D = data.getLocations()[6];
Location r3P = data.getLocations()[2];
Location r3D = data.getLocations()[52];
Location r3D = data.getLocations()[7];
// Opération : Ajoute une paire pickup delivery à la route 0 en position 0 et 0
InsertPair op2 = InsertPair(0, 0, 0, r1P, r1D);
op2.modifySolution(sol);
InsertPair op3 = InsertPair(0, 0, 2, r2P, r2D);
op3.modifySolution(sol);
std::cout << "--- \n";
Pair pair2 = Pair(r2P, r2D);
Pair pair3 = Pair(r3P, r3D);
data::routeCost(data, sol.getRoute(0));
// Modification
InsertPair opInsert = InsertPair(0, 2, 2, pair3);
InsertPair op4 = InsertPair(0, 3, 4, r3P, r3D);
std::cout << "cout d'insert : "<< op4.evaluate(sol) << "\n";
op4.modifySolution(sol);
/*
std::cout << "--- \n";
sol.print();
data::routeCost(data, sol.getRoute(0));
CapacityConstraint cap_const = CapacityConstraint(sol);
// TO DO
// Test supr
std::cout << "--- \n";
RemovePair op5 = RemovePair(0, 3, 5, r3P, r3D);
std::cout << "cout de supr : "<< op5.evaluate(sol) << "\n";
cap_const.initCapacities();
cap_const.print();
op5.modifySolution(sol);
sol.print();
std::cout << "Is Valid ? : " << cap_const.checkVariant(opInsert) << "\n";
data::routeCost(data, sol.getRoute(0));
cap_const.applyVariant(opInsert);
RemoveRoute op6 = RemoveRoute(0);
cap_const.print();
std::cout << "cout de supr : "<< op6.evaluate(sol) << "\n";
RemovePair opRemove = RemovePair(0, 2, 3, pair3);
op6.modifySolution(sol);
cap_const.applyVariant(opRemove);
cap_const.print();
*/
sol.print();
TimeWindowConstraint twconst = TimeWindowConstraint(sol);
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment