Current section
Files
Jump to
Current section
Files
include/meta_controller.hrl
%% @doc Meta-Controller record definitions for LTC-based hyperparameter optimization
%%
%% This module implements a meta-learning system that uses Liquid Time-Constant
%% (LTC) networks to dynamically control neuroevolution hyperparameters.
%%
%% The meta-controller operates at a higher timescale than the task networks,
%% learning to "optimize the optimizer" by adapting parameters based on
%% training dynamics.
%%
%% @author Macula.io
%% @copyright 2025 Macula.io
-ifndef(META_CONTROLLER_HRL).
-define(META_CONTROLLER_HRL, true).
%%% ============================================================================
%%% Types
%%% ============================================================================
-type meta_param() :: mutation_rate | mutation_strength | selection_ratio.
-type reward_component() :: convergence_speed | final_fitness | efficiency_ratio |
diversity_aware | normative_structure.
%%% ============================================================================
%%% Configuration Record
%%% ============================================================================
%% @doc Configuration for the meta-controller.
%%
%% Controls the LTC network architecture and reward signal composition.
-record(meta_config, {
%% Network topology: {Inputs, HiddenLayers, Outputs}
%% Default: {8, [16, 8], 4} - 8 inputs (training metrics), 4 outputs (params)
network_topology = {8, [16, 8], 4} :: {pos_integer(), [pos_integer()], pos_integer()},
%% LTC neuron type: cfc (fast) or ltc (accurate ODE)
neuron_type = cfc :: ltc | cfc,
%% Base time constant for meta-controller neurons
%% Higher values = slower adaptation = more stable
time_constant = 50.0 :: float(),
%% State bound for LTC neurons
state_bound = 1.0 :: float(),
%% Reward component weights (must sum to ~1.0)
reward_weights = #{
convergence_speed => 0.25,
final_fitness => 0.25,
efficiency_ratio => 0.20,
diversity_aware => 0.15,
normative_structure => 0.15
} :: #{reward_component() => float()},
%% Learning rate for gradient-based meta-training
learning_rate = 0.001 :: float(),
%% Parameter bounds: {ParamName, {Min, Max}}
param_bounds = #{
mutation_rate => {0.01, 0.5},
mutation_strength => {0.05, 1.0},
selection_ratio => {0.10, 0.50},
evaluations_per_individual => {3, 20}
} :: #{meta_param() => {float(), float()}},
%% Whether to include population_size as a controllable parameter
%% (disabled by default as it affects computation more than other params)
control_population_size = false :: boolean(),
%% History window size for computing reward signals
history_window = 10 :: pos_integer(),
%% Momentum for parameter updates (smooths changes)
momentum = 0.9 :: float()
}).
-type meta_config() :: #meta_config{}.
%%% ============================================================================
%%% State Record
%%% ============================================================================
%% @doc Internal state for the meta-controller gen_server.
-record(meta_state, {
%% Server identifier
id :: term(),
%% Configuration
config :: meta_config(),
%% Current hyperparameter values
current_params = #{
mutation_rate => 0.10,
mutation_strength => 0.30,
selection_ratio => 0.20
} :: #{meta_param() => float()},
%% LTC network internal states (one per hidden neuron)
%% Maps neuron_id => internal_state
ltc_states = #{} :: #{term() => float()},
%% LTC network weights
%% Structure: #{layer => #{neuron_id => [{input_id, weight}]}}
ltc_weights = #{} :: map(),
%% Training metrics history (circular buffer of last N generations)
metrics_history = [] :: [generation_metrics()],
%% Parameter change momentum (for smooth updates)
param_momentum = #{} :: #{meta_param() => float()},
%% Generation counter
generation = 0 :: non_neg_integer(),
%% Cumulative reward for current training run
cumulative_reward = 0.0 :: float(),
%% Best fitness ever seen (for normalization)
best_fitness_ever = 0.0 :: float(),
%% Stagnation counter (generations without improvement)
stagnation_count = 0 :: non_neg_integer(),
%% Running state
running = false :: boolean()
}).
-type meta_state() :: #meta_state{}.
%%% ============================================================================
%%% Generation Metrics Record
%%% ============================================================================
%% @doc Metrics captured from a single generation for meta-learning.
-record(generation_metrics, {
%% Generation number
generation :: pos_integer(),
%% Fitness metrics
best_fitness :: float(),
avg_fitness :: float(),
worst_fitness :: float(),
fitness_std_dev :: float(),
%% Improvement metrics
fitness_delta :: float(), %% Change from previous generation
relative_improvement :: float(), %% Percentage improvement
%% Diversity metrics
population_diversity :: float(), %% Variance in fitness
strategy_entropy :: float(), %% Information content of strategies
%% Efficiency metrics
evaluations_used :: pos_integer(),
fitness_per_evaluation :: float(),
%% Normative structure metrics
diversity_corridors :: float(), %% Cluster distinctness
adaptation_readiness :: float(), %% Variance in adjacent traits
%% Current parameters used
params_used :: #{meta_param() => float()},
%% Timestamp
timestamp :: erlang:timestamp()
}).
-type generation_metrics() :: #generation_metrics{}.
%%% ============================================================================
%%% Reward Signal Record
%%% ============================================================================
%% @doc Computed reward signal for meta-controller training.
-record(meta_reward, {
%% Individual reward components
convergence_speed :: float(),
final_fitness :: float(),
efficiency_ratio :: float(),
diversity_aware :: float(),
normative_structure :: float(),
%% Composite reward (weighted sum)
total :: float(),
%% Generation this reward is for
generation :: pos_integer()
}).
-type meta_reward() :: #meta_reward{}.
%%% ============================================================================
%%% Network Structure Records
%%% ============================================================================
%% @doc LTC neuron state for the meta-controller network.
-record(meta_neuron, {
%% Neuron identifier: {layer, index}
id :: {pos_integer(), pos_integer()},
%% Internal state x(t)
internal_state = 0.0 :: float(),
%% Base time constant
time_constant :: float(),
%% State bound
state_bound :: float(),
%% Input weights: [{source_id, weight}]
input_weights = [] :: [{term(), float()}],
%% Bias
bias = 0.0 :: float(),
%% Backbone weights for CfC f() function
backbone_weights = [] :: [float()],
%% Head weights for CfC h() function
head_weights = [] :: [float()]
}).
-type meta_neuron() :: #meta_neuron{}.
%% @doc Output mapping for meta-controller.
%% Maps network outputs to parameter adjustments.
-record(output_mapping, {
%% Output index -> parameter name
index_to_param :: #{non_neg_integer() => meta_param()},
%% Parameter name -> output index
param_to_index :: #{meta_param() => non_neg_integer()},
%% Activation functions for each output (e.g., sigmoid for bounded params)
output_activations :: #{non_neg_integer() => atom()}
}).
-type output_mapping() :: #output_mapping{}.
%%% ============================================================================
%%% Training Event Record
%%% ============================================================================
%% @doc Training event for gradient-based meta-learning.
-record(meta_training_event, {
%% Generation
generation :: pos_integer(),
%% Input features (normalized metrics)
inputs :: [float()],
%% Output parameters (raw network outputs before scaling)
outputs :: [float()],
%% Reward received
reward :: float(),
%% Gradient estimate for this step
gradients :: #{term() => float()}
}).
-type meta_training_event() :: #meta_training_event{}.
%%% ============================================================================
%%% Structure Metrics Record (Normative Awareness)
%%% ============================================================================
%% @doc Structure metrics for normative awareness reward component.
%%
%% These metrics capture whether the population maintains the capacity
%% for future adaptation, not just current fitness.
-record(structure_metrics, {
%% Number of distinct strategy clusters in population
diversity_corridors = 0.0 :: float(),
%% Variance in traits that are adjacent to fitness (exploration potential)
adaptation_readiness = 0.0 :: float(),
%% Estimated distance to unexplored fitness regions
breakthrough_potential = 0.0 :: float(),
%% Shannon entropy of strategy distribution
strategy_entropy = 0.0 :: float()
}).
-type structure_metrics() :: #structure_metrics{}.
-endif. %% META_CONTROLLER_HRL