Graph Partitioning (KaHIP)

March 15, 2026 ยท View on GitHub

Original Repository: https://github.com/KaHIP/KaHIP


Overview

KaHIP (Karlsruhe High Quality Partitioning) is a family of graph partitioning programs that tackle the balanced graph partitioning problem: given an undirected graph G = (V, E) with optional node and edge weights, partition the node set into k disjoint blocks of roughly equal weight while minimizing the total weight of edges crossing block boundaries (the edge cut).

The balance constraint ensures each block's weight does not exceed (1 + imbalance) * ceil(total_weight / k).

KaHIP uses a multilevel approach with coarsening, initial partitioning, and local search refinement. CHSZLabLib exposes three KaHIP routines:

MethodPurpose
Decomposition.partition()Balanced k-way graph partitioning
Decomposition.node_separator()Balanced node separator computation
Decomposition.node_ordering()Fill-reducing nested dissection ordering

Decomposition.partition()

Partition a graph into k balanced blocks minimizing the edge cut.

Signature

Decomposition.partition(
    g: Graph,
    num_parts: int = 2,
    mode: str = "eco",
    imbalance: float = 0.03,
    seed: int = 0,
    suppress_output: bool = True,
) -> PartitionResult

Parameters

ParameterTypeDefaultDescription
gGraphrequiredInput graph (undirected, optionally weighted). Must be finalized.
num_partsint2Number of blocks (must be >= 2).
modestr"eco"Quality/speed trade-off (see table below).
imbalancefloat0.03Allowed weight imbalance as a fraction (0.03 = 3%).
seedint0Random seed for reproducibility.
suppress_outputboolTrueSuppress C++ stdout/stderr output.

Available Modes

ModeSpeedQualityBest For
"fast"FastestGoodLarge-scale exploration
"eco"BalancedVery goodDefault choice
"strong"SlowestBestFinal production partitions
"fastsocial"FastestGoodSocial / power-law networks
"ecosocial"BalancedVery goodSocial / power-law networks
"strongsocial"SlowestBestSocial / power-law networks

Returns

PartitionResult

FieldTypeDescription
edgecutintTotal weight of edges crossing block boundaries.
assignmentnp.ndarray (int32)Block ID for each node (0-indexed).

Exceptions

ExceptionCondition
ValueErrornum_parts < 2 or imbalance < 0.
InvalidModeErrormode is not one of the valid choices.

Example

from chszlablib import Graph, Decomposition

g = Graph.from_metis("mesh.graph")
result = Decomposition.partition(g, num_parts=8, mode="strong", imbalance=0.01)
print(f"Edge cut: {result.edgecut}")
print(f"Block assignments: {result.assignment}")

Decomposition.node_separator()

Compute a balanced node separator that splits the graph into two components with no edges between them.

Signature

Decomposition.node_separator(
    g: Graph,
    num_parts: int = 2,
    mode: str = "eco",
    imbalance: float = 0.03,
    seed: int = 0,
    suppress_output: bool = True,
) -> SeparatorResult

Parameters

ParameterTypeDefaultDescription
gGraphrequiredInput graph (undirected, optionally weighted).
num_partsint2Number of blocks (must be >= 2).
modestr"eco"Quality/speed trade-off (same modes as partition()).
imbalancefloat0.03Allowed weight imbalance (0.03 = 3%).
seedint0Random seed for reproducibility.
suppress_outputboolTrueSuppress C++ stdout/stderr output.

Returns

SeparatorResult

FieldTypeDescription
num_separator_verticesintNumber of nodes in the separator.
separatornp.ndarray (int32)Array where each entry is 0 (block A), 1 (block B), or 2 (separator).

Example

from chszlablib import Graph, Decomposition

g = Graph.from_metis("mesh.graph")
result = Decomposition.node_separator(g, mode="strong")
print(f"Separator size: {result.num_separator_vertices}")
separator_nodes = [i for i, v in enumerate(result.separator) if v == 2]

Decomposition.node_ordering()

Compute a fill-reducing nested dissection ordering for sparse matrix factorization.

Signature

Decomposition.node_ordering(
    g: Graph,
    mode: str = "eco",
    seed: int = 0,
    suppress_output: bool = True,
) -> OrderingResult

Parameters

ParameterTypeDefaultDescription
gGraphrequiredInput graph representing the sparsity pattern.
modestr"eco"Quality/speed trade-off (same modes as partition()).
seedint0Random seed for reproducibility.
suppress_outputboolTrueSuppress C++ stdout/stderr output.

Returns

OrderingResult

FieldTypeDescription
orderingnp.ndarray (int32)Permutation array. Node i should be placed at position ordering[i].

Example

from chszlablib import Graph, Decomposition

g = Graph.from_metis("sparse_matrix.graph")
result = Decomposition.node_ordering(g, mode="strong")
perm = result.ordering

Performance Disclaimer

This Python interface wraps the KaHIP C++ library via pybind11. While convenient for prototyping and integration into Python workflows, there is inherent overhead from the Python/C++ boundary and data conversion. For maximum performance on large-scale instances or in production HPC pipelines, use the original C++ implementation directly from the KaHIP repository.


References

@inproceedings{DBLP:conf/wea/SandersS13,
  author    = {Peter Sanders and Christian Schulz},
  title     = {Think Locally, Act Globally: Highly Balanced Graph Partitioning},
  booktitle = {Experimental Algorithms, 12th International Symposium, {SEA} 2013},
  series    = {Lecture Notes in Computer Science},
  volume    = {7933},
  pages     = {164--175},
  publisher = {Springer},
  year      = {2013},
  doi       = {10.1007/978-3-642-38527-8\_16}
}

@article{DBLP:journals/tpds/MeyerhenkeSS17,
  author  = {Henning Meyerhenke and Peter Sanders and Christian Schulz},
  title   = {Parallel Graph Partitioning for Complex Networks},
  journal = {{IEEE} Trans. Parallel Distributed Syst.},
  volume  = {28},
  number  = {9},
  pages   = {2625--2638},
  year    = {2017},
  doi     = {10.1109/TPDS.2017.2671868}
}