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 visualisation · a4e9f18a
    awenjb authored
    - add .ipynb to display capacity (link with solutiion and data file to do)
    a4e9f18a
  • awenjb's avatar
    Replace template by switch case · 4f74e41e
    awenjb authored
    - replace template by switch case for the sorting strategy and the enumeration strategy in reconstruction operator
    - remove generator / modficiation generator
    4f74e41e
  • awenjb's avatar
    Add list_heuristic_cost_oriented · 8ccfd7b7
    awenjb authored
    - add  list_heuristic_cost_oriented, same as list_heuristic_insertion but evaluate cost before feasibility
    8ccfd7b7
Showing
with 514 additions and 166 deletions
......@@ -37,9 +37,9 @@ add_executable(pdptw src/mains/main.cpp
src/output/solution_exporter.cpp
src/lns/operators/sorting_strategy.cpp
src/lns/operators/destruction/random_destroy.cpp
src/lns/operators/generators/enumerate.cpp
src/lns/operators/generators/modification_generator.cpp
src/lns/operators/reconstruction/list_heuristic_insertion.hpp
src/lns/operators/reconstruction/enumerate.cpp
src/lns/operators/reconstruction/list_heuristic_insertion.cpp
src/lns/operators/reconstruction/list_heuristic_cost_oriented.cpp
src/lns/operators/selector/operator_selection.cpp
src/utils.cpp
)
......
This diff is collapsed.
#pragma once
#include "lns/operators/reconstruction/enumerate.h"
#include "sorting_strategy.h"
class Solution;
class DestructionOperator
......@@ -12,6 +15,6 @@ public:
class ReconstructionOperator
{
public:
virtual void reconstructSolution(Solution &solution, double blinkRate) const = 0;
virtual void reconstructSolution(Solution &solution, double blinkRate, SortingStrategyType strategy, EnumerationType enumeration) const = 0;
virtual ~ReconstructionOperator() = default;
};
#include "modification_generator.h"
#include "enumerate.h"
namespace generator
{
/**
*
* @tparam ModificationType the type of modification to be checked
* @param solution the solution to check the modification validity
* @param list the modification will be added to this list if valid
* @return a function that takes a ModificationType and add it to list iff it is valid
*/
template<std::derived_from<AtomicRecreation> ModificationType>
std::function<void(ModificationType &&)> addToListIfValidTemplate(Solution const &solution,
ModificationContainer &list)
{
return [&](ModificationType &&modification) {
if (solution.checkModification(modification))
{
std::cout << " => Insert Modification" << "\n";
list.push_front(std::make_unique<ModificationType>(modification));
}
};
std::cout << " => Insert Modification" << "\n";
}
void AllTypedModifications<InsertPair>::populate(Solution const &solution, Pair const &pair,
std::forward_list<std::unique_ptr<AtomicRecreation>> &list)
{
std::cout << "\n MODIFICATION GENERATOR : \n";
enumeration::enumerateAllInsertPair(
solution, pair, addToListIfValidTemplate<InsertPair>(solution, list));
}
}// namespace generator
#pragma once
#include "input/pair.h"
#include "lns/modification/atomic_recreation.h"
#include "lns/modification/pair/insert_pair.h"
#include <forward_list>
#include <memory>
namespace generator
{
using ModificationContainer = std::forward_list<std::unique_ptr<AtomicRecreation>>;
/**
* Abstract class to generate valid modifications
*/
class ModificationGenerator
{
public:
/**
* Adds valid insertions of request to the solution in the list provided as argument
*/
virtual void populate(Solution const &solution, Pair const &, ModificationContainer &modificationList) = 0;
virtual ~ModificationGenerator() = default;
};
/**
* Empty template class to generate ALL valid modification of a specific type
* @tparam T the type of modification to generate
*/
template<std::derived_from<AtomicRecreation> T>
class AllTypedModifications : public ModificationGenerator
{
// this assert will always fail. Needs a template specification
static_assert(sizeof(T) == 0, "The generator for type T has not been defined yet.");
};
template<>
class AllTypedModifications<InsertPair> : public ModificationGenerator
{
public:
void populate(Solution const &solution, Pair const &, ModificationContainer &list) override;
};
}// namespace generator
\ No newline at end of file
......@@ -4,26 +4,33 @@ namespace enumeration
{
/**
* Enumerate InsertPair modifications.
* consumeModification is called for each modification.
* Does some checks to cut some loops. (TO DO)
* @param solution
* @param pair
* @param consumeModification called when a modification is created
* @param ModificationContainer
*/
void enumerateAllInsertPair(Solution const &solution, Pair const &pair,
std::function<void(InsertPair &&)> const &consumeModification)
void enumerateAllInsertPair(Solution const &solution, Pair const &pair, std::function<void(InsertPair &&)> const &consumeModification)
{
int routeIndex = 0;
// Insert into existing routes
for (Route const &route: solution.getRoutes())
{
for (int p = 0; p <= route.getSize(); p++)
int routeSize = route.getSize();
for (int p = 0; p <= routeSize; ++p)
{
for (int d = p; d <= route.getSize(); d++)
for (int d = p; d <= routeSize; ++d)
{
Index index = std::make_tuple(routeIndex, p, d);
//std::cout << std::get<0>(index) << " " << std::get<1>(index) << " " << std::get<2>(index) << "\n";
consumeModification(InsertPair(index, pair));
consumeModification(InsertPair(index,pair));
// std::unique_ptr<InsertPair> modification = std::make_unique<InsertPair>(index, pair);
// // add to list if valid modification
// if (solution.checkModification(*modification))
// {
// std::cout << " => Insert Modification\n";
// list.push_front(std::move(modification));
// }
}
}
++routeIndex;
......
......@@ -2,21 +2,29 @@
#include "lns/modification/pair/insert_pair.h"
#include <forward_list>
#include <functional>
/**
* A type of enumeration for a specific modification
*/
enum class EnumerationType {
ALL_INSERT_PAIR
};
namespace enumeration
{
using ModificationContainer = std::forward_list<std::unique_ptr<AtomicRecreation>>;
/**
* Enumerate InsertDelivery modifications.
* consumeModification is called for each modification.
* Does some checks to cut some loops.
* @param solution
* @param request
* @param consumeModification called when a modification is created (ex : keepBestSolution)
* @param Pair
* @param list
*/
void enumerateAllInsertPair(Solution const &solution, Pair const &Pair,
std::function<void(InsertPair &&)> const &consumeModification);
void enumerateAllInsertPair(Solution const &solution, Pair const &pair, std::function<void(InsertPair &&)> const &consumeModification);
}// namespace enumeration
......
#include "list_heuristic_cost_oriented.h"
void ListHeuristicCostOriented::reconstructSolution(Solution &solution, double blinkRate, SortingStrategyType strategy,
EnumerationType enumeration) const
{
std::vector<int> sortedPairs;
// selection strategy
switch (strategy)
{
case SortingStrategyType::SHUFFLE: {
std::cout << " \n(Shuffle)\n";
// copy
sortedPairs = sorting_strategy::Shuffle(solution).sortPairs();
break;
}
default:
spdlog::error("Error, invalid strategy selected.");
throw std::invalid_argument("Invalid sorting strategy selected.");
break;
}
for (int pairID: sortedPairs)
{
Pair const &pair = solution.getData().getPair(pairID);
AtomicRecreationPtr bestRecreation;
double bestRecreationCost = std::numeric_limits<double>::max();
// Enumeration strategy
switch (enumeration)
{
case EnumerationType::ALL_INSERT_PAIR: {
std::cout << " \n(All insert pair) \n";
enumeration::enumerateAllInsertPair(
solution,
pair,
keepBestSolution<InsertPair>(solution, bestRecreation, bestRecreationCost, blinkRate));
break;
}
default:
spdlog::error("Error, invalid enumeration selected.");
throw std::invalid_argument("Invalid enumeration strategy selected.");
break;
}
if (bestRecreation)
{
std::cout << "\n --- Apply recreation --- \n";
solution.applyRecreateSolution(*bestRecreation);
}
}
}
\ No newline at end of file
#pragma once
#include "input/data.h"
#include "input/pdptw_data.h"
#include "lns/operators/abstract_operator.h"
#include "lns/operators/sorting_strategy.h"
#include "utils.h"
/**
* List heuristic operator but evaluates costs before trying to know if the modification is feasible
*/
class ListHeuristicCostOriented : public ReconstructionOperator
{
public:
using AtomicRecreationPtr = std::unique_ptr<AtomicRecreation>;
void reconstructSolution(Solution &solution, double blinkRate, SortingStrategyType strategy,
EnumerationType enumeration) const override;
};
/**
* Create a function that will consume all the enumerated modifications
* @tparam ModificationType The type of modification enumerated
* @param bestModificationPtr the pointer to the actual best modification found yet
* @param bestCost the cost of the best modification
* @param blinkRate blinking rate
*/
template<std::derived_from<AtomicRecreation> ModificationType>
std::function<void(ModificationType &&)> keepBestSolution(Solution const &solution,
std::unique_ptr<AtomicRecreation> &bestModificationPtr,
double &bestCost, double blinkRate)
{
return [&](ModificationType &&modification) {
double cost = modification.evaluate(solution);
// first test the cost
// if the modification is better, then blink,
// then check the modification
// then store the best cost and the modification to the pointer
if (cost < bestCost && util::getRandom() >= blinkRate && solution.checkModification(modification))
{
std::cout << " => Better Modification, update pointer"
<< "\n";
bestModificationPtr = std::make_unique<ModificationType>(modification);
bestCost = cost;
}
};
}
#pragma once
#include "list_heuristic_insertion.h"
// This is a header, but it does define templates, so we can't put them in .cpp file
// for forward declaration you can use the .h file, but if you need to use the class, you must include this one instead
#include "lns/operators/sorting_strategy.h"
#include "enumerate.h"
#include "lns/operators/generators/modification_generator.h"
#include <concepts>
template<std::derived_from<sorting_strategy::SortingStrategy> Strategy,
std::derived_from<generator::ModificationGenerator> Generator>
ListHeuristicInsertion<Strategy, Generator>::ListHeuristicInsertion() = default;
ListHeuristicInsertion::ListHeuristicInsertion() = default;
template<std::derived_from<sorting_strategy::SortingStrategy> Strategy,
std::derived_from<generator::ModificationGenerator> Generator>
void ListHeuristicInsertion<Strategy, Generator>::reconstructSolution(Solution &solution, double blinkRate) const
void ListHeuristicInsertion::reconstructSolution(Solution &solution, double blinkRate, SortingStrategyType strategy, EnumerationType enumeration) const
{
std::vector<int> sortedPairs = Strategy(solution).sortPairs();
std::vector<int> sortedPairs;
// selection strategy
switch (strategy) {
case SortingStrategyType::SHUFFLE:
{
std::cout << " \n(Shuffle)\n";
// copy
sortedPairs = sorting_strategy::Shuffle(solution).sortPairs();
break;
}
default:
spdlog::error("Error, invalid strategy selected.");
throw std::invalid_argument("Invalid sorting strategy selected.");
break;
}
AtomicRecreationPtr recreation;
for (int pairID: sortedPairs)
{
Pair const &pair = solution.getData().getPair(pairID);
recreation = ListHeuristicInsertion::choosingStrategy(solution, pair, blinkRate);
recreation = ListHeuristicInsertion::selectRecreation(solution, pair, blinkRate, enumeration);
if (recreation)
{
std::cout << "\n --- Apply recreation --- \n";
......@@ -31,17 +40,30 @@ void ListHeuristicInsertion<Strategy, Generator>::reconstructSolution(Solution &
}
}
template<std::derived_from<sorting_strategy::SortingStrategy> Strategy,
std::derived_from<generator::ModificationGenerator> Generator>
std::unique_ptr<AtomicRecreation> ListHeuristicInsertion<Strategy, Generator>::choosingStrategy(Solution &solution,
Pair const &pair,
double blinkRate)
std::unique_ptr<AtomicRecreation> ListHeuristicInsertion::selectRecreation(Solution &solution, Pair const &pair,
double blinkRate, EnumerationType enumeration)
{
AtomicRecreationPtr bestInsertion;
double bestKnownInsertionCost = std::numeric_limits<double>::max();
generator::ModificationContainer modifications;
Generator().populate(solution, pair, modifications);
enumeration::ModificationContainer modifications;
// Enumeration strategy
switch (enumeration) {
case EnumerationType::ALL_INSERT_PAIR:
{
std::cout << " \n(All insert pair) \n";
enumeration::enumerateAllInsertPair(solution, pair, addToListIfValidTemplate<InsertPair>(solution, modifications));
break;
}
default:
spdlog::error("Error, invalid enumeration selected.");
throw std::invalid_argument("Invalid enumeration strategy selected.");
break;
}
// Keep the modification with the best cost
for (AtomicRecreationPtr &possibleRecreation: modifications)
{
if (util::getRandom() <= 1 - blinkRate)
......
......@@ -3,7 +3,6 @@
#include "input/data.h"
#include "input/pdptw_data.h"
#include "lns/operators/abstract_operator.h"
#include "lns/operators/generators/modification_generator.h"
#include "lns/operators/sorting_strategy.h"
#include "utils.h"
......@@ -17,8 +16,6 @@ class AtomicRecreation;
* @tparam Strategy defines in which order we are treating the requests
* @tparam Generator defines which modifications are going to be used
*/
template<std::derived_from<sorting_strategy::SortingStrategy> Strategy,
std::derived_from<generator::ModificationGenerator> Generator>
class ListHeuristicInsertion : public ReconstructionOperator
{
private:
......@@ -27,13 +24,36 @@ private:
public:
explicit ListHeuristicInsertion();
void reconstructSolution(Solution &solution, double blinkRate) const override;
void reconstructSolution(Solution &solution, double blinkRate, SortingStrategyType strategy,
EnumerationType enumeration) const override;
private:
/**
* @param blinkRate probability to ignore the request insertion
* @return the best insertion found
*/
static std::unique_ptr<AtomicRecreation> choosingStrategy(Solution &solution, Pair const &pair,
double blinkRate);
static std::unique_ptr<AtomicRecreation> selectRecreation(Solution &solution, Pair const &pair, double blinkRate,
EnumerationType enumeration);
};
/**
* Used in enumerate.cpp functions to evaluate modification
* Do not evaluate cost (see list_heuristic_cost_oriented that evaluate cost before feasability)
* @tparam ModificationType the type of modification to be checked
* @param solution the solution to check the modification validity
* @param list the modification will be added to this list if valid
* @return a function that takes a ModificationType and add it to list iff it is valid
*/
template<std::derived_from<AtomicRecreation> ModificationType>
std::function<void(ModificationType &&)> addToListIfValidTemplate(Solution const &solution,
enumeration::ModificationContainer &list)
{
return [&](ModificationType &&modification) {
if (solution.checkModification(modification))
{
std::cout << " => Insert Modification"
<< "\n";
list.push_front(std::make_unique<ModificationType>(modification));
}
};
}
\ No newline at end of file
......@@ -2,6 +2,13 @@
#include "lns/solution/solution.h"
/**
* A type of sorting strategy for the bank of pairs
*/
enum class SortingStrategyType {
SHUFFLE
};
namespace sorting_strategy
{
/**
......
......@@ -14,6 +14,7 @@
#include "input/data.h"
#include "lns/constraints/capacity/capacity_constraint.h"
#include "lns/constraints/time_window/time_window_constraint.h"
#include "lns/operators/reconstruction/list_heuristic_cost_oriented.h"
#include "lns/solution/solution.h"
#include "lns/modification/pair/insert_pair.h"
#include "lns/modification/route/insert_route.h"
......@@ -21,10 +22,10 @@
#include "lns/modification/route/remove_route.h"
#include "lns/operators/reconstruction/list_heuristic_insertion.h"
#include "lns/operators/reconstruction/list_heuristic_insertion.hpp"
#include "lns/operators/generators/modification_generator.h"
#include "lns/operators/sorting_strategy.h"
#include "lns/operators/reconstruction/enumerate.h"
#include "output/solution_exporter.h"
using json = nlohmann::json;
......@@ -69,18 +70,17 @@ int main(int argc, char const *argv[])
std::cout << "--- Empty Solution --- \n";
solution.print();
generator::AllTypedModifications<InsertPair> generator;
generator::ModificationContainer modificationList;
//ListHeuristicInsertion<std::derived_from<sorting_strategy::SortingStrategy> Strategy, std::derived_from<generator::ModificationGenerator> Generator>
double blinkRate = 0;
SortingStrategyType strategy = SortingStrategyType::SHUFFLE;
EnumerationType enumeration = EnumerationType::ALL_INSERT_PAIR;
std::cout << "\n --- Operator - SHUFFLE - ALL_INSERTPAIR -> reconstruction (NO COST UPDATE)\n";
std::cout << "\n --- Operator <SHUFFLE - ALL_INSERTPAIR> -> reconstruction (NO COST UPDATE)\n";
//ListHeuristicInsertion heuristicInsertion;
//heuristicInsertion.reconstructSolution(solution, blinkRate, strategy, enumeration);
ListHeuristicInsertion<sorting_strategy::Shuffle, generator::AllTypedModifications<InsertPair>> operatorInstance;
operatorInstance.reconstructSolution(solution, blinkRate);
ListHeuristicCostOriented heuristic;
heuristic.reconstructSolution(solution, blinkRate, strategy, enumeration);
solution.print();
......