Skip to content

Engine optimizations & testable user guide

Latest

Choose a tag to compare

@pkalivas pkalivas released this 20 Jun 19:50
· 9 commits to master since this release

Radiate has reached 1.3.0! This release includes a major refactor of the engine's iteration model, a new expression DSL pass and operators, a substantial NSGA III simplification and optimization, a NEAT implementation refactor, and various other improvements and cleanups across the codebase. The engine is now much more efficient, and the new expression DSL features should make it easier to implement complex adaptive behaviors without custom code. The user guide has been rebuilt around testable snippets, and a new guide on diversity and speciation has been added. Check below!

User guide has been updated and expanded, if you haven't looked at it in a while, check it out!

Breaking

  • Removed the radiate-pgm crate and its example. Probabilistic
    graphical model support is no longer shipped. The Rust prelude no longer
    re-exports radiate_pgm::*.
    • I don't think this was really used at all and it never really reached more than an infancy state. If PGMs are a desired feature, they can be reintroduced in the future with a more focused scope and better design - please open an issue if you'd like to see them.
  • Removed the radiate-expr crate. The metric expression DSL has moved
    into radiate-core under stats::expression, and the core types are
    re-exported from the radiate-core crate root (Expr, SelectExpr,
    MetricQuery, Evaluate), and are also available through
    radiate::prelude (so use radiate::prelude::*; brings Expr into scope).
    No separate dependency is required, and the prelude no longer re-exports
    radiate_expr::*.
  • Removed the lineage module from radiate-core. Lineage,
    LineageEvent, and LineageUpdate are no longer part of the public API.
  • Removed the Field struct from radiate-utils (and its re-export).
    AnyValue / DataType naming was cleaned up at the same time. If you were
    constructing Field values directly, use DataType / AnyValue instead.
  • Python: run options restructured. EngineUi has been removed in favor
    of a RunParam hierarchy — LogParam, CheckpointParam, and UiParam.
    The bool shorthands on run(...) are unchanged (engine.run(ui=True, log=True) still works); only the typed option objects were renamed. Code
    that imported or constructed EngineUi must switch to UiParam.
  • Python: expression DSL constructors moved onto rd.Expr. The flat
    module functions that previously lived on rdrd.metric, rd.when,
    rd.lit, rd.element, rd.every, and rd.generation — are now
    classmethods on Expr, and rd.metric(...) is renamed to
    rd.Expr.select(...) (so: rd.Expr.when(...), rd.Expr.lit(...),
    rd.Expr.element(...), etc.). This matches the library's
    rd.Noun.factory convention and keeps the rd.* namespace free of names
    that shadowed builtins. The redundant rd.mean/min/max/stddev(metric)
    shorthands were dropped — use rd.Expr.select(metric).mean(). Expressions
    remain experimental; no back-compat aliases are kept.
  • Metric names have changed. The names of certain metrics have changed to be more consistent and intuitive. Run a quick engine and print out the metrics.dashboard() to see new names or checkout the user guide.

Added

  • Expression DSL — compile() pass. Constant subtrees fold to literals
    and affine chains (a*x + b, including the common
    (x - target) / target * gain + 1 controller pattern) collapse to a single
    fused Affine node. Idempotent.
  • Expression DSL — new operators. stagnation / is_stagnant for
    patience-based plateau detection, is_converged for windowed convergence,
    and a streaming P² quantile (.quantile(q)) with constant-memory online
    estimation.
  • Expression DSL (Python) — new constructors & methods. New Expr
    classmethods Expr.stagnation(metric, ...) and
    Expr.is_stagnant(metric, patience, ...), plus instance methods
    Expr.error(target) and Expr.quantile(q).
  • Python: Species is now inspectable. New accessors expose speciation
    results to Python — population(), mascot(), generation(),
    stagnation(), and score().
  • Python: Graph.from_chromosome(chromosome) classmethod for building a
    Graph directly from a chromosome.
  • Python: Dict nested dtype and a Population.population(size) helper.
  • New examplesneat-graph (Rust) demonstrating NEAT-style
    neuroevolution, plus reorganized Python examples (hello_world,
    mona_lisa, playground).
  • Workspace-wide re-exports from radiate-coreAnyValue, DataType,
    SmallStr, dtype, dtype_names, and value are now re-exported from
    radiate-core so downstream crates no longer need to depend on
    radiate-utils directly for these types.

Changed

  • Engine Iterator the engine iterator is now a runtime. Instead of cloning the entire ecosystem every generation, the engine can now operate in a tight loop. The most common type of iterator methods used on the engine (.last(), .take(n)) are overwritten to work with the new design. That being said, if the user decides to use something like .take_while(..) or other more complex iterator methods, they will get the old behavior of cloning the entire ecosystem every generation. This is a pretty big change, but nothing should break from a user's perspective. This change should just make the engine much more efficient.
  • Recombination is substantially faster. Survivor and offspring
    construction now share a single descending walk over the union of
    selected indices, emitting one swap_remove move plus (total - 1)
    clones per unique source rather than cloning every survivor and offspring
    independently. The species path applies the same optimization within
    each species' sub-population. In practice ~20–50% fewer Phenotype
    clones per generation.
  • Metric subsystem cleanup. Stale fixture data and brittle snapshot
    tests removed; MetricView is leaner and now covered by direct unit
    tests.
  • UI refactor. Panel state moved off the PanelId dispatch model into
    a cleaner per-panel ownership scheme.
  • NSGA III - The NSGA III has been greatly simplified and optimized with a better niching technique. This is a pretty nice mathematical and speed improvement over the previous implementation.
  • NEAT - the Graph's NEAT implementation has been refactored to be more true to the original paper. The neat-graph example demonstrates this new implementation.

Docs

  • User guide rebuilt around testable snippets. Every code sample is now
    extracted from a real source file under docs/source/src/{python,rust}/...
    via pymdownx.snippets (check_paths: true), and mkdocs build --strict
    validates that the referenced snippets exist and compile/run. Docs samples
    can no longer silently drift from the API.
  • New diversity / speciation guide (source/diversity/species.md) plus
    expanded Rust + Python parity pages across genome, alters, selectors, GP,
    objectives, events, and executors.
  • Removed PGM documentation (source/gp/pgm.md) alongside the
    radiate-pgm crate removal.

Fixed

  • Various clippy and correctness cleanups across the alters, selectors,
    and engine crates (no behavior changes intended; flagged here only
    because several touched hot paths).

For example and details please refer to the user guide and API docs.

Full Changelog: v1.2.22...v1.3.0