Skip to content

Track: Track2; Team name: r2; Model: PolynomialFilterTNN + FilterBankTNN (SNN/SCNN) - #414

Open
aniervs wants to merge 22 commits into
geometric-intelligence:mainfrom
aniervs:track2-tnn
Open

Track: Track2; Team name: r2; Model: PolynomialFilterTNN + FilterBankTNN (SNN/SCNN)#414
aniervs wants to merge 22 commits into
geometric-intelligence:mainfrom
aniervs:track2-tnn

Conversation

@aniervs

@aniervs aniervs commented Aug 1, 2026

Copy link
Copy Markdown

Checklist

  • My pull request has a clear and explanatory title.
  • My pull request passes the Linting test.
  • I added appropriate unit tests and I made sure the code passes all unit tests. (refer to comment below)
  • My PR follows PEP8 guidelines. (refer to comment below)
  • My code is properly documented, using numpy docs conventions, and I made sure the documentation renders properly.
  • I linked to issues and PRs that are relevant to this PR.

Thesis

This PR extends the "GNNs/TNNs are polynomial filters in a Laplacian-like operator" program to the topological domain. It contributes two modular simplicial backbones: PolynomialFilterTNN (a single polynomial filter in the Hodge Laplacian L_k, per rank) and FilterBankTNN (a two-channel down/up filter bank over the Hodge decomposition). They reuse the same swappable Basis registry as the Track-1 graph backbones, with the graph Laplacian replaced by the Hodge Laplacian L_k. SNN (Ebli et al. 2020) is PolynomialFilterTNN with the Chebyshev basis; SCNN (Yang et al. 2022) is FilterBankTNN with the Monomial basis.

Scope of this diff — builds on #354 and #360

This PR is stacked on the team's two Track-1 PRs and reuses their graph-side spectral modules on the Hodge Laplacian (a Basis only ever sees an L_apply closure, so the graph bases act on L_k verbatim). Because #354 and #360 are not yet merged into main, this diff necessarily re-includes their files. But the new contribution here is the 17 simplicial files below; everything else is inherited and reviewed in those PRs.

New in this PR

  • Backbones — topobench/nn/backbones/simplicial/{poly_filter_tnn, filter_bank_tnn, hodge_utils}.py
  • Wrappers — topobench/nn/wrappers/simplicial/{poly_filter_tnn, filter_bank_tnn}_wrapper.py
  • Configs — configs/model/simplicial/{poly_filter_tnn, poly_filter_tnn_monomial, poly_filter_tnn_jacobi, filter_bank_tnn}.yaml
  • Tests — test/nn/backbones/simplicial/test_{poly_filter_tnn, filter_bank_tnn}.py + the simplicial entries in test/pipeline/test_pipeline.py
  • Results — 2026_tdl_challenge/outputs/results_tnn_*.json, comparison_tnn.csv

Reused (inherited, not new)Basis + apply_polynomial_filter from #354 (backbones/graph/poly_filter/); Channel + SumFusion from #360 (backbones/graph/filter_bank/).

What's new relative to what TopoBench/TopoModelX already ship

TopoModelX (a TopoBench dependency) already provides fixed simplicial layers (SCN2, SCCN, SCCNN, SAN), and TopoBench exposes them as configs. This PR is not a re-wrap of those. The contribution is a modular, basis-swappable Hodge-spectral backbone plus two concrete correctness improvements over the existing code:

  1. A real Chebyshev basis on L_k. TopoModelX's SCNNLayer.chebyshev_conv (scnn_layer.py:135) is, despite its name, a monomial power iteration (X[:,:,k] = conv_operator @ X[:,:,k-1], i.e. L^k x) with no spectral normalization. Our Chebyshev basis runs the true three-term recurrence T_k = 2 z T_{k-1} - T_{k-2} in z = L̃ - I, and SNN (a Chebyshev polynomial in L_k) is absent from TopoModelX entirely.
  2. A λmax spectral rescale. Orthogonal-interval bases (Chebyshev, Jacobi, Legendre) are only bounded on [-1, 1]; the raw Hodge spectrum is [0, λmax]. laplacian_norm='rescale' maps L_k → 2 L_k / bound (spectrum ⊆ [0, 2]) via a deterministic Gershgorin upper bound, so the basis stays inside its domain. Without it, a naive "Chebyshev/Jacobi on the raw Hodge Laplacian" blows up super-exponentially (this is the concrete bug the rescale fixes; pinned by test_rescale_maps_spectrum_to_0_2).

Architecturally, FilterBankTNN with Monomial + laplacian_norm='raw' is the TopoModelX SCNN layer's math (per rank down/up monomial powers, γ-fused), modulo one documented redundant identity term — so it is a faithful, first-in TopoBench runnable SCNN, and swapping the basis or turning on rescale generalizes it to the higher-order spectral filters TopoModelX cannot express.

Design rationale — why two backbones, one registry

A single polynomial filter and a filter bank are structurally different forward passes (Σ_k θ_k T_k(L_k) x vs fuse_q γ_q g_q(L_k) x), so they are two backbones — but both are operator-agnostic: a Basis only ever sees a closure L_apply : h ↦ L h and never the domain. That single interface decision is what lets the graph bases (Monomial, Chebyshev, Jacobi, Legendre, …) act on the Hodge Laplacian verbatim — the simplicial backbones import apply_polynomial_filter, Channel, and the basis modules from the graph side unchanged. Adding a new basis is a single-file change on both domains at once.

Taxonomy placement

The registered bases are the Hodge-Laplacian instantiations of the same Liao et al. (2024, SIGMOD, Appendix B) polynomial families used in Track 1:

Config Backbone Basis (Liao App. B) Published model
simplicial/poly_filter_tnn PolynomialFilterTNN Chebyshev SNN (Ebli et al. 2020)
simplicial/poly_filter_tnn_monomial PolynomialFilterTNN Monomial SCN/SCCNN power pattern
simplicial/poly_filter_tnn_jacobi PolynomialFilterTNN Jacobi (α,β) JacobiConv-in-L_k
simplicial/filter_bank_tnn FilterBankTNN Monomial (down/up) SCNN (Yang et al. 2022)

Per-model citations

  • SNN — Ebli, Defferrard & Spreemann (2020), Simplicial Neural Networks (NeurIPS TDA workshop). A Chebyshev polynomial in L_k per rank.
  • SCNN — Yang, Isufi & Leus (2022), Simplicial Convolutional Neural Networks (ICASSP 2022, arXiv 2110.02585). Separate filters on L^down_k / L^up_k, fused — the Hodge-decomposition filter bank.
  • Basis recurrences — Liao et al. (2024, SIGMOD), Appendix B (canonical translation); Wang & Zhang (2022, arXiv 2205.11172) for Jacobi.
  • Hodge-filtering foundation — Barbarossa & Sardellitti (2020, IEEE TSP, arXiv 1907.11577); Isufi et al. (2024, arXiv 2412.01576).

Evaluation — GraphUniverse sweep (12 settings × 3 seeds)

Full challenge grid (community detection, node accuracy ↑; triangle counting, MSE ↓), mean ± std over the homophily/degree/cluster-variance families:

Model Community detection (acc ↑) Triangle counting (MSE ↓)
SNN (Chebyshev) 0.437 ± 0.114 23,140 ± 49,065
Monomial 0.390 ± 0.140 34,531 ± 86,186
Jacobi 0.432 ± 0.110 15,368 ± 30,757
SCNN (down/up bank) 0.437 ± 0.120 11,333 ± 26,166

Two findings that track the theory:

  1. Basis choice matters on the Hodge Laplacian too. The raw Monomial power basis is worst on both tasks; every structured spectral basis (Chebyshev, Jacobi) and the filter bank beat it — the simplicial analogue of Liao's RQ on basis conditioning (RQ3/RQ7), now on L_k.
  2. The filter bank wins triangle counting by a wide margin (MSE 11.3k vs 34.5k for Monomial). Triangle counting is fundamentally a 2-simplex / up-Laplacian quantity, and FilterBankTNN is the only model here that tunes the curl (L^up) and gradient (L^down) components independently — so the architecture wins exactly where the Hodge decomposition predicts it should.

Baseline note. The GraphUniverse paper (Van Langendonck et al. 2026) reports topological baselines only for TopoTune and Neural Sheaf Diffusion (not the SCNN/SCN/SNN family), and uses normalized MAE for triangle counting, so no published number is directly comparable to the SCNN/SNN-family MSE results above. simplicial/topotune is a TopoBench config and can be run on this exact grid for a same-protocol comparison if reviewers want one.

Scope / what this PR does not do

  • No inter-rank coupling. These are per-rank filters (SCNN/SNN family), not SCCNN-style cross-dimension convolutions— that is a distinct architecture and out of scope here.
  • Reuse-in-place. The simplicial backbones import the operator-agnostic spectral core (apply_polynomial_filter, Channel, bases) from graph/; an optional follow-up could be to move it to a domain-neutral spectral/ module. This shouldn't change any behavior.
  • Batch-global λmax bound. The Gershgorin rescale uses one bound per operator; documented, and safe (guaranteed ⊆ [0, 2], may under-fill).

Tests

15 new unit tests (per-rank forward, sparse + empty-rank layouts, basis swap on L_k, deterministic Gershgorin bound) + all four configs added to the pipeline test (end-to-end on auto-lifted MUTAG). ruff + numpydoc clean.

aniervs and others added 21 commits June 10, 2026 07:57
Add a single-polynomial-filter graph backbone that implements

    y = post(sum_{k=0..K} theta_k * T_k(L_norm) * pre(x))

where {T_k} is a polynomial sequence produced by a swappable basis.
The backbone owns the propagation loop, the coefficients theta_k, the
accumulation, the pre/post MLPs, the Laplacian normalization
convention, and the (x, edge_index, batch, edge_weight) interface
expected by GNNWrapper. The basis owns the recurrence and any
parameters the recurrence needs.

The basis interface (poly_filter/basis.py) is:

    class Basis(nn.Module):
        def init(self, x, L_apply) -> u_0
        def effective_thetas(self, backbone_theta) -> theta_eff
        def forward(self, u_prev, u_prev_prev, L_apply, signal, k) -> u_k

with a single uniform forward signature shared by signal-independent
and signal-dependent bases. Bases are nn.Module subclasses so they can
own learnable parameters. The backbone treats every basis as opaque
and never branches on the concrete class. Adding a new basis is a
single new file plus a Hydra _target_ swap.

Reference: Liao et al. (2024) "A Comprehensive Benchmark on Spectral
GNNs", SIGMOD '26, arXiv:2406.09675 -- survey unifying every variable-
basis spectral GNN under this recurrence-in-L_norm template.

Concrete bases land in a follow-up commit.
Register seven bases under topobench.nn.backbones.graph.poly_filter.bases,
each a Basis subclass with the recurrence transcribed from Liao
Appendix B and the corresponding primary paper:

- Monomial: u_k = L_norm * u_{k-1} (GPR-GNN family;
  Chien, Peng, Li & Milenkovic 2021, arXiv:2006.07988).
- Chebyshev (first kind): three-term recurrence; boundary at k=1
  handled inside the basis via u_prev_prev=None. Covers ChebNet
  (Defferrard et al. 2016, arXiv:1606.09375) and ChebBase
  (He, Wei & Wen 2022, arXiv:2202.03580).
- ChebNetII: Chebyshev recurrence + interpolation reparameterization
  of theta via the discrete Chebyshev transform at Chebyshev nodes
  (He, Wei & Wen 2022). The only basis here that uses the
  effective_thetas protocol hook; the backbone's theta is inert by
  design.
- Jacobi(alpha, beta): three-term recurrence with k-dependent
  coefficients (Wang & Zhang 2022, arXiv:2205.11172). First basis
  where the k argument is genuinely consumed.
- Legendre: shipped as Jacobi(alpha=0, beta=0). Liao's standalone
  Legendre recurrence uses z=L_norm directly, which evaluates P_k
  outside its [-1, 1] orthogonality interval (L_norm has eigenvalues
  in [0, 2]) and grows as Theta(3^k/sqrt(k)) at the spectrum
  boundary. The Jacobi reparameterization shifts to z=I-L_norm and
  is uniformly bounded. Documented as the deviation from Liao's
  literal formula.
- FavardGNN: three-term recurrence with learnable coefficients
  a_k = sqrt(alpha_k) (parameterized via softplus to guarantee
  positivity) and beta_k (Guo & Wei 2023, arXiv:2302.12432).
  First basis owning learnable parameters of its own.
- OptBasisGNN: Lanczos-style orthonormal recurrence where alpha, gamma
  are derived from inner products on the running signal u_prev
  (Guo & Wei 2023, arXiv:2302.12432, Theorem 4.1). The signal-
  dependent basis in the registry; demonstrates the uniform-signature
  protocol survives the load-bearing case.

Add the Hydra config configs/model/graph/polynomial_filter_gnn.yaml
defaulting to Chebyshev; bases are swappable via the CLI override
model.backbone.basis._target_=...<Name>.

Bernstein is deliberately omitted: Liao Appendix B presents it in
closed form per k (O(K^2 m F) vs O(K m F) for every other variable
basis), so it does not fit the three-term recurrence protocol
without stretching the abstraction. Deferred.
Add 70 unit tests under test/nn/backbones/graph/test_polynomial_filter_gnn.py
covering:

- TestPolynomialFilterGNN: backbone propagation loop is basis-agnostic;
  basis receives the uniform (u_prev, u_prev_prev, L_apply, signal, k)
  signature on every step; default Basis.init returns the signal
  untouched; backbone runs under sym/rw/none Laplacian normalizations;
  the _build_laplacian_apply closure matches a hand-computed symmetric
  Laplacian on a path graph; K=0 and invalid-K guard.
- TestMonomialBasis: single-step recurrence applies L_apply once;
  stateless w.r.t. signal and k.
- TestChebyshevBasis: k=1 boundary returns L u_0 (not 2L u_0); for
  L = alpha*I the basis collapses to T_k(alpha)*x for classical
  first-kind T_k.
- TestJacobiBasis: hyperparameter validation; k=1 closed form at L=0;
  for L = gamma*I the basis collapses to P_k^{(alpha,beta)}(1-gamma)*x
  computed from Liao's own recurrence; symmetric (alpha=beta) case
  kills the middle delta'_k term cleanly.
- TestLegendreBasis: literal equivalence to Jacobi(0, 0) on every k;
  uniform boundedness |u_k| <= 1 across the full L eigenvalue range
  [0, 2] -- the property that motivated shipping Jacobi(0, 0) rather
  than Liao's standalone z=L Legendre formula.
- TestChebNetIIBasis: M[k, kappa] = (2/(K+1)) * T_k(x_kappa) matches
  hand computation for K=2; effective_thetas returns M @ theta_interp
  ignoring backbone_theta; K mismatch raises ValueError; gradient
  reaches basis.theta_interp and backbone.theta.grad is None by
  design.
- TestFavardGNNBasis: 2(K+1) learnable parameters; softplus keeps
  a_k strictly positive at extreme raw values; k=1 and k=2 closed
  forms; gradients flow to both a_raw and beta.
- TestOptBasisGNN: init normalizes per-channel and resets state;
  OptBasis(c*x) = OptBasis(x) scale invariance (the literal signature
  of signal-dependence), contrasted with Chebyshev(c*x) = c*Chebyshev(x);
  Lanczos orthonormality <u_k, u_j> approx delta_{kj}; repeated
  forward passes do not leak state across each other.
- TestPolynomialFilterGNNHydraConfig: full run.yaml composes with
  graph/polynomial_filter_gnn + graph/MUTAG; basis swaps via
  model.backbone.basis._target_ overrides for Monomial, Jacobi (with
  hyperparameters), Legendre, ChebNetII (with K interpolation from
  the backbone), FavardGNN (with K interpolation), and OptBasisGNN.

Add graph/polynomial_filter_gnn to MODELS in test/pipeline/test_pipeline.py
so the backbone trains 2 epochs on MUTAG as part of the standard
wire-up gate.
Three style consistency fixes across the new poly_filter/ subpackage
and its tests:

- Switch docstrings that carry .. math:: blocks to raw strings
  (r"""..."""). The runtime content is unchanged, but source code now
  shows \tilde L, \sum, \frac directly instead of \\tilde L, \\sum,
  \\frac. Easier to read and edit.

- Pick one form for the normalized Laplacian per context: \tilde L
  inside .. math:: blocks (where Sphinx renders it), and the Unicode
  character L_tilde everywhere else in prose. Previously mixed across
  the same file.

- Drop em dashes throughout in favour of ASCII punctuation (colons
  for explanatory clauses, semicolons or parentheses elsewhere).
  Matches the rest of the project's plain-ASCII docstring style.

No behaviour change. All pre-commit hooks (ruff, ruff-format,
numpydoc-validation) pass; 70/70 polynomial-filter tests pass.
Add one standalone model config per registered basis so each can be
selected in the TDL challenge evaluation notebook via a single
MODEL_CONFIG string (the notebook is unmodifiable and takes only a
config path, not basis overrides):

  graph/polynomial_filter_gnn_monomial
  graph/polynomial_filter_gnn_chebyshev
  graph/polynomial_filter_gnn_chebnetii
  graph/polynomial_filter_gnn_jacobi
  graph/polynomial_filter_gnn_legendre
  graph/polynomial_filter_gnn_favard
  graph/polynomial_filter_gnn_optbasis

Each file mirrors polynomial_filter_gnn.yaml; only the basis block and
model_name differ. The hyperparameterized bases pin their extra args:
ChebNetII and FavardGNN set K: ${model.backbone.K} so the basis size
tracks the backbone degree, and Jacobi sets explicit alpha=beta=1.0.
Distinct model_name values keep per-basis output dirs and results.json
from colliding.

All seven verified end-to-end through the challenge harness
(topobench.run.run) on both tasks (community_detection node-level,
triangle_counting graph-level), 1 epoch each: 14/14 configs compose,
instantiate the correct basis, and train without error. The default
polynomial_filter_gnn.yaml (Chebyshev) is unchanged and remains the
config exercised by the unit and pipeline tests.
One results.json per registered PolynomialFilterGNN basis, produced by the
challenge harness over the full 12-setting x 3-seed grid on both tasks
(community detection, triangle counting): 72 runs per basis, 504 total.
Includes comparison_summary.csv (in-distribution + OOD aggregate per basis).
Tracked under 2026_tdl_challenge/outputs/ as the challenge submission files.
Register the Bernstein (Bezier) basis, completing coverage of every
variable basis in Liao Appendix B. It is the one non-orthogonal,
closed-form member:

    g(L_norm; theta) = sum_k (theta_k / 2^K) C(K,k) (2I-L_norm)^(K-k) L_norm^k

It fits the unchanged Basis.forward(u_prev, u_prev_prev, L_apply, signal,
k) signature by ignoring the recurrence arguments (the way signal-
independent bases ignore signal) and building each u_k from the input
signal; the binomial / 2^K normalization is folded in via
effective_thetas (a scaling, not a replacement), so the backbone's theta
stays learnable. Takes K in __init__ like ChebNetII/FavardGNN (binomials
are baked in), wired in the config as K: ${model.backbone.K}.

This is the only O(K^2 m F) basis -- the fingerprint of not having the
orthogonal-polynomial three-term-recurrence structure -- documented in
bernstein.py. The partition-of-unity property (all theta_k = 1 gives the
identity filter) is the load-bearing correctness test.

Primary reference: He et al. (2021) "BernNet: Learning Arbitrary Graph
Spectral Filters via Bernstein Approximation" (NeurIPS, arXiv:2106.10994).

Adds bernstein.py, registry entry, polynomial_filter_gnn_bernstein.yaml,
and TestBernsteinBasis (+ Hydra smoke). 79 poly-filter tests pass.
This submission only contributes the polynomial-filter backbone, so the
pipeline smoke test runs just graph/polynomial_filter_gnn (the default
Chebyshev basis), which exercises the encoder -> wrapper -> readout ->
loss -> trainer wire-up for the new backbone.
Bernstein full-grid results (12 settings x 3 seeds x 2 tasks = 72 runs)
from the challenge harness, and the regenerated comparison_summary.csv
now covering all eight bases.

Bernstein lands in the expressive-basis cluster: 4th of 8 on community
detection (in-dist 0.492, OOD 0.438, tied with Favard/Jacobi/Legendre)
and 7th on triangle counting (mse 41.6k) -- the same classification-vs-
regression inversion the other flexible bases show.
…ference

Cross-checked against Liao et al. (2024) "A Comprehensive Benchmark on
Spectral GNNs" official code (gdmnl/Spectral-GNN-Benchmark). These change
the trained model and require retraining all bases:

- Chebyshev: run the recurrence in (L̃ - I) in [-1, 1] rather than
  L̃ in [0, 2] (the standard ChebNet rescale, matching Liao's 'L-I'
  scheme). Keeps T_k bounded; the previous argument blew up at the
  high-frequency end of the spectrum.
- Laplacian: add GCN self-loop renormalization
  (Â = D̂^{-1/2}(A+I)D̂^{-1/2}, L̃ = I - Â) behind a `self_loops` flag
  (default True), matching Liao's gen_norm. Affects every basis.
- ChebNetII: DC half-weight on the interpolation matrix and a ReLU on
  the learnable node values, matching Liao's chebii_conv.
- Legendre: correct the docstring -- our Jacobi(α=β=0) form evaluated at
  Â agrees with Liao's legendre_conv; it does not deviate from it.

Also a framework-neutral documentation pass over the poly_filter
docstrings, test docstrings, and config comments (standard Hydra-override
usage in configs).
…fixes

Re-ran the full GraphUniverse grid (8 bases x 12 settings x 3 seeds x 2
tasks = 576 runs) on the convention-aligned models (b11a542): Chebyshev
domain rescale to [-1,1], GCN self-loop renormalization, and the
ChebNetII interpolation fixes.

ChebNetII is repaired: community-detection accuracy 0.344 -> 0.491 (it
was previously stuck at the heterophily floor across all homophily
levels). The CD spread across bases tightens to 0.481-0.498, and the
triangle-counting ranking shifts -- Chebyshev/Monomial no longer lead it,
ChebNetII/OptBasis now do.
A multi-channel backbone for the filter-bank pattern
y = fuse_q(gamma_q * g_q(L̃) x): Q parallel polynomial filters fused with
learnable channel weights gamma. Each channel reuses the polynomial-filter
basis registry; the backbone owns gamma and the pre/post MLPs and delegates
combination to a swappable Fusion.

Variants (Liao et al. 2024 filter-bank category, cross-checked against the
official gdmnl/Spectral-GNN-Benchmark code):
- ACMGNN  -- LP + HP + identity linear filters (Luan et al. 2022)
- FBGNN   -- LP + HP linear filters (Luan et al. 2022)
- FAGCN   -- LP + HP with a scaling hyperparameter (Bo et al. 2021)
- GNNLFHF -- two PPR channels with an (I +/- beta*L̃) prefactor (Zhu et al. 2021)
- FiGURe  -- Q learnable-theta channels, canonical Monomial/Chebyshev/
             Bernstein set (Ekbote et al. 2023)
- G2CN    -- two Gaussian band-pass channels, sum alpha^k/k! ((1+/-beta)I-L̃)^(2k)
             (Li et al. 2022)

The Laplacian uses the same GCN self-loop renormalization as
PolynomialFilterGNN. Scoped out: AdaGNN (per-feature diagonal filtering, not a
gamma-fused parallel bank) and the original models' node-wise attention /
unsupervised pretraining (the channel-weighted-sum spectral forms are shipped).

Unit tests for every variant plus the shared Channel/Fusion/GaussianChannel
helpers, per-variant Hydra instantiation, and the pipeline test now covering
all six variants on MUTAG.
Full GraphUniverse grid (6 variants x 12 settings x 3 seeds x 2 tasks =
432 runs) for the FilterBankGNN backbone, plus the comparison table.

FiGURe leads (CD 0.499, TRI 42.6k), matching the best single polynomial
filter -- its free degree-K channels recover the poly-filter ceiling.
G2CN / GNN-LF-HF sit mid-pack (CD ~0.467); the three linear banks
(ACM-GNN / FAGCN / FBGNN) span the same {aI + bL̃} family and land
identically at CD 0.406. Channel expressiveness, not the bank structure,
drives the ranking.
The polynomial-filter and filter-bank result JSONs + comparison tables
belong to the Track-1 PRs (geometric-intelligence#354, geometric-intelligence#360); they are removed here so this
Track-2 branch, opened standalone against main, carries only the shared
code it depends on plus the new TNN work -- not another PR's benchmark
outputs.
Two spectral simplicial backbones that reuse the graph-side polynomial
filter machinery on the Hodge Laplacian:

- PolynomialFilterTNN (SNN, Ebli et al. 2020): one polynomial filter in
  the full Hodge Laplacian L_d per rank; SNN = the Chebyshev basis. The
  poly_filter bases act on L_d verbatim -- a Basis only ever sees the
  L_apply closure. laplacian_norm='rescale' hands orthogonal-interval
  bases (Chebyshev/Jacobi/Legendre) a [0,2]-spectrum operator via a
  deterministic Gershgorin upper bound on lambda_max; Monomial uses 'raw'.

- FilterBankTNN (SCNN, Yang et al. 2022): a two-channel down/up filter
  bank on L^down_d / L^up_d per rank, reusing Channel + Monomial; SCNN =
  the Monomial instance. Because L^down L^up = 0 the channels tune the
  gradient and curl components of the Hodge decomposition independently.

Thin simplicial wrappers feed the Hodge operators the batch already
exposes (hodge_laplacian_k, down/up_laplacian_k), hardcoding 3 ranks
like sccnn_wrapper. Shared helpers in hodge_utils (spmm, deterministic
Gershgorin spectral_upper_bound, build_hodge_laplacian_apply).

Configs: SNN / Monomial / Jacobi (poly filter) + SCNN (bank). Unit
tests (per-rank forward, sparse + empty-rank layouts, basis swap,
Gershgorin bound determinism) and the pipeline test now exercise all
four on lifted MUTAG.
The SCNN reference wrongly listed five authors (Yang, Sardellitti,
Barbarossa, Leus & Isufi) -- that list belongs to "Simplicial
Convolutional Filters" (IEEE TSP 2022). The primary SCNN reference is
Yang, Isufi & Leus (2022), "Simplicial Convolutional Neural Networks",
ICASSP 2022 (arXiv:2110.02585). Also add the arXiv id to the SNN
reference (Ebli et al. 2020, arXiv:2010.03633).
Full GraphUniverse sweep (community_detection + triangle_counting,
12 settings x 3 seeds = 72 runs each) for the four simplicial configs,
run on Kaggle P100:

  model     CD acc          Tri MSE
  SNN       0.437 +/- 0.114  23140
  Monomial  0.390 +/- 0.140  34531
  Jacobi    0.432 +/- 0.110  15368
  SCNN      0.437 +/- 0.120  11333

Monomial (raw power basis) is worst on both tasks; the SCNN down/up
filter bank wins triangle counting by a wide margin (the 2-simplex
task the Hodge decomposition is built for). Per-setting detail in
results_tnn_*.json; aggregate in comparison_tnn.csv.
@aniervs

aniervs commented Aug 1, 2026

Copy link
Copy Markdown
Author

The PR seems huge, but that's because it's based on two other PRs of mine for the challenge. This PR is a TNN extension to two PR's I made already in the GNN track. I described it in the PR description above.

Drop the inherited filter-bank GNN entries (those belong to the Track-1
filter-bank PR); this branch's pipeline test should exercise only the
simplicial TNN configs it introduces.
@gbg141 gbg141 added the track-2-tnn 2026 Topological Deep Learning Challenge -- Track 2 TNNs label Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

track-2-tnn 2026 Topological Deep Learning Challenge -- Track 2 TNNs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants