Skip to content

LaNet-vi 5.3.0

Choose a tag to compare

@estcarisimo estcarisimo released this 21 Sep 22:44
· 27 commits to main since this release
bd749d0

LaNet-vi 5.3.0 — k-connectivity, and a minute becomes 26 seconds

LaNet-vi draws large networks by their k-core, k-dense and d-core decomposition: nodes in concentric rings by shell index, so the structure of a graph with a hundred thousand nodes is readable at a glance (Alvarez-Hamelin, Dall'Asta, Barrat & Vespignani, NIPS 2005; the C++ tool of Mariano Beiró and Ignacio Alvarez-Hamelin). 5.1.0 brought the original algorithms back and 5.2.0 closed the option-by-option comparison; 5.3.0 ports the last planned feature of the C++ tool, the k-connectivity analysis of the shells, and makes the whole pipeline two to three times faster on large graphs. Documentation: https://conexdat.github.io/LaNet-vi/.

pip install --upgrade lanet-vi
lanet-vi visualize --input edges.txt --output network.png --kconn

--kconn: which shells are really k-connected

The C++ -kconn (Beiró, Alvarez-Hamelin & Busch, A low complexity visualization tool that helps to perform complex systems analysis, New J. Phys. 10, 2008). A node of the k-shell has degree at least k inside its core, but that does not make its cluster k-connected to the center of the network. The analysis walks the component tree from the top core down: the first cluster of diameter ≤ 2 seeds a k-connected set, and at every lower index a cluster joins when its graph with the set contracted has diameter ≤ 2 and enough of its nodes touch the set (or the cut condition of the paper holds). Nodes that never join are painted black on white / white on black, and drawn as squares in the bw / bwi schemes, exactly as the C++ did. --kconn-type wide (default) gives a skipped cluster another chance at every lower index; strict drops it. --kconn-file writes node shell k_connectivity lines (the C++ log/kconn.log); in Python, Network.compute_kconnectivity().

A synthetic network — ten dense blocks of 60 to 8 nodes hanging from a sparse random tree — with --kconn (left, wide) and --kconn --kconn-type strict (right). The disconnected blocks are never k-connected to the center; wide reaches the periphery through the 1-shell, where the diameter condition does not apply, and strict keeps only the top core:

k-connectivity, wide (left) versus strict (right), on a network of dense blocks hanging from a tree, LaNet-vi 5.3.0

On the Internet AS-level topology (CAIDA AS relationships, October 2025: 78,370 ASes, 489,407 links) wide finds every AS k-connected (803 of them at a lower index than their shell) and strict leaves 1,841 out, all in shells 1–4 — white dots on the rim of this picture:

CAIDA AS relationships with --kconn --kconn-type strict, LaNet-vi 5.3.0

The port was verified against a literal transcription of the C++ loops on 2,400 random graphs. Two things of the C++ are not reproduced: its crash on a shell without clusters and the shell == 77 debugging escape of the strict seed. Like the C++, --kconn is for the k-cores of a simple, unweighted, undirected graph.

Faster on large graphs

The CAIDA graph above took about a minute in 5.2.0 and takes about 26 s now, with the same decomposition and the same pictures up to the random arrangement of a shell:

Stage 5.2.0 5.3.0
k-core decomposition 7.3 s 1.8 s
component tree of the layout 25 s 1.7 s
compute_layout() 30 s 7 s
rasterization twice once
  • The nested component tree that drives the layout (and now the k-connectivity) is built in one union-find pass over the edges grouped by index; the old traversal re-walked the top of the hierarchy once per level (34 million edge visits on CAIDA).
  • The k-core numbers come from a bucket peeling (Batagelj–Zaversnik) for every graph type; nx.core_number deletes neighbors from lists. Identical results, checked against nx.core_number and against brute force on multigraphs.
  • The connected pieces of every level are found in one pass (lanet_vi.decomposition.components.components_by_index, shared by the three decompositions) instead of one induced subgraph per level.
  • The figure is rasterized once: plt.savefig redraws the whole figure after saving; fig.savefig does not.

What remains is matplotlib drawing half a million edge segments, which is the picture itself.

Compatibility

The Python API is unchanged; new members: Network.compute_kconnectivity(), Network.kconnectivity, lanet_vi.decomposition.kconnectivity.compute_kconnectivity, lanet_vi.decomposition.components.components_by_index, lanet_vi.union_find.UnionFind, lanet_vi.visualization.lanet_layout.component_tree. Because sibling components and clusters are now ordered by their first node in graph order, a picture drawn with a given --seed is not byte-identical to the one 5.2.0 drew (it is the same picture up to the random arrangement inside a shell), and --kconn can assign another value to a few nodes for the same seed. The JSON export lists the components of a level in that order. A negative node index or an edge index above one of its endpoints handed to build_component_tree is now a ValueError.

Still open

Nothing from the C++ comparison: the Gomory-Hu connectivity report and the POV-Ray scenes were closed as won't-fix (#25), and this release ports the last planned feature (#47). Community detection and the random generators remain NetworkX-based replacements (#26). The full list of changes is in CHANGELOG.md.

Credits

LaNet-vi is the work of J. Ignacio Alvarez-Hamelin, Mariano G. Beiró, Luca Dall'Asta, Alain Barrat and Alessandro Vespignani; the C++ sources (2005–2016) are the reference for every port. CAIDA AS relationships data: https://www.caida.org/catalog/datasets/as-relationships/.