Current section
Files
Jump to
Current section
Files
src/meta_config.erl
%% @doc Configuration builder for the LTC meta-controller.
%%
%% This module provides helper functions to construct #meta_config{} records
%% from maps, enabling clean integration with Elixir applications.
%%
%% == Usage ==
%%
%% From Elixir:
%% meta_config = :meta_config.from_map(%{
%% network_topology: {11, [24, 16, 8], 5},
%% neuron_type: :cfc,
%% time_constant: 50.0
%% })
%% neuro_config = :neuro_config.from_map(%{
%% meta_controller_config: meta_config,
%% ...
%% })
%%
%% @author Macula.io
%% @copyright 2025 Macula.io
-module(meta_config).
-include("meta_controller.hrl").
-export([
from_map/1,
to_map/1,
default/0,
default_reward_weights/0,
default_param_bounds/0
]).
%%% ============================================================================
%%% API Functions
%%% ============================================================================
%% @doc Build a #meta_config{} record from a map.
%%
%% All fields are optional - missing fields use sensible defaults.
%% This function handles type coercion and validation.
-spec from_map(map()) -> #meta_config{}.
from_map(Map) when is_map(Map) ->
#meta_config{
%% Network architecture for the LTC meta-controller
%% Default: 11 inputs (8 original + 3 resource metrics), 5 outputs
network_topology = maps:get(network_topology, Map, {11, [24, 16, 8], 5}),
%% LTC neuron type: cfc (fast) or ltc (accurate ODE)
neuron_type = maps:get(neuron_type, Map, cfc),
%% Base time constant for meta-controller neurons
%% Higher values = slower adaptation = more stable
time_constant = maps:get(time_constant, Map, 50.0),
%% State bound for LTC neurons
state_bound = maps:get(state_bound, Map, 1.0),
%% Reward component weights (must sum to ~1.0)
reward_weights = maps:get(reward_weights, Map, default_reward_weights()),
%% Learning rate for gradient-based meta-training
learning_rate = maps:get(learning_rate, Map, 0.001),
%% Parameter bounds: {ParamName, {Min, Max}}
param_bounds = maps:get(param_bounds, Map, default_param_bounds()),
%% Whether to include population_size as a controllable parameter
control_population_size = maps:get(control_population_size, Map, false),
%% Whether to control topology mutation rates (NEAT mode)
control_topology = maps:get(control_topology, Map, false),
%% History window size for computing reward signals
history_window = maps:get(history_window, Map, 10),
%% Momentum for parameter updates (smooths changes)
momentum = maps:get(momentum, Map, 0.9)
}.
%% @doc Convert a #meta_config{} record to a map.
%%
%% Useful for serialization, logging, and passing to Elixir code.
-spec to_map(#meta_config{}) -> map().
to_map(Config) when is_record(Config, meta_config) ->
#{
network_topology => Config#meta_config.network_topology,
neuron_type => Config#meta_config.neuron_type,
time_constant => Config#meta_config.time_constant,
state_bound => Config#meta_config.state_bound,
reward_weights => Config#meta_config.reward_weights,
learning_rate => Config#meta_config.learning_rate,
param_bounds => Config#meta_config.param_bounds,
control_population_size => Config#meta_config.control_population_size,
control_topology => Config#meta_config.control_topology,
history_window => Config#meta_config.history_window,
momentum => Config#meta_config.momentum
}.
%% @doc Create a default configuration with sensible defaults.
-spec default() -> #meta_config{}.
default() ->
from_map(#{}).
%% @doc Default reward component weights.
%%
%% These weights balance different aspects of training quality:
%% - convergence_speed: How quickly fitness improves
%% - final_fitness: The ultimate fitness achieved
%% - efficiency_ratio: Fitness improvement per evaluation
%% - diversity_aware: Maintaining population diversity
%% - normative_structure: Preserving adaptation potential
-spec default_reward_weights() -> map().
default_reward_weights() ->
#{
convergence_speed => 0.25,
final_fitness => 0.25,
efficiency_ratio => 0.20,
diversity_aware => 0.15,
normative_structure => 0.15
}.
%% @doc Default parameter bounds for meta-controller outputs.
%%
%% These bounds define the legal ranges for each hyperparameter
%% that the LTC meta-controller can adjust.
%%
%% Includes resource-aware parameters:
%% - evaluations_per_individual: Can drop to 1 under memory pressure
%% - max_concurrent_evaluations: Limits parallelism under load
-spec default_param_bounds() -> map().
default_param_bounds() ->
#{
%% Basic evolution parameters
mutation_rate => {0.01, 0.5},
mutation_strength => {0.05, 1.0},
selection_ratio => {0.10, 0.50},
%% Resource-aware parameters (NEW)
evaluations_per_individual => {1, 20},
max_concurrent_evaluations => {1, 1000000}, % This is Erlang - can handle millions of processes
%% Population control (when enabled)
population_size => {10, 200},
%% Topology control (NEAT mode)
add_node_rate => {0.0, 0.10},
add_connection_rate => {0.0, 0.20},
complexity_penalty => {0.0, 0.5}
}.