Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
8e2b314
docs: design proposal for hypergraph network backboning
claude Jun 2, 2026
2469831
docs: add hypergraph library interop + sui generis method inventory
claude Jun 2, 2026
ed4d6c8
docs: re-scope hypergraph backboning proposal to the actual paper (MD…
claude Jun 2, 2026
db424f8
feat: add MDL hypergraph backbone (Kirkley et al. 2026)
claude Jun 2, 2026
63fa1ea
test: update disparity_filter expected edge count to match corrected …
claude Jun 2, 2026
7e3d77d
feat: add structural hypergraph backbone methods (Phase 2)
claude Jun 2, 2026
4e9d288
feat: add statistically validated hypergraphs (SVH/SVC)
claude Jun 3, 2026
87599f7
feat: add hypergraph ingestion / interoperability adapters (Phase 0)
claude Jun 3, 2026
b20e441
feat: add MDL "node"/"auto" optimizers; hypergraph tutorial
claude Jun 3, 2026
006b385
docs: evaluate Backbone 3.0 coverage; add references
claude Jun 3, 2026
edcf851
feat: add multiple-testing correction (mtc) to address Backbone 3.0 gap
claude Jun 3, 2026
3046d09
feat: add signed backbones to address Backbone 3.0 gap
claude Jun 3, 2026
0dc71e0
feat: add SDSM-EC edge constraints to sdsm (Backbone 3.0 gap)
claude Jun 3, 2026
757d80f
docs: reference mtc, signed, and SDSM-EC across README, tutorials, co…
claude Jun 3, 2026
9af138b
docs: fill reference gaps from Neal 2026 (Backbone 3.0) bibliography
claude Jun 3, 2026
b1b8eaa
docs: fix Sphinx -W build failure (18 warnings -> 0)
claude Jun 3, 2026
3ab4836
ci: update actions to avoid Node.js 20 deprecation
claude Jun 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,20 @@ concurrency:
group: "pages"
cancel-in-progress: false

env:
# Force Node 24 for JS actions still on Node 20 (deprecation 2026-06-16).
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

jobs:
build:
name: Build documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0

- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: "3.10"

Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/generate-visualizations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@ on:
- "docs/**/*.rst"
- ".github/workflows/generate-visualizations.yml"

env:
# Force Node 24 for JS actions still on Node 20 (deprecation 2026-06-16).
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

jobs:
generate-gallery:
name: Build visual comparison gallery
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: "3.10"

Expand Down
12 changes: 8 additions & 4 deletions .github/workflows/publish-to-PyPI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@ on:
permissions:
contents: read

env:
# Force Node 24 for JS actions still on Node 20 (deprecation 2026-06-16).
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

jobs:
run-tests:
name: Run tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: "3.10"

Expand All @@ -34,11 +38,11 @@ jobs:
needs: run-tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0

- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: "3.10"

Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/publish-to-conda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ on:
types: [published]
workflow_dispatch:

env:
# Force Node 24 for JS actions still on Node 20 (deprecation 2026-06-16).
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

jobs:
build-and-test:
name: Build and test conda package
Expand All @@ -19,7 +23,7 @@ jobs:
max-parallel: 5

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0

Expand Down
68 changes: 65 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

Backbone extraction algorithms for complex networks, built on [NetworkX](https://networkx.org/).

This library provides 65 functions across 9 modules for extracting backbone
structures from weighted and unweighted networks.
This library provides 87 functions across 10 modules for extracting backbone
structures from weighted, unweighted, and higher-order (hypergraph) networks.

Full documentation: https://www.brianckeegan.com/networkx_backbone/

Expand Down Expand Up @@ -36,6 +36,7 @@ pip install -e ".[full]"
| **proximity** | Neighborhood-similarity scoring | `jaccard_backbone`, `dice_backbone`, `cosine_backbone`, `hub_promoted_index`, `hub_depressed_index`, `adamic_adar_index`, `resource_allocation_index`, `local_path_index`, and more |
| **hybrid** | Combined approaches | `glab_filter` |
| **bipartite** | Bipartite projection backbones | `simple_projection`, `hyper_projection`, `probs_projection`, `ycn_projection`, `sdsm`, `fdsm`, `fixedfill`, `fixedrow`, `fixedcol`, `backbone` |
| **hypergraph** | Higher-order (hypergraph) backbones | `mdl_hypergraph_backbone`, `hypergraph_compression_ratio`, `intersection_graph`, `maximal_hyperedges`, `order_filter`, `s_components`, `statistically_validated_hypergraph`, `statistically_validated_cores` |
| **unweighted** | Sparsification for unweighted graphs | `sparsify`, `lspar`, `local_degree` |
| **filters** | Post-hoc filtering utilities | `multigraph_to_weighted`, `threshold_filter`, `fraction_filter`, `boolean_filter`, `consensus_backbone` |
| **measures** | Evaluation and comparison | `node_fraction`, `edge_fraction`, `weight_fraction`, `reachability`, `ks_degree`, `ks_weight`, `compare_backbones` |
Expand All @@ -50,6 +51,17 @@ Core method families used in [netbone](https://gitlab.liris.cnrs.fr/coregraphie/
- Structural: `global_threshold_filter`, `global_sparsification`, `primary_linkage_analysis`, `edge_betweenness_filter`, `high_salience_skeleton`, `doubly_stochastic_filter`, `maximum_spanning_tree_backbone`
- Hybrid: `glab_filter`

Every backbone *model* in Neal's
[Backbone 3.0](https://doi.org/10.1371/journal.pone.0349258) R package is also
covered (`disparity`, `mlf`, `lans`, `sdsm`, `fdsm`, `fixedfill`/`fixedrow`/`fixedcol`,
`bicm`, `fastball`, and the `backbone_from_*` wrappers), including its
hypergraph-projection input via `hypergraph_to_bipartite`, plus its
cross-cutting **features**: multiple-testing correction (`adjust_pvalues`,
`threshold_filter(mtc=...)`), **signed** backbones (`signed=True` adds a `sign`
edge attribute), and **SDSM-EC** edge constraints (`sdsm(prohibited=, required=)`).
See [docs/design/backbone-3.0-coverage.md](docs/design/backbone-3.0-coverage.md)
for the full coverage analysis.

## Quick Start

```python
Expand All @@ -70,6 +82,19 @@ print(f"Edges kept: {nb.edge_fraction(G, backbone):.1%}")
print(f"Nodes kept: {nb.node_fraction(G, backbone):.1%}")
```

### Significance options: multiple-testing correction and signed backbones

```python
# Correct p-values for the number of edges tested (Bonferroni, Holm, BH/FDR, BY)
backbone = nb.threshold_filter(scored, "disparity_pvalue", 0.05, mtc="bh")

# Signed backbone: keep significantly strong (+1) and significantly weak (-1)
# edges under a two-tailed test; read direction from the "sign" attribute
signed = nb.disparity_filter(G, signed=True)
strong = nb.threshold_filter(signed, "disparity_pvalue", 0.05, mtc="holm")
positives = [(u, v) for u, v, d in strong.edges(data=True) if d["sign"] == 1]
```

### Disparity filter visualization

![Disparity filter on Les Miserables](docs/_static/graph_gallery/les_miserables/disparity_filter.png)
Expand All @@ -96,6 +121,35 @@ backbone = nb.threshold_filter(scored, "sdsm_pvalue", 0.05, mode="below")
Projection weights follow the simple/hyper/ProbS/YCN formulations described in
[Coscia & Neffke (2017)](https://arxiv.org/abs/1906.09081).

### Hypergraph backbones

Backbone a hypergraph (a collection of arbitrary-size hyperedges) directly:

```python
# Parameter-free MDL backbone -- prunes nested/redundant hyperedges
# (Kirkley, Felippe, Malizia & Battiston, 2026)
H = [(1, 2, 3, 4), (1, 2, 3), (2, 3, 4), (8, 9)]
result = nb.mdl_hypergraph_backbone(H) # method="auto" runs both greedy
print(result.backbone) # [frozenset({1, 2, 3, 4}), frozenset({8, 9})]
print(result.compression_ratio) # inverse compression ratio eta
# method="edge" (fastest single pass) or "node" are also available

# Statistically validated hypergraph (Musciotto, Battiston & Mantegna, 2021)
events = [(1, 2)] * 5 + [(3, 4)] * 100 # repeats = interaction counts
svh = nb.statistically_validated_hypergraph(events, alpha=0.05)
```

Interoperate with the higher-order ecosystem (all optional, lazily imported), or
reuse the bipartite projection backbones via the incidence graph:

```python
B, nodes = nb.hypergraph_to_bipartite(H) # -> NetworkX bipartite graph
scored = nb.sdsm(B, agent_nodes=nodes) # projection backbone of a hypergraph

nb.write_hif(H, "graph.hif") # HIF interchange (xgi/HNX/HGX/HAT)
edges = nb.from_xgi(xgi_hypergraph) # xgi / hypernetx / hypergraphx / hat
```

### Comparing multiple methods

```python
Expand Down Expand Up @@ -137,13 +191,21 @@ Key papers behind the implemented methods:

- Coscia, M. & Neffke, F. M. (2017). [Network backboning with noisy data](https://doi.ieeecomputersociety.org/10.1109/ICDE.2017.100). *Proc. IEEE ICDE*, 425-436.
- Coscia, M. & Neffke, F. M. (2017). [Network backboning with noisy data (arXiv:1906.09081)](https://arxiv.org/abs/1906.09081).
- Dianati, N. (2016). [Unwinding the hairball graph: Pruning algorithms for weighted complex networks](https://doi.org/10.1103/PhysRevE.93.012304). *Physical Review E*, 93, 012304.
- Foti, N. J., Hughes, J. M., & Rockmore, D. N. (2011). [Nonparametric sparsification of complex multiscale networks](https://doi.org/10.1371/journal.pone.0016431). *PLoS One*, 6(2), e16431.
- Girvan, M., & Newman, M. E. J. (2002). [Community structure in social and biological networks](https://doi.org/10.1073/pnas.122653799). *PNAS*, 99(12), 7821-7826.
- Godard, K., & Neal, Z. P. (2022). [fastball: A fast algorithm to sample bipartite graphs with fixed degree sequences](https://doi.org/10.1093/comnet/cnac049). *J. Complex Networks*, 10(6), cnac049.
- Grady, D., Thiemann, C., & Brockmann, D. (2012). [Robust classification of salient links in complex networks](https://doi.org/10.1038/ncomms1847). *Nature Communications*, 3, 864.
- Hamann, M., Lindner, G., Meyerhenke, H., Staudt, C. L., and Wagner, D. (2016). [Structure-Preserving Sparsification Methods for Social Networks](https://doi.org/10.1007/s13278-016-0332-2). Social Network Analysis and Mining, 6, 22.
- Simas, T., Correia, R. B., & Rocha, L. M. (2021). [The distance backbone of complex networks](https://doi.org/10.1093/comnet/cnab021). *J. Complex Networks*, 9(6), cnab021.
- Neal, Z. P. (2014). [The backbone of bipartite projections](https://doi.org/10.1016/j.socnet.2014.06.001). *Social Networks*, 39, 84-97.
- Neal, Z. P., Domagalski, R., & Sagan, B. (2021). [Comparing alternatives to the fixed degree sequence model for extracting the backbone of bipartite projections](https://doi.org/10.1038/s41598-021-03238-3). *Scientific Reports*, 11, 23929.
- Neal, Z. P. (2022). [backbone: An R package to extract network backbones](https://doi.org/10.1371/journal.pone.0269137). *PLoS One*, 17(5), e0269137.
- Satuluri, V., Parthasarathy, S., & Ruan, Y. (2011). [Local graph sparsification for scalable clustering](https://doi.org/10.1145/1989323.1989399). *SIGMOD*, 721-732.Serrano, M. A., Boguna, M., & Vespignani, A. (2009). [Extracting the multiscale backbone of complex weighted networks](https://doi.org/10.1073/pnas.0808904106). *PNAS*, 106(16), 6483-6488.
- Neal, Z. P. (2026). [Backbone 3.0: An R package for extracting network backbones](https://doi.org/10.1371/journal.pone.0349258). *PLoS One*, 21, e0349258.
- Neal, Z. P., & Neal, J. W. (2023). [Stochastic Degree Sequence Model with Edge Constraints (SDSM-EC) for Backbone Extraction](https://doi.org/10.1007/978-3-031-53468-3_11). *Complex Networks 12*, 127-136.
- Saracco, F., Di Clemente, R., Gabrielli, A., & Squartini, T. (2015). [Randomizing bipartite networks: the case of the World Trade Web](https://doi.org/10.1038/srep10595). *Scientific Reports*, 5, 10595.
- Satuluri, V., Parthasarathy, S., & Ruan, Y. (2011). [Local graph sparsification for scalable clustering](https://doi.org/10.1145/1989323.1989399). *SIGMOD*, 721-732.
- Serrano, M. A., Boguna, M., & Vespignani, A. (2009). [Extracting the multiscale backbone of complex weighted networks](https://doi.org/10.1073/pnas.0808904106). *PNAS*, 106(16), 6483-6488.
- Van Nuffel, N., Heyndrickx, C., & Wets, G. (2010). Measuring hierarchy and reciprocity in networks.
- Yassin, A., Haidar, A., Cherifi, H., Seba, H., & Togni, O. (2023). [An evaluation tool for backbone extraction techniques in weighted complex networks](https://doi.org/10.1038/s41598-023-42076-3). *Scientific Reports*, 13, 17000.
- Yassin A., Cherifi, H., Seba, H., & Togni, O. (2025). [Backbone extraction through statistical edge filtering: A comparative study](https://doi.org/10.1371/journal.pone.0316141). *PLoS One*, 20(1): e0316141.
Expand Down
2 changes: 2 additions & 0 deletions docs/api/filters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ Complexity classes are provided in each function docstring.
.. autofunction:: boolean_filter

.. autofunction:: consensus_backbone

.. autofunction:: adjust_pvalues
87 changes: 87 additions & 0 deletions docs/api/hypergraph.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
Hypergraph Methods
==================

Methods that operate directly on hypergraphs (collections of arbitrary-size
hyperedges) rather than on dyadic graphs. Inputs are plain iterables of
hyperedges (each hyperedge an iterable of node labels); the backbone is returned
as a list of :class:`frozenset` hyperedges inside a
:class:`~networkx_backbone.HypergraphBackbone` result.

The :func:`~networkx_backbone.mdl_hypergraph_backbone` method implements the
parameter-free, information-theoretic (minimum description length) backbone of
Kirkley, Felippe, Malizia & Battiston (2026), which prunes nested and redundant
hyperedges and naturally extends to weighted hypergraphs.

.. automodule:: networkx_backbone.hypergraph
:no-members:

.. currentmodule:: networkx_backbone

.. autofunction:: mdl_hypergraph_backbone

.. autofunction:: hypergraph_compression_ratio

.. autofunction:: intersection_graph

.. autoclass:: HypergraphBackbone
:no-members:

.. rubric:: Structural methods

Purely structural hypergraph backbones and utilities with no dyadic analog.
These return plain hyperedge collections rather than a
:class:`~networkx_backbone.HypergraphBackbone`.

.. autofunction:: maximal_hyperedges

.. autofunction:: order_filter

.. autofunction:: s_components

.. rubric:: Statistical methods

Hypothesis-testing hypergraph backbones that validate hyperedges/groups
recurring more than expected under a null model (Musciotto, Battiston &
Mantegna, 2021). These require ``scipy`` and return a
:class:`~networkx_backbone.ValidatedHypergraph`.

.. autofunction:: statistically_validated_hypergraph

.. autofunction:: statistically_validated_cores

.. autoclass:: ValidatedHypergraph
:no-members:

.. rubric:: Interoperability and ingestion

Convert between the hyperedge-list representation and a NetworkX incidence
bipartite graph (enabling the bipartite projection backbones), the HIF
interchange format, and the ``xgi`` / ``HyperNetX`` / ``HypergraphX`` / HAT
hypergraph classes. The third-party libraries are optional and imported lazily.

.. automodule:: networkx_backbone.hypergraph_io
:no-members:

.. currentmodule:: networkx_backbone

.. autofunction:: hypergraph_to_bipartite

.. autofunction:: read_hif

.. autofunction:: write_hif

.. autofunction:: from_xgi

.. autofunction:: to_xgi

.. autofunction:: from_hypernetx

.. autofunction:: to_hypernetx

.. autofunction:: from_hypergraphx

.. autofunction:: to_hypergraphx

.. autofunction:: from_hat

.. autofunction:: to_hat
10 changes: 7 additions & 3 deletions docs/api/index.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
API Reference
=============

Complete API documentation for backbone functions across 9 modules.
Complete API documentation for backbone functions across 10 modules.
API examples are standardized on ``nx.les_miserables_graph()`` for
non-bipartite methods and ``nx.davis_southern_women_graph()`` for
bipartite methods.
Expand Down Expand Up @@ -32,12 +32,15 @@ an aggregate summary in :doc:`../user_guide/complexity`.
* - :doc:`bipartite`
- 11
- Projection backbones, fixed null models, and high-level wrappers
* - :doc:`hypergraph`
- 12
- MDL backbone, compression ratio, intersection / s-line graph, inclusion (toplex) reduction, order filter, s-components, and statistically validated hypergraphs / cores
* - :doc:`unweighted`
- 3
- Sparsification for unweighted graphs (LSpar, local degree)
* - :doc:`filters`
- 5
- Post-hoc filtering utilities and graph-conversion support
- 6
- Post-hoc filtering utilities, multiple-testing correction, and graph-conversion support
* - :doc:`measures`
- 7
- Evaluation measures for comparing backbones
Expand All @@ -54,6 +57,7 @@ an aggregate summary in :doc:`../user_guide/complexity`.
proximity
hybrid
bipartite
hypergraph
unweighted
filters
measures
Expand Down
Loading
Loading