Skip to content
Snippets Groups Projects
Commit 2fc0df0b authored by awenjb's avatar awenjb
Browse files

Update Code

- revised some parts of the code
- add some comments
- add config.h and types.h
- data init with the list of Pair
- Solution init and link with constraints
parent 0a8185f2
Branches
No related tags found
No related merge requests found
Showing
with 268 additions and 98 deletions
......@@ -19,7 +19,8 @@ find_package(spdlog REQUIRED)
add_executable(pdptw src/main.cpp
add_executable(pdptw src/mains/main.cpp
src/mains/main_interface.cpp
src/input/data.cpp
src/input/location.cpp
src/input/pair.cpp
......
const int EXCLUSION_PENALTY = 100;
\ No newline at end of file
......@@ -41,9 +41,9 @@ double data::routeCost(PDPTWData const & data, Route const & route)
return cost;
}
double data::TravelCost(PDPTWData const &data, int index1, int index2)
double data::TravelCost(PDPTWData const &data, int from, int to)
{
return data.getMatrix()[index1][index2];
return data.getMatrix()[from][to];
}
double data::TravelTime(PDPTWData const &data, int from, int to)
......
......@@ -3,7 +3,8 @@
#include "time_window.h"
#include "pdptw_data.h"
#include "location.h"
#include "../lns/solution/route.h"
#include "lns/solution/solution.h"
/**
* Functions for PDPTWData
......@@ -38,7 +39,7 @@ namespace data
* Return the travel cost between two location
* (take location id in parameters)
*/
double TravelCost(PDPTWData const &data, int index1, int index2);
double TravelCost(PDPTWData const &data, int from, int to);
/**
* Return the travel time between two location
......
......@@ -51,7 +51,7 @@ PDPTWData parsing::parseJson(std::string filepath)
PDPTWData json_to_data(const json& j)
{
unsigned int size = j.at("size").get<unsigned int>();
int size = j.at("size").get<int>();
int capacity = j.at("capacity").get<int>();
auto depot_json = j.at("depot");
......@@ -68,7 +68,6 @@ PDPTWData json_to_data(const json& j)
LocType::DEPOT
);
std::vector<Location> locations;
for (const auto& loc : j.at("locations"))
......@@ -90,5 +89,5 @@ PDPTWData json_to_data(const json& j)
Matrix distance_matrix = j.at("distance_matrix").get<Matrix>();
return PDPTWData(size, capacity, depot, locations, distance_matrix);
return {size, capacity, depot, locations, distance_matrix};
}
#include "location.h"
Location::Location(unsigned int id, double lon, double lat, int dem, TimeWindow tw, double service, unsigned int pairId, LocType type)
: id(id), longitude(lon), latitude(lat), demand(dem), timeWindow(tw), serviceDuration(service), pairedLocation(pairId), locType(type) {}
Location::Location(int id, double lon, double lat, int dem, TimeWindow tw, double service, int pairId, LocType type)
: id(id), longitude(lon), latitude(lat), demand(dem), timeWindow(tw), serviceDuration(service), pairedLocationID(pairId), locType(type)
{}
double Location::getLongitude() const {
return longitude;
......@@ -17,12 +17,12 @@ double Location::getServiceDuration() const {
return serviceDuration;
}
unsigned int Location::getId() const {
int Location::getId() const {
return id;
}
unsigned int Location::getPair() const {
return pairedLocation;
int Location::getPair() const {
return pairedLocationID;
}
int Location::getDemand() const {
......@@ -37,7 +37,7 @@ TimeWindow Location::getTimeWindow() const {
return timeWindow;
}
std::string Location::LocTypeToString(LocType type) const
std::string Location::LocTypeToString(LocType type)
{
switch (type) {
case LocType::DEPOT: return "Depot";
......@@ -47,11 +47,10 @@ std::string Location::LocTypeToString(LocType type) const
}
}
void Location::print() const
{
std::cout << "Location ID: " << id << ", Coordinates: (" << longitude << ", " << latitude << ")\n";
std::cout << "Location Type : " << Location::LocTypeToString(locType) << ", Associated location : " << pairedLocation << "\n";
std::cout << "Location Type : " << Location::LocTypeToString(locType) << ", Associated location : " << pairedLocationID << "\n";
std::cout << "Demand : " << demand << "\n";
timeWindow.print();
}
\ No newline at end of file
......@@ -23,30 +23,45 @@ enum class LocType
*/
class Location
{
unsigned int id;
/*
* The location ID
*/
int id;
double longitude;
double latitude;
/*
* Represent the capacity used by that location.
* The location demand must be positive if it is a PICKUP, negative if it is a DELIVERY and 0 for a DEPOT.
*/
int demand;
double serviceDuration;
unsigned int pairedLocation;
/*
* The location ID associated to form a pickup and delivery pair.
* (the same ID if the location is a depot)
*/
int pairedLocationID;
/*
* The type of the location (PICKUP, DELIVERY, DEPOT).
*/
LocType locType;
TimeWindow timeWindow;
public:
Location(unsigned int id, double lon, double lat, int dem, TimeWindow tw, double service, unsigned int pairId, LocType type);
Location(int id, double lon, double lat, int dem, TimeWindow tw, double service, int pairId, LocType type);
double getLongitude() const;
double getLatitude() const;
double getServiceDuration() const;
unsigned getId() const;
unsigned int getPair() const;
int getId() const;
int getPair() const;
int getDemand() const;
LocType getLocType() const;
TimeWindow getTimeWindow() const;
void print() const;
std::string LocTypeToString(LocType type) const;
static std::string LocTypeToString(LocType type);
// Json parsing
friend void from_json(nlohmann::json const &json, Location &location);
......
#include "pair.h"
Pair::Pair(const Location& pickupLoc, const Location& deliveryLoc)
: pickup(pickupLoc), delivery(deliveryLoc) {}
Pair::Pair(const Location& pickup, const Location& delivery, int pairID)
: pickup(pickup), delivery(delivery), pairID(pairID) {}
const Location& Pair::getPickup() const
{
......@@ -12,3 +12,25 @@ const Location& Pair::getDelivery() const
{
return delivery.get();
}
const Location& Pair::getP() const
{
return pickup.get();
}
const Location& Pair::getD() const
{
return delivery.get();
}
int Pair::getID() const
{
return pairID;
}
void Pair::print() const
{
pickup.get().print();
std::cout << "\n";
delivery.get().print();
}
\ No newline at end of file
......@@ -2,16 +2,31 @@
#include "location.h"
// Represent a pair pickup/delivery of location
/**
* Represent a pair pickup/delivery of location
* The pair ID is the pickup ID
*/
class Pair
{
private:
std::reference_wrapper<Location const> pickup;
std::reference_wrapper<Location const> delivery;
int pairID;
public:
Pair(const Location& pickupLoc, const Location& deliveryLoc);
Pair(const Location& pickup, const Location& delivery, int pairID);
const Location& getPickup() const;
const Location& getDelivery() const;
/**
* getPickup() but shorter
*/
const Location& getP() const;
/**
* getDelivery() but shorter
*/
const Location& getD() const;
int getID() const;
void print() const;
};
\ No newline at end of file
......@@ -2,12 +2,10 @@
#include <iostream>
#include <fstream>
#include <vector>
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
unsigned int PDPTWData::getSize()
int PDPTWData::getSize() const
{
return size;
}
......@@ -22,6 +20,11 @@ std::vector<Location> const &PDPTWData::getLocations() const
return locations;
}
std::vector<Pair> const &PDPTWData::getPairs() const
{
return pairs;
}
Location const &PDPTWData::getDepot() const
{
return depot;
......@@ -29,7 +32,12 @@ Location const &PDPTWData::getDepot() const
Location const &PDPTWData::getLocation(int id) const
{
return locations[id];
if (id==0)
{
return getDepot();
}
// location index from 0 to n-1
return locations.at(id -1);
}
Matrix const &PDPTWData::getMatrix() const
......@@ -37,8 +45,20 @@ Matrix const &PDPTWData::getMatrix() const
return distanceMatrix;
}
PDPTWData::PDPTWData(unsigned int size, int capacity, Location depot, std::vector<Location> location, Matrix distanceMatrix)
: size(size), capacity(capacity), depot(depot), locations(std::move(location)), distanceMatrix(std::move(distanceMatrix)) {}
PDPTWData::PDPTWData(int size, int capacity, Location depot, std::vector<Location> locations, Matrix distanceMatrix)
: size(size), capacity(capacity), depot(depot), locations(std::move(locations)), distanceMatrix(std::move(distanceMatrix))
{
// Associate pair of locations
pairs.clear();
for (const Location & loc : this->locations)
{
if( loc.getLocType() == LocType::PICKUP )
{
// vector indexed from 0 / Location indexed from 1
pairs.emplace_back(loc, locations[loc.getPair()-1], loc.getId());
}
}
}
void PDPTWData::print() const
......@@ -60,6 +80,13 @@ void PDPTWData::print() const
}
std::cout << "\n";
}
std::cout << "Pair IDs:\n";
for (const auto& pair : pairs)
{;
std::cout << pair.getID() << " ";
}
std::cout << " \n";
}
void PDPTWData::checkData() const
......
#pragma once
#include "location.h"
#include <functional>
#include <nlohmann/json_fwd.hpp>
#include <vector>
#include "pair.h"
#include "location.h"
#include "types.h"
using json = nlohmann::json;
using Matrix = std::vector<std::vector<double>>;
/**
* Throw this exception after errors in the input has been found.
......@@ -20,29 +21,28 @@ public:
char const *what() const noexcept override;
};
class PDPTWData
{
unsigned int size;
int size;
int capacity;
Location depot;
std::vector<Location> locations;
std::vector<Pair> pairs; // std::unordered_map<int, Pair> pair; if getPair(index) is needed ?
Matrix distanceMatrix;
public:
PDPTWData();
PDPTWData(PDPTWData const &rhs) = delete;
PDPTWData(PDPTWData &&rhs) noexcept;
PDPTWData &operator=(PDPTWData &&rhs) noexcept;
PDPTWData &operator=(PDPTWData const &rhs) = delete;
~PDPTWData() = default;
/**
* Constructs an empty PDPTWData.
* @see parsing::parseJson
*/
PDPTWData(unsigned int size, int capacity, Location depot, std::vector<Location> requests, Matrix distanceMatrix);
PDPTWData(int size, int capacity, Location depot, std::vector<Location> locations, Matrix distanceMatrix);
/**
* Checks some data coherence
*/
......@@ -52,11 +52,18 @@ public:
std::vector<Location> const &getLocations() const;
std::vector<Pair> const &getPairs() const;
/**
* 0 return the depot.
* Other numbers return the associated location.
*/
Location const &getLocation(int id) const;
Location const &getDepot() const;
Matrix const &getMatrix() const;
unsigned int getSize();
int getSize() const;
int getCapacity() const;
void print() const;
......
......@@ -31,10 +31,3 @@ void TimeWindow::print() const
{
std::cout << "Time Window : [" << start << ", " << end << "] \n";
}
/*
TimeInteger TimeWindow::waitingTimeBefore(TimeInteger t) const
{
return std::max<TimeInteger>(0, t - start);
}
*/
#pragma once
#include <iostream>
#include <limits>
#include <nlohmann/json_fwd.hpp>
/**
* A point in time or a duration.
*/
using TimeInteger = double;
TimeInteger constexpr UNDEF_TIMESTAMP = std::numeric_limits<TimeInteger>::max();
#include "types.h"
/**
* Represents a time window [start, end] with some basic utilities.
......@@ -29,12 +23,7 @@ public:
//Checks whether the time t is inside the time window OR before
bool isValid(TimeInteger t) const;
/**
* return the time to wait from t to the start of this time window.
* @return 0 if t is after start, or start - t
*/
//TimeInteger waitingTimeBefore(TimeInteger t) const;
void print() const;
friend void from_json(nlohmann::json const &json, TimeWindow &tw);
};
\ No newline at end of file
#pragma once
#include <vector>
#include "./../constraint.h"
#include "./../../../input/pair.h"
#include "lns/constraints/constraint.h"
#include "lns/solution/solution.h"
#include "lns/modification/pair/insert_pair.h"
#include "lns/modification/pair/remove_pair.h"
#include "lns/modification/route/insert_route.h"
#include "lns/modification/route/remove_route.h"
/**
* Capacity constraint.
......
#include "constraint.h"
#include "lns/solution/solution.h"
Constraint::Constraint(Solution const &solution) : solution(solution) {}
......
#pragma once
#include <memory>
#include <stdexcept>
#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"
// forward declaration of all modifications
class InsertPair;
class RemovePair;
class InsertRoute;
class RemoveRoute;
class Solution;
class PDPTWData;
using ModificationApplyVariant =
......
#include "time_window_constraint.h"
#include "input/data.h"
#include "input/pdptw_data.h"
#include "input/time_window.h"
#include "lns/modification/pair/insert_pair.h"
#include "lns/modification/pair/remove_pair.h"
#include "lns/modification/route/remove_route.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());
}
TimeWindowConstraint::~TimeWindowConstraint()
{
// Empty
allRouteReachTimes.clear();
}
std::unique_ptr<Constraint> TimeWindowConstraint::clone(Solution const &newOwningSolution) const {
......@@ -16,6 +26,37 @@ std::unique_ptr<Constraint> TimeWindowConstraint::clone(Solution const &newOwnin
return clonePtr;
}
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 + previous service time + travel time)
for (int i = 1; i < routeIDs.size(); ++i) {
TimeInteger travelTime = data::TravelTime(data, routeIDs[i - 1], routeIDs[i]);
// locations are indexed from 0 to n-1,
TimeInteger serviceTime = data.getLocation(routeIDs[i - 1]).getServiceDuration();
TimeInteger startTW = data.getLocation(routeIDs[i - 1]).getTimeWindow().getStart();
reachTimes[i] = std::max(reachTimes[i - 1], startTW) + serviceTime + travelTime;
}
}
void TimeWindowConstraint::initReachTimes()
{
allRouteReachTimes = std::vector<ReachTimeVector>();
int i = 0;
for (const Route& route : getSolution().getRoutes())
{
// init and calculate reach time value
allRouteReachTimes.emplace_back();
computeReachTimes(getSolution().getData(), route.getRoute(), allRouteReachTimes.at(i));
++i;
}
}
// Copie le vecteur de reach time de la route concernée
// Insère les positions pickup/delivery
......@@ -30,14 +71,29 @@ bool TimeWindowConstraint::checkInsertion(const PDPTWData& data, const Pair & pa
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());
route.insert(route.begin() + pickupPos, pair.getPickup().getId());
std::cout << "\n";
for (auto pos : route)
{
std::cout << pos << " ";
}
std::cout << "\n";
// Compute new reach time
computeReachTimes(data, route, newReachTimes);
std::cout << "\n";
for (auto pos : newReachTimes)
{
std::cout << pos << " ";
}
std::cout << "\n";
// Check Time Windows
for (int i = 0; i < reachTimes.size(); ++i)
for (int i = 0; i < newReachTimes.size(); ++i)
{
if (! data.getLocation(route[i]).getTimeWindow().isValid(newReachTimes.at(i)) )
{
......@@ -47,20 +103,6 @@ bool TimeWindowConstraint::checkInsertion(const PDPTWData& data, const Pair & pa
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)
......@@ -71,8 +113,8 @@ void TimeWindowConstraint::ApplyModif(const PDPTWData& data, const Pair & pair,
// Adjust pickup and delivery
if (addPair)
{
routeIDs.insert(routeIDs.begin() + pickupPos, pair.getPickup().getId());
routeIDs.insert(routeIDs.begin() + deliveryPos, pair.getDelivery().getId());
routeIDs.insert(routeIDs.begin() + pickupPos, pair.getPickup().getId());
}
else
{
......@@ -88,11 +130,25 @@ void TimeWindowConstraint::ApplyModif(const PDPTWData& data, const Pair & pair,
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);
TimeInteger startTW = data.getLocation(routeIDs[i - 1]).getTimeWindow().getStart();
allRouteReachTimes[routeIndex][i] = std::max(allRouteReachTimes[routeIndex][i - 1], startTW) + serviceTime + travelTime;
}
}
/*
// 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 + previous service time + travel time)
for (int i = 1; i < routeIDs.size(); ++i) {
TimeInteger travelTime = data::TravelTime(data, routeIDs[i - 1], routeIDs[i]);
// locations are indexed from 0 to n-1,
TimeInteger serviceTime = data.getLocation(routeIDs[i - 1]).getServiceDuration();
TimeInteger startTW = data.getLocation(routeIDs[i - 1]).getTimeWindow().getStart();
reachTimes[i] = std::max(reachTimes[i - 1], startTW) + serviceTime + travelTime;
}
*/
bool TimeWindowConstraint::check(InsertPair const &op) const
{
......@@ -132,6 +188,25 @@ void TimeWindowConstraint::apply(RemoveRoute const &op)
allRouteReachTimes.erase(allRouteReachTimes.begin() + op.getRouteIndex());
}
const std::vector<TimeWindowConstraint::ReachTimeVector>& TimeWindowConstraint::getallRouteReachTimes() const {
return allRouteReachTimes;
}
void TimeWindowConstraint::print() const
{
std::cout << "Reach Times : \n";
int i = 0;
for (const auto& reachTimes : getallRouteReachTimes())
{
//std::cout << reachTimes.size() << ", ";
std::cout << "#" << i << " : ";
for (const TimeInteger reachTime : reachTimes)
{
std::cout << reachTime << ", ";
}
std::cout << "\n ";
i++;
}
std::cout << "\n";
}
......@@ -3,6 +3,7 @@
#include "lns/constraints/constraint.h"
#include "input/pair.h"
#include "input/time_window.h"
#include "lns/solution/route.h"
#include <vector>
/**
......@@ -14,15 +15,22 @@
class TimeWindowConstraint : public Constraint
{
public:
using ReachTimeVector = std::vector<TimeInteger>;
explicit TimeWindowConstraint(Solution const &);
TimeWindowConstraint(TimeWindowConstraint const &) = default;
~TimeWindowConstraint() override;
std::unique_ptr<Constraint> clone(Solution const &newOwningSolution) const override;
// Given the solution, calculate the reachTimes of each location.
// Modify the routeCapacities vector !
void initReachTimes();
private:
using ReachTimeVector = std::vector<TimeInteger>;
std::unique_ptr<Constraint> clone(Solution const &newOwningSolution) const override;
const std::vector<ReachTimeVector> & getallRouteReachTimes() const;
void print() const;
private:
/**
* For each route, store the reach time of each location
......
#pragma once
#include "atomic_modification.h"
#include <vector>
class Location;
......@@ -11,6 +11,7 @@ class Location;
class AtomicDestruction : public AtomicModification
{
public:
~AtomicDestruction() override = default;
/**
* @return the location ID removed from the solution.
*/
......
#pragma once
#include <vector>
#include "lns/constraints/constraint.h"
class Solution;
/**
......@@ -10,6 +13,8 @@ class Solution;
class AtomicModification
{
public:
virtual ~AtomicModification() = default;
/**
* Return the cost of the operation.
* @return a positive number if the solution cost is bigger after the modification.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment