Skip to content
Snippets Groups Projects
Commit 056b4f35 authored by awenjb's avatar awenjb
Browse files

Add Basic Operators

- add enumeration of all Insert position for a pair
- add shuffle strategy
parent 3249e1b3
No related branches found
No related tags found
No related merge requests found
Showing
with 276 additions and 3 deletions
......@@ -36,6 +36,8 @@ add_executable(pdptw src/mains/main.cpp
src/output/solution_checker.cpp
src/lns/operators/sorting_strategy.cpp
src/lns/operators/destruction/random_destroy.cpp
src/lns/operators/generation/enumerate.cpp
src/lns/operators/generation/modification_generator.cpp
src/lns/operators/selector/operator_selection.cpp
src/utils.cpp
)
......
......@@ -12,6 +12,13 @@ class AtomicRecreation : public AtomicModification
public:
~AtomicRecreation() override = default;
/**
* Visitor pattern double dispatch.
* Only need to be implemented with `return *this;`
* Update ModificationCheckVariant alias when adding new recreate modification
*/
virtual ModificationCheckVariant asCheckVariant() const = 0;
/**
* @return the pickup location added to the solution, nullptr if none were added
*/
......
......@@ -57,6 +57,11 @@ double InsertPair::evaluate(Solution const &solution) const {
}
ModificationCheckVariant InsertPair::asCheckVariant() const
{
return *this;
}
int InsertPair::getPickupInsertion() const
{
return pickupInsertion;
......
......@@ -65,4 +65,5 @@ public:
Pair const &getPair() const;
Index getIndex() const;
ModificationCheckVariant asCheckVariant() const override;
};
\ No newline at end of file
......@@ -19,3 +19,7 @@ Location const *InsertRoute::getAddedLocation() const
return nullptr;
}
ModificationCheckVariant InsertRoute::asCheckVariant() const
{
return *this;
}
......@@ -17,4 +17,6 @@ public:
void modifySolution(Solution &solution) override;
double evaluate(Solution const &solution) const override;
Location const *getAddedLocation() const override;
ModificationCheckVariant asCheckVariant() const override;
};
\ No newline at end of file
#include "enumerate.h"
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
*/
void enumerateAllInsertPair(Solution const &solution, Pair const &pair,
std::function<void(InsertPair &&)> const &consumeModification)
{
int routeIndex = 0;
for (const Route &route : solution.getRoutes())
{
for (int p=0; p <= route.getSize(); p++)
{
for (int d=p; d <= route.getSize(); d++)
{
Index index = std::make_tuple(routeIndex, p,d);
consumeModification(InsertPair(index, pair));
}
}
++routeIndex;
}
}
}// namespace enumeration
\ No newline at end of file
#pragma once
#include "lns/modification/pair/insert_pair.h"
#include <functional>
namespace enumeration
{
/**
* 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)
*/
void enumerateAllInsertPair(Solution const &solution, Pair const &Pair,
std::function<void(InsertPair &&)> const &consumeModification);
}// namespace enumeration
#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))
{
list.push_front(std::make_unique<ModificationType>(modification));
}
};
}
void AllTypedModifications<InsertPair>::populate(Solution const &solution, Pair const &request,
std::forward_list<std::unique_ptr<AtomicRecreation>> &list)
{
enumeration::enumerateAllInsertPair(
solution, request, 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
#pragma once
#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"
#include <optional>
class AtomicRecreation;
/**
* This is a template class for list heuristic operator.
* Implementation is in the .hpp file
* @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:
using AtomicRecreationPtr = std::unique_ptr<AtomicRecreation>;
public:
explicit ListHeuristicInsertion();
void reconstructSolution(Solution &solution, double blinkRate) 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);
};
#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/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;
template<std::derived_from<sorting_strategy::SortingStrategy> Strategy,
std::derived_from<generator::ModificationGenerator> Generator>
void ListHeuristicInsertion<Strategy, Generator>::reconstructSolution(Solution &solution, double blinkRate) const
{
std::vector<int> sortedPairs = Strategy(solution).sortRequests();
AtomicRecreationPtr recreation;
for (int pairID: sortedPairs)
{
Pair const &pair = solution.getData().getPair(pairID);
recreation = ListHeuristicInsertion::choosingStrategy(solution, pair, blinkRate);
if (recreation)
{
solution.applyRecreateSolution(*recreation);
}
}
}
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)
{
AtomicRecreationPtr bestInsertion;
double bestKnownInsertionCost = std::numeric_limits<double>::max();
generator::ModificationContainer modifications;
Generator().populate(solution, pair, modifications);
for (AtomicRecreationPtr &possibleRecreation: modifications)
{
if (util::getRandom() < 1 - blinkRate)
{
double newInsertionCost = possibleRecreation->evaluate(solution);
if (newInsertionCost < bestKnownInsertionCost)
{
bestKnownInsertionCost = newInsertionCost;
bestInsertion = std::move(possibleRecreation);
}
}
}
return bestInsertion;
}
\ No newline at end of file
......@@ -5,7 +5,7 @@
#include <algorithm>
#include <ranges>
std::vector<int> const &sorting_strategy::Shuffle::sortRequests() const
std::vector<int> const &sorting_strategy::Shuffle::sortPairs() const
{
auto &bank = getSolution().getPairBank();
std::ranges::shuffle(bank, util::getRawRandom());
......
......@@ -14,7 +14,7 @@ namespace sorting_strategy
Solution &getSolution() const { return solution; }
virtual std::vector<int> const &sortRequests() const = 0;
virtual std::vector<int> const &sortPairs() const = 0;
virtual ~SortingStrategy() = default;
private:
......@@ -30,7 +30,7 @@ namespace sorting_strategy
using SortingStrategy::SortingStrategy;
public:
std::vector<int> const &sortRequests() const override;
std::vector<int> const &sortPairs() const override;
};
......
......@@ -143,6 +143,21 @@ int Solution::requestsFulFilledCount() const
return count;
}
bool Solution::checkModification(AtomicRecreation const &modification) const
{
ModificationCheckVariant const &checkVariant = modification.asCheckVariant();
// visitor pattern
for (std::unique_ptr<Constraint> const &constraint: constraints)
{
if (!constraint->checkVariant(checkVariant))
{
return false;
}
}
return true;
}
void Solution::beforeApplyModification(AtomicModification &modification)
{
// pre check to do ?
......
......@@ -68,6 +68,12 @@ public:
*/
int requestsFulFilledCount() const;
/**
* 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;
/**
* Pre modification check.
......
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