Skip to content

research: Bridson rewrite + spatial sampling investigation (WIP)#42

Open
bwyard wants to merge 11 commits intodevfrom
feat/parallel-spatial-sampling
Open

research: Bridson rewrite + spatial sampling investigation (WIP)#42
bwyard wants to merge 11 commits intodevfrom
feat/parallel-spatial-sampling

Conversation

@bwyard
Copy link
Copy Markdown
Owner

@bwyard bwyard commented Apr 5, 2026

Summary

Research branch — do not merge until investigation is complete.

Bridson rewrite (prime-random)

  • poisson_disk() — new implementation using internal mutation with pure external contract
  • poisson_disk_2d() — original pure-fold preserved alongside for benchmarking
  • Both coexist intentionally: the comparison is part of the research record

Benchmark results (min_dist=5.0, 30 attempts, seed=42):

Domain Pure fold Internal mutation Speedup
50×50 221.6 µs 162.1 µs 1.4×
100×100 1249.8 µs 696.2 µs 1.8×
200×200 7594 µs 2874 µs 2.6×
500×500 157.5 ms 18.2 ms 8.6×

Research documentation (docs/research/parallel-spatial-sampling.md)

  • Hypothesis: Scatter-Cull spatial sampling — inversion of Bridson's build-toward-sufficiency model
  • Two tracks: Partition-Bridson vs Scatter-Cull (seeded + entropy variants)
  • Three geometries: rectangular (C), Voronoi K₁₀ (D), SDF curve (E)
  • Baselines: Bridson 2007 ✅, Wei 2008 (pending)
  • Determinism fork explicitly documented
  • Measurement plan defined

Status: Pending updated handoff — additional algorithms to be added without modifying existing results.

🤖 Generated with Claude Code

bwyard and others added 11 commits April 5, 2026 18:03
Bridson rewrite (prime-random):
- Add poisson_disk() — internal mutation, pure external contract, O(1) grid access
- Preserve poisson_disk_2d() — original pure-fold implementation, kept for benchmarking
- Fix: original was cloning entire grid on every step (O(cols×rows) per point)
- Benchmark result: 8.6× faster at 500×500, non-linear speedup with domain size

Research (docs/research/parallel-spatial-sampling.md):
- Hypothesis: Scatter-Cull spatial sampling — mass-drop then cull vs incremental Bridson
- Two implementation tracks: Partition-Bridson vs Scatter-Cull (seeded + entropy variants)
- Three geometries: rectangular (C), Voronoi K10 (D), SDF curve (E)
- Two baselines: Bridson 2007 (implemented), Wei 2008 (pending)
- Determinism fork documented: seeded variants preserve PRIME thesis contract,
  entropy variant intentionally violates it — both included for comparison
- Measurement plan: performance, coverage, uniformity, seam quality, determinism
- Benchmark data recorded for pure-fold vs internal-mutation across 4 domain sizes

Note: implementation direction pending updated handoff — current work stands as
documented baseline. Additional algorithms to be added without modifying existing results.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…S_PROOF

- research doc: corrected for scatter-cull design (v1 partition-Bridson was wrong)
- research doc: both strategies kept — partition-Bridson (reference) + scatter-cull (hypothesis)
- research doc: open questions documented with Bree's answers (u64 deferred, shift TBD, observational)
- ACCURACY.md: benchmark result tables scaffolded, Bridson baseline data filled in
- THESIS_PROOF.md: structure only — Bree writes claims and conclusions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ecorded

Implementations (prime-spatial):
- poisson_rect_partitioned: Strategy A, Bridson per rectangular cell, seam inset min_dist/2
- scatter_cull_rect: Strategy B, scatter-cull per rectangular cell, no inset
- cull_to_min_dist: shared O(1)-grid cull pass used by scatter-cull strategies

Benchmarks (Approach C, min_dist=5.0, overage_ratio=1.5):
- 100×100 (4×4): partition-Bridson 426µs, scatter-cull 17µs → 25× faster
- 200×200 (6×6): partition-Bridson 2.0ms, scatter-cull 50µs → 40× faster
- 500×500 (8×8): partition-Bridson 15.1ms, scatter-cull 106µs → 143× faster
- scatter-cull is 172× faster than serial Bridson at 500×500

ACCURACY.md updated with full Approach C results.

Note: target_per_partition=20 in benchmark (small-scale validation). Full-scale
parameters (500 drops/partition, 40 partitions) benchmarking pending.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…esign

- Move poisson_disk_wei to src/research.rs (not for production — convergence
  loop and shared mutable grid violate pure contract; marked ADVANCE-EXCEPTION)
- Scatter phase in scatter_cull_rect now uses scan to thread PRNG state
  functionally rather than mut in map closure
- Add Wei 2008 single-threaded benchmark results to ACCURACY.md (2.4–7.5×
  slower than serial Bridson — expected without par_iter)
- Record Approach C results in research doc (C-B: 172× faster than Bridson at 500×500)
- Add Approach F: sheared variable-size partitions (straight edges, non-orthogonal,
  non-equal cell sizes) — design documented, implementation pending after Approach D

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
prime-voronoi:
- Add voronoi_sites_seeded — K random sites in rectangle from seed (scan/PRNG)
- Add voronoi_partition — assign candidate set to nearest Voronoi site (pure fold)
- Add lloyd_relax_n — N steps of Lloyd relaxation (fold over steps)
- Add prime-random dependency for PRNG in site generation
- 18 new tests (sites, partition, lloyd_relax_n — all determinism, bounds, correctness)

prime-spatial:
- Add scatter_cull_voronoi (Approach D): K sites + Lloyd relax + full-domain scatter
  + voronoi partition + per-cell min-dist cull
- Add Approach D benchmark (K=10, 3 Lloyd iters, three domain sizes)
- Add statistical coverage_cv helper in tests
- D-B results: 25–85µs across 100–500 domain; faster than C-B at 200+ domain sizes

ACCURACY.md / research doc:
- Record D-B benchmark results with comparison to C-B and serial Bridson
- Note Lloyd overhead trades off against coarser cell count at scale
- Update implementation order (D complete)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add scatter_cull_voronoi_recursive: k^levels leaf cells, full-domain scatter
  up front, recursive partition by bounding-box Voronoi sites, cull at leaves
- Private voronoi_recursive_inner: bounding box per cell, candidates-as-Lloyd-samples,
  derived seed per sub-cell
- 5 new tests (basic, invalid inputs, min-dist holds, deterministic, levels=1 structure)
- Add D-R benchmark group: L=1 and L=2 at three domain sizes
- D-R results: L=1 30–200µs, L=2 110–932µs — each level adds ~3-5x cost
  Single-level D is faster; recursive offers finer geometric granularity

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add scatter_cull_sheared: F-1 (variable cell widths/heights from seeded PRNG,
  normalised to domain) + F-2 (row shear — parallelogram basis, shear_factor=0.5
  gives brick-pattern offset)
- seeded_variable_sizes and prefix_sums private helpers (scan-based, pure)
- 7 new tests (cell count, invalid inputs, min-dist holds, deterministic, zero-shear,
  domain bounds, different seeds)
- Add Approach F benchmark: shear=0.5 and variable_rect variants at 3 domain sizes
- F results: 0.6× vs C-B at small domains; 11.6× slower at 500×500 (full domain
  grid overhead during cull — noted as post-research optimisation target)
- Update ACCURACY.md and research doc with F results and implementation note

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add scatter_cull_half_heart: N seeds along parameterized diagonal + N shifted
  copies = 2N Voronoi sites; scatter-cull over the resulting irregular cells
- half_heart_sites private helper: generates 2*n_seeds interleaved sites
  (origin, shifted) using diagonal_angle and (shift_x, shift_y) parameters
- 7 new tests (cell count, invalid inputs, min-dist holds, deterministic,
  produces points, domain bounds, shift changes output)
- Add Approach E benchmark: two shift vectors at 3 domain sizes with scaling n_seeds
- E results: shift(-9,6) at 100x100 is 16.6µs — marginally faster than C-B (17.2µs)
  Larger shift at 500x500 is 2.5x faster than small shift
- Note in ACCURACY.md: boundary clipping creates irregular fragments at domain edge;
  acceptable — goal is abnormal partition shapes, not exact half-heart geometry
- Update research doc with E first-pass results and open questions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add global_cull_to_min_dist: public utility that applies global min-dist cull
  to any flat point set — produces output equivalent to Bridson (globally valid).
  All scatter-cull approaches chain through this for the final guarantee.
- Add tests/coverage_stats.rs: integration tests comparing all approaches at
  100x100 and 200x200; reports seam_kept, CV at 5x5 and 10x10 grids, empty cells
- Record full stats in ACCURACY.md Coverage Uniformity section

Key findings from stats (observational, not conclusions):
- Best CV: C-B (0.095) and F-variable-rect (0.126) closest to Bridson (0.066) at 200x200
- E shift(-15,10) strong at 200x200: CV 0.183/0.303 with only 10 cells vs 36 for C-B
- F shear=0.5 worst CV (0.514) and only approach with empty cells — shear creates
  dense/sparse zones at domain edges
- D and E have highest seam_kept (0.96-0.97) — irregular geometry produces fewer
  boundary conflicts than grid-aligned cells
- All approaches produce fewer points than Bridson post-global-cull; overage needs
  tuning to match Bridson's near-maximal packing density

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…alysis

Implements all scatter-cull Poisson disk sampling approaches (C–H) with
full calibration data across 100/200/500 domains. Empirically establishes
R stability for global_rect (≈0.185), F shear=0 (≈0.099), H single j=0
(≈0.175) — the foundation for the formal R proof in future theory work.

- Approaches C–H: rect, Voronoi, half-heart, sheared, SDF ellipse, triangles
- G-Inset, G-Corner: geometric inset variants with corner fill
- Single-pass (global) vs two-pass pipeline; seam ceiling documented
- Test split: coverage_stats.rs (7 fixed-overage) + calibration.rs (8 binary-search, ceiling=50)
- Spectral analysis: blue noise confirmed via PCF + power spectrum (rustfft)
- ACCURACY.md: complete calibrated overage tables + R formula derivation
- research.rs removed; prime-research crate (gitignored) holds baselines

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…esearch crate)

Research baselines (Wei 2008, sample elimination) live in crates/prime-research/
which is gitignored. No research content belongs in the production crate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant