variety-point-clouds

View on GitHub

Sampling algebraic varieties in real and complex projective space as point clouds.

with Fabian Lander

Readme

Sample point clouds on algebraic varieties in real and complex projective space (including links of singularities and Milnor fibers), embed them into high-dimensional matrix spaces via Veronese and projector embeddings, and visualize or export the results.

Quick start

npm install
npm run dev weierstrass-cubic

Demos

Each demo is a standalone Three.js app in demos/. Run any with npm run dev <name>.

DemoWhat it shows
weierstrass-cubicElliptic curve in CP², rotating under U(3), with CSV export controls
real-curve-rp2Real cubic in RP² in affine chart, O(3) rotation
real-surface-rp3Steiner surface in RP³ in affine chart, O(4) rotation
hyperellipticHyperelliptic curves y² = f(x) of various genera in CP²
milnor-fiberMilnor fiber of various singularities with θ slider (includes the trefoil)
seifert-surfaceClosed Seifert surfaces (custom shader) with θ slider
slice-rp4Quartic 3-fold in RP⁴, sliced through the 4th affine axis
poincare-spherePoincaré homology sphere (link of E₈), sliced from R⁶ to R³
complex-surface-cp3Fermat quartic surface in CP³, 3 slice sliders through R⁶
complete-intersectionReal curves in RP³, complex curves in CP³, surfaces in RP⁴/⁵

Export

Sample a variety and write the embedded point cloud to disk. Every export also writes a sidecar <out>.meta.json describing the dataset (variety ID, sampling parameters, embedding, shape) so the file is self-describing.

# List all available varieties by stable ID
npm run export -- --list

# Weierstrass cubic, 10k points, ν₂ then projector → R³⁶, CSV
npm run export -- --variety weierstrass-cubic --points 10000 --veronese 2 --out points.csv

# Klein quartic → projector → R⁹, NumPy binary (load directly in Python)
npm run export -- --variety klein-quartic --points 5000 --format npy --out klein.npy

# Real-flat output: ν₂ then flatten C^N → R^{2N}
npm run export -- --variety weierstrass-cubic --veronese 2 --output real-flat --out flat.csv

# Singularity link (default = link, V(F) ∩ S^{2n-1})
npm run export -- --variety sing-z2-w3 --points 5000 --out trefoil.csv

# Singularity Milnor fiber at θ = π/4
npm run export -- --variety sing-z3-w5 --points 5000 --mode fiber --theta 0.785 --out e8-fiber.csv

Each row is a point in R^{N²} (projector) or R^{2N} (real-flat), where N is the target dimension after the optional Veronese map.

Building for the web

npm run build weierstrass-cubic     # writes dist/weierstrass-cubic/ as a static site

Each demo builds into its own self-contained dist/<demo>/ subfolder (relative paths, can be dropped anywhere on a site). Building another demo doesn’t clobber previous builds.

Project structure

See src/README.md for the architecture overview. In brief:

src/
  math/         Pure math primitives (complex, polynomials + algebra DSL, rotations, ...)
  solvers/      Numerical samplers: rootfind + hypersurface/intersection/link samplers
  embeddings/   High-dim embeddings: Veronese, projector
  projections/  Pure functions CPnPoint → R³ (affine, stereographic, slicing, random projection, ...)
  viewer/       Three.js infrastructure: Scene + PointBuffer + overlay
  export/       Composable sample-and-embed pipeline + CSV / NPY / metadata writers
  examples/     Predefined varieties (curves, surfaces, threefolds, singularities, intersections)

demos/          Standalone demos, one main.ts each
scripts/        CLI tools (run-demo, export)
tests/          Vitest suite — invariants over math, solvers, embeddings, projections, export

Docs

How the math works

Sampling hypersurfaces. For a single polynomial F in CP^n, we sample V(F) by intersecting random complex lines with the variety and solving the resulting univariate polynomial via Durand-Kerner. A random walk grows a dense cloud.

Sampling complete intersections. For k > 1 equations V(F₁,…,Fₖ), line intersection doesn’t work (codimension k > 1 generically misses any line). Instead we use the non-square Newton: random starting point, Newton-correct via the minimum-norm pseudoinverse step Δz = J*(JJ*)⁻¹F.

Links of singularities. For F: C^n → C with a singularity at 0, the link V(F) ∩ S^{2n-1}_ε is sampled by random points on the sphere + Newton correction with radial reprojection. Same idea for Milnor fibers (preimage of a ray, restricted to the sphere).

Embeddings. Veronese ν_d : CP^n → CP^N (multinomial-weighted monomials) and the rank-1 projector embedding CP^n → R^{(n+1)²} give isometric embeddings into Euclidean space. Composed, they map any complex projective variety into a real vector space with no chart singularities — suitable for ML pipelines.

Tests

npm test         # one-shot
npm run test:watch

Each test asserts a mathematical invariant (Veronese is norm-preserving, projector trace = 1, Newton-corrected samples lie on V(F), etc.).

Limitations

  • Veronese multinomial weights overflow for degree > ~20.
  • The complete-intersection sampler uses random starts: for varieties with very small basin of attraction the convergence rate can be poor.
  • Random walks on the real locus can get stuck on one connected component.
← All software