Bardo

Status

This is in beta... any feedback or contributions are welcome!

I still don't fully understand substrate encoding so I would appreciate a technical review of this code.

About

Bardo is a focused neuroevolution library for Elixir that evolves neural networks through evolutionary algorithms. Built on the Erlang VM, it leverages concurrent processes for efficient neural network simulation and evolution.

Features

Installation

Add bardo to your list of dependencies in mix.exs:

def deps do
  [
    {:bardo, "~> 0.1.0"}
  ]
end

Then run:

mix deps.get

Start the Bardo processes in your application's supervision tree or startup code:

# In your application.ex
def start(_type, _args) do
  children = [
    # ...your other children
    {Bardo, []}
  ]

  Supervisor.start_link(children, strategy: :one_for_one)
end

Or start it manually in your code:

Bardo.start()

Documentation

Comprehensive documentation is available:

Quick Start

XOR Example

The simplest way to get started is to run the XOR example:

# Start IEx with Bardo
iex -S mix

# Run the XOR example
iex> Bardo.Examples.Simple.Xor.run()

Creating Your Own Experiment

To set up your own neuroevolution experiment:

# Create a new experiment
experiment = Bardo.ExperimentManager.new_experiment("my_experiment")

# Configure it
Bardo.ExperimentManager.configure(experiment, %{
  population_size: 100,
  max_generations: 200,
  mutation_rate: 0.3
})

# Define a fitness function
defmodule MyFitness do
  def evaluate(agent) do
    # Your fitness calculation here
    # Returns a numeric score
  end
end

# Start the experiment with your fitness function
Bardo.ExperimentManager.start(experiment, &MyFitness.evaluate/1)

# Check progress
Bardo.ExperimentManager.status(experiment)

# Get the best solution
best_agent = Bardo.ExperimentManager.get_best_solution(experiment)

Core Examples

Bardo includes several examples to demonstrate different aspects of neuroevolution:

1. XOR

A simple example that evolves a neural network to solve the XOR problem.

Bardo.Examples.Simple.Xor.run(population_size: 100, max_generations: 50)

2. Double Pole Balancing

A classic control problem where a neural network learns to balance two poles on a cart.

iex> Bardo.Examples.Benchmarks.Dpb.run_with_damping(:dpb_example, 50, 20, 10000)

3. Flatland

A predator-prey simulation in a 2D world where agents co-evolve.

iex> Bardo.Examples.Applications.Flatland.run(:flatland_example, 10, 10, 20, 500, 10)

4. Simple FX

A basic forex trading simulation to demonstrate time series prediction.

# Standard FX example
iex> Bardo.Examples.Applications.Fx.run(:fx_example, 50, 1000, 20)

Core Concepts

Genotypes

Genetic representations of neural networks:

# Create a new genotype
genotype = Bardo.PopulationManager.Genotype.new()

# Add neurons
genotype = Bardo.PopulationManager.Genotype.add_neuron(genotype, :hidden)

# Add connections between neurons
genotype = Bardo.PopulationManager.Genotype.add_connection(genotype, input_id, output_id, weight)

# Mutate the genotype
mutated_genotype = Bardo.PopulationManager.GenomeMutator.mutate(genotype)

Neural Networks

Working with the neural networks created from genotypes:

# Convert genotype to neural network
nn = Bardo.AgentManager.Cortex.from_genotype(genotype)

# Activate the network with inputs
outputs = Bardo.AgentManager.Cortex.activate(nn, [1.0, 0.0])

Sensors and Actuators

Interface between neural networks and their environment:

# Add a sensor to a neural network
nn = Bardo.AgentManager.Cortex.add_sensor(nn, MyApp.Sensors.Vision)

# Add an actuator to a neural network
nn = Bardo.AgentManager.Cortex.add_actuator(nn, MyApp.Actuators.Motor)

Architecture

Bardo is organized into several key modules:

Custom Environments

To create your own environment, you'll need to define custom sensors and actuators:

defmodule MyEnvironment.Sensor do
  @behaviour Bardo.AgentManager.Sensor

  # Implementation of the Sensor behaviour
  def sense(state) do
    # Convert environment state to neural network inputs
  end
end

defmodule MyEnvironment.Actuator do
  @behaviour Bardo.AgentManager.Actuator

  # Implementation of the Actuator behaviour
  def act(outputs, state) do
    # Convert neural network outputs to actions
    # Return updated state
  end
end

Then create a morphology that defines the neural network structure:

defmodule MyEnvironment.Morphology do
  @behaviour Bardo.Morphology

  # Implementation of the Morphology behaviour
  def sensor_spec do
    # Define sensor inputs
  end

  def actuator_spec do
    # Define actuator outputs
  end
end

Testing

To run the tests:

mix test

License

Distributed under the Apache License 2.0. See LICENSE for more information.

Acknowledgements

This is a vibe coded port of this project: github - Rober-t/apxr_run

Which was based on this code: Gene Sher - DXNN2

Based on concepts from this amazing book: Handbook of Neuroevolution Through Erlang by Gene Sher.

DISLAIMER

Please use at your own risk as this is experimental and awaiting contributions and code review.