From 3c29d865756fc290e412f7a74cda365d575f1a12 Mon Sep 17 00:00:00 2001 From: Sebastian Brockmeyer <937096+sebrockm@users.noreply.github.com> Date: Sun, 15 Oct 2023 00:21:12 +0200 Subject: [PATCH] Push finished LBs back for reevaluation --- tsplp/src/BranchAndCutQueue.cpp | 34 +++++++++++++++++++++++++++++---- tsplp/src/BranchAndCutQueue.hpp | 2 ++ tsplp/src/MtspModel.cpp | 19 +++++++++++++++--- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/tsplp/src/BranchAndCutQueue.cpp b/tsplp/src/BranchAndCutQueue.cpp index e08cd1d..6115e9f 100644 --- a/tsplp/src/BranchAndCutQueue.cpp +++ b/tsplp/src/BranchAndCutQueue.cpp @@ -66,6 +66,29 @@ void tsplp::BranchAndCutQueue::UpdateCurrentLowerBound(size_t threadId, double c m_workedOnLowerBounds.at(threadId) = currentLowerBound; } +void tsplp::BranchAndCutQueue::PushResult(double lowerBound) +{ + bool needsNotify = false; + + { + std::unique_lock lock { m_mutex }; + + if (m_isCleared) + return; + + if (lowerBound < CalculateLowerBound()) + throw std::logic_error("cannot push smaller lower bound"); + + needsNotify = m_heap.empty() && m_workedOnCount > 0; + + m_heap.push_back({ lowerBound, {}, {}, true }); + std::push_heap(begin(m_heap), end(m_heap), m_comparer); + } + + if (needsNotify) + m_cv.notify_one(); +} + void tsplp::BranchAndCutQueue::Push( double lowerBound, std::vector fixedVariables0, std::vector fixedVariables1) { @@ -82,7 +105,8 @@ void tsplp::BranchAndCutQueue::Push( needsNotify = m_heap.empty() && m_workedOnCount > 0; - m_heap.push_back({ lowerBound, std::move(fixedVariables0), std::move(fixedVariables1) }); + m_heap.push_back( + { lowerBound, std::move(fixedVariables0), std::move(fixedVariables1), false }); std::push_heap(begin(m_heap), end(m_heap), m_comparer); } @@ -116,11 +140,12 @@ void tsplp::BranchAndCutQueue::PushBranch( copyFixedVariables0.insert( copyFixedVariables0.end(), recursivelyFixed0.begin(), recursivelyFixed0.end()); - m_heap.push_back({ lowerBound, std::move(fixedVariables0), std::move(fixedVariables1) }); + m_heap.push_back( + { lowerBound, std::move(fixedVariables0), std::move(fixedVariables1), false }); std::push_heap(begin(m_heap), end(m_heap), m_comparer); m_heap.push_back( - { lowerBound, std::move(copyFixedVariables0), std::move(copyFixedVariables1) }); + { lowerBound, std::move(copyFixedVariables0), std::move(copyFixedVariables1), false }); std::push_heap(begin(m_heap), end(m_heap), m_comparer); } @@ -173,7 +198,7 @@ void tsplp::BranchAndCutQueue::Print() const std::unique_lock lock { m_mutex }; std::cout << "BranchAndCutQueue:\nHeap:"; - for (const auto& [lb, v0, v1] : m_heap) + for (const auto& [lb, v0, v1, r] : m_heap) { std::cout << "LB:" << lb << ", v0:"; for (const auto& v : v0) @@ -181,6 +206,7 @@ void tsplp::BranchAndCutQueue::Print() const std::cout << " v1:"; for (const auto& v : v1) std::cout << v.GetId() << ","; + std::cout << " is result: " << r; std::cout << std::endl; } diff --git a/tsplp/src/BranchAndCutQueue.hpp b/tsplp/src/BranchAndCutQueue.hpp index b54abd0..60af5b0 100644 --- a/tsplp/src/BranchAndCutQueue.hpp +++ b/tsplp/src/BranchAndCutQueue.hpp @@ -18,6 +18,7 @@ struct SData double LowerBound = -std::numeric_limits::max(); std::vector FixedVariables0 {}; std::vector FixedVariables1 {}; + bool IsResult = false; bool operator>(SData const& sd) const { return LowerBound > sd.LowerBound; } }; @@ -67,6 +68,7 @@ class BranchAndCutQueue void ClearAll(); void UpdateCurrentLowerBound(size_t threadId, double currentLowerBound); + void PushResult(double lowerBound); void Push( double lowerBound, std::vector fixedVariables0, std::vector fixedVariables1); diff --git a/tsplp/src/MtspModel.cpp b/tsplp/src/MtspModel.cpp index 9731639..68f075c 100644 --- a/tsplp/src/MtspModel.cpp +++ b/tsplp/src/MtspModel.cpp @@ -352,6 +352,20 @@ void tsplp::MtspModel::BranchAndCutSolve( auto& [sdata, nodeDoneNotifier] = *top; + if (sdata.IsResult) + { + const auto globalLowerBound + = m_bestResult.UpdateLowerBound(queue.GetLowerBound()).Lower; + if (sdata.LowerBound > globalLowerBound) + { + // As this was just popped but is not the global LB, this means other threads + // are currently working on smaller LBs. Push it back to be reevaluated later. + queue.PushResult(sdata.LowerBound); + } + + continue; + } + fixedVariables0 = std::move(sdata.FixedVariables0); fixedVariables1 = std::move(sdata.FixedVariables1); @@ -414,6 +428,7 @@ void tsplp::MtspModel::BranchAndCutSolve( << ": currentLowerBound=" << currentLowerBound << " >= currentUpperBound=" << currentUpperBound << " skipping" << std::endl; + queue.PushResult(currentLowerBound); continue; } @@ -492,14 +507,12 @@ void tsplp::MtspModel::BranchAndCutSolve( currentLowerBound, CreatePathsFromVariables(model)); } - // make sure the this lower bound is set if it is the global one - m_bestResult.UpdateLowerBound(queue.GetLowerBound()); - { std::unique_lock lock { print_mutex }; std::cout << m_name << ", thread " << threadId << ": non-fractional solution found: " << currentLowerBound << std::endl; + queue.PushResult(currentLowerBound); continue; } }