Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • a24jacqb/pdptw-main
1 result
Show changes
Commits on Source (3)
  • awenjb's avatar
    Add Route Penalty · 4b30bfec
    awenjb authored
    4b30bfec
  • awenjb's avatar
    Some fixes · 7c427502
    awenjb authored
    - call clean empty route for every new best solution
    - add new elements in the config  file
    - clean up some of the code
    7c427502
  • awenjb's avatar
    Add code to run multiple instances · e462496a
    awenjb authored
    - add code to run multiple instances and store the result in a specific directory
    - add new config
    - add a complete json output
    e462496a
Showing
with 341 additions and 181 deletions
...@@ -49,6 +49,7 @@ add_executable(pdptw src/mains/main.cpp ...@@ -49,6 +49,7 @@ add_executable(pdptw src/mains/main.cpp
src/lns/operators/selector/small_large_selector.cpp src/lns/operators/selector/small_large_selector.cpp
src/lns/lns.cpp src/lns/lns.cpp
src/utils.cpp src/utils.cpp
src/output/run.cpp
) )
target_link_libraries(pdptw PRIVATE CLI11::CLI11 nlohmann_json::nlohmann_json spdlog::spdlog) target_link_libraries(pdptw PRIVATE CLI11::CLI11 nlohmann_json::nlohmann_json spdlog::spdlog)
......
...@@ -188,7 +188,7 @@ end ...@@ -188,7 +188,7 @@ end
function euclidean_distance(x1, y1, x2, y2) function euclidean_distance(x1, y1, x2, y2)
return round(sqrt((x2 - x1)^2 + (y2 - y1)^2), digits=2) return sqrt((x2 - x1)^2 + (y2 - y1)^2)
end end
......
const int EXCLUSION_PENALTY = 100; #include <string>
const int RANDOM_SEED = 100; // Parameters
const int NUMBER_VEHICLE = 20; // Penalty for excluding a certain pickup-delivery pair, aims to minimize the number of excluded pairs.
\ No newline at end of file int const EXCLUSION_PENALTY = 1000000;
// 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;
// Flag indicating whether the solution is stored with complete information or not.
bool const COMPLETE_STORE = true;
// Directories
std::string const OUTPUT_DIRECTORY = "./../../output/100_complete";
\ 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.h"
#include "lns/acceptance/acceptance_function.h" #include "lns/acceptance/acceptance_function.h"
#include "lns/operators/destruction/clean_empty_route.h"
#include "lns/operators/selector/operator_selector.h" #include "lns/operators/selector/operator_selector.h"
#include "output/solution_checker.h" #include "output/solution_checker.h"
#include "config.h"
#include <chrono> #include <chrono>
...@@ -81,7 +83,7 @@ output::LnsOutput lns::runLns(Solution const &initialSolution, OperatorSelector ...@@ -81,7 +83,7 @@ output::LnsOutput lns::runLns(Solution const &initialSolution, OperatorSelector
LnsRuntimeData runtime = {actualSolution}; LnsRuntimeData runtime = {actualSolution};
// temporary fixed iteration // temporary fixed iteration
int iterationMax = 100; int iterationMax = NUMBER_ITERATION;
while (iterationMax > 0) while (iterationMax > 0)
{ {
// Init iteration // Init iteration
...@@ -107,6 +109,10 @@ output::LnsOutput lns::runLns(Solution const &initialSolution, OperatorSelector ...@@ -107,6 +109,10 @@ output::LnsOutput lns::runLns(Solution const &initialSolution, OperatorSelector
std::cout << "\n > new Best Solution \n"; std::cout << "\n > new Best Solution \n";
checker::checkAll(candidateSolution, candidateSolution.getData(), false); checker::checkAll(candidateSolution, candidateSolution.getData(), false);
// remove empty route from the solution
CleanEmptyRoute clean = CleanEmptyRoute();
clean.destroySolution(candidateSolution);
runtime.bestSolution = candidateSolution; runtime.bestSolution = candidateSolution;
opSelector.betterSolutionFound(); opSelector.betterSolutionFound();
} }
......
...@@ -5,7 +5,6 @@ CleanEmptyRoute::CleanEmptyRoute() {} ...@@ -5,7 +5,6 @@ CleanEmptyRoute::CleanEmptyRoute() {}
void CleanEmptyRoute::destroySolution(Solution &solution) const void CleanEmptyRoute::destroySolution(Solution &solution) const
{ {
std::cout << "Clean ";
for (int routeIndex = solution.getRoutes().size() - 1; routeIndex >= 0; --routeIndex) for (int routeIndex = solution.getRoutes().size() - 1; routeIndex >= 0; --routeIndex)
{ {
if (solution.getRoute(routeIndex).getRoute().empty()) if (solution.getRoute(routeIndex).getRoute().empty())
......
...@@ -11,7 +11,7 @@ void RandomDestroy::destroySolution(Solution &solution) const ...@@ -11,7 +11,7 @@ void RandomDestroy::destroySolution(Solution &solution) const
{ {
std::cout << "RD "; std::cout << "RD ";
int nbRequests = solution.requestsFulFilledCount(); int nbRequests = solution.requestsFulfilledCount();
int actualNumberOfPairsToDestroy = std::min(nbRequests, numberOfPairsToDestroy); int actualNumberOfPairsToDestroy = std::min(nbRequests, numberOfPairsToDestroy);
int remainingPairToDelete = actualNumberOfPairsToDestroy; int remainingPairToDelete = actualNumberOfPairsToDestroy;
......
#pragma once #pragma once
#include <vector> #include <vector>
#include "input/pdptw_data.h" #include "input/pdptw_data.h"
#include "input/time_window.h" #include "input/time_window.h"
/** /**
* Represent a route for the PDPTW * Represents a route for the PDPTW.
* A route does not include the depot at the begining and the end ! * A route does not include the depot at the beginning and the end.
*/ */
class Route class Route
{ {
private: private:
std::vector<int> route; std::vector<int> route; // Stores the route as a sequence of location IDs.
int cost; int cost; // The cost of the route.
public:
public:
// Constructors
Route(); Route();
Route(std::vector<int> route, int cost); Route(std::vector<int> route, int cost);
// Getters
int getCost() const; int getCost() const;
const std::vector<int> & getRoute() const; const std::vector<int>& getRoute() const;
// get Location // Get the location at a given index in the route
int getLocation(int index) const; int getLocation(int index) const;
/** /**
* Given a locationID, return the Index in the route. * Given a locationID, returns the index in the route.
* return -1 if no such location. * @return -1 if the locationID is not found in the route.
*/ */
int getIndex(int locationID) const; int getIndex(int locationID) const;
/** /**
* Given the position of a location in a route, return the paired location position. * Given the position of a location in the route, returns the paired location position.
* Example, a pair of location ID 3 and 4 are in a route at position 7 and 18, * Example: if location ID 3 and 4 are in the route at positions 7 and 18,
* getPairLocationPosition(7) must return 18 and vice versa. * 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; 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); 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); void deleteAt(int position);
// Returns the number of locations in the route
int getSize() const; int getSize() const;
}; };
\ No newline at end of file
...@@ -30,7 +30,7 @@ void Solution::initRoutes() ...@@ -30,7 +30,7 @@ void Solution::initRoutes()
routes.clear(); routes.clear();
for (unsigned int i = 0; i < NUMBER_VEHICLE; ++i) for (unsigned int i = 0; i < NUMBER_VEHICLE; ++i)
{ {
this->routes.emplace_back(); routes.emplace_back();
} }
} }
...@@ -44,8 +44,6 @@ void Solution::initConstraints() ...@@ -44,8 +44,6 @@ void Solution::initConstraints()
void Solution::computeAndStoreSolutionCost() void Solution::computeAndStoreSolutionCost()
{ {
rawCost = computeSolutionCost(); rawCost = computeSolutionCost();
// add penalty for solution in the pairBank ?
totalCost = rawCost + computePenalisation(); totalCost = rawCost + computePenalisation();
} }
...@@ -61,7 +59,20 @@ double Solution::computeSolutionCost() const ...@@ -61,7 +59,20 @@ double Solution::computeSolutionCost() const
double Solution::computePenalisation() const double Solution::computePenalisation() const
{ {
return getBank().size() * EXCLUSION_PENALTY; return getBank().size() * EXCLUSION_PENALTY + getNumberOfRoutes() * ROUTE_PENALTY;
}
int Solution::getNumberOfRoutes() const
{
int count = 0;
for (Route const &route: getRoutes())
{
if (!route.getRoute().empty())
{
count++;
}
}
return count;
} }
void Solution::init() void Solution::init()
...@@ -84,7 +95,7 @@ Solution::Solution(PDPTWData const &data) : data(data) ...@@ -84,7 +95,7 @@ Solution::Solution(PDPTWData const &data) : data(data)
Solution Solution::emptySolution(PDPTWData const &data) Solution Solution::emptySolution(PDPTWData const &data)
{ {
Solution sol = Solution(data); Solution sol(data);
return sol; return sol;
} }
...@@ -97,19 +108,14 @@ Solution::Solution(Solution const &rhs) : Solution(rhs.getData()) ...@@ -97,19 +108,14 @@ Solution::Solution(Solution const &rhs) : Solution(rhs.getData())
Solution &Solution::operator=(Solution const &rhs) Solution &Solution::operator=(Solution const &rhs)
{ {
if (&rhs == this) if (this == &rhs) return *this;
{
return *this;
}
data = rhs.data; data = rhs.data;
rawCost = rhs.rawCost; rawCost = rhs.rawCost;
totalCost = rhs.totalCost; totalCost = rhs.totalCost;
pairBank = rhs.pairBank; pairBank = rhs.pairBank;
routes.clear();
routes = rhs.routes; routes = rhs.routes;
constraints.clear(); constraints.clear();
std::ranges::transform(rhs.constraints, std::back_inserter(constraints), [this](auto const &constraintPtr) { std::ranges::transform(rhs.constraints, std::back_inserter(constraints), [this](auto const &constraintPtr) {
return constraintPtr->clone(*this); return constraintPtr->clone(*this);
...@@ -118,21 +124,18 @@ Solution &Solution::operator=(Solution const &rhs) ...@@ -118,21 +124,18 @@ Solution &Solution::operator=(Solution const &rhs)
return *this; return *this;
} }
Solution::Solution(Solution &&sol) noexcept : data(sol.data) Solution::Solution(Solution &&sol) noexcept : data(std::move(sol.data))
{ {
*this = std::move(sol); *this = std::move(sol);
} }
Solution &Solution::operator=(Solution &&sol) noexcept Solution &Solution::operator=(Solution &&sol) noexcept
{ {
if (&sol == this) if (this == &sol) return *this;
{
return *this;
}
data = sol.data; data = std::move(sol.data);
rawCost = sol.rawCost; rawCost = std::move(sol.rawCost);
totalCost = sol.totalCost; totalCost = std::move(sol.totalCost);
pairBank = std::move(sol.pairBank); pairBank = std::move(sol.pairBank);
routes = std::move(sol.routes); routes = std::move(sol.routes);
...@@ -211,7 +214,7 @@ std::vector<std::unique_ptr<Constraint>> const &Solution::getConstraints() const ...@@ -211,7 +214,7 @@ std::vector<std::unique_ptr<Constraint>> const &Solution::getConstraints() const
return constraints; return constraints;
} }
int Solution::requestsFulFilledCount() const int Solution::requestsFulfilledCount() const
{ {
int count = 0; int count = 0;
for (Route const &route: getRoutes()) for (Route const &route: getRoutes())
...@@ -242,34 +245,30 @@ unsigned int Solution::missingPairCount() const ...@@ -242,34 +245,30 @@ unsigned int Solution::missingPairCount() const
return pairBank.size(); return pairBank.size();
} }
bool Solution::checkModification(AtomicRecreation const &modification) const bool Solution::checkModification(AtomicRecreation const &modification) const
{ {
//std::cout << "--- Check Modification Validity : ";
ModificationCheckVariant const &checkVariant = modification.asCheckVariant(); ModificationCheckVariant const &checkVariant = modification.asCheckVariant();
// visitor pattern
for (std::unique_ptr<Constraint> const &constraint: constraints) for (auto const &constraint: constraints)
{ {
if (!constraint->checkVariant(checkVariant)) if (!constraint->checkVariant(checkVariant))
{ {
//std::cout << "\n";
return false; return false;
} }
} }
//std::cout << "\n";
return true; return true;
} }
void Solution::beforeApplyModification(AtomicModification &modification) void Solution::beforeApplyModification(AtomicModification &modification)
{ {
// pre modification check // Pre-modification check
check(); check();
} }
void Solution::afterApplyModification(AtomicModification &modification) void Solution::afterApplyModification(AtomicModification &modification)
{ {
// constraint status update // Constraint status update
for (std::unique_ptr<Constraint> &constraint: constraints) for (auto &constraint: constraints)
{ {
constraint->applyVariant(modification.asApplyVariant()); constraint->applyVariant(modification.asApplyVariant());
} }
...@@ -278,9 +277,9 @@ void Solution::afterApplyModification(AtomicModification &modification) ...@@ -278,9 +277,9 @@ void Solution::afterApplyModification(AtomicModification &modification)
void Solution::applyRecreateSolution(AtomicRecreation &modification) void Solution::applyRecreateSolution(AtomicRecreation &modification)
{ {
beforeApplyModification(modification); beforeApplyModification(modification);
modification.modifySolution(*this); modification.modifySolution(*this);
// we update the request bank
// Update the request bank
if (int pairID = modification.getAddedPairs()) if (int pairID = modification.getAddedPairs())
{ {
pairBank.erase(std::ranges::find(pairBank, pairID)); pairBank.erase(std::ranges::find(pairBank, pairID));
...@@ -292,12 +291,10 @@ void Solution::applyRecreateSolution(AtomicRecreation &modification) ...@@ -292,12 +291,10 @@ void Solution::applyRecreateSolution(AtomicRecreation &modification)
void Solution::applyDestructSolution(AtomicDestruction &modification) void Solution::applyDestructSolution(AtomicDestruction &modification)
{ {
beforeApplyModification(modification); beforeApplyModification(modification);
modification.modifySolution(*this); 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()); pairBank.insert(pairBank.end(), deletedPair.begin(), deletedPair.end());
afterApplyModification(modification); afterApplyModification(modification);
...@@ -310,17 +307,16 @@ void Solution::check() const ...@@ -310,17 +307,16 @@ void Solution::check() const
void Solution::print() const void Solution::print() const
{ {
std::cout << "\nRawCost : " << rawCost << "\n" std::cout << "\nRawCost: " << rawCost << "\n"
<< "TotalCost : " << totalCost << "\n"; << "TotalCost: " << totalCost << "\n";
std::cout << "Pair Bank : \n";
std::cout << "Pair Bank:\n";
for (int const id: getBank()) for (int const id: getBank())
{ {
std::cout << id << ", "; std::cout << id << ", ";
} }
std::cout << "\nRoutes : \n"; std::cout << "\nRoutes:\n";
int i = 0; int i = 0;
for (Route const &route: getRoutes()) for (Route const &route: getRoutes())
{ {
...@@ -329,10 +325,11 @@ void Solution::print() const ...@@ -329,10 +325,11 @@ void Solution::print() const
++i; ++i;
} }
std::cout << "Constraints : \n"; std::cout << "Constraints:\n";
for (std::unique_ptr<Constraint> const &constraint: constraints) for (auto const &constraint: constraints)
{ {
constraint->print(); constraint->print();
} }
std::cout << "\n"; std::cout << "\n";
} }
\ No newline at end of file
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "route.h" #include "route.h"
#include <iostream> #include <iostream>
#include <memory>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <vector> #include <vector>
...@@ -15,8 +16,8 @@ class AtomicDestruction; ...@@ -15,8 +16,8 @@ class AtomicDestruction;
class TimeWindowConstraint; class TimeWindowConstraint;
class CapacityConstraint; class CapacityConstraint;
/** /*
* Represent a solution of PDPTW * Represents a solution of the PDPTW problem.
*/ */
class Solution class Solution
{ {
...@@ -24,134 +25,169 @@ public: ...@@ -24,134 +25,169 @@ public:
using PairBank = std::vector<int>; using PairBank = std::vector<int>;
private: private:
std::reference_wrapper<PDPTWData const> data; std::reference_wrapper<const PDPTWData> data;// Reference to PDPTW data
//PDPTWData const &data; PairBank pairBank; // Unassigned pairs (Pickup & Delivery)
/* std::vector<Route> routes; // Routes in the solution
* 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;
double rawCost; double rawCost;
double totalCost; double totalCost;
std::vector<std::unique_ptr<Constraint>> constraints; std::vector<std::unique_ptr<Constraint>> constraints;
public: public:
//========CONSTRUCTORS, COPY, MOVE, DESTRUCTORS=========== /*
/** * Creates an empty solution with all pairs in the pairBank and one empty route.
* Expected way to construct a solution.
* Generate an empty solution with all pairs in the pairBank and one empty route.
*/ */
static Solution emptySolution(PDPTWData const &data); static Solution emptySolution(PDPTWData const &data);
/**
* In depth copy of the solution /*
* In-depth copy of the solution.
*/ */
Solution(Solution const &); Solution(Solution const &);
/** /*
* In depth copy of the solution * Copy assignment.
*/ */
Solution &operator=(Solution const &); Solution &operator=(Solution const &);
/*
* Move constructor.
*/
Solution(Solution &&) noexcept; Solution(Solution &&) noexcept;
/*
* Move assignment.
*/
Solution &operator=(Solution &&) noexcept; Solution &operator=(Solution &&) noexcept;
/*
* Destructor.
*/
~Solution() noexcept; ~Solution() noexcept;
/*
* Constructs a solution with given data.
*/
explicit Solution(PDPTWData const &data); explicit Solution(PDPTWData const &data);
/*
/** * Constructs a solution with specified parameters.
* For testing/debugging.
* Use emptySolution(const PDPTWData &data) to create an initial empty solution.
*/ */
Solution(PDPTWData const &data, Solution::PairBank pairbank, std::vector<Route> routes, double routeCost, Solution(PDPTWData const &data, PairBank pairbank, std::vector<Route> routes, double routeCost, double totalCost);
double totalCost);
/*
* Returns the pair bank.
*/
PairBank const &getBank() const; PairBank const &getBank() const;
/*
* Returns the pair bank.
*/
PairBank const &getPairBank() const; PairBank const &getPairBank() const;
/*
* Returns a mutable reference to the pair bank.
*/
PairBank &getPairBank(); PairBank &getPairBank();
/*
* Returns the list of routes.
*/
std::vector<Route> const &getRoutes() const; 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; Route const &getRoute(int routeIndex) const;
/*
* Returns the PDPTW data reference.
*/
PDPTWData const &getData() const; PDPTWData const &getData() const;
/*
* Returns the raw cost of the solution.
*/
double getRawCost() const; double getRawCost() const;
/*
* Returns the total cost of the solution.
*/
double getCost() const; double getCost() const;
/*
* Returns the number of routes.
*/
int getNumberOfRoutes() const;
/*
* Returns the count of missing pairs.
*/
unsigned int missingPairCount() const; unsigned int missingPairCount() const;
/*
* Returns the constraints applied to the solution.
*/
std::vector<std::unique_ptr<Constraint>> const &getConstraints() const; std::vector<std::unique_ptr<Constraint>> const &getConstraints() const;
/** /*
* Return the route index associated to the given location ID. * Returns the route index associated with a given location ID, or -1 if not in a route.
* -1 if the location is not in a route.
*/ */
int getRouteIDOf(int locationID) const; int getRouteIDOf(int locationID) const;
/*
/** * Returns the number of fulfilled requests.
* Return the number of fullfilled requests.
* The solution must be consistent !
* (compute this number by looking at the size of each routes)
*/ */
int requestsFulFilledCount() const; int requestsFulfilledCount() const;
/*
/** * Checks if the modification is valid according to all constraints.
* Check that the modification is valid regarding all the constraints
* @param modification
* @return true if the modification is valid
*/ */
bool checkModification(AtomicRecreation const &modification) const; 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; void check() const;
/** /*
* Pre modification check. * Pre-modification check. The modification must be valid.
* @param modification Must be a valid modification.
*/ */
void beforeApplyModification(AtomicModification &modification); void beforeApplyModification(AtomicModification &modification);
/*
/** * Updates constraints after modification is applied.
* Update constraints, it is expected that the solution has already been modified.
* @param modification Must be a valid modification.
*/ */
void afterApplyModification(AtomicModification &modification); void afterApplyModification(AtomicModification &modification);
/** /*
* Apply the given the modification on the solution. Does not check validity. * Applies recreation modification to the solution without validity checks.
* @param modification Must be a valid recreation.
*/ */
void applyRecreateSolution(AtomicRecreation &modification); void applyRecreateSolution(AtomicRecreation &modification);
/*
/** * Applies destruction modification to the solution without validity checks.
* Apply the given the modification on the solution. Does not check validity.
* @param modification Must be a destruction.
*/ */
void applyDestructSolution(AtomicDestruction &modification); void applyDestructSolution(AtomicDestruction &modification);
/*
* Computes and returns the penalty value.
*/
double computePenalisation() const; double computePenalisation() const;
/*
// For route modification * Returns a mutable reference to the routes.
*/
std::vector<Route> &getRoutes(); std::vector<Route> &getRoutes();
Route &getRoute(int routeIndex); /*
* Prints the solution details.
*/
void print() const; void print() const;
/*
* Computes and stores the total solution cost.
*/
void computeAndStoreSolutionCost(); void computeAndStoreSolutionCost();
private: private:
/** /*
* Does the initialisation of the object, called by the constructor * Initializes the object, called by the constructor.
*/ */
void init(); void init();
/*
/** * Initializes or resets the problem constraints.
* Init/reset the constraints of the problem
*/ */
void initConstraints(); void initConstraints();
/*
* Initializes the routes.
*/
void initRoutes(); void initRoutes();
/*
* Initializes the pair bank.
*/
void initPairBank(); void initPairBank();
/*
/** * Computes the total cost of the solution.
* Compute the cost of the solution (routes cost)
*/ */
double computeSolutionCost() const; double computeSolutionCost() const;
};
};
\ No newline at end of file
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include "output/solution_checker.h" #include "output/solution_checker.h"
#include "output/solution_exporter.h" #include "output/solution_exporter.h"
#include "types.h" #include "types.h"
#include "output/run.h"
#include "config.h"
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
...@@ -49,7 +51,7 @@ void simpleLNS(PDPTWData const &data, Solution &startingSolution) ...@@ -49,7 +51,7 @@ void simpleLNS(PDPTWData const &data, Solution &startingSolution)
int pairs = requests * 2 / 100; int pairs = requests * 2 / 100;
int manyPairs = requests * 40 / 100; int manyPairs = requests * 40 / 100;
// threshold function to do // threshold function
ThresholdAcceptance acceptor(0.05); ThresholdAcceptance acceptor(0.05);
// lns operators // lns operators
...@@ -73,11 +75,10 @@ void simpleLNS(PDPTWData const &data, Solution &startingSolution) ...@@ -73,11 +75,10 @@ void simpleLNS(PDPTWData const &data, Solution &startingSolution)
// run lns // run lns
output::LnsOutput result = lns::runLns(startingSolution, smallLargeSelector, acceptor); output::LnsOutput result = lns::runLns(startingSolution, smallLargeSelector, acceptor);
Solution sol = result.getBestSolution(); if (STORE_SOLUTION)
{
CleanEmptyRoute clean = CleanEmptyRoute(); output::exportToJson(result);
clean.destroySolution(sol); }
sol.print();
} }
int main(int argc, char **argv) int main(int argc, char **argv)
...@@ -86,14 +87,17 @@ int main(int argc, char **argv) ...@@ -86,14 +87,17 @@ 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/n100/bar-n100-1.json";
//std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/pdp_100/lc102.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/Nantes_1.json";
//std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/n5000/bar-n5000-1.json"; //std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/n5000/bar-n5000-1.json";
PDPTWData data = parsing::parseJson(filepath); // PDPTWData data = parsing::parseJson(filepath);
Solution startingSolution = Solution::emptySolution(data); // Solution startingSolution = Solution::emptySolution(data);
simpleLNS(data, startingSolution); // simpleLNS(data, startingSolution);
std::string path = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/pdp_100";
runAllInDirectory(path, simpleLNS);
return 0; return 0;
} }
...@@ -20,8 +20,3 @@ unsigned long output::LnsOutput::getTimeSpent() const ...@@ -20,8 +20,3 @@ unsigned long output::LnsOutput::getTimeSpent() const
output::LnsOutput::LnsOutput(Solution &&bestSolution, unsigned int numberOfIteration, unsigned long timeSpent) output::LnsOutput::LnsOutput(Solution &&bestSolution, unsigned int numberOfIteration, unsigned long timeSpent)
: bestSolution(std::move(bestSolution)), numberOfIteration(numberOfIteration), timeSpent(timeSpent) : bestSolution(std::move(bestSolution)), numberOfIteration(numberOfIteration), timeSpent(timeSpent)
{} {}
void output::LnsOutput::writeSolutionToFile() const
{
output::exportToJson(getBestSolution());
}
\ No newline at end of file
...@@ -15,6 +15,5 @@ namespace output ...@@ -15,6 +15,5 @@ namespace output
unsigned int getNumberOfIteration() const; unsigned int getNumberOfIteration() const;
Solution const &getBestSolution() const; Solution const &getBestSolution() const;
unsigned long getTimeSpent() const; unsigned long getTimeSpent() const;
void writeSolutionToFile() const;
}; };
}// namespace output }// namespace output
\ No newline at end of file
#include "run.h"
#include "input/json_parser.h"
#include "lns/lns.h"
namespace fs = std::filesystem;
std::vector<std::string> getFilesInDirectory(std::string const &directoryPath)
{
std::vector<std::string> filePaths;
try
{
for (auto const &entry: fs::directory_iterator(directoryPath))
{
if (entry.is_regular_file())
{
filePaths.push_back(entry.path().string());
}
}
} catch (std::filesystem::filesystem_error const &e)
{
std::cerr << "Error : " << e.what() << std::endl;
}
return filePaths;
}
void runAllInDirectory(std::string const &directoryPath, std::function<void(PDPTWData &, Solution &)> function)
{
std::vector<std::string> files = getFilesInDirectory(directoryPath);
for (std::string file: files)
{
PDPTWData data = parsing::parseJson(file);
Solution startingSolution = Solution::emptySolution(data);
function(data, startingSolution);
}
}
#pragma once
#include "input/pdptw_data.h"
#include "lns/solution/solution.h"
#include <functional>
#include <iostream>
#include <vector>
#include <string>
#include <filesystem>
std::vector<std::string> getFilesInDirectory(const std::string& directoryPath);
void runAllInDirectory(const std::string& directoryPath, std::function<void(PDPTWData &, Solution &)> function);
\ No newline at end of file
#include "solution_exporter.h" #include "solution_exporter.h"
#include "config.h"
std::string getCurrentDate() std::string getCurrentDate()
{ {
std::time_t t = std::time(nullptr); std::time_t t = std::time(nullptr);
...@@ -30,17 +32,35 @@ nlohmann::ordered_json output::getMinimalJson(Solution const &solution) ...@@ -30,17 +32,35 @@ nlohmann::ordered_json output::getMinimalJson(Solution const &solution)
return jsonSolution; return jsonSolution;
} }
nlohmann::ordered_json output::getCompleteJson(Solution const &solution) nlohmann::ordered_json output::getCompleteJson(Solution const &solution, int iteration, double time)
{ {
nlohmann::ordered_json jsonSolution; nlohmann::ordered_json jsonSolution;
// TO DO
nlohmann::ordered_json jsonRoutes = nlohmann::ordered_json::array();
int routeID = 0;
for (auto const &route: solution.getRoutes())
{
jsonRoutes.push_back(routeToJson(routeID, route));
++routeID;
}
jsonSolution["InstanceName"] = solution.getData().getDataName();
jsonSolution["Authors"] = "...";
jsonSolution["Date"] = getCurrentDate();
jsonSolution["Reference"] = "...";
jsonSolution["Cost"] = std::ceil(solution.getRawCost() * 100.0) / 100.0;
jsonSolution["Time"] = time;
jsonSolution["Iteration"] = iteration;
jsonSolution["Unfullfilled"] = solution.getPairBank().size();
jsonSolution["routes"] = jsonRoutes;
return jsonSolution; return jsonSolution;
} }
void output::exportToJson(Solution const &solution) void output::exportToJson(output::LnsOutput result)
{ {
std::string directory = "./../../output"; std::string directory = OUTPUT_DIRECTORY;
std::string filename = directory + "/" + solution.getData().getDataName() + "_sol.json"; std::string filename = directory + "/" + result.getBestSolution().getData().getDataName() + "_sol.json";
if (!std::filesystem::exists(directory)) if (!std::filesystem::exists(directory))
{ {
...@@ -55,8 +75,18 @@ void output::exportToJson(Solution const &solution) ...@@ -55,8 +75,18 @@ void output::exportToJson(Solution const &solution)
return; return;
} }
nlohmann::ordered_json jsonData = output::getMinimalJson(solution); nlohmann::ordered_json jsonData;
file << jsonData.dump(); if (COMPLETE_STORE)
{
jsonData =
output::getCompleteJson(result.getBestSolution(), result.getNumberOfIteration(), result.getTimeSpent());
}
else
{
jsonData = output::getMinimalJson(result.getBestSolution());
}
file << jsonData.dump(4);
file.close(); file.close();
std::cout << "Solution exported" << std::endl; std::cout << "Solution exported" << std::endl;
} }
......
#pragma once #pragma once
#include "lns/solution/solution.h" #include "lns/solution/solution.h"
#include "output/lns_output.h"
#include <nlohmann/json.hpp> #include <ctime>
#include <ctime>
#include <fstream> #include <fstream>
#include <nlohmann/json.hpp>
namespace output namespace output
{ {
...@@ -17,13 +17,13 @@ namespace output ...@@ -17,13 +17,13 @@ namespace output
/** /**
* Get a complete json representation of a solution (heavier) * Get a complete json representation of a solution (heavier)
*/ */
nlohmann::ordered_json getCompleteJson(Solution const &solution); nlohmann::ordered_json getCompleteJson(Solution const &solution, int iteration, double time);
nlohmann::ordered_json routeToJson(int routeID, const Route& route); nlohmann::ordered_json routeToJson(int routeID, Route const &route);
void exportToJson(Solution const &solution); void exportToJson(output::LnsOutput result);
}// namespace output }// namespace output
......
...@@ -19,5 +19,4 @@ using TimeInteger = double; ...@@ -19,5 +19,4 @@ using TimeInteger = double;
TimeInteger constexpr UNDEF_TIMESTAMP = std::numeric_limits<TimeInteger>::max(); 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 @@ ...@@ -7,7 +7,7 @@
namespace// anonymous namespace namespace// anonymous namespace
{ {
std::mt19937_64 randomGenerator;// NOLINT(*-msc51-cpp) => deterministic random! std::mt19937_64 randomGenerator;// NOLINT(*-msc51-cpp) => deterministic random!
bool seedSet = false; bool seedSet = SEED_SET;
std::uniform_real_distribution<> distribution(0, 1); std::uniform_real_distribution<> distribution(0, 1);
}// namespace }// namespace
......