Skip to content

Release/v4.0#3

Merged
rkv0id merged 9 commits intomainfrom
release/v4.0
Apr 19, 2026
Merged

Release/v4.0#3
rkv0id merged 9 commits intomainfrom
release/v4.0

Conversation

@rkv0id
Copy link
Copy Markdown
Owner

@rkv0id rkv0id commented Apr 19, 2026

biota v4.0.0 — CVT-MAP-Elites, signal overhaul, archive gallery, ecosystem fixes

Replaces the fixed 32×32×16 grid archive with CVT-MAP-Elites, rebuilds the archive viewer as a gallery, overhauled signal descriptors and batched rollouts, and fixes several ecosystem bugs.

Archive

  • CVT-MAP-Elites replaces fixed grid. Calibration phase fits k-means centroids to observed survivor distributions; per-axis scale factors normalize descriptor ranges. Lookup is O(log k) via cKDTree. creature_id replaces 3D coords as stable creature identity.
  • _is_too_similar now maintains a persistent occupied-centroid tree (lazy dirty-flag rebuild); similarity epsilon operates in scaled space matching cell_for().

Search / rollouts

  • _batched_sim_step returns (new_A, U_sum); signal step reuses U_sum, eliminating a duplicate FFT per step.
  • _build_batched_signal_params uses build_signal_kernel_fft() directly without constructing B FlowLenia instances. make_signal_fields_batch() replaces per-element init loop.
  • New public FlowLenia API: mass_kernels_fft, decay, build_signal_kernel_fft(), make_signal_fields_batch(). localized.py drops all reportPrivateUsage suppressions.

Signal descriptors

  • emission_activity, receptor_sensitivity, signal_retention removed -- all returned zero for equilibrium solitons. Replaced with signal_field_variance, signal_mass_ratio, dominant_channel_fraction, which measure final field state and work correctly for stable creatures.
  • Quality metric: retention term replaced by signal_activity = clip(final_signal_mass / initial_signal_mass, 0, 1). Weights: compactness 0.5 / stability 0.3 / signal_activity 0.2.

CLI / TTY

  • TTY-aware search display: 7-line overwriting block in TTY mode, append-only in non-TTY. Calibration spinner with survivor count and fitted axis ranges.

Archive viewer

  • Full rebuild: gallery grid (auto-fill, aspect-ratio:1 thumbnails), filter bar in header, 2×2 analytics panel (three descriptor histograms + quality distribution), compact Pearson correlation matrix below. Click opens modal directly. Hover highlights corresponding bin across all histograms simultaneously.

Ecosystem

  • receptor_alignment bug fixed: compute_ecosystem now loads creatures eagerly so _compute_outputs always has them, not just in the Ray dispatcher path.
  • _extract_primary_source handles "cell": null in creature_id-based summaries.
  • Interaction coefficients and emission-reception compatibility matrices replaced with compact HTML tables (consistent style, readable at any size).
  • Ecosystem cards on index: badges and outcome label on title row, stats consolidated.

Docs / diagrams

  • docs/archive-grid.svg, docs/search-loop.svg updated to CVT language.
  • README descriptor table 15→18 entries, emission_rate range corrected, quality metric updated.
  • Full v4.0.0 CHANGELOG entry.

rkv0id added 9 commits April 19, 2026 13:56
…criptors (v4.0.0)

Replace fixed 32x32x16 grid archive with Voronoi tessellation fitted from
observed rollout distributions. No normalizers anywhere.

- archive.py: cKDTree-based CVT archive, attach_centroids(), similarity
  rejection against occupied centroid subset
- loop.py: _calibration_phase() runs N_CAL rollouts before search, fits
  k-means centroids, assigns creature_id="{run_id}-{seed}" at insertion;
  SearchConfig gains calibration and centroids fields
- rollout.py: SIGNAL_STEPS and PRESET_CALIBRATION tables replace
  signal_preset(); SIGNAL_CALIBRATION_BONUS=50 for signal runs
- descriptors.py: all 18 compute() return raw float in [0, 100]; normalizer
  divisions removed; SPECTRAL_ENTROPY_FLOOR remap removed
- result.py: creature_id and parent_id replace parent_cell and CellCoord;
  LegacyCellCoord alias kept for old pickle compat
- cli.py: --calibration and --centroids flags; preset-derived calibration
  defaults; signal step override via SIGNAL_STEPS for all presets
- ecosystem/config.py: CreatureSource gains creature_id field; parser
  accepts creature_id or cell (deprecated)
- ecosystem/run.py: load_creature looks up by creature_id first, falls
  back to coords for old archives
- smoke_ecosystem.sh: CVT archive seeding, creature_id in YAML
- All tests updated; ruff clean, pyright 0 errors, 422 tests passing
Add src/biota/viz/tty.py: SearchDisplay class with two rendering modes.
TTY mode: 7-line overwriting block (header, progress bar, archive stats,
last-10 insertion summary, per-descriptor coverage bars). Non-TTY mode:
append-only lines matching pre-v4.0.0 format plus summary every 50 rollouts.

loop.py: add CalibrationProgressFn / CalibrationDoneFn callback types,
thread them through _calibration_phase and search(). cli.py: wire
SearchDisplay to the event stream; pass live Archive to search() so
coverage bars read real descriptor distributions.
archive.html: three-panel layout replacing the fixed grid. Left panel
(58%): virtual-scrolled creature cards with filter/sort and inline YAML
copy. Right panel: descriptor histograms (quality-colored bars, selected-
creature marker) and Pearson correlation matrix. Collapsible health header
with calibration stats. All JS uses creature_id / parent_id; deep-link is

render.py: remove body_inner stub, add calibration_n/survivors from
manifest. ecosystem.html: coords_hash deep-links now use creature_id when
available. index.html: CVT language in System tab, creature_id in Reproduce
tab YAML, stat block updated (1024 centroids / CVT-MAP-Elites).
build_index.py: _build_sources_context emits creature_id for deep-links.
… quality metric

Replace emission_activity/receptor_sensitivity/signal_retention with
signal_field_variance, signal_mass_ratio, dominant_channel_fraction --
descriptors that measure final field state and work for equilibrium solitons.

Add batched signal physics to rollout_batch (was silently skipped before).
Fix alive filter: exclude initial_signal_mass from conservation check since
signal decays by design. Add initial_signal_mass to RolloutEvaluation for
signal_activity quality term (replaces retention).

Update README, index.html, tests.
…dates

archive.py: persistent _occupied_tree rebuilt lazily on dirty flag instead
of O(n) rebuild per insertion; similarity epsilon now operates in scaled
space matching cell_for().

rollout.py: _batched_sim_step returns (new_A, U_sum) -- signal step reuses
U_sum directly, eliminating a duplicate FFT per step. _build_batched_signal_
params uses build_signal_kernel_fft() without constructing B FlowLenia
instances. make_signal_fields_batch() replaces per-element init loop.

flowlenia.py: add build_signal_kernel_fft() and make_signal_fields_batch()
module-level functions; add mass_kernels_fft and decay public properties.
localized.py: remove all reportPrivateUsage suppressions; use public API.

docs: archive-grid.svg and search-loop.svg updated to CVT language.
README: emission_rate range corrected, render.py stale comment cleaned.
Gallery grid replaces card list; thumbnails fill card width via aspect-ratio.
Filter bar moves to header row. Click opens modal directly (no preview strip).
Right panel (38% width) holds 2x2 histogram grid (velocity, gyradius, d2,
quality distribution) plus compact correlation matrix below. Hover highlights
bins across all three descriptor histograms simultaneously.
@rkv0id rkv0id self-assigned this Apr 19, 2026
@rkv0id rkv0id merged commit f962e45 into main Apr 19, 2026
1 check passed
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