silentbicycle / hopscotch

An implementation of Tarjan's Strongly Connected Components algorithm

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Hopscotch

An implementation of Tarjan's Strongly Connected Components algorithm.

This analyzes a directed graph and yields the graph's nodes in reverse-topologically sorted order, grouped into strongly connected components. In other words, it groups nodes together that refer to each other with cycle(s), and orders the groups so that every group only refers to nodes appearing in later groups.

For a nice overview of the algorithm, see Vaibhav Sagar's "An All-in-One DAG Toolkit" post.

This builds both a C library and a standalone command-line program. The latter previously appeared in a slightly different form, as my winning 2018 IOCCC entry.

Note: The TSCC algorithm assumes that its input is a single connected graph. If there are disconnected subgraphs in the input, their relative order will be based on where they appear in the input.

Building

To build, just run make (GNU make).

To run the tests, run make test. Note that the property tests depend on theft to build.

Example

Given the following input:

$ build/hopscotch << HERE
1: 2
2: 3 4
3: 4 5
4: 3 5
5: 6 7
6: 7 8
7: 6 8
HERE

it will print:

0: 8
1: 6 7
2: 5
3: 3 4
4: 2
5: 1

because 8 doesn't depend on anything, then 6 and 7 reference each other but otherwise only refer to 8, 5 only refers to 6 and 7, etc.

The equivalent C API usage looks like:

struct hopscotch *t = hopscotch_new();

struct {
    uint32_t id;
    size_t count;
    uint32_t successors[MAX_COUNT];
} rows[] = {
    { 1, 1, { 2 }, },
    { 2, 2, { 3, 4 }, },
    { 3, 2, { 4, 5 }, },
    { 4, 2, { 3, 5 }, },
    { 5, 2, { 6, 7 }, },
    { 6, 2, { 7, 8 }, },
    { 7, 2, { 6, 8 }, },
};
for (size_t i = 0; i < sizeof(rows)/sizeof(rows[0]); i++) {
    if (!hopscotch_add(t, rows[i].id, rows[i].count, rows[i].successors)) {
        /* handle error */
    }
}

if (!hopscotch_seal(t)) { /* handle error */ }
hopscotch_solve(t, 0, callback, NULL);
hopscotch_free(t);

and the callback will be called with each group ID, count, and array of members. The last argument to hopscotch_solve is opaque to hopscotch, but passed to the callback, so the callback can be used as a closure.

Diagrams

The command-line program can also generate Graphviz dot, by using the -d flag:

$ build/hopscotch -d < examples/abc

This output can be used to generate PNGs, SVGs, etc.

Several environment variables can be used to add attributes to the generated DOT:

env HOPSCOTCH_DOT_GRAPH_ATTR='bgcolor=black' \
    HOPSCOTCH_DOT_NODE_ATTR='color=mintcream;fontcolor="#ffffff";fontname="terminus"' \
    HOPSCOTCH_DOT_EDGE_ATTR='color=mediumspringgreen' \
    HOPSCOTCH_DOT_CLUSTER_ATTR='color=mediumturquoise' \
    build/hopscotch -d < examples/abc

[...]

About

An implementation of Tarjan's Strongly Connected Components algorithm

License:ISC License


Languages

Language:C 96.3%Language:Makefile 3.5%Language:C++ 0.3%