evolib 0.2.0b4.dev8__tar.gz → 0.2.0b4.dev10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {evolib-0.2.0b4.dev8/evolib.egg-info → evolib-0.2.0b4.dev10}/PKG-INFO +1 -1
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/config_guide.md +16 -4
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/config_parameter.md +30 -14
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/config/base_component_config.py +41 -16
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/config/evonet_component_config.py +76 -69
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/config/vector_component_config.py +40 -9
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/initializers/evonet_initializers.py +2 -3
- evolib-0.2.0b4.dev10/evolib/initializers/registry.py +112 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/interfaces/enums.py +1 -2
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/operators/evonet_structural_mutation.py +1 -2
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/operators/selection.py +12 -7
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/representation/evonet.py +5 -3
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10/evolib.egg-info}/PKG-INFO +1 -1
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib.egg-info/SOURCES.txt +0 -1
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/02_strategies/01_step_by_step_evolution.py +2 -2
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/05_advanced_topics/06_evolving_mutation_strength_as_a_module.py +1 -1
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/07_evonet/03_delay_bitseq_echo.py +1 -1
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/07_evonet/05_image_approximation.py +1 -2
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/pyproject.toml +1 -1
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/tests/test_config_loader.py +1 -1
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/tests/test_evonet_neuron_dynamics.py +10 -4
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/tests/test_initializer_evonet.py +6 -2
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/tests/test_initializer_net.py +3 -3
- evolib-0.2.0b4.dev8/evolib/initializers/registry.py +0 -85
- evolib-0.2.0b4.dev8/evolib/interfaces/enum_helpers.py +0 -31
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/LICENSE +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/MANIFEST.in +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/README.md +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_core_individual.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_core_population.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_operators_crossover.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_operators_evonet_structural_mutation.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_operators_mutation.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_operators_replacement.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_operators_reproduction.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_operators_selection.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_operators_strategy.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_public_api.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_representation_evonet.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_representation_netvector.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_representation_vector.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_utils_benchmarks.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_utils_history_logger.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_utils_loss_functions.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/api_utils_plotting.rst +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/conf.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/getting_started.md +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/docs/index.md +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/__init__.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/api.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/config/__init__.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/config/component_registry.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/config/schema.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/core/README.md +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/core/__init__.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/core/individual.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/core/population.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/envs/gym_wrapper.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/globals/README.md +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/globals/__init__.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/globals/numeric.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/initializers/__init__.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/initializers/net_initializers.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/initializers/vector_initializers.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/interfaces/__init__.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/interfaces/structs.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/interfaces/types.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/io/checkpoint.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/io/serialization.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/operators/README.md +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/operators/__init__.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/operators/crossover.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/operators/heli.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/operators/mutation.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/operators/replacement.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/operators/reproduction.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/operators/strategy.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/registry/__init__.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/registry/replacement_registry.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/registry/selection_registry.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/registry/strategy_registry.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/representation/__init__.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/representation/_apply_config_mapping.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/representation/base.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/representation/composite.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/representation/dummy.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/representation/evo_params.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/representation/netvector.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/representation/vector.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/README.md +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/__init__.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/benchmarks.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/config_loader.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/fitness.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/heli_experiment_logger.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/heli_utils.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/history_logger.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/lineage_logger.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/loss_functions.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/parallel.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/plotting.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/random.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib/utils/registry.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib.egg-info/dependency_links.txt +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib.egg-info/requires.txt +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/evolib.egg-info/top_level.txt +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/01_basic_usage/01_getting_started.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/01_basic_usage/02_mutation.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/01_basic_usage/03_population_mutation.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/01_basic_usage/04_fitness.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/02_strategies/02_mu_lambda_step.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/02_strategies/03_mu_lambda.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/02_strategies/04_flexible.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/03_comparisons/01_history.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/03_comparisons/02_plotting.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/03_comparisons/03_compare_runs.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/03_comparisons/04_exponential_decay_vs_static.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/03_comparisons/05_adaptive_global_vs_static.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/03_comparisons/06_adaptive_individual_vs_static.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/03_comparisons/07_selection_comparison.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/03_comparisons/08_selection_pressure.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/03_comparisons/09_selection_vs_mutation_pressure.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/03_comparisons/10_selection_stochastic_vs_deterministic.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/03_comparisons/11_crossover_comparison.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/04_function_approximation/01_polynomial_sine.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/04_function_approximation/02_sine_point_approximation.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/04_function_approximation/03_approximation_with_noise.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/05_advanced_topics/01_fitness_landscape_exploration.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/05_advanced_topics/02_rosenbrock_surface_path.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/05_advanced_topics/03_vector_control.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/05_advanced_topics/04_vector_control_with_obstacles.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/05_advanced_topics/05_piecewise_linear_xsys.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/06_netvector/01_netvector_sine_approximation.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/06_netvector/02_netvector_modulated_output.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/06_netvector/03_netvector_gain_and_bias.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/07_evonet/01_sine_approximation.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/07_evonet/02_sine_delay.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/07_evonet/04_leaky_temporal_smoothing.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/07_evonet/06_structural_xor.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/07_evonet/07_recurrent_bit_prediction.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/07_evonet/08_recurrent_timeseries.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/07_evonet/09_recurrent_trading.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/08_gym/01_frozen_lake.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/08_gym/02_cliff_walking.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/08_gym/03_cartpole.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/08_gym/04_lunar_lander.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/08_gym/05_bipedal_walker.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/09_meta_learning/01_lamarck_linear_mapping.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/examples/09_meta_learning/02_meta_mapping_baldwin.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/setup.cfg +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/tests/test_benchmarks.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/tests/test_elitism_preserves_best_fitness.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/tests/test_evonet_deepcopy.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/tests/test_evonet_vector_io.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/tests/test_mutation.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/tests/test_population.py +0 -0
- {evolib-0.2.0b4.dev8 → evolib-0.2.0b4.dev10}/tests/test_selection.py +0 -0
|
@@ -30,7 +30,7 @@ evolution:
|
|
|
30
30
|
modules:
|
|
31
31
|
test-vector: # logical module name
|
|
32
32
|
type: vector
|
|
33
|
-
initializer:
|
|
33
|
+
initializer: uniform
|
|
34
34
|
dim: 2
|
|
35
35
|
bounds: [-1.0, 1.0]
|
|
36
36
|
|
|
@@ -89,7 +89,7 @@ modules:
|
|
|
89
89
|
xs:
|
|
90
90
|
type: vector
|
|
91
91
|
dim: 6
|
|
92
|
-
initializer:
|
|
92
|
+
initializer: uniform
|
|
93
93
|
bounds: [0.0, 6.283185307] # [0, 2π]
|
|
94
94
|
mutation:
|
|
95
95
|
strategy: adaptive_individual
|
|
@@ -120,6 +120,11 @@ This configuration demonstrates EvoNet evolution: weight mutation, bias-specific
|
|
|
120
120
|
|
|
121
121
|
`dim: [2, 0, 0, 1]` starts with empty hidden layers, letting structural mutation grow nodes and edges.
|
|
122
122
|
|
|
123
|
+
Connectivity:
|
|
124
|
+
- `scope` controls which feedforward edges are allowed at initialization.
|
|
125
|
+
- `density` controls how many of those allowed edges are actually created at init.
|
|
126
|
+
- `recurrent` enables recurrent edge kinds (empty list means none).
|
|
127
|
+
|
|
123
128
|
Topology constraints:
|
|
124
129
|
- `max_neurons` and `max_connections` keep growth bounded (these are the current names; avoid older `max_nodes/max_edges`).
|
|
125
130
|
|
|
@@ -127,6 +132,8 @@ Delay:
|
|
|
127
132
|
- `delay:` initializes delays of recurrent connections at build time.
|
|
128
133
|
- `mutation.delay:` mutates delays during evolution (recurrent connections only).
|
|
129
134
|
|
|
135
|
+
|
|
136
|
+
|
|
130
137
|
```yaml
|
|
131
138
|
parent_pool_size: 20
|
|
132
139
|
offspring_pool_size: 40
|
|
@@ -145,17 +152,22 @@ modules:
|
|
|
145
152
|
type: evonet
|
|
146
153
|
dim: [2, 0, 0, 1] # hidden layers start empty
|
|
147
154
|
activation: [linear, tanh, tanh, sigmoid]
|
|
155
|
+
|
|
156
|
+
connectivity:
|
|
157
|
+
scope: crosslayer # adjacent | crosslayer
|
|
158
|
+
density: 1.0 # (0, 1]
|
|
159
|
+
recurrent: [direct] # [], [direct], [lateral], [indirect]
|
|
160
|
+
|
|
148
161
|
weights:
|
|
149
162
|
initializer: normal
|
|
150
163
|
std: 0.5
|
|
151
164
|
bounds: [-5.0, 5.0]
|
|
165
|
+
|
|
152
166
|
bias:
|
|
153
167
|
initializer: normal
|
|
154
168
|
std: 0.5
|
|
155
169
|
bounds: [-1.0, 1.0]
|
|
156
170
|
|
|
157
|
-
recurrent: direct # REQUIRED for delay to have any effect
|
|
158
|
-
|
|
159
171
|
# NOTE: Delays only apply to recurrent connections.
|
|
160
172
|
# If `recurrent` is not enabled, this block has no effect.
|
|
161
173
|
delay:
|
|
@@ -152,7 +152,7 @@ The `vector` module defines an evolvable parameter vector.
|
|
|
152
152
|
| `type` | `"vector"` | — | Module type identifier. |
|
|
153
153
|
| `dim` | `int \| list[int]` | — | Vector length (`int`) or structured dimensions (`list[int]`). Must be > 0. |
|
|
154
154
|
| `structure` | `"flat" \| "net" | `"flat"` | Structural interpretation of the vector. |
|
|
155
|
-
| `initializer` | `str` | — | Initializer name from the registry (e.g. `
|
|
155
|
+
| `initializer` | `str` | — | Initializer name from the registry (e.g. `uniform`, `zero`, `normal`, `fixed`). |
|
|
156
156
|
| `bounds` | `tuple[float, float]` | `[-1.0, 1.0]` | Hard clamp range applied after mutation. |
|
|
157
157
|
| `init_bounds` | `tuple[float, float] \| null` | `null` | Clamp applied only during initialization. Falls back to `bounds` if not set. |
|
|
158
158
|
| `shape` | `tuple[int, ...] \| null` | `null` | Optional explicit shape. If set, `dim = product(shape)`. Shape is retained as metadata. |
|
|
@@ -232,7 +232,7 @@ modules:
|
|
|
232
232
|
main:
|
|
233
233
|
type: vector
|
|
234
234
|
dim: 8
|
|
235
|
-
initializer:
|
|
235
|
+
initializer: uniform
|
|
236
236
|
bounds: [-1.0, 1.0]
|
|
237
237
|
|
|
238
238
|
mutation:
|
|
@@ -288,13 +288,31 @@ modules:
|
|
|
288
288
|
|-------------------|---------------------|---------|-------------|
|
|
289
289
|
| `dim` | list[int] | — | Layer sizes, e.g. `[4, 0, 0, 2]`. Hidden layers can start empty (0) and grow through structural mutation. |
|
|
290
290
|
| `activation` | str \| list[str] | — | If list: activation per layer. If str: used for non-input layers; input layer is treated as linear. |
|
|
291
|
-
| `initializer` | str |
|
|
291
|
+
| `initializer` | str | default | Topology preset (e.g. `default`, `unconnected`, `identity`). Parameter initialization is configured via `weights`, `bias`, and `delay`. |
|
|
292
|
+
| `connectivity` | `dict` | — | **Required.** Defines feedforward scope/density and allowed recurrent kinds. |
|
|
292
293
|
| `weights` | dict | — | Weight init and bounds configuration (initializer, bounds, optional params). |
|
|
293
294
|
| `bias` | dict | — | Bias init and bounds configuration (initializer, bounds, optional params). |
|
|
294
295
|
| `neuron_dynamics` | list[dict] \| null | null | Optional per-layer neuron dynamics specification. Must match `len(dim)`. |
|
|
295
296
|
| `mutation` | dict \| null | null | Mutation settings for weights, biases, activations, delay, and structure. |
|
|
296
297
|
| `crossover` | dict \| null | null | Optional crossover settings (weight/bias level). |
|
|
297
298
|
|
|
299
|
+
#### Connectivity (`connectivity`)
|
|
300
|
+
|
|
301
|
+
| Field | Type | Default | Notes |
|
|
302
|
+
|------------|------------------------------|---------|------|
|
|
303
|
+
| `scope` | `"adjacent" \| "crosslayer"` | — | **Required.** Allowed feedforward edge scope at initialization. |
|
|
304
|
+
| `density` | `float` | — | **Required.** Fraction of allowed feedforward edges created at init `(0,1]`. |
|
|
305
|
+
| `recurrent`| `list[str]` | `[]` | Allowed recurrent edge kinds. Empty list means none. |
|
|
306
|
+
|
|
307
|
+
Example:
|
|
308
|
+
|
|
309
|
+
```yaml
|
|
310
|
+
connectivity:
|
|
311
|
+
scope: crosslayer
|
|
312
|
+
density: 0.5
|
|
313
|
+
recurrent: [direct]
|
|
314
|
+
```
|
|
315
|
+
|
|
298
316
|
##### weights block
|
|
299
317
|
|Parameter | Type | Default | Explanation |
|
|
300
318
|
|------------|-------|-----------|-------------|
|
|
@@ -324,9 +342,9 @@ Allowed presets:
|
|
|
324
342
|
|
|
325
343
|
| Initializer | Meaning (topology only) |
|
|
326
344
|
|------------------------|-------------------------|
|
|
327
|
-
| `
|
|
328
|
-
| `
|
|
329
|
-
| `
|
|
345
|
+
| `default` | Standard EvoNet topology preset (uses `connection_scope`, `connection_density`, and `recurrent`). |
|
|
346
|
+
| `unconnected` | Creates neurons/layers but starts with **no connections** (use structural mutation to grow). |
|
|
347
|
+
| `identity` | Special preset intended for stable recurrent memory (may override parameters internally; see notes below). |
|
|
330
348
|
|
|
331
349
|
---
|
|
332
350
|
|
|
@@ -493,13 +511,12 @@ structural:
|
|
|
493
511
|
|
|
494
512
|
### Topology constraints
|
|
495
513
|
|
|
496
|
-
| Field
|
|
497
|
-
|
|
498
|
-
| `recurrent`
|
|
499
|
-
| `connection_scope`
|
|
500
|
-
| `
|
|
501
|
-
| `
|
|
502
|
-
| `max_connections` | int \| null | null | Maximum number of edges (`null` = unlimited). |
|
|
514
|
+
| Field | Type | Default | Description |
|
|
515
|
+
|-------------------|--------------------------------|-------------|-------------|
|
|
516
|
+
| `recurrent` | `list[str]` | `[]` | Allowed recurrent kinds for `add_connection`. Empty list means none. |
|
|
517
|
+
| `connection_scope` | `"adjacent" \| "crosslayer" \| null` | `"adjacent"` | Constraint for structural add-neuron / add-connection edge placement. |
|
|
518
|
+
| `max_neurons` | `int \| null` | `null` | Upper bound on total neurons allowed (implementation-defined counting). |
|
|
519
|
+
| `max_connections` | `int \| null` | `null` | Upper bound on total connections allowed. |
|
|
503
520
|
|
|
504
521
|
---
|
|
505
522
|
|
|
@@ -544,7 +561,6 @@ modules:
|
|
|
544
561
|
type: evonet
|
|
545
562
|
dim: [4, 0, 0, 2]
|
|
546
563
|
activation: [linear, tanh, tanh, tanh]
|
|
547
|
-
initializer: normal_evonet
|
|
548
564
|
|
|
549
565
|
delay:
|
|
550
566
|
initializer: uniform
|
|
@@ -8,10 +8,11 @@ should be configured, not *how* it is executed. Any runtime behavior belongs
|
|
|
8
8
|
into the respective Para* representations and operator modules.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
from typing import Literal, Optional, Union
|
|
11
|
+
from typing import Any, Literal, Optional, Union
|
|
12
12
|
|
|
13
13
|
from evonet.activation import ACTIVATIONS
|
|
14
|
-
from
|
|
14
|
+
from evonet.enums import RecurrentKind
|
|
15
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
|
15
16
|
|
|
16
17
|
from evolib.interfaces.enums import (
|
|
17
18
|
CrossoverOperator,
|
|
@@ -221,15 +222,21 @@ class AddNeuron(BaseModel):
|
|
|
221
222
|
"neurons in hidden layers.",
|
|
222
223
|
)
|
|
223
224
|
|
|
224
|
-
@
|
|
225
|
-
|
|
225
|
+
@field_validator("activations_allowed")
|
|
226
|
+
@classmethod
|
|
227
|
+
def validate_activations_allowed(
|
|
228
|
+
cls, acts: Optional[list[str]]
|
|
229
|
+
) -> Optional[list[str]]:
|
|
226
230
|
"""Ensure only valid activation function names are allowed."""
|
|
227
|
-
if
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
231
|
+
if acts is None:
|
|
232
|
+
return None
|
|
233
|
+
for a in acts:
|
|
234
|
+
if a not in ACTIVATIONS:
|
|
235
|
+
raise ValueError(
|
|
236
|
+
f"Invalid activation function '{a}'. "
|
|
237
|
+
f"Valid options are: {sorted(ACTIVATIONS.keys())}"
|
|
238
|
+
)
|
|
239
|
+
return acts
|
|
233
240
|
|
|
234
241
|
|
|
235
242
|
class RemoveNeuron(BaseModel):
|
|
@@ -267,7 +274,12 @@ class StructuralTopology(BaseModel):
|
|
|
267
274
|
mutation operators.
|
|
268
275
|
"""
|
|
269
276
|
|
|
270
|
-
recurrent:
|
|
277
|
+
recurrent: list[RecurrentKind] = Field(
|
|
278
|
+
default_factory=list,
|
|
279
|
+
description="Allowed recurrent edge kinds for structural "
|
|
280
|
+
"add_connection. Empty means none.",
|
|
281
|
+
)
|
|
282
|
+
|
|
271
283
|
connection_scope: Optional[Literal["adjacent", "crosslayer"]] = "adjacent"
|
|
272
284
|
|
|
273
285
|
max_neurons: Optional[int] = Field(
|
|
@@ -282,21 +294,34 @@ class StructuralTopology(BaseModel):
|
|
|
282
294
|
ge=1,
|
|
283
295
|
)
|
|
284
296
|
|
|
297
|
+
@field_validator("recurrent", mode="before")
|
|
298
|
+
@classmethod
|
|
299
|
+
def normalize_recurrent(cls, v: Any) -> list[RecurrentKind]:
|
|
300
|
+
"""
|
|
301
|
+
Allow YAML convenience values like:
|
|
302
|
+
recurrent: none
|
|
303
|
+
recurrent: []
|
|
304
|
+
"""
|
|
305
|
+
if v is None:
|
|
306
|
+
return []
|
|
307
|
+
if isinstance(v, str):
|
|
308
|
+
if v.lower() == "none":
|
|
309
|
+
return []
|
|
310
|
+
return [v]
|
|
311
|
+
return v
|
|
312
|
+
|
|
285
313
|
@model_validator(mode="after")
|
|
286
314
|
def _validate_topology(self) -> "StructuralTopology":
|
|
287
|
-
if self.recurrent not in {None, "none", "direct", "local", "all"}:
|
|
288
|
-
raise ValueError(f"Invalid recurrent value: {self.recurrent}")
|
|
289
|
-
|
|
290
315
|
if self.connection_scope not in {None, "adjacent", "crosslayer"}:
|
|
291
316
|
raise ValueError(f"Invalid connection_scope: {self.connection_scope}")
|
|
292
317
|
|
|
293
|
-
# Only positive limits allowed
|
|
294
318
|
if self.max_connections is not None and self.max_connections <= 0:
|
|
295
319
|
raise ValueError("max_connections must be > 0")
|
|
296
|
-
|
|
297
320
|
if self.max_neurons is not None and self.max_neurons <= 0:
|
|
298
321
|
raise ValueError("max_neurons must be > 0")
|
|
299
322
|
|
|
323
|
+
# ensure deterministic unique list
|
|
324
|
+
self.recurrent = sorted(set(self.recurrent), key=lambda x: x.value)
|
|
300
325
|
return self
|
|
301
326
|
|
|
302
327
|
|
|
@@ -11,16 +11,16 @@ After parsing, raw dicts are converted into this strongly typed Pydantic model d
|
|
|
11
11
|
config resolution.
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
-
from typing import Literal, Optional, Tuple, Union
|
|
14
|
+
from typing import Any, Literal, Optional, Tuple, Union
|
|
15
15
|
|
|
16
16
|
from evonet.activation import ACTIVATIONS
|
|
17
|
+
from evonet.enums import RecurrentKind
|
|
17
18
|
from pydantic import (
|
|
18
19
|
BaseModel,
|
|
19
20
|
ConfigDict,
|
|
20
21
|
Field,
|
|
21
22
|
field_validator,
|
|
22
23
|
model_validator,
|
|
23
|
-
validator,
|
|
24
24
|
)
|
|
25
25
|
from pydantic_core import core_schema
|
|
26
26
|
|
|
@@ -30,10 +30,60 @@ from evolib.config.base_component_config import (
|
|
|
30
30
|
EvoNetNeuronDynamicsConfig,
|
|
31
31
|
StructuralMutationConfig,
|
|
32
32
|
)
|
|
33
|
+
from evolib.interfaces.enums import RepresentationType
|
|
33
34
|
|
|
34
35
|
Bounds = Tuple[float, float]
|
|
35
36
|
|
|
36
37
|
|
|
38
|
+
class ConnectivityConfig(BaseModel):
|
|
39
|
+
"""
|
|
40
|
+
EvoNet connectivity configuration.
|
|
41
|
+
|
|
42
|
+
recurrent:
|
|
43
|
+
Allowed recurrent edge kinds (DIRECT/LATERAL/INDIRECT).
|
|
44
|
+
If omitted, no recurrent edges are allowed.
|
|
45
|
+
|
|
46
|
+
scope:
|
|
47
|
+
adjacent -> only adjacent-layer feedforward connections during init
|
|
48
|
+
crosslayer -> cross-layer feedforward connections during init
|
|
49
|
+
|
|
50
|
+
density:
|
|
51
|
+
Fraction of allowed feedforward edges to create at init (0 < density <= 1).
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
model_config = ConfigDict(extra="forbid")
|
|
55
|
+
|
|
56
|
+
recurrent: list[RecurrentKind] = Field(default_factory=list)
|
|
57
|
+
|
|
58
|
+
# Required: must be explicitly set in YAML
|
|
59
|
+
scope: Literal["adjacent", "crosslayer"]
|
|
60
|
+
|
|
61
|
+
# Required: must be explicitly set in YAML
|
|
62
|
+
density: float = Field(..., gt=0.0, le=1.0)
|
|
63
|
+
|
|
64
|
+
@field_validator("recurrent", mode="before")
|
|
65
|
+
@classmethod
|
|
66
|
+
def normalize_recurrent(cls, v: Any) -> list[RecurrentKind]:
|
|
67
|
+
"""
|
|
68
|
+
Allow YAML convenience values like:
|
|
69
|
+
recurrent: none
|
|
70
|
+
recurrent: []
|
|
71
|
+
"""
|
|
72
|
+
if v is None:
|
|
73
|
+
return []
|
|
74
|
+
if isinstance(v, str):
|
|
75
|
+
if v.lower() == "none":
|
|
76
|
+
return []
|
|
77
|
+
return [v]
|
|
78
|
+
return v
|
|
79
|
+
|
|
80
|
+
@model_validator(mode="after")
|
|
81
|
+
def _normalize(self) -> "ConnectivityConfig":
|
|
82
|
+
# deterministic, unique
|
|
83
|
+
self.recurrent = sorted(set(self.recurrent), key=lambda x: x.value)
|
|
84
|
+
return self
|
|
85
|
+
|
|
86
|
+
|
|
37
87
|
class WeightsConfig(BaseModel):
|
|
38
88
|
# None means: no parameter-level initialization requested (preset may initialize).
|
|
39
89
|
initializer: Optional[str] = None # normal | uniform | zero | None
|
|
@@ -208,7 +258,10 @@ class EvoNetComponentConfig(BaseModel):
|
|
|
208
258
|
model_config = ConfigDict(extra="forbid")
|
|
209
259
|
|
|
210
260
|
# Module type is fixed to "evonet"
|
|
211
|
-
type:
|
|
261
|
+
type: RepresentationType = Field(
|
|
262
|
+
default=RepresentationType.EVONET,
|
|
263
|
+
description='Fixed module discriminator; must be "evonet" for this schema.',
|
|
264
|
+
)
|
|
212
265
|
|
|
213
266
|
# Layer structure: list of neuron counts per layer [input, hidden..., output]
|
|
214
267
|
dim: list[int]
|
|
@@ -223,33 +276,13 @@ class EvoNetComponentConfig(BaseModel):
|
|
|
223
276
|
"neurons in hidden layers.",
|
|
224
277
|
)
|
|
225
278
|
|
|
226
|
-
# Recurrent connections
|
|
227
|
-
recurrent: Optional[Literal["none", "direct", "local", "all"]] = "none"
|
|
228
|
-
|
|
229
279
|
# Name of the initializer function (resolved via initializer registry)
|
|
230
280
|
initializer: str = Field(
|
|
231
|
-
default="
|
|
281
|
+
default="default", description="Name of the initializer to use"
|
|
232
282
|
)
|
|
233
283
|
|
|
234
|
-
#
|
|
235
|
-
|
|
236
|
-
default="adjacent",
|
|
237
|
-
description=(
|
|
238
|
-
"Defines how layers are connected during initialization. "
|
|
239
|
-
"'adjacent' connects only consecutive layers, while 'crosslayer' "
|
|
240
|
-
"connects all earlier layers to all later layers."
|
|
241
|
-
),
|
|
242
|
-
)
|
|
243
|
-
|
|
244
|
-
connection_density: float = Field(
|
|
245
|
-
default=1.0,
|
|
246
|
-
ge=0.0,
|
|
247
|
-
le=1.0,
|
|
248
|
-
description=(
|
|
249
|
-
"Fraction of possible connections actually created during initialization. "
|
|
250
|
-
"1.0 = fully connected, <1.0 = sparse."
|
|
251
|
-
),
|
|
252
|
-
)
|
|
284
|
+
# Connectivity
|
|
285
|
+
connectivity: ConnectivityConfig
|
|
253
286
|
|
|
254
287
|
# Numeric bounds for values; used by initialization and mutation
|
|
255
288
|
weights: WeightsConfig = Field(default_factory=WeightsConfig)
|
|
@@ -276,9 +309,9 @@ class EvoNetComponentConfig(BaseModel):
|
|
|
276
309
|
Parameter initialization is handled exclusively via weights/bias/delay blocks.
|
|
277
310
|
"""
|
|
278
311
|
allowed = {
|
|
279
|
-
"
|
|
280
|
-
"
|
|
281
|
-
"
|
|
312
|
+
"default",
|
|
313
|
+
"unconnected",
|
|
314
|
+
"identity",
|
|
282
315
|
}
|
|
283
316
|
|
|
284
317
|
if name not in allowed:
|
|
@@ -331,45 +364,19 @@ class EvoNetComponentConfig(BaseModel):
|
|
|
331
364
|
raise ValueError("Length of 'activation' list must match 'dim'")
|
|
332
365
|
return act
|
|
333
366
|
|
|
334
|
-
@
|
|
335
|
-
def validate_activation_name(cls, act_name: str) -> str:
|
|
336
|
-
"""Ensure only valid activation function names are allowed."""
|
|
337
|
-
if act_name not in ACTIVATIONS:
|
|
338
|
-
raise ValueError(
|
|
339
|
-
f"Invalid activation function '{act_name}'. "
|
|
340
|
-
f"Valid options are: {list(ACTIVATIONS.keys())}"
|
|
341
|
-
)
|
|
342
|
-
return act_name
|
|
343
|
-
|
|
344
|
-
@validator("recurrent")
|
|
345
|
-
def validate_recurrent(cls, recurrent: Optional[str]) -> str:
|
|
346
|
-
"""Ensure recurrent preset is valid and normalized."""
|
|
347
|
-
if recurrent is None:
|
|
348
|
-
return "none"
|
|
349
|
-
allowed = {"none", "direct", "local", "all"}
|
|
350
|
-
if recurrent not in allowed:
|
|
351
|
-
raise ValueError(
|
|
352
|
-
f"Invalid recurrent preset '{recurrent}'. "
|
|
353
|
-
f"Valid options are: {sorted(allowed)}"
|
|
354
|
-
)
|
|
355
|
-
return recurrent
|
|
356
|
-
|
|
357
|
-
@field_validator("connection_scope")
|
|
367
|
+
@field_validator("activations_allowed")
|
|
358
368
|
@classmethod
|
|
359
|
-
def
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
f"Valid options are: {sorted(allowed)}"
|
|
366
|
-
)
|
|
367
|
-
return scope
|
|
369
|
+
def validate_activations_allowed(
|
|
370
|
+
cls, acts: Optional[list[str]]
|
|
371
|
+
) -> Optional[list[str]]:
|
|
372
|
+
"""Validate that all activation names are known."""
|
|
373
|
+
if acts is None:
|
|
374
|
+
return None
|
|
368
375
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
return
|
|
376
|
+
for a in acts:
|
|
377
|
+
if a not in ACTIVATIONS:
|
|
378
|
+
raise ValueError(
|
|
379
|
+
f"Invalid activation function '{a}'. "
|
|
380
|
+
f"Valid options are: {sorted(ACTIVATIONS.keys())}"
|
|
381
|
+
)
|
|
382
|
+
return acts
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# SPDX-License-Identifier: MIT
|
|
2
2
|
from typing import Any, Literal, Optional, Tuple, Union
|
|
3
3
|
|
|
4
|
-
from pydantic import
|
|
4
|
+
from pydantic import (
|
|
5
|
+
BaseModel,
|
|
6
|
+
ConfigDict,
|
|
7
|
+
Field,
|
|
8
|
+
ValidationInfo,
|
|
9
|
+
field_validator,
|
|
10
|
+
model_validator,
|
|
11
|
+
)
|
|
5
12
|
|
|
6
13
|
from evolib.config.base_component_config import CrossoverConfig, MutationConfig
|
|
7
14
|
from evolib.interfaces.enums import RepresentationType
|
|
@@ -21,7 +28,7 @@ class VectorComponentConfig(BaseModel):
|
|
|
21
28
|
type: vector
|
|
22
29
|
structure: flat # "flat" | "net"
|
|
23
30
|
dim: 16 # or a list for structured cases
|
|
24
|
-
initializer:
|
|
31
|
+
initializer: normal # name from the initializer registry
|
|
25
32
|
bounds: [-1.0, 1.0]
|
|
26
33
|
mutation:
|
|
27
34
|
strategy: constant
|
|
@@ -86,7 +93,7 @@ class VectorComponentConfig(BaseModel):
|
|
|
86
93
|
values: Optional[list[float]] = Field(
|
|
87
94
|
default=None,
|
|
88
95
|
description=(
|
|
89
|
-
"Explicit values for '
|
|
96
|
+
"Explicit values for 'fixed' initializer. If 'dim' is absent it "
|
|
90
97
|
"will be inferred from the length of 'values'."
|
|
91
98
|
),
|
|
92
99
|
)
|
|
@@ -102,7 +109,6 @@ class VectorComponentConfig(BaseModel):
|
|
|
102
109
|
|
|
103
110
|
# Evolution (mutation / crossover)
|
|
104
111
|
mutation: MutationConfig = Field(
|
|
105
|
-
default=None,
|
|
106
112
|
description=(
|
|
107
113
|
"Mutation configuration. By default, 'probability' is an element-wise rate "
|
|
108
114
|
"(per gene) in [0,1]; operators may optionally treat it as an apply gate."
|
|
@@ -143,18 +149,16 @@ class VectorComponentConfig(BaseModel):
|
|
|
143
149
|
@classmethod
|
|
144
150
|
def set_dim_for_fixed_vector(cls, config: dict[str, Any]) -> dict[str, Any]:
|
|
145
151
|
"""
|
|
146
|
-
If using '
|
|
152
|
+
If using 'fixed', ensure 'values' is provided and infer 'dim' if absent.
|
|
147
153
|
|
|
148
154
|
This keeps YAML concise and catches common mistakes early.
|
|
149
155
|
"""
|
|
150
156
|
initializer = config.get("initializer")
|
|
151
157
|
values = config.get("values")
|
|
152
158
|
|
|
153
|
-
if initializer == "
|
|
159
|
+
if initializer == "fixed":
|
|
154
160
|
if not values:
|
|
155
|
-
raise ValueError(
|
|
156
|
-
"When using 'fixed_vector', 'values' must be provided."
|
|
157
|
-
)
|
|
161
|
+
raise ValueError("When using 'fixed', 'values' must be provided.")
|
|
158
162
|
if "dim" not in config:
|
|
159
163
|
config["dim"] = len(values)
|
|
160
164
|
return config
|
|
@@ -181,3 +185,30 @@ class VectorComponentConfig(BaseModel):
|
|
|
181
185
|
else:
|
|
182
186
|
raise TypeError("dim must be an int or list of ints")
|
|
183
187
|
return dim
|
|
188
|
+
|
|
189
|
+
@field_validator("initializer")
|
|
190
|
+
@classmethod
|
|
191
|
+
def validate_initializer(cls, name: str, info: ValidationInfo) -> str:
|
|
192
|
+
"""Validate allowed initializer names and provide clear errors for deprecated
|
|
193
|
+
names."""
|
|
194
|
+
if not isinstance(name, str) or not name.strip():
|
|
195
|
+
raise ValueError("initializer must be a non-empty string")
|
|
196
|
+
|
|
197
|
+
name = name.strip()
|
|
198
|
+
|
|
199
|
+
allowed = {"normal", "uniform", "zero", "fixed", "adaptive"}
|
|
200
|
+
if name not in allowed:
|
|
201
|
+
raise ValueError(
|
|
202
|
+
f"Unknown initializer '{name}'. " f"Allowed: {sorted(allowed)}"
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
# structure-aware check (only if structure is available in the data)
|
|
206
|
+
data = info.data or {}
|
|
207
|
+
structure = data.get("structure") or "flat"
|
|
208
|
+
if structure == "net" and name != "normal":
|
|
209
|
+
raise ValueError(
|
|
210
|
+
"For structure='net', initializer must be 'normal' "
|
|
211
|
+
"(use initializer: normal and structure: net)."
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
return name
|
|
@@ -14,7 +14,6 @@ from evonet.enums import ConnectionType, NeuronRole
|
|
|
14
14
|
|
|
15
15
|
from evolib.config.evonet_component_config import DelayConfig, EvoNetComponentConfig
|
|
16
16
|
from evolib.config.schema import FullConfig
|
|
17
|
-
from evolib.interfaces.enum_helpers import resolve_recurrent_kinds
|
|
18
17
|
from evolib.representation.evonet import EvoNet
|
|
19
18
|
|
|
20
19
|
|
|
@@ -158,14 +157,14 @@ def _build_architecture(
|
|
|
158
157
|
dynamics_name = dynamics_cfg.name
|
|
159
158
|
dynamics_params = dynamics_cfg.params or {}
|
|
160
159
|
|
|
161
|
-
|
|
160
|
+
allowed_kinds = set(cfg.connectivity.recurrent)
|
|
162
161
|
para.net.add_neuron(
|
|
163
162
|
count=num_neurons,
|
|
164
163
|
activation=activation_name,
|
|
165
164
|
role=role,
|
|
166
165
|
connection_init=connection_init,
|
|
167
166
|
bias=0.0,
|
|
168
|
-
recurrent=
|
|
167
|
+
recurrent=allowed_kinds if role != NeuronRole.INPUT else None,
|
|
169
168
|
connection_scope=para.connection_scope,
|
|
170
169
|
connection_density=para.connection_density,
|
|
171
170
|
dynamics_name=dynamics_name,
|