diff --git a/dkaminpar/coarsening/contraction/cluster_contraction.cc b/dkaminpar/coarsening/contraction/cluster_contraction.cc index 52c09ef9..4c24c431 100644 --- a/dkaminpar/coarsening/contraction/cluster_contraction.cc +++ b/dkaminpar/coarsening/contraction/cluster_contraction.cc @@ -806,6 +806,7 @@ void rebalance_cluster_placement( } } // namespace +namespace debug { bool validate_clustering(const DistributedGraph &graph, const GlobalClustering &lnode_to_gcluster) { for (const NodeID lnode : graph.all_nodes()) { const GlobalNodeID gcluster = lnode_to_gcluster[lnode]; @@ -848,6 +849,7 @@ bool validate_clustering(const DistributedGraph &graph, const GlobalClustering & ); return failed == 0; } +} // namespace debug ContractionResult contract_clustering( const DistributedGraph &graph, @@ -859,7 +861,9 @@ ContractionResult contract_clustering( START_TIMER("Contract clustering"); KASSERT( - validate_clustering(graph, lnode_to_gcluster), "input clustering is invalid", assert::heavy + debug::validate_clustering(graph, lnode_to_gcluster), + "input clustering is invalid", + assert::heavy ); const PEID size = mpi::get_comm_size(graph.communicator()); diff --git a/dkaminpar/coarsening/contraction/cluster_contraction.h b/dkaminpar/coarsening/contraction/cluster_contraction.h index 6c17f449..8e4ef8d6 100644 --- a/dkaminpar/coarsening/contraction/cluster_contraction.h +++ b/dkaminpar/coarsening/contraction/cluster_contraction.h @@ -4,7 +4,6 @@ * @file: cluster_contraction.h * @author: Daniel Seemaier * @date: 06.02.2023 - * @brief: Graph contraction for arbitrary clusterings. ******************************************************************************/ #pragma once @@ -17,9 +16,30 @@ #include "common/datastructures/noinit_vector.h" namespace kaminpar::dist { +/// Data type to map node IDs of the fine graph to node IDs in the coarse graph. using GlobalMapping = NoinitVector; + +/// Data type for clusterings, i.e., a mapping from node IDs in the graph to cluster IDs. using GlobalClustering = NoinitVector; +namespace debug { +/** + * Validates the given clustering, i.e., whether it is a valid input to the `contract_clustering()` + * function. + * + * @param graph The graph for which the clustering was computed. + * @param lnode_to_gcluster The clustering to validate. + * + * @return `true` if the clustering is valid, `false` otherwise. If `false` is returned, calling + * `contract_clustering()` with the same clustering is undefined behavior. + */ +bool validate_clustering(const DistributedGraph &graph, const GlobalClustering &lnode_to_gcluster); +} // namespace debug + +/** + * Stores technical mappings necessary to project a partition of the coarse graph to the fine graph. + * Part of the contraction result and should not be used outside the `project_partition()` function. + */ struct MigratedNodes { NoinitVector nodes; @@ -29,16 +49,54 @@ struct MigratedNodes { std::vector rdispls; }; +/** + * Stores the contracted graph along with information necessary to project a partition of the coarse + * graph to the fine graph. + */ struct ContractionResult { DistributedGraph graph; NoinitVector mapping; MigratedNodes migration; }; +/** + * Constructs the coarse graph given a clustering of the fine graph. + * + * @param graph The fine graph. + * @param clustering The clustering of the fine graph: this is an array of size `graph.total_n()` + * (i.e., one entry for each owned node *and* ghost node). The assignment of ghost nodes must be + * consistent with their assignment on other PEs. Cluster IDs can be arbitrary integers in the range + * `0 <= ID < graph.global_n()`. + * @param c_ctx Coarsening context with configuration parameters that influence the distribution of + * the contracted graph. + * + * @return The coarse graph along with information necessary to project a partition of the coarse to + * the fine graph. + */ ContractionResult contract_clustering( const DistributedGraph &graph, GlobalClustering &clustering, const CoarseningContext &c_ctx ); +/** + * Constructs the coarse graph given a clustering of the fine graph. + * + * @param graph The fine graph. + * @param clustering The clustering of the fine graph: this is an array of size `graph.total_n()` + * (i.e., one entry for each owned node *and* ghost node). The assignment of ghost nodes must be + * consistent with their assignment on other PEs. Cluster IDs can be arbitrary integers in the range + * `0 <= ID < graph.global_n()`. + * @param max_cnode_imbalance The maximum allowed imbalance of coarse nodes (per PE). If a PE would + * end up with too many coarse nodes, the contraction algorithm will move coarse nodes to rebalance + * the assignment. + * @param migrate_cnode_prefix If `true`, the contraction algorithm will move a prefix of coarse + * nodes if their assignment violates the maximum allowed imbalance factor; otherwise, it moves a + * suffix. + * @param force_perfect_cnode_balance If `true`, the contraction algorithm will perfectly balance + * the coarse node assignment if their natural assignment would violate the given imbalance factor. + * + * @return The coarse graph along with information necessary to project a partition of the coarse to + * the fine graph. + */ ContractionResult contract_clustering( const DistributedGraph &graph, GlobalClustering &clustering, @@ -47,6 +105,16 @@ ContractionResult contract_clustering( bool force_perfect_cnode_balance = true ); +/** + * Projects the partition of a coarse graph back onto the fine graph. + * + * @param graph The fine graph. + * @param p_c_graph The partition of the coarse graph. + * @param c_mapping The mapping from coarse nodes to fine nodes (part of `ContractionResult`). + * @param migration The migration information for coarse nodes (part of `ContractionResult`). + * + * @return The partition of the fine graph. + */ DistributedPartitionedGraph project_partition( const DistributedGraph &graph, DistributedPartitionedGraph p_c_graph, @@ -54,3 +122,4 @@ DistributedPartitionedGraph project_partition( const MigratedNodes &migration ); } // namespace kaminpar::dist +