evolib 0.2.0b4.dev6__tar.gz → 0.2.0b4.dev7__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.
Files changed (156) hide show
  1. {evolib-0.2.0b4.dev6/evolib.egg-info → evolib-0.2.0b4.dev7}/PKG-INFO +1 -1
  2. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/config/evonet_component_config.py +102 -14
  3. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/initializers/evonet_initializers.py +105 -64
  4. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/representation/evonet.py +26 -14
  5. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7/evolib.egg-info}/PKG-INFO +1 -1
  6. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/pyproject.toml +1 -1
  7. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/tests/test_evonet_neuron_dynamics.py +13 -0
  8. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/tests/test_initializer_evonet.py +10 -0
  9. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/LICENSE +0 -0
  10. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/MANIFEST.in +0 -0
  11. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/README.md +0 -0
  12. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_core_individual.rst +0 -0
  13. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_core_population.rst +0 -0
  14. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_operators_crossover.rst +0 -0
  15. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_operators_evonet_structural_mutation.rst +0 -0
  16. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_operators_mutation.rst +0 -0
  17. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_operators_replacement.rst +0 -0
  18. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_operators_reproduction.rst +0 -0
  19. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_operators_selection.rst +0 -0
  20. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_operators_strategy.rst +0 -0
  21. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_public_api.rst +0 -0
  22. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_representation_evonet.rst +0 -0
  23. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_representation_netvector.rst +0 -0
  24. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_representation_vector.rst +0 -0
  25. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_utils_benchmarks.rst +0 -0
  26. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_utils_history_logger.rst +0 -0
  27. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_utils_loss_functions.rst +0 -0
  28. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/api_utils_plotting.rst +0 -0
  29. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/conf.py +0 -0
  30. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/config_guide.md +0 -0
  31. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/config_parameter.md +0 -0
  32. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/getting_started.md +0 -0
  33. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/docs/index.md +0 -0
  34. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/__init__.py +0 -0
  35. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/api.py +0 -0
  36. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/config/__init__.py +0 -0
  37. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/config/base_component_config.py +0 -0
  38. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/config/component_registry.py +0 -0
  39. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/config/schema.py +0 -0
  40. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/config/vector_component_config.py +0 -0
  41. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/core/README.md +0 -0
  42. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/core/__init__.py +0 -0
  43. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/core/individual.py +0 -0
  44. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/core/population.py +0 -0
  45. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/envs/gym_wrapper.py +0 -0
  46. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/globals/README.md +0 -0
  47. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/globals/__init__.py +0 -0
  48. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/globals/numeric.py +0 -0
  49. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/initializers/__init__.py +0 -0
  50. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/initializers/net_initializers.py +0 -0
  51. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/initializers/registry.py +0 -0
  52. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/initializers/vector_initializers.py +0 -0
  53. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/interfaces/__init__.py +0 -0
  54. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/interfaces/enum_helpers.py +0 -0
  55. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/interfaces/enums.py +0 -0
  56. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/interfaces/structs.py +0 -0
  57. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/interfaces/types.py +0 -0
  58. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/io/checkpoint.py +0 -0
  59. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/io/serialization.py +0 -0
  60. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/operators/README.md +0 -0
  61. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/operators/__init__.py +0 -0
  62. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/operators/crossover.py +0 -0
  63. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/operators/evonet_structural_mutation.py +0 -0
  64. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/operators/heli.py +0 -0
  65. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/operators/mutation.py +0 -0
  66. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/operators/replacement.py +0 -0
  67. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/operators/reproduction.py +0 -0
  68. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/operators/selection.py +0 -0
  69. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/operators/strategy.py +0 -0
  70. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/registry/__init__.py +0 -0
  71. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/registry/replacement_registry.py +0 -0
  72. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/registry/selection_registry.py +0 -0
  73. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/registry/strategy_registry.py +0 -0
  74. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/representation/__init__.py +0 -0
  75. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/representation/_apply_config_mapping.py +0 -0
  76. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/representation/base.py +0 -0
  77. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/representation/composite.py +0 -0
  78. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/representation/dummy.py +0 -0
  79. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/representation/evo_params.py +0 -0
  80. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/representation/netvector.py +0 -0
  81. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/representation/vector.py +0 -0
  82. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/README.md +0 -0
  83. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/__init__.py +0 -0
  84. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/benchmarks.py +0 -0
  85. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/config_loader.py +0 -0
  86. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/fitness.py +0 -0
  87. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/heli_experiment_logger.py +0 -0
  88. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/heli_utils.py +0 -0
  89. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/history_logger.py +0 -0
  90. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/lineage_logger.py +0 -0
  91. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/loss_functions.py +0 -0
  92. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/parallel.py +0 -0
  93. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/plotting.py +0 -0
  94. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/random.py +0 -0
  95. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib/utils/registry.py +0 -0
  96. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib.egg-info/SOURCES.txt +0 -0
  97. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib.egg-info/dependency_links.txt +0 -0
  98. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib.egg-info/requires.txt +0 -0
  99. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/evolib.egg-info/top_level.txt +0 -0
  100. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/01_basic_usage/01_getting_started.py +0 -0
  101. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/01_basic_usage/02_mutation.py +0 -0
  102. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/01_basic_usage/03_population_mutation.py +0 -0
  103. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/01_basic_usage/04_fitness.py +0 -0
  104. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/02_strategies/01_step_by_step_evolution.py +0 -0
  105. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/02_strategies/02_mu_lambda_step.py +0 -0
  106. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/02_strategies/03_mu_lambda.py +0 -0
  107. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/02_strategies/04_flexible.py +0 -0
  108. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/03_comparisons/01_history.py +0 -0
  109. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/03_comparisons/02_plotting.py +0 -0
  110. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/03_comparisons/03_compare_runs.py +0 -0
  111. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/03_comparisons/04_exponential_decay_vs_static.py +0 -0
  112. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/03_comparisons/05_adaptive_global_vs_static.py +0 -0
  113. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/03_comparisons/06_adaptive_individual_vs_static.py +0 -0
  114. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/03_comparisons/07_selection_comparison.py +0 -0
  115. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/03_comparisons/08_selection_pressure.py +0 -0
  116. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/03_comparisons/09_selection_vs_mutation_pressure.py +0 -0
  117. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/03_comparisons/10_selection_stochastic_vs_deterministic.py +0 -0
  118. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/03_comparisons/11_crossover_comparison.py +0 -0
  119. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/04_function_approximation/01_polynomial_sine.py +0 -0
  120. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/04_function_approximation/02_sine_point_approximation.py +0 -0
  121. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/04_function_approximation/03_approximation_with_noise.py +0 -0
  122. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/05_advanced_topics/01_fitness_landscape_exploration.py +0 -0
  123. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/05_advanced_topics/02_rosenbrock_surface_path.py +0 -0
  124. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/05_advanced_topics/03_vector_control.py +0 -0
  125. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/05_advanced_topics/04_vector_control_with_obstacles.py +0 -0
  126. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/05_advanced_topics/05_piecewise_linear_xsys.py +0 -0
  127. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/05_advanced_topics/06_evolving_mutation_strength_as_a_module.py +0 -0
  128. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/06_netvector/01_netvector_sine_approximation.py +0 -0
  129. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/06_netvector/02_netvector_modulated_output.py +0 -0
  130. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/06_netvector/03_netvector_gain_and_bias.py +0 -0
  131. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/07_evonet/01_sine_approximation.py +0 -0
  132. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/07_evonet/02_sine_delay.py +0 -0
  133. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/07_evonet/03_delay_bitseq_echo.py +0 -0
  134. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/07_evonet/04_leaky_temporal_smoothing.py +0 -0
  135. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/07_evonet/05_image_approximation.py +0 -0
  136. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/07_evonet/06_structural_xor.py +0 -0
  137. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/07_evonet/07_recurrent_bit_prediction.py +0 -0
  138. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/07_evonet/08_recurrent_timeseries.py +0 -0
  139. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/07_evonet/09_recurrent_trading.py +0 -0
  140. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/08_gym/01_frozen_lake.py +0 -0
  141. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/08_gym/02_cliff_walking.py +0 -0
  142. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/08_gym/03_cartpole.py +0 -0
  143. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/08_gym/04_lunar_lander.py +0 -0
  144. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/08_gym/05_bipedal_walker.py +0 -0
  145. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/09_meta_learning/01_lamarck_linear_mapping.py +0 -0
  146. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/examples/09_meta_learning/02_meta_mapping_baldwin.py +0 -0
  147. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/setup.cfg +0 -0
  148. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/tests/test_benchmarks.py +0 -0
  149. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/tests/test_config_loader.py +0 -0
  150. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/tests/test_elitism_preserves_best_fitness.py +0 -0
  151. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/tests/test_evonet_deepcopy.py +0 -0
  152. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/tests/test_evonet_vector_io.py +0 -0
  153. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/tests/test_initializer_net.py +0 -0
  154. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/tests/test_mutation.py +0 -0
  155. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/tests/test_population.py +0 -0
  156. {evolib-0.2.0b4.dev6 → evolib-0.2.0b4.dev7}/tests/test_selection.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evolib
3
- Version: 0.2.0b4.dev6
3
+ Version: 0.2.0b4.dev7
4
4
  Summary: A modular framework for evolutionary strategies and neuroevolution.
5
5
  Author-email: EvoLib <evolib@dismail.de>
6
6
  License: MIT License
@@ -31,25 +31,112 @@ from evolib.config.base_component_config import (
31
31
  StructuralMutationConfig,
32
32
  )
33
33
 
34
+ Bounds = Tuple[float, float]
35
+
34
36
 
35
37
  class WeightsConfig(BaseModel):
36
- """Configuration for connection weight initialization and bounds."""
38
+ # None means: no parameter-level initialization requested (preset may initialize).
39
+ initializer: Optional[str] = None # normal | uniform | zero | None
40
+ std: Optional[float] = None
41
+ bounds: Bounds = (-1.0, 1.0) # mutation/search bounds
42
+ init_bounds: Optional[Bounds] = None # init-time clipping bounds
37
43
 
38
- initializer: Literal["normal", "uniform", "zero"] = "normal"
39
- bounds: tuple[float, float] = Field(default=(-1.0, 1.0))
40
- std: Optional[float] = (
41
- None # required if initializer == "normal" (optional for now)
42
- )
44
+ @model_validator(mode="after")
45
+ def _validate(self) -> "WeightsConfig":
46
+ # Validate bounds
47
+ lo, hi = self.bounds
48
+ if lo >= hi:
49
+ raise ValueError("weights.bounds must satisfy lower < upper")
50
+
51
+ if self.init_bounds is not None:
52
+ ilo, ihi = self.init_bounds
53
+ if ilo >= ihi:
54
+ raise ValueError("weights.init_bounds must satisfy lower < upper")
55
+ if not (lo <= ilo and ihi <= hi):
56
+ raise ValueError("weights.init_bounds must lie within weights.bounds")
57
+
58
+ # Validate initializer-specific fields
59
+ if self.initializer is None:
60
+ # Preset-based initialization
61
+ if self.std is not None:
62
+ raise ValueError(
63
+ "weights.std is not allowed when " "weights.initializer is not set"
64
+ )
65
+ return self
66
+
67
+ if self.initializer == "normal":
68
+ if self.std is None or self.std <= 0:
69
+ raise ValueError(
70
+ "weights.std must be set and > 0 for initializer=normal"
71
+ )
72
+
73
+ elif self.initializer in ("uniform", "zero"):
74
+ if self.std is not None:
75
+ raise ValueError("weights.std is only allowed for initializer=normal")
76
+
77
+ else:
78
+ raise ValueError(f"Unknown weights initializer: {self.initializer}")
79
+
80
+ return self
43
81
 
44
82
 
45
83
  class BiasConfig(BaseModel):
46
- """Configuration for Neuron-Bias nitialization and bounds."""
84
+ # None means: no parameter-level initialization requested (preset may initialize).
85
+ initializer: Optional[str] = None # fixed | normal | uniform | zero | None
86
+ std: Optional[float] = None
87
+ value: Optional[float] = None
88
+ bounds: Bounds = (-0.5, 0.5) # mutation/search bounds
89
+ init_bounds: Optional[Bounds] = None # init-time clipping bounds (optional)
47
90
 
48
- initializer: Literal["fixed", "normal", "uniform", "zero"] = "normal"
49
- bounds: tuple[float, float] = Field(default=(-1.0, 1.0))
50
- std: Optional[float] = (
51
- None # required if initializer == "normal" (optional for now)
52
- )
91
+ @model_validator(mode="after")
92
+ def _validate(self) -> "BiasConfig":
93
+ # Validate bounds
94
+ lo, hi = self.bounds
95
+ if lo >= hi:
96
+ raise ValueError("bias.bounds must satisfy lower < upper")
97
+
98
+ if self.init_bounds is not None:
99
+ ilo, ihi = self.init_bounds
100
+ if ilo >= ihi:
101
+ raise ValueError("bias.init_bounds must satisfy lower < upper")
102
+ if not (lo <= ilo and ihi <= hi):
103
+ raise ValueError("bias.init_bounds must lie within bias.bounds")
104
+
105
+ # Validate initializer-specific fields
106
+ if self.initializer is None:
107
+ # Preset-based initialization
108
+ if self.std is not None:
109
+ raise ValueError(
110
+ "bias.std is not allowed when bias.initializer is not set"
111
+ )
112
+ if self.value is not None:
113
+ raise ValueError(
114
+ "bias.value is not allowed when bias.initializer is not set"
115
+ )
116
+ return self
117
+
118
+ if self.initializer == "fixed":
119
+ if self.value is None:
120
+ raise ValueError("bias.value is required for initializer=fixed")
121
+ if self.std is not None:
122
+ raise ValueError("bias.std is not allowed for initializer=fixed")
123
+
124
+ elif self.initializer == "normal":
125
+ if self.std is None or self.std <= 0:
126
+ raise ValueError("bias.std must be set and > 0 for initializer=normal")
127
+ if self.value is not None:
128
+ raise ValueError("bias.value is only allowed for initializer=fixed")
129
+
130
+ elif self.initializer in ("uniform", "zero"):
131
+ if self.std is not None:
132
+ raise ValueError("bias.std is only allowed for initializer=normal")
133
+ if self.value is not None:
134
+ raise ValueError("bias.value is only allowed for initializer=fixed")
135
+
136
+ else:
137
+ raise ValueError(f"Unknown bias initializer: {self.initializer}")
138
+
139
+ return self
53
140
 
54
141
 
55
142
  class DelayConfig(BaseModel):
@@ -106,11 +193,12 @@ class EvoNetComponentConfig(BaseModel):
106
193
 
107
194
  weights:
108
195
  initializer: normal
196
+ std: 0.5
109
197
  bounds: [-1.0, 1.0]
110
198
 
111
199
  bias:
112
- initializer: uniform
113
- bounds: [-0.5, 0.5]
200
+ initializer: uniform
201
+ bounds: [-0.5, 0.5]
114
202
 
115
203
  mutation:
116
204
  strategy: constant
@@ -18,6 +18,74 @@ from evolib.interfaces.enum_helpers import resolve_recurrent_kinds
18
18
  from evolib.representation.evonet import EvoNet
19
19
 
20
20
 
21
+ def _clip(x: np.ndarray, bounds: tuple[float, float]) -> np.ndarray:
22
+ lo, hi = bounds
23
+ return np.clip(x, lo, hi)
24
+
25
+
26
+ def _apply_weights_init(para: EvoNet, cfg: EvoNetComponentConfig) -> None:
27
+ weights_cfg = cfg.weights
28
+ size = para.net.num_weights
29
+
30
+ if weights_cfg.initializer is None:
31
+ return
32
+
33
+ elif weights_cfg.initializer == "zero":
34
+ weights = np.zeros(size, dtype=float)
35
+
36
+ elif weights_cfg.initializer == "uniform":
37
+ # uniform uses init_bounds if present, otherwise bounds
38
+ lo, hi = weights_cfg.init_bounds or weights_cfg.bounds
39
+ weights = np.random.uniform(lo, hi, size=size)
40
+
41
+ elif weights_cfg.initializer == "normal":
42
+ assert weights_cfg.std is not None
43
+ weights = np.random.normal(loc=0.0, scale=weights_cfg.std, size=size)
44
+
45
+ # clip ONLY if init_bounds explicitly provided
46
+ if weights_cfg.init_bounds is not None:
47
+ lo, hi = weights_cfg.init_bounds
48
+ weights = np.clip(weights, lo, hi)
49
+
50
+ else:
51
+ raise ValueError(f"Unknown weights initializer: {weights_cfg.initializer}")
52
+
53
+ para.net.set_weights(weights)
54
+
55
+
56
+ def _apply_bias_init(para: EvoNet, cfg: EvoNetComponentConfig) -> None:
57
+ bias_cfg = cfg.bias
58
+ size = para.net.num_biases
59
+
60
+ if bias_cfg.initializer is None:
61
+ return
62
+
63
+ elif bias_cfg.initializer == "zero":
64
+ bias = np.zeros(size, dtype=float)
65
+
66
+ elif bias_cfg.initializer == "fixed":
67
+ assert bias_cfg.value is not None
68
+ bias = np.full(size, float(bias_cfg.value), dtype=float)
69
+
70
+ elif bias_cfg.initializer == "uniform":
71
+ lo, hi = bias_cfg.init_bounds or bias_cfg.bounds
72
+ bias = np.random.uniform(lo, hi, size=size)
73
+
74
+ elif bias_cfg.initializer == "normal":
75
+ assert bias_cfg.std is not None
76
+ bias = np.random.normal(loc=0.0, scale=bias_cfg.std, size=size)
77
+
78
+ # clip only if init_bounds explicitly provided
79
+ if bias_cfg.init_bounds is not None:
80
+ lo, hi = bias_cfg.init_bounds
81
+ bias = np.clip(bias, lo, hi)
82
+
83
+ else:
84
+ raise ValueError(f"Unknown bias initializer: {bias_cfg.initializer}")
85
+
86
+ para.net.set_biases(bias)
87
+
88
+
21
89
  def _apply_delay_init(para: EvoNet, cfg: EvoNetComponentConfig) -> None:
22
90
  """Initialize delay on recurrent connections only."""
23
91
 
@@ -26,19 +94,19 @@ def _apply_delay_init(para: EvoNet, cfg: EvoNetComponentConfig) -> None:
26
94
 
27
95
  delay_cfg: DelayConfig = cfg.delay
28
96
 
29
- for c in para.net.get_all_connections():
30
- if c.type is not ConnectionType.RECURRENT:
97
+ for connection in para.net.get_all_connections():
98
+ if connection.type is not ConnectionType.RECURRENT:
31
99
  continue
32
100
 
33
101
  if delay_cfg.initializer == "uniform" and delay_cfg.bounds is not None:
34
102
  assert delay_cfg.bounds is not None
35
103
  lo, hi = delay_cfg.bounds
36
- d = int(np.random.randint(lo, hi + 1))
104
+ delay = int(np.random.randint(lo, hi + 1))
37
105
  else:
38
106
  assert delay_cfg.value is not None
39
- d = int(delay_cfg.value)
107
+ delay = int(delay_cfg.value)
40
108
 
41
- c.set_delay(d)
109
+ connection.set_delay(delay)
42
110
 
43
111
 
44
112
  def _build_architecture(
@@ -121,80 +189,57 @@ def initializer_unconnected_evonet(config: FullConfig, module: str) -> EvoNet:
121
189
  para.apply_config(cfg)
122
190
 
123
191
  _build_architecture(para, cfg, connection_init="none")
124
-
125
- # Initialize biases
126
- para.net.set_biases(np.zeros(para.net.num_biases))
192
+ _apply_bias_init(para, cfg)
127
193
 
128
194
  return para
129
195
 
130
196
 
131
197
  def initializer_normal_evonet(config: FullConfig, module: str) -> EvoNet:
132
198
  """
133
- Initializes an EvoNet with normally distributed weights.
199
+ Build a standard EvoNet architecture and initialize parameters according to the
200
+ explicit configuration blocks.
134
201
 
135
- Args:
136
- config (FullConfig): Full experiment configuration
137
- module (str): Module name (e.g. "brain")
202
+ - Topology is created via `_build_architecture(...)`.
203
+ - Weights are initialized using `cfg.weights`.
204
+ - Biases are initialized using `cfg.bias`.
205
+ - Delay (if configured) is initialized using `cfg.delay`.
138
206
 
139
- Returns:
140
- EvoNet: Initialized EvoNet representation
207
+ No implicit parameter initialization is performed here.
208
+ All parameter distributions are controlled explicitly via the config.
141
209
  """
210
+
142
211
  para = EvoNet()
143
212
  cfg = config.modules[module].model_copy(deep=True)
144
213
  para.apply_config(cfg)
145
214
 
146
- _build_architecture(para, cfg)
215
+ _build_architecture(para, cfg, connection_init="zero")
147
216
  _apply_delay_init(para, cfg)
148
-
149
- # Initialize weights and biases with normal distribution
150
- weights = np.random.normal(loc=0.0, scale=0.5, size=para.net.num_weights)
151
- biases = np.random.normal(loc=0.0, scale=0.5, size=para.net.num_biases)
152
-
153
- para.net.set_weights(weights)
154
- para.net.set_biases(biases)
217
+ _apply_weights_init(para, cfg)
218
+ _apply_bias_init(para, cfg)
155
219
  return para
156
220
 
157
221
 
158
222
  def initializer_random_evonet(config: FullConfig, module: str) -> EvoNet:
159
223
  """
160
- Initializes an EvoNet with uniformly random weights and biases within init_bounds
161
- (fallback: weight_bounds, bias_bounds).
162
-
163
- Args:
164
- config (FullConfig): Full experiment configuration
165
- module (str): Module name
224
+ Backward-compatible alias for the standard EvoNet initializer. Will be removed.
166
225
 
167
- Returns:
168
- EvoNet: Initialized EvoNet representation
226
+ Parameter initialization is controlled by `cfg.weights`, `cfg.bias`,
227
+ and `cfg.delay`.
169
228
  """
170
- para = EvoNet()
171
- cfg = config.modules[module].model_copy(deep=True)
172
- para.apply_config(cfg)
173
-
174
- _build_architecture(para, cfg, connection_init="random")
175
- _apply_delay_init(para, cfg)
176
-
177
- bias_bounds = cfg.bias.bounds or (-0.5, 0.5)
178
- min_bias = bias_bounds[0]
179
- max_bias = bias_bounds[1]
180
-
181
- biases = np.random.uniform(min_bias, max_bias, size=para.net.num_biases)
182
-
183
- para.net.set_biases(biases)
184
- return para
229
+ return initializer_normal_evonet(config, module)
185
230
 
186
231
 
187
232
  def initializer_zero_evonet(config: FullConfig, module: str) -> EvoNet:
188
233
  """
189
- Initializes an EvoNet with all weights and biases set to zero.
234
+ Build a standard EvoNet architecture and initialize all parameters to zero.
190
235
 
191
- Args:
192
- config (FullConfig): Full experiment configuration
193
- module (str): Module name
236
+ - All connection weights are set to 0.
237
+ - All biases are set to 0.
238
+ - Delay initialization follows `cfg.delay` if applicable.
194
239
 
195
- Returns:
196
- EvoNet: Initialized EvoNet representation
240
+ This initializer ignores `cfg.weights` and `cfg.bias` distributions.
197
241
  """
242
+
198
243
  para = EvoNet()
199
244
  cfg = config.modules[module].model_copy(deep=True)
200
245
  para.apply_config(cfg)
@@ -202,27 +247,23 @@ def initializer_zero_evonet(config: FullConfig, module: str) -> EvoNet:
202
247
  _build_architecture(para, cfg, connection_init="zero")
203
248
  _apply_delay_init(para, cfg)
204
249
 
250
+ para.net.set_weights(np.zeros(para.net.num_weights))
205
251
  para.net.set_biases(np.zeros(para.net.num_biases))
252
+
206
253
  return para
207
254
 
208
255
 
209
256
  def initializer_identity_evonet(config: FullConfig, module: str) -> EvoNet:
210
257
  """
211
- Initialize EvoNet with damped self-recurrence and zeroed weights elsewhere.
212
-
213
- - All feedforward weights are near-zero
214
- - Self-recurrent connections get weight ~0.8 (memory)
215
- - Biases are randomized slightly to break symmetry
258
+ Build a feedforward EvoNet and initialize parameters with an identity-like
259
+ structure.
216
260
 
217
- This initializer encourages stable internal state retention from the start,
218
- making recurrent behavior immediately available to evolution.
261
+ - Feedforward connections are created normally.
262
+ - Self-recurrent connections are added explicitly.
263
+ - Weights and biases are set to fixed values
264
+ to approximate identity behavior.
219
265
 
220
- Args:
221
- config (FullConfig): Full experiment configuration
222
- module (str): Name of the EvoNet module in the config
223
-
224
- Returns:
225
- EvoNet: Initialized network with identity-style dynamics
266
+ This preset intentionally overrides standard parameter initialization.
226
267
  """
227
268
 
228
269
  SELF_LOOP_WEIGHT = 0.8
@@ -156,7 +156,11 @@ class EvoNet(ParaBase):
156
156
  raise ValueError("mutation_strength must be set.")
157
157
 
158
158
  mutation_strength = self.evo_params.mutation_strength
159
- mutation_probability = self.evo_params.mutation_probability or 1.0
159
+ mutation_probability = (
160
+ self.evo_params.mutation_probability
161
+ if self.evo_params.mutation_probability is not None
162
+ else 1.0
163
+ )
160
164
  low, high = self.weight_bounds or (-np.inf, np.inf)
161
165
 
162
166
  for connection in self.net.get_all_connections():
@@ -166,12 +170,18 @@ class EvoNet(ParaBase):
166
170
 
167
171
  # Biases (optional override)
168
172
  if self.bias_evo_params is not None:
169
- bias_strength = self.bias_evo_params.mutation_strength or mutation_strength
170
- bias_probability = (
171
- self.bias_evo_params.mutation_probability or mutation_probability
172
- )
173
+ if self.bias_evo_params.mutation_strength is not None:
174
+ bias_strength = self.bias_evo_params.mutation_strength
175
+ else:
176
+ bias_strength = mutation_strength
177
+
178
+ if self.bias_evo_params.mutation_probability is not None:
179
+ bias_probability = self.bias_evo_params.mutation_probability
180
+ else:
181
+ bias_probability = mutation_probability
173
182
  else:
174
- bias_strength, bias_probability = mutation_strength, mutation_probability
183
+ bias_strength = mutation_strength
184
+ bias_probability = mutation_probability
175
185
 
176
186
  low, high = self.bias_bounds or (-np.inf, np.inf)
177
187
  for neuron in self.net.get_all_neurons():
@@ -344,7 +354,11 @@ class EvoNet(ParaBase):
344
354
  # If Bias-Override exists
345
355
  if self.bias_evo_params is not None:
346
356
  bep = self.bias_evo_params
347
- if ep.mutation_strategy == MutationStrategy.EXPONENTIAL_DECAY:
357
+
358
+ # Use per-scope strategy if set; otherwise fall back to global.
359
+ bias_strategy = bep.mutation_strategy or ep.mutation_strategy
360
+
361
+ if bias_strategy == MutationStrategy.EXPONENTIAL_DECAY:
348
362
  bep.mutation_strength = exponential_mutation_strength(
349
363
  bep, generation, max_generations
350
364
  )
@@ -352,10 +366,10 @@ class EvoNet(ParaBase):
352
366
  bep, generation, max_generations
353
367
  )
354
368
 
355
- elif ep.mutation_strategy == MutationStrategy.ADAPTIVE_GLOBAL:
369
+ elif bias_strategy == MutationStrategy.ADAPTIVE_GLOBAL:
356
370
  if diversity_ema is None:
357
371
  raise ValueError(
358
- "diversity_ema must be provided for ADAPTIVE_GLOBAL (biases)"
372
+ "diversity_ema must be provided for " "ADAPTIVE_GLOBAL (biases)"
359
373
  )
360
374
  if bep.mutation_strength is None or bep.mutation_probability is None:
361
375
  raise ValueError(
@@ -369,8 +383,7 @@ class EvoNet(ParaBase):
369
383
  bep.mutation_strength, diversity_ema, bep
370
384
  )
371
385
 
372
- elif ep.mutation_strategy == MutationStrategy.ADAPTIVE_INDIVIDUAL:
373
- # Ensure tau is initialized
386
+ elif bias_strategy == MutationStrategy.ADAPTIVE_INDIVIDUAL:
374
387
  if bep.tau is None or bep.tau == 0.0:
375
388
  bep.tau = adapted_tau(len(self.get_vector()))
376
389
 
@@ -379,8 +392,8 @@ class EvoNet(ParaBase):
379
392
  or bep.max_mutation_strength is None
380
393
  ):
381
394
  raise ValueError(
382
- "biases override requires min/max mutation_strength for "
383
- "ADAPTIVE_INDIVIDUAL."
395
+ "biases override requires min/max mutation_strength "
396
+ "for ADAPTIVE_INDIVIDUAL."
384
397
  )
385
398
  if self.bias_bounds is None:
386
399
  raise ValueError("bias_bounds must be set for bias adaptation.")
@@ -389,7 +402,6 @@ class EvoNet(ParaBase):
389
402
  bep.min_mutation_strength, bep.max_mutation_strength
390
403
  )
391
404
 
392
- # Perform adaptive update
393
405
  bounds = (bep.min_mutation_strength, bep.max_mutation_strength)
394
406
  bep.mutation_strength = adapt_mutation_strength(bep, bounds)
395
407
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evolib
3
- Version: 0.2.0b4.dev6
3
+ Version: 0.2.0b4.dev7
4
4
  Summary: A modular framework for evolutionary strategies and neuroevolution.
5
5
  Author-email: EvoLib <evolib@dismail.de>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "evolib"
7
- version = "0.2.0b4.dev6"
7
+ version = "0.2.0b4.dev7"
8
8
  description = "A modular framework for evolutionary strategies and neuroevolution."
9
9
  authors = [
10
10
  { name = "EvoLib", email = "evolib@dismail.de" }
@@ -17,6 +17,16 @@ def test_neuron_dynamics_config_length_matches_dim() -> None:
17
17
  dim=[1, 2, 1],
18
18
  activation=["linear", "tanh", "tanh"],
19
19
  initializer="zero_evonet",
20
+ weights={
21
+ "initializer": "normal",
22
+ "std": 0.5,
23
+ "bounds": [-1.0, 1.0],
24
+ },
25
+ bias={
26
+ "initializer": "normal",
27
+ "std": 0.1,
28
+ "bounds": [-0.5, 0.5],
29
+ },
20
30
  neuron_dynamics=[
21
31
  {"name": "standard", "params": {}},
22
32
  {"name": "standard", "params": {}},
@@ -44,9 +54,12 @@ def test_neuron_dynamics_applied_to_neurons() -> None:
44
54
  "connection_density": 1.0,
45
55
  "weights": {
46
56
  "initializer": "normal",
57
+ "std": 0.5,
47
58
  "bounds": [-1.0, 1.0],
48
59
  },
49
60
  "bias": {
61
+ "initializer": "normal",
62
+ "std": 0.1,
50
63
  "bounds": [-0.5, 0.5],
51
64
  },
52
65
  "neuron_dynamics": [
@@ -16,6 +16,16 @@ def test_normal_initializer_evonet_builds_expected_structure() -> None:
16
16
  "dim": [2, 3, 1],
17
17
  "activation": "linear",
18
18
  "initializer": "normal_evonet",
19
+ "weights": {
20
+ "initializer": "normal",
21
+ "std": 0.5,
22
+ "bounds": [-1.0, 1.0],
23
+ },
24
+ "bias": {
25
+ "initializer": "normal",
26
+ "std": 0.1,
27
+ "bounds": [-0.5, 0.5],
28
+ },
19
29
  "mutation": {
20
30
  "strategy": "constant",
21
31
  "strength": 0.1,
File without changes
File without changes
File without changes
File without changes