Skip to main content

Graph Dependence

This repository contains the reference implementation for Dependence Is Not Advantage: What Randomizing the Graph Does Not Measure. The paper is by Prahas Duggireddy and the package is maintained by Third Wheel.

The package reports two comparisons that are easy to mix up in graph-ablation studies:

  • Dependence: how a graph procedure changes when the observed graph is replaced by a stated graph null.
  • Advantage: how that procedure compares with a named scorer that does not receive the graph.

Randomization answers the first question. It does not answer the second one by itself. The implementation is intentionally small, typed, and close to these definitions. Version 0.1.0 is an early reference implementation, not a general graph-learning framework or a full reproduction of the paper.

Paper and project links:

Quick start

The smallest complete example needs no network access. From a checkout:

python -m pip install .
python examples/minimal.py

It uses a fixed graph, fixed node-content features, a degree-preserving null, and seed 7. The command prints a JSON-compatible report that is small enough to read alongside the source.

For an evaluation of your own, the central call looks like this:

from graph_dependence import DegreePreservingNull, binary_auc, diagnose

# Provide these objects from your evaluation protocol.
report = diagnose(
    graph=graph,
    examples=examples,
    targets=targets,
    graph_scorer=score_with_graph,
    graph_free_scorer=score_without_graph,
    null_model=DegreePreservingNull(attempts_per_edge=10),
    metric=binary_auc,
    null_draws=10,
    seed=7,
)
print(report.to_dict())

The call keeps the intact, null, and graph-free comparator scores together. The resulting report can be serialized with to_dict() without a custom encoder.

What the report means

Field Comparison Interpretation
dependence observed_score - null_score Change under the declared graph intervention.
advantage observed_score - comparator_score Difference from the named graph-free scorer.
null_survival null_score / observed_score Fraction of the observed score that remains after randomization.

advantage is None when no graph-free scorer is supplied. null_survival is None when the observed score is not positive, because the ratio is undefined there. The report also records the three reference scores, the seed, the null model name, and sampler diagnostics.

The public API

Symbol Use
diagnose Evaluate the intact, null, and optional graph-free arms and return one report.
DegreePreservingNull Generate fixed-budget double-edge-swap null graphs and record the checks performed.
DependenceReport Store scores, contrasts, seed, and metadata; to_dict() returns JSON-compatible values.
binary_auc Provide a small dependency-free binary ranking metric for examples and tests.
GraphScorer, GraphFreeScorer, Metric, NullModel Define the typed callable boundaries supplied by the caller.

The formal definitions, empirical results, and claim boundaries remain in the paper. The package implements the diagnostic around them; it does not recreate the paper's training runs or manuscript tables.

Supplying scorers and metrics

A graph scorer receives a NetworkX graph and the evaluation examples. A graph-free scorer receives the same examples without the graph. Both return one score per example. A metric receives those scores and the targets and returns a scalar, with larger values meaning better performance.

def score_with_graph(graph, examples):
    return [len(list(nx.common_neighbors(graph, u, v))) for u, v in examples]


def score_without_graph(examples):
    return [content_similarity[u, v] for u, v in examples]

Custom scorers and metrics are ordinary callables. If a scorer trains a model or uses randomness, condition-specific fitting and seed control are the caller's responsibility. The seed argument controls null generation only.

The degree-preserving null

DegreePreservingNull applies a fixed budget of double-edge-swap attempts to an undirected, simple, unweighted graph. It rejects self-loops, duplicate edges, and new edges listed in forbidden_edges. Each draw records accepted swaps, edge retention, component counts, and explicit degree and edge-count checks.

Degree preservation describes a constraint, not a unique probability distribution. The implementation records its sampler and budget and does not claim uniform sampling over all graphs with the same degree sequence. Edge attributes are rejected because assigning them to newly formed edges would silently define a different intervention.

Public-data example

examples/cora.py downloads the public Cora citation graph, constructs a deterministic link-prediction split, and compares common-neighbor scores with a graph-free bag-of-words Jaccard scorer:

python examples/cora.py

This is an API example, not a reproduction of the paper's Cora row. The paper uses the published HeaRT split, its hard negatives, and Hits@20. The example uses a small deterministic split and AUC so that it can remain independent of a training framework.

Repository layout

src/graph_dependence/  package implementation and py.typed marker
examples/minimal.py    deterministic, network-free example
examples/cora.py       optional public-data example
tests/                 package and scientific-boundary tests
site/                  paper page, searchable PDF, figure, and citations

The paper and visible landing page are authoritative for scholarly claims. pyproject.toml is authoritative for package version and support metadata; CITATION.cff is authoritative for software citation metadata.

Scope

This repository does not train GraphSAGE, recreate manuscript tables, prescribe a universally valid null model, or turn predictive improvement into evidence of downstream recommendation benefit. It is a reference implementation for separating dependence from advantage in an evaluation protocol.

For the formal definitions and empirical study, see the paper. For software reuse, cite the version used and see CITATION.cff.

Development

The package supports Python 3.11 and newer. To run the local checks after an editable install:

python -m pip install -e '.[dev]'
ruff check .
mypy --strict .
pytest --cov=graph_dependence --cov-branch

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

graph_dependence-0.1.0.tar.gz (1.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

graph_dependence-0.1.0-py3-none-any.whl (14.8 kB view details)

Uploaded Python 3

File details

Details for the file graph_dependence-0.1.0.tar.gz.

File metadata

  • Download URL: graph_dependence-0.1.0.tar.gz
  • Upload date:
  • Size: 1.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for graph_dependence-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2285965c1c604b4cb1bd10beabb2f03e735aae674f0c719dbb35fb0df7836855
MD5 19ad9d02ed71801a4e93a9c9aa3a7aef
BLAKE2b-256 b64451a6142086c7080b3c435804a2e1baaa71e8beb8dbc54160a6323815b68c

See more details on using hashes here.

File details

Details for the file graph_dependence-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for graph_dependence-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7cad3eb4dada382e271716a722edc3914ea5609d5140ccc391044ae1e18c22ac
MD5 87618fbe91504f9c4f87d797902f8485
BLAKE2b-256 cea164e958d40ceb016bd21b94b9a5d10d73505dd5e53c7b335de367ac9c7c72

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page