Skip to content
Snippets Groups Projects
Commit 7e8b7040 authored by awenjb's avatar awenjb
Browse files

Update Capacity Constraint

- use a matrix to store the max capacity between every location
parent c15267e0
No related branches found
No related tags found
No related merge requests found
......@@ -12,7 +12,7 @@ int const ROUTE_PENALTY = 0;
int const NUMBER_VEHICLE = 50;
// Number of iterations for the algorithm or simulation to run.
int const NUMBER_ITERATION = 5000;
int const NUMBER_ITERATION = 100000;
// Flags
......@@ -33,4 +33,4 @@ bool const COMPLETE_STORE = true;
// Directories
std::string const OUTPUT_DIRECTORY = "./../../output/selection";
\ No newline at end of file
std::string const OUTPUT_DIRECTORY = "./../../output/test2";
\ No newline at end of file
#include "simulated_annealing_acceptance.h"
#pragma once
#include "acceptance_function.h"
class SimulatedAnnealingAcceptance : public AcceptanceFunction
{
};
\ No newline at end of file
#include "capacity_constraint.h"
#include "input/location.h"
#include "input/pdptw_data.h"
#include <unistd.h>
CapacityConstraint::CapacityConstraint(Solution const &solution) : Constraint(solution)
{
// Init an empty vector of reach time for all routes
routeCapacities.resize(getSolution().getRoutes().size());
// Init an empty maxCapacity
int n = getSolution().getData().getSize();
maxCapacity = std::vector<std::vector<double>>(n, std::vector<double>(n, 0));
}
std::unique_ptr<Constraint> CapacityConstraint::clone(Solution const &newOwningSolution) const
{
std::unique_ptr<CapacityConstraint> clonePtr = std::make_unique<CapacityConstraint>(newOwningSolution);
clonePtr->routeCapacities = routeCapacities;
clonePtr->maxCapacity = maxCapacity;
return clonePtr;
}
void CapacityConstraint::initRouteCapacities()
void CapacityConstraint::initMaxCapacity()
{
routeCapacities.clear();
// n = number of location (depot include)
int n = getSolution().getData().getSize();
maxCapacity.assign(n, std::vector<double>(n, 0));
for (Route const &route: getSolution().getRoutes())
{
CapacityVector capacities;
int currentCapacity = 0;
for (int locationID: route.getRoute())
int m = route.getSize();// depot + route
std::vector<int> routeIDs = route.getRoute();
std::vector<double> cumulated = std::vector<double>(m, 0.0);
// calculate the cumulated capacity
// + maxCharge from the depot to another location in the route
double maxCharge = 0;
for (int i = 0; i < m; i++)
{
currentCapacity += getSolution().getData().getLocation(locationID).getDemand();
capacities.push_back(currentCapacity);
int locationID = routeIDs.at(i);
double demand = getSolution().getData().getLocation(locationID).getDemand();
cumulated.at(i) = (i == 0) ? demand : cumulated.at(i - 1) + demand;
// Why i - 1 ?, the insertion is done before i, so we look at the state of the capacity at the previous location
if (i != 0)
{
maxCharge = std::max(maxCharge, cumulated.at(i - 1));
}
maxCapacity.at(0).at(locationID) = maxCharge;
}
routeCapacities.push_back(capacities);
// charge_max between i and j
for (int i = 0; i < m; i++)
{
maxCharge = 0;
int firstLocationID = routeIDs.at(i);
if (i != 0)
{
maxCharge = cumulated.at(i - 1);
}
for (int j = i; j < m; j++)
{
int secondLocationID = routeIDs.at(j);
if (j != 0)
{
maxCharge = std::max(maxCharge, cumulated.at(j - 1));
}
maxCapacity.at(firstLocationID).at(secondLocationID) = maxCharge;
}
}
}
}
std::vector<int> const &CapacityConstraint::getRouteCapacities(int routeIndex) const
void CapacityConstraint::updateMaxCapacity(Route const &route)
{
return routeCapacities.at(routeIndex);
}
std::vector<int> const &routeIDs = route.getRoute();
PDPTWData const &data = getSolution().getData();
int m = routeIDs.size();
/*
* Check if an insertion is feasible by computing new capacity values between the PickupPosition and DeliveryPosition.
* Assume the constraint is valid beforehand.
* O(n), n the size of the route
*/
bool CapacityConstraint::checkModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition) const
{
int max_capacity = getSolution().getData().getCapacity();
int demand = pair.getPickup().getDemand();
CapacityVector const &routeCapacity = getRouteCapacities(routeIndex);
// Recalculate cumulated
std::vector<double> cumulated(m, 0.0);
// if PickupPosition != DeliveryPosition, check from pickup-1 to delivery-1
// if PickupPosition is 0, don't check -1 ...
for (int i = std::max(0, PickupPosition - 1); i < DeliveryPosition; i++)
double maxCharge = 0;
for (int i = 0; i < m; ++i)
{
if (routeCapacity.at(i) + demand > max_capacity)
int locationID = routeIDs.at(i);
double demand = data.getLocation(locationID).getDemand();
cumulated.at(i) = (i == 0) ? demand : cumulated.at(i - 1) + demand;
// Why i - 1 ?, the insertion is done before i, so we look at the state of the capacity at the previous location
if (i != 0)
{
return false;
maxCharge = std::max(maxCharge, cumulated.at(i - 1));
}
maxCapacity.at(0).at(locationID) = maxCharge;
}
return true;
}
// update the route and the weight
void CapacityConstraint::applyModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition,
bool addPair)
{
if (addPair)
// Update maxCapacity
for (int i = 0; i < m; ++i)
{
// Insert new values
routeCapacities.at(routeIndex).insert(routeCapacities.at(routeIndex).begin() + DeliveryPosition, 0);
if (DeliveryPosition != 0)
{
routeCapacities.at(routeIndex).at(DeliveryPosition) +=
routeCapacities.at(routeIndex).at(DeliveryPosition - 1);
}
routeCapacities.at(routeIndex)
.insert(routeCapacities.at(routeIndex).begin() + PickupPosition, pair.getPickup().getDemand());
if (PickupPosition != 0)
{
routeCapacities.at(routeIndex).at(PickupPosition) += routeCapacities.at(routeIndex).at(PickupPosition - 1);
}
maxCharge = (i == 0) ? 0.0 : cumulated.at(i - 1);
int firstLocationID = routeIDs.at(i);
// Update value
for (int i = PickupPosition + 1; i < DeliveryPosition + 1; ++i)
auto maxCapacityRow = maxCapacity.at(firstLocationID);
for (int j = i; j < m; ++j)
{
routeCapacities.at(routeIndex).at(i) += pair.getPickup().getDemand();
int secondLocationID = routeIDs.at(j);
if (j != 0)
{
maxCharge = std::max(maxCharge, cumulated.at(j - 1));
}
maxCapacityRow.at(secondLocationID) = maxCharge;
}
}
else
}
bool CapacityConstraint::checkModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition) const
{
Solution const &solution = getSolution();
std::vector<int> const &routeIDs = solution.getRoutes().at(routeIndex).getRoute();
double vehicleCapacity = solution.getData().getCapacity();
if (PickupPosition > DeliveryPosition)
{
for (int i = PickupPosition + 1; i < DeliveryPosition; ++i)
{
routeCapacities.at(routeIndex).at(i) += pair.getDelivery().getDemand();
}
return false;
}
int m = routeIDs.size();
// remove pair
routeCapacities.at(routeIndex).erase(routeCapacities.at(routeIndex).begin() + DeliveryPosition);
routeCapacities.at(routeIndex).erase(routeCapacities.at(routeIndex).begin() + PickupPosition);
if (m == 0)
{
return true;
}
double demand = pair.getPickup().getDemand();
int lastLocationID = routeIDs.at(m - 1);
int pickupLocationID = (PickupPosition >= m) ? lastLocationID : routeIDs.at(PickupPosition);
int deliveryLocationID = (DeliveryPosition >= m) ? lastLocationID : routeIDs.at(DeliveryPosition);
return maxCapacity.at(pickupLocationID).at(deliveryLocationID) + demand <= vehicleCapacity;
}
void CapacityConstraint::applyModif(Pair const &pair, int routeIndex, int PickupPosition, int DeliveryPosition,
bool addPair)
{
updateMaxCapacity(getSolution().getRoute(routeIndex));
}
bool CapacityConstraint::check(InsertPair const &op) const
......@@ -118,8 +165,7 @@ bool CapacityConstraint::check(InsertRoute const &op) const
void CapacityConstraint::apply(InsertRoute const &op)
{
// add new empty route
routeCapacities.emplace_back();
}
bool CapacityConstraint::check(RemovePair const &op) const
......@@ -140,22 +186,18 @@ bool CapacityConstraint::check(RemoveRoute const &op) const
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 (auto const &capaVector: routeCapacities)
std::cout << "Max Capacity Matrix : " << std::endl;
for (auto const &maxVector: maxCapacity)
{
std::cout << "#" << i << " : ";
for (int const capa: capaVector)
for (int const maxCapa: maxVector)
{
std::cout << capa << ", ";
std::cout << maxCapa << "\t";
}
std::cout << "\n";
i++;
std::cout << std::endl;
}
}
......@@ -5,6 +5,7 @@
#include "lns/modification/route/insert_route.h"
#include "lns/modification/route/remove_route.h"
#include "lns/solution/solution.h"
#include "types.h"
#include <vector>
......@@ -17,10 +18,12 @@ public:
using CapacityVector = std::vector<int>;
private:
/**
* Store the used capacity value when leaving one location in each route.
* Store the maximum used capacity between two locations.
* A cell is not updated to 0 when the location is removed from a route.
*/
std::vector<CapacityVector> routeCapacities;
Matrix maxCapacity;
void apply(InsertPair const &op) override;
void apply(InsertRoute const &op) override;
......@@ -39,28 +42,22 @@ public:
std::unique_ptr<Constraint> clone(Solution const &newOwningSolution) const override;
/*
* Compute from scratch the routeCapacities vector.
* Compute from scratch the maxCapacity matrix.
*/
void initMaxCapacity();
/*
* Update MaxCapacity.
* Suppose the route has already been updated
*/
void initRouteCapacities();
void updateMaxCapacity(Route const &route);
/*
* 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 override;
......
......@@ -78,6 +78,35 @@ void simpleLNS(PDPTWData const &data, Solution &startingSolution)
{
output::exportToJson(result);
}
// Solution sol = result.getBestSolution();
// CapacityConstraint capa = CapacityConstraint(sol);
// capa.initRouteCapacities();
// capa.initMaxCapacity();
// capa.print();
// RemovePair rem = RemovePair(0, 1, 4, sol.getData().getPair(1));
// sol.applyDestructSolution(rem);
// sol.print();
// capa.updateMaxCapacity(sol.getData(), sol.getRoute(0));
// capa.print();
// int pickup = 8;
// int delivery = 8;
// std::cout << std::endl<< capa.checkModif(sol.getData().getPair(1), 0, pickup, delivery) << std::endl;
// std::cout << std::endl<< capa.checkModif2(sol.getData().getPair(1), 0, pickup, delivery) << std::endl;
// InsertPair add = InsertPair(0, pickup, delivery, sol.getData().getPair(1));
// sol.applyRecreateSolution(add);
// checker::checkAll(sol, sol.getData());
// capa.updateMaxCapacity(sol.getData(), sol.getRoute(0));
// capa.print();
}
int main(int argc, char **argv)
......@@ -91,12 +120,14 @@ int main(int argc, char **argv)
//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";
// PDPTWData data = parsing::parseJson(filepath);
// Solution startingSolution = Solution::emptySolution(data);
// simpleLNS(data, startingSolution);
PDPTWData data = parsing::parseJson(filepath);
Solution startingSolution = Solution::emptySolution(data);
simpleLNS(data, startingSolution);
// std::string path = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/selection";
// runAllInDirectory(path, simpleLNS);
std::string path = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/selection";
runAllInDirectory(path, simpleLNS);
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment