MATLAB graph/cyclebasis: How can I extract labeling-independent “minimal loop units”?
7 Comments
Hi @Taehyub,
You are absolutely correct - avoiding arbitrary maxNodes limits is the right approach. Your 4-step algorithm addresses the core problem, but needs some theoretical refinements:
Responding to Your Algorithm:
Steps 1-2: Correct approach. Finding all cycles and sorting by length is the foundation of minimum cycle basis algorithms.
Step 3: Needs adjustment. "Always include triangles" isn't mathematically sound. Triangles aren't guaranteed to be in every minimum cycle basis - sometimes longer cycles can form a shorter total basis.
Step 4: Critical issue. "Same sequence of edges" doesn't determine linear independence. You need proper linear independence over GF(2), not edge overlap checking.
Refined Implementation with Pseudo-code:
ALGORITHM: Labeling-Invariant Minimum Cycle Basis
INPUT: Graph G OUTPUT: Canonical minimum cycle basis
1. CANONICALIZE_GRAPH(G): edges = sort(G.edges) nodes = canonical_ordering(G) // degree sequence + neighbor degrees G_canon = relabel_graph(G, nodes) return G_canon
2. FIND_ALL_CYCLES(G_canon): cycles = [] for each simple cycle C in G_canon: cycles.append(C) return sort(cycles, by=length)
3. SELECT_BASIS_CYCLES(sorted_cycles): basis = [] cycle_matrix = empty_matrix(num_edges)
for cycle C in sorted_cycles: vector_C = cycle_to_binary_vector(C, edge_list)
// Check linear independence over GF(2) if rank(cycle_matrix + vector_C) > rank(cycle_matrix): basis.append(C) cycle_matrix.add_row(vector_C)
if len(basis) == cyclomatic_number: break
return basis
4. CANONICALIZE_CYCLES(basis): for each cycle in basis: start_from_min_node() choose_consistent_direction() return sorted(basis, lexicographically)
Key Functions You Need to Implement:
- cycle_to_binary_vector(): Maps cycle to GF(2) vector over edges
- rank(): Matrix rank over GF(2)
- canonical_ordering(): Consistent node labeling
References: * Horton, J.D. (1987). "Shortest cycle basis algorithm." SIAM J. Computing, 16(2), 358-366 * McKay, B.D. & Piperno, A. (2014). "Practical graph isomorphism, II." J. Symbolic Computation, 60, 94-112
Question: Can you implement the GF(2) linear algebra operations? This is essential for proper independence testing in step 3.
Answers (2)
3 Comments
Hi @Taehyub,
Thanks for sharing your questions. I understand you want a labeling-independent way to find “minimal loop units,” like the 3-node triangles in your graphs. Below, I’ve addressed your questions step by step and provided a MATLAB script you can run to get consistent results across isomorphic graphs.
Question 1
You mentioned, I know cyclebasis can vary with spanning tree/edge ordering. What’s the recommended way in MATLAB to obtain “minimal loop units” that do not depend on node labeling or edge input order?
Solution
The built-in cyclebasis function depends on the spanning tree and edge order, which can vary with node labeling. To get a labeling-independent set of minimal loops (triangles in your example), the recommended approach is to explicitly enumerate all 3-node cycles and verify which combinations form triangles. This guarantees consistent results for isomorphic graphs.
Question 2
You mentioned, For example, in the above case, each cycle is a 3-node triangle, and there should be seven such cycles. How can I obtain them reliably?
Solution
The MATLAB script below implements this approach:
- It generates all 3-node combinations of nodes.
- Checks which combinations form triangles by verifying all three edges exist.
- Plots the graphs with highlighted triangles, each with a distinct color and label.
This ensures you get the exact seven triangles for each graph, independent of node labels or edge ordering.
Implementation
clc; clear; close all;
%% ----------------------------- %% Graph 1 %% ----------------------------- node = [ 2 7 2 3 3 4 4 5 5 6 6 1 1 4 1 5 3 6 1 3 5 7 6 7 2 6 5 8];
G = graph(node(:, 1), node(:, 2), []);
figure(1); h1 = plot(G, 'Layout', 'force'); title('Graph 1'); labelnode(h1, 1:numnodes(G), arrayfun(@num2str, 1:numnodes(G), 'UniformOutput', false));
T = nchoosek(1:numnodes(G), 3); % all 3-node combinations triangles = []; edges = sort(node, 2);
for k = 1:size(T,1) comb = sort(T(k,:)); if all(ismember(sort([comb(1) comb(2)]), edges, 'rows')) && ... all(ismember(sort([comb(2) comb(3)]), edges, 'rows')) && ... all(ismember(sort([comb(1) comb(3)]), edges, 'rows')) triangles = [triangles; comb]; end end
disp('Triangles in Graph 1:'); disp(triangles);
colors = lines(size(triangles,1)); hold on for k = 1:size(triangles,1) highlight(h1, triangles(k,:), 'EdgeColor', colors(k,:), 'LineWidth', 2); coords = mean([h1.XData(triangles(k,:))' h1.YData(triangles(k,:))'], 1); text(coords(1), coords(2), ['T' num2str(k)], 'FontWeight','bold', 'Color', colors(k,:)); end
%% ----------------------------- %% Graph 2 %% ----------------------------- node2 = [ 1 2 2 3 3 4 4 1 1 5 5 6 2 4 6 7 3 6 2 5 3 7 4 7 2 6 6 8];
G2 = graph(node2(:, 1), node2(:, 2), []);
figure(2); h2 = plot(G2, 'Layout', 'force'); title('Graph 2'); labelnode(h2, 1:numnodes(G2), arrayfun(@num2str, 1:numnodes(G2), 'UniformOutput', false));
T2 = nchoosek(1:numnodes(G2), 3); triangles2 = []; edges2 = sort(node2, 2);
for k = 1:size(T2,1) comb = sort(T2(k,:)); if all(ismember(sort([comb(1) comb(2)]), edges2, 'rows')) && ... all(ismember(sort([comb(2) comb(3)]), edges2, 'rows')) && ... all(ismember(sort([comb(1) comb(3)]), edges2, 'rows')) triangles2 = [triangles2; comb]; end end
disp('Triangles in Graph 2:'); disp(triangles2);
colors = lines(size(triangles2,1)); hold on for k = 1:size(triangles2,1) highlight(h2, triangles2(k,:), 'EdgeColor', colors(k,:), 'LineWidth', 2); coords = mean([h2.XData(triangles2(k,:))' h2.YData(triangles2(k,:))'], 1); text(coords(1), coords(2), ['T' num2str(k)], 'FontWeight','bold', 'Color', colors(k,:)); end
Please see attached.



This script gives a reliable, labeling-independent set of minimal loops (triangles) for any graph. You can run it for both graphs in your example and verify that each has exactly seven triangles. Each triangle is plotted with a distinct color and labeled for clarity.
3 Comments
@Matt J, Agreed, this approach is not scalable in general. My graphs are relatively small, and the minimal loops of interest are triangles, so brute-force enumeration is simple, labeling-invariant, and guarantees the exact set of loops I need. For larger or more complex graphs, I would turn to more efficient methods such as spatialgraph2D or minimum cycle basis algorithms.
See Also
Categories
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!