Configuration Guide

EvoLib experiments are defined via YAML configuration files. This makes setups explicit, reproducible, and easy to adapt.

Below you find three representative configurations:

  • A minimal example – the smallest viable run.

  • A full vector-based setup – showing multiple modules, selection, and replacement.

  • A full EvoNet setup – demonstrating weight, delay, and structural mutation.


A) Minimal configuration

This is the smallest possible (μ + λ) run. It demonstrates the core building blocks: pools, a single vector module, and constant mutation. A fitness function (e.g. sphere) must still be provided in practice.

# Minimum configuration — smallest viable building block for a (μ + λ) run.
parent_pool_size: 2         # μ: number of parents kept
offspring_pool_size: 4      # λ: number of offspring produced
max_generations: 10         # hard stop
num_elites: 0               # no elitism

evolution:
  strategy: mu_plus_lambda  # classic (μ + λ) evolution strategy

modules:
  test-vector:              # logical module name
    type: vector
    initializer: uniform
    dim: 2
    bounds: [-1.0, 1.0]

    mutation:
      strategy: constant    # fixed-strength perturbation
      strength: 0.01
      probability: 1.0

Minimal Python usage:

from evolib import Pop
import numpy as np

def sphere(indiv) -> None:
    # Example: sum of squares on a 2D vector module named "test-vector"
    x = np.asarray(indiv.para["test-vector"].vector, dtype=float)
    indiv.fitness = float(np.sum(x**2))

pop = Pop(config_path="population.yaml", initialize=True)
pop.set_fitness_function(sphere)
pop.run(verbosity=1)

B) Maximum Vector configuration

This example shows a more complete setup: tournament selection, steady-state replacement, stopping criteria, and two vector modules with different operator settings.

random_seed: 42             # reproducibility

parent_pool_size: 40
offspring_pool_size: 80
max_generations: 120
max_indiv_age: 2
num_elites: 4

stopping:
  target_fitness: 0.001

evolution:
  strategy: flexible

selection:
  strategy: tournament
  tournament_size: 3

replacement:
  strategy: steady_state
  num_replace: 5

modules:
  xs:
    type: vector
    dim: 6
    initializer: uniform
    bounds: [0.0, 6.283185307]   # [0, 2π]
    mutation:
      strategy: adaptive_individual
      probability: 0.8
      min_strength: 0.01
      max_strength: 0.05

  ys:
    type: vector
    dim: 6
    initializer: zero_vector
    bounds: [-1.5, 1.5]
    mutation:
      strategy: constant
      probability: 0.8
      strength: 0.06
    crossover:
      strategy: constant
      probability: 0.3
      operator: blx

C) Maximum EvoNet configuration

This configuration demonstrates EvoNet evolution: weight mutation, bias-specific overrides, activation mutation, delay mutation, and structural mutation.

dim: [2, 0, 0, 1] starts with empty hidden layers, letting structural mutation grow nodes and edges.

Connectivity:

  • scope controls which feedforward edges are allowed at initialization.

  • density controls how many of those allowed edges are actually created at init.

  • recurrent enables recurrent edge kinds (empty list means none).

Topology constraints:

  • max_neurons and max_connections keep growth bounded (these are the current names; avoid older max_nodes/max_edges).

Delay:

  • delay: initializes delays of recurrent connections at build time.

  • mutation.delay: mutates delays during evolution (recurrent connections only).

parent_pool_size: 20
offspring_pool_size: 40
max_generations: 200
max_indiv_age: 0
num_elites: 0

stopping:
  target_fitness: 0.001

evolution:
  strategy: mu_plus_lambda

modules:
  brain:
    type: evonet
    dim: [2, 0, 0, 1]       # hidden layers start empty
    activation: [linear, tanh, tanh, sigmoid]

    connectivity:
      scope: crosslayer          # adjacent | crosslayer
      density: 1.0               # (0, 1]
      recurrent: [direct]        # [], [direct], [lateral], [indirect]
    
    weights:
      initializer: normal
      std: 0.5
      bounds: [-5.0, 5.0]
    
    bias:      
      initializer: normal
      std: 0.5
      bounds: [-1.0, 1.0]

    # NOTE: Delays only apply to recurrent connections.
    # If `recurrent` is not enabled, this block has no effect.
    delay:
      initializer: uniform   # uniform | fixed
      bounds: [1, 8]
      # value: 3            # only for fixed

    mutation:
      strategy: constant
      probability: 1.0
      strength: 0.1

      # Optional override for biases
      biases:
        strategy: constant
        probability: 0.8
        strength: 0.05

      # Optional activation mutation
      activations:
        probability: 0.01
        allowed: [tanh, relu, sigmoid]

      # Optional delay mutation (recurrent connections only)
      delay:
        probability: 0.05
        bounds: [1, 16]
        mode: delta_step     # delta_step | resample
        delta: 1

      # Structural mutation
      structural:

        add_neuron:
          probability: 0.015
          init_connection_ratio: 0.5
          activations_allowed: [tanh]
          init: random

        remove_neuron:
          probability: 0.015

        add_connection:
          probability: 0.05
          max: 3
          init: random

        remove_connection:
          probability: 0.05
          max: 3

        topology:
          recurrent: none
          connection_scope: crosslayer
          max_neurons: 25
          max_connections: 50

D) Parallel Evaluation (optional)

For expensive problems, EvoLib can evaluate individuals in parallel using Ray.

parallel:
  backend: ray         # backend: none | ray
  num_cpus: 2          # number of logical CPUs (only used in local mode)
  address: auto        # "auto" = local Ray; or "ray://host:10001" for remote

If omitted, EvoLib runs in single-threaded mode.


Further examples

For complete, runnable examples including fitness definitions and visualization, please refer to the GitHub repository:

👉 EvoLib Examples on GitHub

For a complete list of all available configuration fields, see the Configuration Parameters reference.