neuroevolution_events behaviour (faber_neuroevolution v1.2.4)

View Source

Event publishing abstraction for neuroevolution.

This module provides a pluggable event system that can use different backends for event distribution:

- neuroevolution_events_local - Local pg-based pubsub (default) - neuroevolution_events_macula - Distributed via Macula mesh (future)

Event Types

Commands (requests for work): - {evaluate_request, #{request_id, realm, individual_id, network, options}} - {evaluate_batch_request, #{request_id, realm, individuals, options}}

Events (facts that happened): - {evaluated, #{request_id, individual_id, metrics, evaluator_node}} - {generation_started, #{realm, generation, population_size, timestamp}} - {generation_completed, #{realm, generation, best_fitness, avg_fitness, ...}} - {training_started, #{realm, config}} - {training_stopped, #{realm, generation, reason}}

Topic Design

Topics follow the pattern: evolution:<realm>:<type> - evolution:default:generation_complete - Generation lifecycle events - evolution:default:training - Training lifecycle events - evolution:default:intervention - LC intervention events - evolution:default:resource_alert - Resource pressure alerts

Legacy topics (for distributed evaluation): - neuro.default.evaluate - Evaluation requests - neuro.default.evaluated - Evaluation results

Summary

Functions

Get the evaluation request topic for a realm.

Get the evaluation results topic for a realm.

events_topic(Realm) deprecated

Get the training events topic for a realm.

Get the current event backend module.

Create a standardized event map with realm, source, and timestamp.

Create a standardized event with explicit event type.

Publish an event to a topic.

Create and publish a standardized event in one call.

Set the event backend module.

Subscribe the calling process to a topic.

Subscribe a specific process to a topic.

Topic for competitive coevolution events (medium frequency).

Topic for environment change events (low frequency).

Topic for generation lifecycle events (low frequency, rich payload).

Topic for individual-level events (high frequency, use sparingly).

Topic for LC intervention events (Task Silo actions).

Topic for island model events (medium frequency).

Topic for meta-controller parameter updates (low frequency).

Topic for novelty search events (medium frequency).

Topic for population-level events (medium frequency).

Topic for strategy-agnostic progress events (configurable frequency).

Topic for quality-diversity (MAP-Elites) events (medium frequency).

Topic for resource pressure alerts (Resource Silo warnings).

Topic for real-time LC silo sensor updates (high frequency).

Topic for species lifecycle events (low frequency).

Topic for training lifecycle events (rare, important).

Unsubscribe the calling process from a topic.

Callbacks

publish/2

-callback publish(Topic :: binary(), Event :: term()) -> ok.

subscribe/2

-callback subscribe(Topic :: binary(), Pid :: pid()) -> ok.

unsubscribe/2

-callback unsubscribe(Topic :: binary(), Pid :: pid()) -> ok.

Functions

evaluate_topic(Realm)

-spec evaluate_topic(Realm) -> binary() when Realm :: binary().

Get the evaluation request topic for a realm.

evaluated_topic(Realm)

-spec evaluated_topic(Realm) -> binary() when Realm :: binary().

Get the evaluation results topic for a realm.

events_topic(Realm)

This function is deprecated. Use topic_generation/1, topic_population/1, etc. instead..
-spec events_topic(Realm) -> binary() when Realm :: binary().

Get the training events topic for a realm.

get_backend()

-spec get_backend() -> module().

Get the current event backend module.

make_event(Realm, Source, Payload)

-spec make_event(Realm, Source, Payload) -> {atom(), map()}
                    when Realm :: binary(), Source :: atom(), Payload :: map().

Create a standardized event map with realm, source, and timestamp.

Example:

  Event = neuroevolution_events:make_event(<<"snake_duel">>, task_silo, #{
      event_type => task_silo_intervention_started,
      stagnation_severity => 0.75,
      exploration_boost => 0.3
  }).

make_event(EventType, Realm, Source, Payload)

-spec make_event(EventType, Realm, Source, Payload) -> {atom(), map()}
                    when EventType :: atom(), Realm :: binary(), Source :: atom(), Payload :: map().

Create a standardized event with explicit event type.

Example:

  Event = neuroevolution_events:make_event(generation_complete, <<"snake_duel">>,
      neuroevolution_server, #{
          cohort => 42,
          best_fitness => 0.95
      }).

publish(Topic, Event)

-spec publish(Topic, Event) -> ok when Topic :: binary(), Event :: term().

Publish an event to a topic.

The event will be delivered to all subscribers of the topic. Event format is typically {EventType, EventData} where EventData is a map.

publish_event(Topic, EventType, Realm, Source, Payload)

-spec publish_event(Topic, EventType, Realm, Source, Payload) -> ok
                       when
                           Topic :: binary(),
                           EventType :: atom(),
                           Realm :: binary(),
                           Source :: atom(),
                           Payload :: map().

Create and publish a standardized event in one call.

Example:

  neuroevolution_events:publish_event(
      topic_intervention(Realm),
      task_silo_intervention_started,
      Realm,
      task_silo,
      #{stagnation_severity => 0.75, exploration_boost => 0.3}
  ).

set_backend(Module)

-spec set_backend(Module) -> ok when Module :: module().

Set the event backend module.

The backend module must implement the neuroevolution_events behaviour. Default is neuroevolution_events_local.

subscribe(Topic)

-spec subscribe(Topic) -> ok when Topic :: binary().

Subscribe the calling process to a topic.

subscribe(Topic, Pid)

-spec subscribe(Topic, Pid) -> ok when Topic :: binary(), Pid :: pid().

Subscribe a specific process to a topic.

topic_competition(Realm)

-spec topic_competition(Realm) -> binary() when Realm :: binary().

Topic for competitive coevolution events (medium frequency).

Competitive Coevolution (Red Team vs Blue Team) events: - {red_team_updated, #{realm, red_team_size, red_team_avg_fitness, red_team_max_fitness, members_added}} - {blue_team_evaluated, #{realm, blue_team_best_fitness, red_team_opponent_id, result}} - {immigration_occurred, #{realm, direction, count, individuals}} direction: blue_to_red or red_to_blue - {arms_race_progress, #{realm, generation, blue_best, red_best, blue_improvement_rate, red_improvement_rate}}

The arms race dynamic is key: both populations must continuously improve to beat each other, preventing overfitting to static opponents.

topic_environment(Realm)

-spec topic_environment(Realm) -> binary() when Realm :: binary().

Topic for environment change events (low frequency).

Events: - {environment_changed, #environment_changed{}} - Fitness landscape changed

Used for curriculum learning, adaptive difficulty, or simulating changing real-world conditions.

topic_generation(Realm)

-spec topic_generation(Realm) -> binary() when Realm :: binary().

Topic for generation lifecycle events (low frequency, rich payload).

Events: - {generation_started, #{realm, generation, population_size, timestamp}} - {generation_complete, #{realm, generation, generation_stats, history_point, meta_params, silo_state, convergence_status, ...}}

topic_individual(Realm)

-spec topic_individual(Realm) -> binary() when Realm :: binary().

Topic for individual-level events (high frequency, use sparingly).

Events: - {individual_evaluated, #{realm, individual_id, fitness, metrics}}

Note: For UI purposes, prefer subscribing to topic_population/1 which provides aggregated data. This topic is for distributed evaluation workers.

topic_intervention(Realm)

-spec topic_intervention(Realm) -> binary() when Realm :: binary().

Topic for LC intervention events (Task Silo actions).

Events: - {task_silo_intervention_started, #{realm, generation, exploration_boost, ...}} - {task_silo_intervention_ended, #{realm, generation, prev_boost}} - {task_silo_intervention_intensified, #{realm, generation, old_boost, new_boost}}

These events are emitted when the Task Silo intervenes to address stagnation. The dashboard subscribes directly to this topic for immediate UI updates.

topic_island(Realm)

-spec topic_island(Realm) -> binary() when Realm :: binary().

Topic for island model events (medium frequency).

Events: - {island_migration, #island_migration{}} - Individual migrated between islands - {island_topology_changed, #island_topology_changed{}} - Island connectivity changed

topic_meta(Realm)

-spec topic_meta(Realm) -> binary() when Realm :: binary().

Topic for meta-controller parameter updates (low frequency).

Events: - {meta_params_updated, #{realm, generation, params, silo_states}}

topic_novelty(Realm)

-spec topic_novelty(Realm) -> binary() when Realm :: binary().

Topic for novelty search events (medium frequency).

Events: - {archive_updated, #archive_updated{}} - Novelty archive changed - {niche_discovered, #niche_discovered{}} - New behavioral niche found

topic_population(Realm)

-spec topic_population(Realm) -> binary() when Realm :: binary().

Topic for population-level events (medium frequency).

Events: - {population_evaluated, #{realm, generation, population, top_individuals, ...}} - {selection_complete, #{realm, generation, survivors, offspring}}

topic_progress(Realm)

-spec topic_progress(Realm) -> binary() when Realm :: binary().

Topic for strategy-agnostic progress events (configurable frequency).

Events: - {progress_checkpoint, #progress_checkpoint{}} - Periodic progress updates

This topic is useful for continuous evolution strategies (steady-state) where traditional "generation" boundaries don't apply. Progress checkpoints are emitted every N evaluations (configurable).

topic_qd(Realm)

-spec topic_qd(Realm) -> binary() when Realm :: binary().

Topic for quality-diversity (MAP-Elites) events (medium frequency).

Events: - {niche_discovered, #niche_discovered{}} - New cell in grid occupied - {niche_updated, #niche_updated{}} - Better individual in existing cell - {archive_updated, #archive_updated{}} - Grid coverage/QD-score updated

topic_resource_alert(Realm)

-spec topic_resource_alert(Realm) -> binary() when Realm :: binary().

Topic for resource pressure alerts (Resource Silo warnings).

Events: - {resource_alert, #{realm, action, memory_pressure, message}}

Emitted when resource pressure changes from continue to throttle or pause, or when recovering from a resource-constrained state.

topic_silo_sensors(Realm)

-spec topic_silo_sensors(Realm) -> binary() when Realm :: binary().

Topic for real-time LC silo sensor updates (high frequency).

Events: - {task_sensors_updated, #{realm, sensors}} Emitted when Task Silo L0 sensors change significantly. - {resource_sensors_updated, #{realm, sensors}} Emitted when Resource Silo L0 sensors change significantly. - {distribution_sensors_updated, #{realm, sensors}} Emitted when Distribution Silo L0 sensors change significantly.

Sensors map contains all current L0 sensor values. Events are throttled to avoid flooding - only emitted when significant changes occur or at a maximum rate of 10Hz.

topic_species(Realm)

-spec topic_species(Realm) -> binary() when Realm :: binary().

Topic for species lifecycle events (low frequency).

Events: - {species_updated, #{realm, generation, species, species_count}} - {species_emerged, #{realm, species_id, founding_member}} - {species_extinct, #{realm, species_id, final_generation}}

topic_training(Realm)

-spec topic_training(Realm) -> binary() when Realm :: binary().

Topic for training lifecycle events (rare, important).

Events: - {training_started, #{realm, config, timestamp}} - {training_paused, #{realm, generation, reason}} - {training_resumed, #{realm, generation}} - {training_stopped, #{realm, generation, reason, final_stats}} - {training_complete, #{realm, generation, best_individual, elapsed_ms}}

unsubscribe(Topic)

-spec unsubscribe(Topic) -> ok when Topic :: binary().

Unsubscribe the calling process from a topic.