diff --git a/CMakeLists.txt b/CMakeLists.txt index 96feadf83e7a405968380ac25da9ba5a57283f6d..357cd492e33cedf097373193c8c2ad64420c4303 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,8 @@ add_executable(pdptw src/mains/main.cpp 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/lns/operators/selector/operator_selector.cpp + src/lns/operators/selector/small_large_selector.cpp src/utils.cpp ) diff --git a/src/lns/operators/selector/operator_selection.cpp b/src/lns/lns.cpp similarity index 100% rename from src/lns/operators/selector/operator_selection.cpp rename to src/lns/lns.cpp diff --git a/src/lns/lns.h b/src/lns/lns.h new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/lns/operators/selector/operator_selector.cpp b/src/lns/operators/selector/operator_selector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e187ed1495993a9ac2d9cbbeb32597af847654b3 --- /dev/null +++ b/src/lns/operators/selector/operator_selector.cpp @@ -0,0 +1,33 @@ +#include "operator_selector.h" + +#include "utils.h" + +ReconstructionOperator &OperatorPair::reconstructor() +{ + return reconstruct; +} + +DestructionOperator &OperatorPair::destructor() +{ + return destruct; +} + +bool OperatorPair::forceTakeSolution() const +{ + return forceAcceptance; +} + +OperatorPair::OperatorPair(DestructionOperator &destruct, ReconstructionOperator &reconstruct, bool forceAcceptance) + : destruct(destruct), reconstruct(reconstruct), forceAcceptance(forceAcceptance) +{} + +void OperatorPair::setForceAcceptance() +{ + forceAcceptance = true; +} + +OperatorPair SimpleOperatorSelector::getOperatorPair() +{ + return {*destructOperators.at(destructDistribution(util::getRawRandom())), + *reconstructOperators.at(reconstructDistribution(util::getRawRandom()))}; +} diff --git a/src/lns/operators/selector/operator_selector.h b/src/lns/operators/selector/operator_selector.h index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1dd721324ef2ca0ef13c95c83d6e7e776b1d3ef0 100644 --- a/src/lns/operators/selector/operator_selector.h +++ b/src/lns/operators/selector/operator_selector.h @@ -0,0 +1,104 @@ +#pragma once + +#include "lns/operators/abstract_operator.h" +#include <algorithm> +#include <memory> +#include <random> +#include <utility> +#include <vector> + +/** + * Represent a pair (destruction and reconstruction) of operators. + */ +class OperatorPair +{ + DestructionOperator &destruct; + ReconstructionOperator &reconstruct; + /** + * Allow the operator pair to force to accept the solution that will be created with the last getOperatorPair(); + * @return true to force the acceptance of the solution after the operators calls. + */ + bool forceAcceptance; + +public: + OperatorPair(DestructionOperator &destruct, ReconstructionOperator &reconstruct, bool forceAcceptance = false); + DestructionOperator &destructor(); + ReconstructionOperator &reconstructor(); + // the solution obtained with this operator pair will be accepted by the lns + void setForceAcceptance(); + bool forceTakeSolution() const; +}; + + +/** + * Abstract class which defines an interface for an operator selector + */ +class OperatorSelector +{ +public: + /** + * Called once per iteration, defines which destruction reconstruction pair is going to be used. + */ + virtual OperatorPair getOperatorPair() = 0; + /** + * Callback if a better solution has been found by the algorithm + */ + virtual void betterSolutionFound() = 0; + virtual ~OperatorSelector() = default; +}; + +/** + * Simple operator selector with weighted random distribution + */ +class SimpleOperatorSelector : public OperatorSelector +{ + std::vector<std::unique_ptr<DestructionOperator>> destructOperators; + std::vector<std::unique_ptr<ReconstructionOperator>> reconstructOperators; + std::discrete_distribution<> destructDistribution; + std::discrete_distribution<> reconstructDistribution; + +public: + SimpleOperatorSelector() = default; + SimpleOperatorSelector(SimpleOperatorSelector &rhs) = delete; + SimpleOperatorSelector &operator=(SimpleOperatorSelector &rhs) = delete; + SimpleOperatorSelector(SimpleOperatorSelector &&rhs) = default; + SimpleOperatorSelector &operator=(SimpleOperatorSelector &&rhs) noexcept = default; + + template<std::derived_from<DestructionOperator> T> + void addDestructor(T destructor, int weight = 1); + + template<std::derived_from<ReconstructionOperator> T> + void addReconstructor(T reconstructor, int weight = 1); + + OperatorPair getOperatorPair() override; + + void betterSolutionFound() override {} +}; + + + +template<std::derived_from<DestructionOperator> T> +void SimpleOperatorSelector::addDestructor(T destructor, int weight) +{ + auto newDistribution = std::vector<double>(destructDistribution.probabilities()); + int deconstructCount = destructOperators.size(); + newDistribution.resize(deconstructCount); + std::ranges::transform( + newDistribution, newDistribution.begin(), [&](double elmt) { return elmt * deconstructCount; }); + newDistribution.push_back(weight); + destructDistribution = std::discrete_distribution<>(newDistribution.begin(), newDistribution.end()); + destructOperators.push_back(std::make_unique<T>(std::move(destructor))); +} + +template<std::derived_from<ReconstructionOperator> T> +void SimpleOperatorSelector::addReconstructor(T reconstructor, int weight) +{ + auto newDistribution = std::vector<double>(reconstructDistribution.probabilities()); + int reconstructCount = reconstructOperators.size(); + newDistribution.resize(reconstructCount); + std::ranges::transform( + newDistribution, newDistribution.begin(), [&](double elmt) { return elmt * reconstructCount; }); + newDistribution.push_back(weight); + reconstructDistribution = std::discrete_distribution<>(newDistribution.begin(), newDistribution.end()); + reconstructOperators.push_back(std::make_unique<T>(std::move(reconstructor))); +} \ No newline at end of file diff --git a/src/lns/operators/selector/small_large_selector.cpp b/src/lns/operators/selector/small_large_selector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eaebf5d1c4d282fe1e96612585715052f7e4f3b7 --- /dev/null +++ b/src/lns/operators/selector/small_large_selector.cpp @@ -0,0 +1,38 @@ +#include "small_large_selector.h" + +#include <algorithm> +#include <spdlog/spdlog.h> + +SmallLargeOperatorSelector::SmallLargeOperatorSelector(std::vector<StepSelector> selectorsList) + : iterationAtCurrentStep(0), selectorStep(0), selectorPerSize(std::move(selectorsList)) +{ + iterationForNextStep = selectorPerSize.at(0).first; +} + +OperatorPair SmallLargeOperatorSelector::getOperatorPair() +{ + if (iterationAtCurrentStep > iterationForNextStep) [[unlikely]] + { + ++selectorStep; + if (selectorStep == selectorPerSize.size()) + { + betterSolutionFound(); + } + iterationForNextStep = selectorPerSize.at(selectorStep).first; + } + SimpleOperatorSelector &selector = selectorPerSize.at(selectorStep).second; + OperatorPair pair = selector.getOperatorPair(); + // when we arrive at the last iteration of the last selector, we force the acceptance + if (iterationAtCurrentStep == iterationForNextStep - 1 && selectorStep == selectorPerSize.size()) [[unlikely]] + { + pair.setForceAcceptance(); + } + ++iterationAtCurrentStep; + return pair; +} + +void SmallLargeOperatorSelector::betterSolutionFound() +{ + iterationAtCurrentStep = 0; + selectorStep = 0; +} diff --git a/src/lns/operators/selector/small_large_selector.h b/src/lns/operators/selector/small_large_selector.h new file mode 100644 index 0000000000000000000000000000000000000000..247326bc24fc324d53427492a6e6101075578729 --- /dev/null +++ b/src/lns/operators/selector/small_large_selector.h @@ -0,0 +1,33 @@ +#pragma once + +#include "lns/operators/selector/operator_selector.h" + +/** + * + */ +class SmallLargeOperatorSelector : public OperatorSelector +{ +public: + using StepSelector = std::pair<unsigned int, SimpleOperatorSelector>; + +private: + // the number of call to getOperatorPair (ie. lns iteration) done with the current step + unsigned int iterationAtCurrentStep; + // the index of the selector used, called step + unsigned int selectorStep; + // number of iterations needed to use the next selector + unsigned int iterationForNextStep; + // vector of all the selector and the number of iterations for each + std::vector<StepSelector> selectorPerSize; + +public: + /** + * @param selectorPerSize each pair is the maximum of iterations for a given selector. + * ie. {{300,A},{700,B}} means that the A will be used for 300 iterations, + * then B is used for 700. Then cycle on A again. + */ + explicit SmallLargeOperatorSelector(std::vector<StepSelector> selectorPerSize); + OperatorPair getOperatorPair() override; + void betterSolutionFound() override; +}; + diff --git a/src/mains/main.cpp b/src/mains/main.cpp index 3d63ca676d35a1e66fa20b7eabafe1c92b7817aa..41d5485992ee9fc2575541a09ea5379e8b484872 100644 --- a/src/mains/main.cpp +++ b/src/mains/main.cpp @@ -55,49 +55,40 @@ int main(int argc, char const *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"; - std::cout << filepath << "\n"; - - PDPTWData data = parsing::parseJson(filepath); - data.checkData(); - - data.print(); - std::cout << " \n"; - /* - * test - */ - Solution solution = Solution::emptySolution(data); - - std::cout << "--- Empty Solution --- \n"; - solution.print(); - 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"; + ///////////////////////////////////////////////////////////////////////:: - //ListHeuristicInsertion heuristicInsertion; - //heuristicInsertion.reconstructSolution(solution, blinkRate, strategy, enumeration); + // std::cout << filepath << "\n"; - ListHeuristicCostOriented heuristic; - heuristic.reconstructSolution(solution, blinkRate, strategy, enumeration); + // PDPTWData data = parsing::parseJson(filepath); + // data.checkData(); - solution.print(); + // data.print(); - solution.print(); + // std::cout << " \n"; + // /* + // * test + // */ + // Solution solution = Solution::emptySolution(data); + + // std::cout << "--- Empty Solution --- \n"; + // solution.print(); + + // 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 << " --- supr !!! --- \n "; + // ListHeuristicCostOriented heuristic; + // heuristic.reconstructSolution(solution, blinkRate, strategy, enumeration); - RandomDestroy randomdestroy = RandomDestroy(5); - randomdestroy.destroySolution(solution); + // RandomDestroy randomdestroy = RandomDestroy(4); + // randomdestroy.destroySolution(solution); - //Index index = std::make_tuple(0,7,9); - //RemovePair remPair = RemovePair(index, solution.getData().getPair(2)); - //solution.applyDestructSolution(remPair); - //solution.print(); - //output::exportToJson(solution); + //output::exportToJson(solution); return 0; } diff --git a/src/mains/main_interface.cpp b/src/mains/main_interface.cpp index 58ad8a727ee4235b18f650bf44ed403240ab7470..aeb283a90dc1c91e79f031d65c316b4196da484c 100644 --- a/src/mains/main_interface.cpp +++ b/src/mains/main_interface.cpp @@ -36,6 +36,6 @@ int mainInterface(int argc, char **argv, std::function<void(PDPTWData &, Solutio return 1; } - spdlog::info("Fin"); + spdlog::info("End"); return 0; }