Skip to content

InducingVariables API design: structured solve interface for Points, VFF, and Spherical Harmonics #15

@bwengals

Description

@bwengals

With VFF landing in #3 and spherical harmonics (Dutordoir et al. 2020) planned, we need to settle the InducingVariables abstraction.

Current interface

SVGP dispatches through the inducing variable, which implements:

  • K_uu(kernel) — dense Kuu (for compatibility/debugging)
  • K_uf(kernel, X) — cross-covariance between inducing variables and data
  • Kuu_solve(kernel, rhs) — Kuu^{-1} @ rhs
  • Kuu_sqrt_solve(kernel, rhs) — R^{-1} @ rhs where R @ R.T = Kuu
  • Kuu_logdet(kernel) — log determinant of Kuu

The base class provides dense defaults for the solve/sqrt_solve/logdet methods. Subclasses override with structured implementations.

Subclasses and their Kuu structure

Subclass Kuu structure Solve strategy
Points Dense (M, M) Dense defaults (no override needed)
FourierFeatures1D diag + low-rank Woodbury identity
Spherical Harmonics (future) Diagonal Elementwise division

None of the structured subclasses have a .Z attribute. Points does.

Initialization and validation are subclass-specific

greedy_variance_init, kmeans_init, and random_subsample_init are specific to Points. They select locations in input space, which doesn't apply to spectral methods. VFF is configured by domain bounds and frequency count, SH by truncation level. These should stay separate from the base interface.

Domain validation (_domain_check) is also subclass-specific. VFF needs to check that inputs fall within [a, b]. SH may need to check that inputs are on the sphere. Points doesn't need any check.

Open questions

  • Is .Z a Points-only attribute, or should there be a base-class method for "give me something plottable/inspectable" that other subclasses can implement differently?
  • Should _domain_check be a formal optional method on the base class, or stay informal (hasattr dispatch)?
  • Where should initialization utilities live and be organized? greedy_variance_init, kmeans_init, and random_subsample_init are currently in ptgp/inducing.py alongside the base class, but they're Points-specific. VFF and SH will have their own initialization patterns (from_data, frequency/truncation config). Should each subclass module own its init utilities, or should there be a shared ptgp/init/ namespace? These utilities also need to be accessible to Claude Code skills files for VFF and SH workflows.
  • Does Points actually need K_uu, K_uf, and the solve/sqrt_solve/logdet methods? Before VFF, Points just held .Z and SVGP called kernel(Z) directly. The new methods on Points are thin wrappers (K_uu calls kernel(self.Z), K_uf calls kernel(self.Z, X)). Is that indirection worth it for API consistency, or should Points stay simple and SVGP only dispatch through the structured methods when the inducing variable isn't Points?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions