%% @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