API reference¶
Public API¶
- gasm.match(G1, G2, *, platform='GPU', attributes=None, vertex_matrices=None, edge_matrices=None, structure=True, complement=True, lap='auto', noise=1e-10, convergence='adaptive', tol=1e-06, patience=2, max_iterations=None, normalize=True, match_on='vertices', return_scores=False, seed=None)[source]¶
Match two graphs with the GASM algorithm.
- Parameters:
G1 – The two graphs to match, as
networkx.Graphornetworkx.DiGraph. Both must share the same directedness.G2 – The two graphs to match, as
networkx.Graphornetworkx.DiGraph. Both must share the same directedness.platform (str) –
'GPU'(default) runs on OpenCL, falling back to the CPU with a warning when no device is available;'CPU'forces the reference implementation.attributes –
Nonefor a purely structural matching, or a list ofgasm.Attribute(or equivalent dicts) describing the vertex and edge attributes to use, each with its uncertaintyrho.vertex_matrices – Optional precomputed vertex similarity matrix of shape
(nA, nB), or a sequence of such matrices, injected directly as extra Hadamard factors of the vertex distance matrixV(eq. 9). Rows follow theG1node order, columns theG2node order. Values must lie in[0, 1]and are clipped otherwise.edge_matrices – Optional precomputed edge similarity matrix of shape
(mA, mB), or a sequence of such matrices, injected directly as extra Hadamard factors of the edge distance matrixE(eq. 10). Rows follow theG1edge order, columns theG2edge order. Values must lie in[0, 1]and are clipped otherwise.structure (bool) – When
False, ignore the graph structure and match on attributes only.complement (bool) – Allow the complement procedure (eq. 18 / 26) for dense graphs.
Falsealways uses the original incidence matrices.lap (str) – Linear assignment solver:
'auto','jv'(Jonker-Volgenant) or'auction'.noise (float) – Amplitude
etaof the symmetry-lifting noise (eq. 11).0disables it.convergence (str) –
'adaptive'(early stopping) or'diameter'(fixed number of iterations, eq. 30).tol (float) – Parameters of the adaptive convergence criterion.
patience (int) – Parameters of the adaptive convergence criterion.
max_iterations (int | None) – Hard cap on the number of iterations; defaults to
min(diam_A, diam_B)(eq. 30).normalize (bool) – Apply the approximate normalization
fx = 4 dA dB + 1(eq. S2).match_on (str) –
'vertices'(match on the vertex score matrixX) or'edges'(match on the edge score matrixY).return_scores (bool) – For the GPU platform, transfer the score matrix immediately instead of lazily. Ignored on the CPU, where scores are always available.
seed (int | None) – Seed for the noise generator, for reproducible matchings.
- Returns:
The matching result.
- Return type:
- class gasm.Matching(labels_a, labels_b, rows, cols, match_on='vertices', score_matrix=None, score_loader=None)[source]¶
Result of a graph matching.
A matching associates vertices (or edges) of graph
Awith vertices (or edges) of graphB. The full score matrix is transferred from the GPU lazily: accessingscore,scoresorscore_matrixtriggers a single device-to-host transfer that is then cached.- Parameters:
labels_a – Ordered labels of the matched elements of each graph (vertices or edges), indexed by the internal integer indices.
labels_b – Ordered labels of the matched elements of each graph (vertices or edges), indexed by the internal integer indices.
rows – Assignment index arrays: internal index
rows[k]ofAis matched with internal indexcols[k]ofB.cols – Assignment index arrays: internal index
rows[k]ofAis matched with internal indexcols[k]ofB.match_on (str) –
'vertices'or'edges'.score_matrix (np.ndarray | None) – The dense score matrix, if already available on the host (CPU path).
score_loader (Callable[[], np.ndarray] | None) – Callable returning the dense score matrix, used for lazy GPU transfer.
- matchup_A(nodes=None)[source]¶
Matchups keyed by elements of
A.- Parameters:
nodes – If
None, return the full{a: b}dict. If a single label, return its match. If an iterable of labels, return the list of matches.
- matchup_B(nodes=None)[source]¶
Matchups keyed by elements of
B(seematchup_A()).
- accuracy(ground_truth)[source]¶
Accuracy
gammaagainst a ground truth (seegasm.accuracy()).- Return type:
- structural_quality(G1, G2)[source]¶
Structural quality
qS(seegasm.structural_quality()).- Return type:
- class gasm.Attribute(name, on, kind='measurable', rho='auto')[source]¶
Specification of a graph attribute used for matching.
- Parameters:
name (str) – Key under which the attribute is stored in the networkx node or edge data dictionaries.
on (Literal['vertex', 'edge']) –
'vertex'or'edge'.kind (Literal['measurable', 'categorical']) –
'measurable'(a distance can be defined, eq. 8) or'categorical'(only equality is meaningful, eq. 6-7).rho (float | str) – Uncertainty over the attribute values. A non-negative float, or
'auto'to use the standard deviation of all pairwise comparisons as a safe upper bound.
- gasm.accuracy(matching, ground_truth)[source]¶
Accuracy
gammaof a matching against a ground truth (Section 2.2).- Parameters:
matching – A
gasm.matching.Matching, or any iterable of(a, b)pairs.ground_truth – Mapping
{a: b}of the true correspondence, or an iterable of(a, b)pairs.
- Returns:
Proportion of matched pairs that agree with the ground truth.
- Return type:
- gasm.structural_quality(G1, G2, matching)[source]¶
Structural quality
qSof a matching (eq. 3).- Parameters:
G1 – The two networkx graphs that were matched.
G2 – The two networkx graphs that were matched.
matching – A
gasm.matching.Matching, or any iterable of(a, b)pairs.
- Returns:
qSin[0, 1]; higher is a better structural match. Returns0when both graphs have no edge.- Return type:
Graphs¶
Internal graph representation for GASM.
Converts a networkx.Graph or networkx.DiGraph into the sparse
incidence structures used by the iterative procedure, following the notations of
Candelier, Graph Matching Based on Similarities in Structure and Attributes,
JGAA 29(1) 289-320 (2025).
Notations¶
Undirected graphs use the unoriented incidence matrix
R(eq. 14), of shapen x m: each column is an edge with two non-zero entries (one for a self-loop).Directed graphs use the source-edge matrix
Sand terminus-edge matrixT(eq. 24-25), both of shapen x m.
- class gasm.graph.Graph(nodes, directed, n, m, mu, edges, adjacency, degree, isolated, R=None, S=None, T=None, _node_index=None, _raw_node_data=None, _raw_edge_data=None)[source]¶
Sparse, GASM-ready view of a networkx graph.
- Parameters:
nodes (list)
directed (bool)
n (int)
m (int)
mu (int)
edges (list)
adjacency (csr_matrix)
degree (ndarray)
isolated (ndarray)
R (csr_matrix | None)
S (csr_matrix | None)
T (csr_matrix | None)
_node_index (dict | None)
_raw_node_data (dict | None)
_raw_edge_data (dict | None)
- nodes¶
Ordered list of the original networkx node labels. The position in this list is the internal integer index used by all matrices.
- Type:
- n, m, mu
Number of vertices, edges and self-loops.
- edges¶
Ordered list of
(u, v)edges (original labels), one per column of the incidence matrices.- Type:
- R¶
Unoriented incidence matrix (
n x m), CSR.Nonefor directed graphs.- Type:
scipy.sparse._csr.csr_matrix | None
- S, T
Source-edge and terminus-edge matrices (
n x m), CSR.Nonefor undirected graphs.
- adjacency¶
Sparse adjacency matrix
Lambda(n x n), CSR.
- degree¶
Vertex degree (out-degree for directed graphs), as a dense vector.
- Type:
- isolated¶
Boolean mask of isolated vertices (degree 0, ignoring self-loops).
- Type:
- gasm.graph.from_networkx(graph)[source]¶
Build a
Graphfrom a networkx graph.- Parameters:
graph (Graph) – A
networkx.Graphornetworkx.DiGraph. Multigraphs are not supported.- Return type:
Attributes¶
Attribute handling for GASM (Section 3.2 of the reference article).
Builds the vertex distance matrix V (eq. 9) and edge distance matrix E
(eq. 10) from user-specified attributes, each with an uncertainty parameter
rho. Categorical attributes use eq. (6)-(7); measurable attributes use
eq. (8).
- gasm.attributes.build_matrices(specs, ga, gb, vertex_matrices=None, edge_matrices=None)[source]¶
Build the vertex (
V) and edge (E) distance matrices.- Parameters:
specs – Iterable of
Attributeor dict specifications, orNone.ga (Graph) – The two graphs being matched.
gb (Graph) – The two graphs being matched.
vertex_matrices – Optional precomputed vertex similarity matrix of shape
(nA, nB), or a sequence of such matrices, injected directly as extra Hadamard factors ofV(eq. 9). Rows follow theganode order, columns thegbnode order. Values must lie in[0, 1]and are clipped otherwise.edge_matrices – Optional precomputed edge similarity matrix of shape
(mA, mB), or a sequence of such matrices, injected directly as extra Hadamard factors ofE(eq. 10). Rows follow thegaedge order, columns thegbedge order. Values must lie in[0, 1]and are clipped otherwise.
- Returns:
V – Vertex distance matrix of shape
(nA, nB)(eq. 9). All-ones when no vertex attribute is specified.E – Edge distance matrix of shape
(mA, mB)(eq. 10). All-ones when no edge attribute is specified.
Metrics¶
Matching quality and accuracy metrics (Section 2 of the reference article).
- gasm.metrics.structural_quality(G1, G2, matching)[source]¶
Structural quality
qSof a matching (eq. 3).- Parameters:
G1 – The two networkx graphs that were matched.
G2 – The two networkx graphs that were matched.
matching – A
gasm.matching.Matching, or any iterable of(a, b)pairs.
- Returns:
qSin[0, 1]; higher is a better structural match. Returns0when both graphs have no edge.- Return type:
- gasm.metrics.accuracy(matching, ground_truth)[source]¶
Accuracy
gammaof a matching against a ground truth (Section 2.2).- Parameters:
matching – A
gasm.matching.Matching, or any iterable of(a, b)pairs.ground_truth – Mapping
{a: b}of the true correspondence, or an iterable of(a, b)pairs.
- Returns:
Proportion of matched pairs that agree with the ground truth.
- Return type:
Convergence¶
Convergence criteria for the GASM iterative procedure.
The reference article (eq. 30) fixes the number of iterations to
k_tilde = min(diam_A, diam_B). Supp. Fig. S3 shows the accuracy usually
plateaus well before that bound, so this module also provides an adaptive
early-stop criterion that monitors the stabilisation of the row-wise argmax
assignment – a cheap surrogate for the final LAP that avoids running the LAP at
every iteration – capped by the diameter for safety.
- class gasm.convergence.ConvergenceMonitor(mode='adaptive', diameter_cap=1, max_iterations=None, tol=1e-06, patience=2, floor=2)[source]¶
Track convergence of the vertex score matrix across iterations.
- Parameters:
mode (str) –
'adaptive'(default) for early stopping, or'diameter'to reproduce the fixed-iteration behaviour of the article.diameter_cap (int) – Hard upper bound on the number of iterations
k_tilde(eq. 30).max_iterations (int | None) – Optional manual override of the hard cap.
tol (float) – Relative Frobenius-norm tolerance for the early-stop criterion.
patience (int) – Number of consecutive iterations with an unchanged argmax assignment required to declare convergence.
floor (int) – Minimum number of iterations before early stopping is allowed.
Linear assignment solvers¶
Linear Assignment Problem (LAP) solver registry.
GASM ends with a LAP on the converged vertex (or edge) score matrix, searching
for a maximum-score assignment. Solvers are registered by name so that new ones
can be added without touching the rest of the code base. The lap argument of
gasm.match() selects one of them, 'auto' picking the best available
solver for the active platform.
Currently available:
'jv': Jonker-Volgenant, viascipy.optimize.linear_sum_assignment()(CPU).'auction': Bertsekas auction algorithm with epsilon-scaling (native GPU implementation; falls back to a NumPy reference on CPU).
- gasm.lap.get_cpu_solver(name)[source]¶
Return the CPU LAP solver registered under
name.'auto'resolves to the Jonker-Volgenant solver.
Jonker-Volgenant LAP solver (CPU), via SciPy.
scipy.optimize.linear_sum_assignment() implements the rectangular
shortest-augmenting-path algorithm of Crouse (2016), a Jonker-Volgenant
variant, in polynomial time.
- gasm.lap.jv.solve(score)[source]¶
Return a maximum-score assignment of rows to columns.
- Parameters:
score (ndarray) – Dense score matrix of shape
(nA, nB); higher is better.- Returns:
Index arrays such that row
rows[k]is assigned to columncols[k]. The assignment has sizemin(nA, nB).- Return type:
rows, cols
Bertsekas auction algorithm with epsilon-scaling (CPU reference).
This is a NumPy reference implementation, used as a CPU fallback and to validate
the native OpenCL auction kernel. With epsilon-scaling the auction converges to
an optimal assignment (identical total score to Jonker-Volgenant); the GASM
noise term lifts ties so both solvers return the same matching. For production
CPU use prefer the 'jv' solver, which is considerably faster in pure Python.
CPU back-end¶
CPU implementation of the GASM iterative procedure (eq. 15-31).
This is the reference implementation, faithful to Candelier (JGAA 29(1), 2025).
It uses dense NumPy score matrices with sparse incidence multiplications and is
the platform used when platform='CPU' or when no OpenCL device is available.
- gasm.cpu.core.run(ga, gb, V, E, *, structure=True, complement=True, noise=1e-10, convergence='adaptive', tol=1e-06, patience=2, max_iterations=None, normalize=True, match_on='vertices', seed=None)[source]¶
Run the GASM iterations on the CPU.
- Returns:
score_matrix – The converged score matrix the LAP should be run on: the vertex score matrix
X(match_on='vertices') or the edge score matrixY(match_on='edges').labels_a, labels_b – Labels of the rows and columns of
score_matrix(node labels for vertices,(u, v)edge tuples for edges).iterations – Number of iterations actually performed.
- Parameters:
GPU back-end¶
GPU (OpenCL/pyopencl) implementation of the GASM iterations.
The expensive part of GASM is the repeated sparse-times-dense products of the
iteration equations (eq. 16-17 / 28-29). This back-end runs them on the device
in single precision, using CSR incidence matrices and the kernels in
kernels/gasm.cl. Initialization, isolated-vertex restoration (eq. 31) and the
final LAP are performed on the host.
Importing this module requires pyopencl and at least one usable OpenCL
device; otherwise an exception is raised and gasm.match() falls back to the
CPU back-end.
- gasm.gpu.core.run(ga, gb, V, E, *, lap='auto', return_scores=False, structure=True, complement=True, noise=1e-10, convergence='adaptive', tol=1e-06, patience=2, max_iterations=None, normalize=True, match_on='vertices', seed=None)[source]¶
Run the GASM iterations on the GPU.
Returns the converged vertex score matrix on the host (float64), the row and column labels, the number of iterations performed, and
None(no lazy device loader is used in this version; the score matrix is materialised for the host LAP).
Warnings¶
Internal utilities: warnings and validation helpers for GASM.
- exception gasm.utils.PlatformWarning[source]¶
Emitted when the requested compute platform is unavailable.
- exception gasm.utils.AttributeWarning[source]¶
Emitted when attribute specifications are inconsistent with the graphs.
- exception gasm.utils.ConvergenceWarning[source]¶
Emitted when the iterative procedure may not have converged.
- gasm.utils.warn(message, category=<class 'gasm.utils.GASMWarning'>)[source]¶
Emit a GASM warning with a controlled stack level.
- Parameters:
message (str)
category (type[GASMWarning])
- Return type:
None