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

Some fixes

- call clean empty route for every new best solution
- add new elements in the config  file
- clean up some of the code
parent 4b30bfec
No related branches found
No related tags found
No related merge requests found
const int EXCLUSION_PENALTY = 1000000;
// Parameters
const int ROUTE_PENALTY = 1000;
// Penalty for excluding a certain pickup-delivery pair, aims to minimize the number of excluded pairs.
int const EXCLUSION_PENALTY = 1000000;
const int RANDOM_SEED = 100;
// Penalty applied to a route, aims to minimize the number of routes.
int const ROUTE_PENALTY = 0;
// Number of vehicles involved at the start of the optimization process (cannot be increased).
int const NUMBER_VEHICLE = 20;
// Number of iterations for the algorithm or simulation to run.
int const NUMBER_ITERATION = 500;
// Flags
// Flag indicating whether the random seed has been set (true means it is set).
bool const SEED_SET = true;
// Seed for random number generation (ensures reproducibility).
int const RANDOM_SEED = 100;
// Flag indicating whether we print during the execution.
bool const PRINT = true;
// Flag indicating whether the final solution is stored.
bool const STORE_SOLUTION = true;
const int NUMBER_VEHICLE = 20;
\ 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 "lns.h"
#include "lns/acceptance/acceptance_function.h"
#include "lns/operators/destruction/clean_empty_route.h"
#include "lns/operators/selector/operator_selector.h"
#include "output/solution_checker.h"
#include "config.h"
#include <chrono>
......@@ -81,7 +83,7 @@ output::LnsOutput lns::runLns(Solution const &initialSolution, OperatorSelector
LnsRuntimeData runtime = {actualSolution};
// temporary fixed iteration
int iterationMax = 100;
int iterationMax = NUMBER_ITERATION;
while (iterationMax > 0)
{
// Init iteration
......@@ -107,6 +109,10 @@ output::LnsOutput lns::runLns(Solution const &initialSolution, OperatorSelector
std::cout << "\n > new Best Solution \n";
checker::checkAll(candidateSolution, candidateSolution.getData(), false);
// remove empty route from the solution
CleanEmptyRoute clean = CleanEmptyRoute();
clean.destroySolution(candidateSolution);
runtime.bestSolution = candidateSolution;
opSelector.betterSolutionFound();
}
......
......@@ -5,7 +5,6 @@ CleanEmptyRoute::CleanEmptyRoute() {}
void CleanEmptyRoute::destroySolution(Solution &solution) const
{
std::cout << "Clean ";
for (int routeIndex = solution.getRoutes().size() - 1; routeIndex >= 0; --routeIndex)
{
if (solution.getRoute(routeIndex).getRoute().empty())
......
......@@ -11,7 +11,7 @@ void RandomDestroy::destroySolution(Solution &solution) const
{
std::cout << "RD ";
int nbRequests = solution.requestsFulFilledCount();
int nbRequests = solution.requestsFulfilledCount();
int actualNumberOfPairsToDestroy = std::min(nbRequests, numberOfPairsToDestroy);
int remainingPairToDelete = actualNumberOfPairsToDestroy;
......
#pragma once
#include <vector>
#include "input/pdptw_data.h"
#include "input/time_window.h"
/**
* Represent a route for the PDPTW
* A route does not include the depot at the begining and the end !
* Represents a route for the PDPTW.
* A route does not include the depot at the beginning and the end.
*/
class Route
{
private:
std::vector<int> route;
int cost;
public:
std::vector<int> route; // Stores the route as a sequence of location IDs.
int cost; // The cost of the route.
public:
// Constructors
Route();
Route(std::vector<int> route, int cost);
// Getters
int getCost() const;
const std::vector<int> & getRoute() const;
const std::vector<int>& getRoute() const;
// get Location
int getLocation(int index) const;
// Get the location at a given index in the route
int getLocation(int index) const;
/**
* Given a locationID, return the Index in the route.
* return -1 if no such location.
* Given a locationID, returns the index in the route.
* @return -1 if the locationID is not found in the route.
*/
int getIndex(int locationID) const;
/**
* Given the position of a location in a route, return the paired location position.
* Example, a pair of location ID 3 and 4 are in a route at position 7 and 18,
* getPairLocationPosition(7) must return 18 and vice versa.
* Given the position of a location in the route, returns the paired location position.
* Example: if location ID 3 and 4 are in the route at positions 7 and 18,
* getPairLocationPosition(7) should return 18 and vice versa.
*/
int getPairLocationPosition(int position, const PDPTWData &data) const;
int getPairLocationPosition(int position, const PDPTWData& data) const;
// Utility function to print the route details
void print() const;
/**
* Add a location index in the route (does not update the route cost)
* Adds a location index in the route at a specified position.
* Does not update the route cost.
*/
void insertAt(int locationIndex, int position);
/*
* Remove the element at "position"
*/
/**
* Removes the element at the specified position in the route.
*/
void deleteAt(int position);
// Returns the number of locations in the route
int getSize() const;
};
\ No newline at end of file
......@@ -30,7 +30,7 @@ void Solution::initRoutes()
routes.clear();
for (unsigned int i = 0; i < NUMBER_VEHICLE; ++i)
{
this->routes.emplace_back();
routes.emplace_back();
}
}
......@@ -44,8 +44,6 @@ void Solution::initConstraints()
void Solution::computeAndStoreSolutionCost()
{
rawCost = computeSolutionCost();
// add penalty for solution in the pairBank ?
totalCost = rawCost + computePenalisation();
}
......@@ -64,20 +62,19 @@ double Solution::computePenalisation() const
return getBank().size() * EXCLUSION_PENALTY + getNumberOfRoutes() * ROUTE_PENALTY;
}
int Solution::getNumberOfRoutes() const
int Solution::getNumberOfRoutes() const
{
int cpt = 0;
for (Route const &route : getRoutes())
int count = 0;
for (Route const &route: getRoutes())
{
if (!(route.getRoute().empty()))
if (!route.getRoute().empty())
{
cpt++;
count++;
}
}
return cpt;
return count;
}
void Solution::init()
{
initPairBank();
......@@ -98,7 +95,7 @@ Solution::Solution(PDPTWData const &data) : data(data)
Solution Solution::emptySolution(PDPTWData const &data)
{
Solution sol = Solution(data);
Solution sol(data);
return sol;
}
......@@ -111,19 +108,14 @@ Solution::Solution(Solution const &rhs) : Solution(rhs.getData())
Solution &Solution::operator=(Solution const &rhs)
{
if (&rhs == this)
{
return *this;
}
if (this == &rhs) return *this;
data = rhs.data;
rawCost = rhs.rawCost;
totalCost = rhs.totalCost;
pairBank = rhs.pairBank;
routes.clear();
routes = rhs.routes;
constraints.clear();
std::ranges::transform(rhs.constraints, std::back_inserter(constraints), [this](auto const &constraintPtr) {
return constraintPtr->clone(*this);
......@@ -132,21 +124,18 @@ Solution &Solution::operator=(Solution const &rhs)
return *this;
}
Solution::Solution(Solution &&sol) noexcept : data(sol.data)
Solution::Solution(Solution &&sol) noexcept : data(std::move(sol.data))
{
*this = std::move(sol);
}
Solution &Solution::operator=(Solution &&sol) noexcept
{
if (&sol == this)
{
return *this;
}
if (this == &sol) return *this;
data = sol.data;
rawCost = sol.rawCost;
totalCost = sol.totalCost;
data = std::move(sol.data);
rawCost = std::move(sol.rawCost);
totalCost = std::move(sol.totalCost);
pairBank = std::move(sol.pairBank);
routes = std::move(sol.routes);
......@@ -225,7 +214,7 @@ std::vector<std::unique_ptr<Constraint>> const &Solution::getConstraints() const
return constraints;
}
int Solution::requestsFulFilledCount() const
int Solution::requestsFulfilledCount() const
{
int count = 0;
for (Route const &route: getRoutes())
......@@ -256,34 +245,30 @@ unsigned int Solution::missingPairCount() const
return pairBank.size();
}
bool Solution::checkModification(AtomicRecreation const &modification) const
{
//std::cout << "--- Check Modification Validity : ";
ModificationCheckVariant const &checkVariant = modification.asCheckVariant();
// visitor pattern
for (std::unique_ptr<Constraint> const &constraint: constraints)
for (auto const &constraint: constraints)
{
if (!constraint->checkVariant(checkVariant))
{
//std::cout << "\n";
return false;
}
}
//std::cout << "\n";
return true;
}
void Solution::beforeApplyModification(AtomicModification &modification)
{
// pre modification check
// Pre-modification check
check();
}
void Solution::afterApplyModification(AtomicModification &modification)
{
// constraint status update
for (std::unique_ptr<Constraint> &constraint: constraints)
// Constraint status update
for (auto &constraint: constraints)
{
constraint->applyVariant(modification.asApplyVariant());
}
......@@ -292,9 +277,9 @@ void Solution::afterApplyModification(AtomicModification &modification)
void Solution::applyRecreateSolution(AtomicRecreation &modification)
{
beforeApplyModification(modification);
modification.modifySolution(*this);
// we update the request bank
// Update the request bank
if (int pairID = modification.getAddedPairs())
{
pairBank.erase(std::ranges::find(pairBank, pairID));
......@@ -306,12 +291,10 @@ void Solution::applyRecreateSolution(AtomicRecreation &modification)
void Solution::applyDestructSolution(AtomicDestruction &modification)
{
beforeApplyModification(modification);
modification.modifySolution(*this);
// updating request bank
std::vector<int> const &deletedPair = modification.getDeletedPairs();
//pairBank.reserve(pairBank.size() + deletedPair.size());
// Update the request bank
std::vector<int> const &deletedPair = modification.getDeletedPairs();
pairBank.insert(pairBank.end(), deletedPair.begin(), deletedPair.end());
afterApplyModification(modification);
......@@ -324,17 +307,16 @@ void Solution::check() const
void Solution::print() const
{
std::cout << "\nRawCost : " << rawCost << "\n"
<< "TotalCost : " << totalCost << "\n";
std::cout << "Pair Bank : \n";
std::cout << "\nRawCost: " << rawCost << "\n"
<< "TotalCost: " << totalCost << "\n";
std::cout << "Pair Bank:\n";
for (int const id: getBank())
{
std::cout << id << ", ";
}
std::cout << "\nRoutes : \n";
std::cout << "\nRoutes:\n";
int i = 0;
for (Route const &route: getRoutes())
{
......@@ -343,10 +325,11 @@ void Solution::print() const
++i;
}
std::cout << "Constraints : \n";
for (std::unique_ptr<Constraint> const &constraint: constraints)
std::cout << "Constraints:\n";
for (auto const &constraint: constraints)
{
constraint->print();
}
std::cout << "\n";
}
\ No newline at end of file
}
......@@ -6,6 +6,7 @@
#include "route.h"
#include <iostream>
#include <memory>
#include <spdlog/spdlog.h>
#include <vector>
......@@ -15,8 +16,8 @@ class AtomicDestruction;
class TimeWindowConstraint;
class CapacityConstraint;
/**
* Represent a solution of PDPTW
/*
* Represents a solution of the PDPTW problem.
*/
class Solution
{
......@@ -24,135 +25,169 @@ public:
using PairBank = std::vector<int>;
private:
std::reference_wrapper<PDPTWData const> data;
//PDPTWData const &data;
/*
* Store IDs of a pairs (Pickup & Delivery) that are not assigned yet to a route.
*/
PairBank pairBank;
/*
* Vector of routes representing the solution
*/
std::vector<Route> routes;
std::reference_wrapper<const PDPTWData> data;// Reference to PDPTW data
PairBank pairBank; // Unassigned pairs (Pickup & Delivery)
std::vector<Route> routes; // Routes in the solution
double rawCost;
double totalCost;
std::vector<std::unique_ptr<Constraint>> constraints;
public:
//========CONSTRUCTORS, COPY, MOVE, DESTRUCTORS===========
/**
* Expected way to construct a solution.
* Generate an empty solution with all pairs in the pairBank and one empty route.
/*
* Creates an empty solution with all pairs in the pairBank and one empty route.
*/
static Solution emptySolution(PDPTWData const &data);
/**
* In depth copy of the solution
/*
* In-depth copy of the solution.
*/
Solution(Solution const &);
/**
* In depth copy of the solution
/*
* Copy assignment.
*/
Solution &operator=(Solution const &);
/*
* Move constructor.
*/
Solution(Solution &&) noexcept;
/*
* Move assignment.
*/
Solution &operator=(Solution &&) noexcept;
/*
* Destructor.
*/
~Solution() noexcept;
/*
* Constructs a solution with given data.
*/
explicit Solution(PDPTWData const &data);
/**
* For testing/debugging.
* Use emptySolution(const PDPTWData &data) to create an initial empty solution.
/*
* Constructs a solution with specified parameters.
*/
Solution(PDPTWData const &data, Solution::PairBank pairbank, std::vector<Route> routes, double routeCost,
double totalCost);
Solution(PDPTWData const &data, PairBank pairbank, std::vector<Route> routes, double routeCost, double totalCost);
/*
* Returns the pair bank.
*/
PairBank const &getBank() const;
/*
* Returns the pair bank.
*/
PairBank const &getPairBank() const;
/*
* Returns a mutable reference to the pair bank.
*/
PairBank &getPairBank();
/*
* Returns the list of routes.
*/
std::vector<Route> const &getRoutes() const;
/*
* Returns a mutable reference to a specific route.
*/
Route &getRoute(int routeIndex);
/*
* Returns a constant reference to a specific route.
*/
Route const &getRoute(int routeIndex) const;
/*
* Returns the PDPTW data reference.
*/
PDPTWData const &getData() const;
/*
* Returns the raw cost of the solution.
*/
double getRawCost() const;
/*
* Returns the total cost of the solution.
*/
double getCost() const;
/*
* Returns the number of routes.
*/
int getNumberOfRoutes() const;
/*
* Returns the count of missing pairs.
*/
unsigned int missingPairCount() const;
/*
* Returns the constraints applied to the solution.
*/
std::vector<std::unique_ptr<Constraint>> const &getConstraints() const;
/**
* Return the route index associated to the given location ID.
* -1 if the location is not in a route.
/*
* Returns the route index associated with a given location ID, or -1 if not in a route.
*/
int getRouteIDOf(int locationID) const;
/**
* Return the number of fullfilled requests.
* The solution must be consistent !
* (compute this number by looking at the size of each routes)
/*
* Returns the number of fulfilled requests.
*/
int requestsFulFilledCount() const;
/**
* Check that the modification is valid regarding all the constraints
* @param modification
* @return true if the modification is valid
int requestsFulfilledCount() const;
/*
* Checks if the modification is valid according to all constraints.
*/
bool checkModification(AtomicRecreation const &modification) const;
// using solution checker to verify that the solution is correct. Most used for debug as it is correctness oriented and not performance oriented
/*
* Verifies the correctness of the solution, mainly for debugging.
*/
void check() const;
/**
* Pre modification check.
* @param modification Must be a valid modification.
/*
* Pre-modification check. The modification must be valid.
*/
void beforeApplyModification(AtomicModification &modification);
/**
* Update constraints, it is expected that the solution has already been modified.
* @param modification Must be a valid modification.
/*
* Updates constraints after modification is applied.
*/
void afterApplyModification(AtomicModification &modification);
/**
* Apply the given the modification on the solution. Does not check validity.
* @param modification Must be a valid recreation.
/*
* Applies recreation modification to the solution without validity checks.
*/
void applyRecreateSolution(AtomicRecreation &modification);
/**
* Apply the given the modification on the solution. Does not check validity.
* @param modification Must be a destruction.
/*
* Applies destruction modification to the solution without validity checks.
*/
void applyDestructSolution(AtomicDestruction &modification);
/*
* Computes and returns the penalty value.
*/
double computePenalisation() const;
// For route modification
/*
* Returns a mutable reference to the routes.
*/
std::vector<Route> &getRoutes();
Route &getRoute(int routeIndex);
/*
* Prints the solution details.
*/
void print() const;
/*
* Computes and stores the total solution cost.
*/
void computeAndStoreSolutionCost();
private:
/**
* Does the initialisation of the object, called by the constructor
/*
* Initializes the object, called by the constructor.
*/
void init();
/**
* Init/reset the constraints of the problem
/*
* Initializes or resets the problem constraints.
*/
void initConstraints();
/*
* Initializes the routes.
*/
void initRoutes();
/*
* Initializes the pair bank.
*/
void initPairBank();
/**
* Compute the cost of the solution (routes cost)
/*
* Computes the total cost of the solution.
*/
double computeSolutionCost() const;
};
\ No newline at end of file
double computeSolutionCost() const;
};
......@@ -49,7 +49,7 @@ void simpleLNS(PDPTWData const &data, Solution &startingSolution)
int pairs = requests * 2 / 100;
int manyPairs = requests * 40 / 100;
// threshold function to do
// threshold function
ThresholdAcceptance acceptor(0.05);
// lns operators
......@@ -73,11 +73,7 @@ void simpleLNS(PDPTWData const &data, Solution &startingSolution)
// run lns
output::LnsOutput result = lns::runLns(startingSolution, smallLargeSelector, acceptor);
Solution sol = result.getBestSolution();
CleanEmptyRoute clean = CleanEmptyRoute();
clean.destroySolution(sol);
sol.print();
result.getBestSolution().print();
}
int main(int argc, char **argv)
......@@ -87,7 +83,7 @@ int main(int argc, char **argv)
///////////////////////////////////////////////////////////////////////
//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/pdp_100/lc101.json";
std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/pdp_100/lc103.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";
......
......@@ -19,5 +19,4 @@ using TimeInteger = double;
TimeInteger constexpr UNDEF_TIMESTAMP = std::numeric_limits<TimeInteger>::max();
using Matrix = std::vector<std::vector<double>>;
using Matrix = std::vector<std::vector<double>>;
......@@ -7,7 +7,7 @@
namespace// anonymous namespace
{
std::mt19937_64 randomGenerator;// NOLINT(*-msc51-cpp) => deterministic random!
bool seedSet = false;
bool seedSet = SEED_SET;
std::uniform_real_distribution<> distribution(0, 1);
}// namespace
......
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