Genex v0.1.2 Genex behaviour View Source

Genetic Algorithms in Elixir!

Genex is a simple library for creating Genetic Algorithms in Elixir. A Genetic Algorithm is a search-based optimization technique based on the principles of Genetics and Natural Selection.

The basic life-cycle of a Genetic Algorithm is as follows:

1) Initialize the Population
2) Loop until goal is reached
  a) Select Parents
  b) Perform Crossover
  c) Mutate some of population
  d) Select Survivors

Genex follows a structure similar to the one above and offers callbacks corresponding to each stage in the genetic algorithm to allow for full customization.

Implementation

Genex requires an implementation module:

defmodule OneMax do
  use Genex

  def encoding do
    for _ <- 1..15, do: Enum.random(0..1)
  end

  def fitness_function(chromosome), do: Enum.sum(chromosome.genes)

  def terminate?(population), do: population.max_fitness == 15
end

Genex requires 3 function definitions: encoding/0, fitness_function/1, and terminate?/1. Let's take a closer look at each of these:

Encoding

def encoding do
  for _ <- 1..15, do: Enum.random(0..1)
end

encoding/0 defines your encoding of the chromosome's genes for your use-case. In the example above, we define a Binary Gene Set of length 15. Genex uses this function to generate an initial population of Chromosomes matching your encoding.

Fitness Function

def fitness_function(chromosome) do
  Enum.sum(chromosome.genes)
end

fitness_function/1 defines how the algorithm evaluates the fitness of a chromosome. It takes in a chromosome struct and returns a number. Fitness is how your algorithm determines which chromosomes should be persisted to the next generation as well as which chromosomes should be selected to crossover. In this case, we want to maximize 1's in our set of genes, so we define fitness as the sum of genes.

Termination Criteria

def terminate?(population) do
  population.max_fitness == 15
end

terminate?/1 defines the termination criteria for your algorithm. This tells Genex when your algorithm should stop running. In this case we use a Max Fitness; however, you can also tell the algorithm to stop after a certain number of generations.

Running

Once you have defined an implementation module. Utilize the run/0 function to run the algorithm. The function will return the solution population for analysis. You can display a summary of the solution with the: Genex.Visualizers.Text.display_summary/1 function.

soln = OneMax.run()
Genex.Visualizers.Text.display_summary(soln)

Configuration

Genex offers a number of settings to adjust the algorithm to your liking. You can adjust: strategies, rates, and more. Below is a comprehensive list of settings and options.

Strategies

  • :crossover_type- :single_point, :two_point, :uniform, :blend
  • :mutation_type- :scramble, :invert, :bit_flip
  • :parent_selection- :natural, :random, :worst
  • :survivor_selection- :natural, :random, :worst

Rates

  • :crossover_rate- between 0 and 1
  • :mutation_rate- between 0 and 1

Population

  • :population_size- integer greater than 0

Unique to some Strategies

  • :uniform_crossover_rate- between 0 and 1 (Uniform Crossover)
  • :alpha- between 0 and 1 (Blend Crossover)

Customization

You can customize every step of your genetic algorithm utilizing some of the many callbacks Genex provides. A list of callbacks is provided below.

  • seed/0 - Seed the Population.
  • evaluate/1 - Evaluate the entire Population.
  • cycle/1 - The Genetic Algorithm Cycle.
  • select_parents/1 - Select Parents for Crossover.
  • crossover/1 - Perform Crossover.
  • mutate/1 - Perform Mutation.
  • select_survivors/1 - Select a number of chromosomes to survive.
  • advance/1 - Advance to the next generation.

Link to this section Summary

Callbacks

Crossover a number of individuals to create a new population. The number of individuals depends on the crossover rate. This phase populates the children field of the populaton struct with a List of Chromosomes.

Crossover rate as a function of the population.

Generates a random gene set.

Evaluates a population's fitness.

Calculates a Chromosome's fitness.

Mutate a number of individuals to add novelty to the population. The number of individuals depends on the mutation rate. This phase populates the mutant field of the population struct with a List of Chromosomes.

Mutation rate as a function of the population.

Radiation level is affects the "aggressiveness" of mutations.

Seeds a population.

Selects a number of individuals for crossover. The number of individuals selected depends on the crossover rate. This phase populates the parent field of the population struct with a List of tuples. Each tuple is a pair of parents to crossover.

Select a number of individuals to survive to the next generation. The number of individuals depends on the survival rate. This phase populates the survivors field of the population struct with a List of Chromosomes.

Specifies the statistics to collect on the population.

Tests the population for some termination criteria.

Link to this section Functions

Link to this macro

valid_rate?(rate)

View Source (macro)

Link to this section Callbacks

Link to this callback

crossover(population)

View Source
crossover(population :: Genex.Population.t()) ::
  {:ok, Genex.Population.t()} | {:error, any()}

Crossover a number of individuals to create a new population. The number of individuals depends on the crossover rate. This phase populates the children field of the populaton struct with a List of Chromosomes.

Link to this callback

crossover_rate(arg1)

View Source
crossover_rate(Genex.Population.t()) :: number()

Crossover rate as a function of the population.

Generates a random gene set.

Link to this callback

evaluate(population)

View Source
evaluate(population :: Genex.Population.t()) :: number()

Evaluates a population's fitness.

Link to this callback

fitness_function(chromosome)

View Source
fitness_function(chromosome :: Genex.Chromosome.t()) :: number()

Calculates a Chromosome's fitness.

Link to this callback

mutate(population)

View Source
mutate(population :: Genex.Population.t()) ::
  {:ok, Genex.Population.t()} | {:error, any()}

Mutate a number of individuals to add novelty to the population. The number of individuals depends on the mutation rate. This phase populates the mutant field of the population struct with a List of Chromosomes.

Link to this callback

mutation_rate(arg1)

View Source
mutation_rate(Genex.Population.t()) :: number()

Mutation rate as a function of the population.

Radiation level is affects the "aggressiveness" of mutations.

Seeds a population.

Link to this callback

select_parents(population)

View Source
select_parents(population :: Genex.Population.t()) ::
  {:ok, Genex.Population.t()} | {:error, any()}

Selects a number of individuals for crossover. The number of individuals selected depends on the crossover rate. This phase populates the parent field of the population struct with a List of tuples. Each tuple is a pair of parents to crossover.

Link to this callback

select_survivors(population)

View Source
select_survivors(population :: Genex.Population.t()) ::
  {:ok, Genex.Population.t()} | {:error, any()}

Select a number of individuals to survive to the next generation. The number of individuals depends on the survival rate. This phase populates the survivors field of the population struct with a List of Chromosomes.

Link to this callback

statistics()

View Source
statistics() :: Keyword.t()

Specifies the statistics to collect on the population.

Link to this callback

terminate?(population)

View Source
terminate?(population :: Genex.Population.t()) :: boolean()

Tests the population for some termination criteria.