From 10b334d218d6975ae7158e3b07dda8b5ae019470 Mon Sep 17 00:00:00 2001 From: Nikolai Maas Date: Tue, 26 Nov 2024 13:50:56 +0100 Subject: [PATCH] raise error if target graph is not connected --- mt-kahypar/partition/mapping/target_graph.cpp | 30 ++++++++++++++++++- mt-kahypar/partition/mapping/target_graph.h | 3 ++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/mt-kahypar/partition/mapping/target_graph.cpp b/mt-kahypar/partition/mapping/target_graph.cpp index 34aaa7480..3b5c465b4 100644 --- a/mt-kahypar/partition/mapping/target_graph.cpp +++ b/mt-kahypar/partition/mapping/target_graph.cpp @@ -38,13 +38,17 @@ namespace mt_kahypar { #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC void TargetGraph::precomputeDistances(const size_t max_connectivity) { ALWAYS_ASSERT(max_connectivity >= 2); + if (!inputGraphIsConnected()) { + throw InvalidInputException("Target graph must be connected, but it is not."); + } + const size_t num_entries = std::pow(_k, max_connectivity); if ( num_entries > MEMORY_LIMIT ) { throw SystemException( "Too much memory requested for precomputing steiner trees " "of connectivity sets in the target graph."); } - _distances.assign(num_entries, std::numeric_limits::max() / 3); + _distances.assign(num_entries, kInvalidDistance); SteinerTree::compute(_graph, max_connectivity, _distances); _max_precomputed_connectitivty = max_connectivity; @@ -57,6 +61,7 @@ HyperedgeWeight TargetGraph::distance(const ds::StaticBitset& connectivity_set) const size_t idx = index(connectivity_set); ASSERT(idx < _distances.size()); if constexpr ( TRACK_STATS ) ++_stats.precomputed; + ASSERT(_distances[idx] < kInvalidDistance); return _distances[idx]; } else { const uint64_t hash_key = computeHash(connectivity_set); @@ -152,6 +157,29 @@ HyperedgeWeight TargetGraph::computeWeightOfMSTOnMetricCompletion(const ds::Stat ASSERT(pq.empty()); return res; } + +bool TargetGraph::inputGraphIsConnected() const { + // stack-based DFS + std::vector visited; + std::vector stack; + visited.resize(_graph.initialNumNodes(), 0); + stack.push_back(0); + visited[0] = 1; + HypernodeID num_visited = 1; + while (!stack.empty() && num_visited < _graph.initialNumNodes()) { + HypernodeID hn = stack.back(); + stack.pop_back(); + for (HyperedgeID edge: _graph.incidentEdges(hn)) { + HypernodeID neighbor = _graph.edgeTarget(edge); + if (visited[neighbor] == 0) { + stack.push_back(neighbor); + visited[neighbor] = 1; + num_visited++; + } + } + } + return num_visited == _graph.initialNumNodes(); +} #endif } // namespace kahypar diff --git a/mt-kahypar/partition/mapping/target_graph.h b/mt-kahypar/partition/mapping/target_graph.h index 83871b794..5cfca9dc6 100644 --- a/mt-kahypar/partition/mapping/target_graph.h +++ b/mt-kahypar/partition/mapping/target_graph.h @@ -64,6 +64,7 @@ namespace mt_kahypar { #ifdef KAHYPAR_ENABLE_STEINER_TREE_METRIC class TargetGraph { + static constexpr HyperedgeWeight kInvalidDistance = std::numeric_limits::max() / 3; static constexpr size_t INITIAL_HASH_TABLE_CAPACITY = 100000; static constexpr size_t MEMORY_LIMIT = 100000000; @@ -256,6 +257,8 @@ class TargetGraph { // ! connecting u and v. This gives a 2-approximation for steiner tree problem. HyperedgeWeight computeWeightOfMSTOnMetricCompletion(const ds::StaticBitset& connectivity_set) const; + bool inputGraphIsConnected() const; + #ifdef __linux__ HashTableHandle getHandle() const { return _cache.get_handle();