Walks, cycles and components
#include <flint/bool_mat.h>void bool_mat_transitive_closure(bool_mat_t B, const bool_mat_t A)sourceSets to the transitive closure of : if and only if there is a walk of positive length from to . Uses Warshall's algorithm [War1962], in operations.
slong bool_mat_get_strongly_connected_components(slong * p, const bool_mat_t A)sourceComputes the strongly connected components of the graph of and returns their number . Sets , for each vertex , to the index in of the component containing . The components form a directed acyclic graph, and they are numbered in postorder with respect to it: if there is an edge from a vertex of component to a vertex of a different component , then . Uses Tarjan's algorithm [Tar1972], in operations.
slong bool_mat_nilpotency_degree(const bool_mat_t A)sourceReturns the nilpotency degree of , the smallest with , or if is not nilpotent. For an empty matrix it returns 0. For a nilpotent matrix the degree is one more than the length of the longest path in the graph, which is computed by a topological sort.
slong bool_mat_all_pairs_longest_walk(fmpz_mat_t B, const bool_mat_t A)sourceSets to the length of the longest walk from vertex to vertex in the graph of , where the empty walk from a vertex to itself has length 0. if there is no walk from to , and if there are arbitrarily long walks (a walk from to through a cycle). The matrix must be .
Returns if some entry of is , and otherwise the largest entry of , which is one less than bool_mat_nilpotency_degree; for an empty matrix it returns .
The function works on the condensation of the graph, the acyclic graph of its strongly connected components. An application is to matrix power series: if has the sparsity pattern of a real or complex matrix and , then for all , so the tail of a power series vanishes for .
A square Boolean matrix of order is the adjacency matrix of a directed graph on the vertices , and the Boolean product of matrices composes walks: exactly when there is a walk of length from to . The four functions described here compute properties of all powers of at once from the structure of the graph, without forming the powers.
bool_mat_transitive_closuregives , the reachability relation, by Warshall's algorithm [War1962] in operations.bool_mat_get_strongly_connected_componentspartitions the vertices into strongly connected components (maximal sets of vertices that can all reach each other) with Tarjan's depth-first search [Tar1972], in operations since the graph is given by a dense matrix. The components are numbered so that edges between different components go from higher to lower numbers.bool_mat_nilpotency_degreefinds the least with . Such a exists exactly when the graph has no cycle, and it is then one more than the number of edges of a longest path. The function finds a topological order by depth-first search and computes longest paths along it.bool_mat_all_pairs_longest_walkrefines this to each pair of vertices: the largest with , or if there is none, or if there is none largest. A pair has arbitrarily long walks when some walk from to passes through a component containing a cycle. The function works on the condensation of the graph (the acyclic graph of components).
The last function serves to bound the error of truncated matrix power series: if is a real or complex matrix with the sparsity pattern , then whenever , so the entry of is a finite sum when . arb_mat_exp and acb_mat_exp use this to compute exponentials of nilpotent and partly nilpotent matrices with exact zero error bounds where possible.
Example#
The graph with edges , , and has the components , and , numbered 0, 1 and 2. Every walk into the cycle can be made arbitrarily long. Removing the edge leaves an acyclic graph whose longest path, (or ), has two edges, so .
#include <flint/flint.h>
#include <flint/bool_mat.h>
#include <flint/fmpz_mat.h>
int main(void)
{
bool_mat_t A, C;
fmpz_mat_t W;
slong p[4], k, w;
bool_mat_init(A, 4, 4);
bool_mat_init(C, 4, 4);
fmpz_mat_init(W, 4, 4);
bool_mat_set_entry(A, 0, 1, 1);
bool_mat_set_entry(A, 1, 2, 1);
bool_mat_set_entry(A, 2, 1, 1);
bool_mat_set_entry(A, 1, 3, 1);
flint_printf("A =\n");
bool_mat_print(A);
bool_mat_transitive_closure(C, A);
flint_printf("transitive closure =\n");
bool_mat_print(C);
k = bool_mat_get_strongly_connected_components(p, A);
flint_printf("%wd components: %{slong*}\n", k, p, (slong) 4);
flint_printf("nilpotent: %d\n", bool_mat_is_nilpotent(A));
w = bool_mat_all_pairs_longest_walk(W, A);
flint_printf("longest walks (return value %wd):\n", w);
fmpz_mat_print_pretty(W);
flint_printf("\n");
/* remove the cycle 1 -> 2 -> 1 */
bool_mat_set_entry(A, 2, 1, 0);
flint_printf("without 2 -> 1: nilpotency degree %wd\n",
bool_mat_nilpotency_degree(A));
w = bool_mat_all_pairs_longest_walk(W, A);
flint_printf("longest walks (return value %wd):\n", w);
fmpz_mat_print_pretty(W);
flint_printf("\n");
bool_mat_clear(A);
bool_mat_clear(C);
fmpz_mat_clear(W);
return 0;
}A = [0, 1, 0, 0] [0, 0, 1, 1] [0, 1, 0, 0] [0, 0, 0, 0] transitive closure = [0, 1, 1, 1] [0, 1, 1, 1] [0, 1, 1, 1] [0, 0, 0, 0] 3 components: [2, 1, 1, 0] nilpotent: 0 longest walks (return value -2): [[0 -2 -2 -2] [-1 -2 -2 -2] [-1 -2 -2 -2] [-1 -1 -1 0] ] without 2 -> 1: nilpotency degree 3 longest walks (return value 2): [[0 1 2 2] [-1 0 1 1] [-1 -1 0 -1] [-1 -1 -1 0] ]
The diagonal entries of the walk matrix are 0 for vertices off any cycle (the empty walk) and for vertices on a cycle.
References#
- [War1962] S. Warshall. A theorem on Boolean matrices. Journal of the ACM 9(1), 11–12, 1962.
- [Tar1972] R. E. Tarjan. Depth-first search and linear graph algorithms. SIAM Journal on Computing 1(2), 146–160, 1972.
The FLINT team, “Walks, cycles and components (bool_mat.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/bool_mat/graphs.html (generated 2026-11-02).
@misc{flint-doc-bool-mat-graphs,
author = {{The FLINT team}},
title = {{Walks, cycles and components (bool\_mat.h)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/bool_mat/graphs.html},
note = {Generated 2026-11-02}
}