genetics

package
v0.0.0-...-e2110b8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 7, 2021 License: MIT Imports: 19 Imported by: 11

Documentation

Overview

Package genetics holds data holders and helper utilities used to implement genetic evolution algorithm

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrUnsupportedGenomeEncoding = errors.New("unsupported genome encoding")
)

Functions

This section is empty.

Types

type ByOrganismFitness

type ByOrganismFitness []*Species

This is used for list sorting of species by maximal fitness

func (ByOrganismFitness) Len

func (f ByOrganismFitness) Len() int

func (ByOrganismFitness) Less

func (f ByOrganismFitness) Less(i, j int) bool

func (ByOrganismFitness) Swap

func (f ByOrganismFitness) Swap(i, j int)

type EpochExecutorType

type EpochExecutorType int

The epoch executor type definition

const (
	// The sequential executor
	SequentialExecutorType EpochExecutorType = 0
	// The parallel executor to perform reproduction cycle in parallel threads
	ParallelExecutorType = 1
)

type Gene

type Gene struct {
	// The link between nodes
	Link *network.Link
	// The current innovation number for this gene
	InnovationNum int64
	// Used to see how much mutation has changed the link
	MutationNum float64
	// If true the gene is enabled
	IsEnabled bool
}

The Gene class in this system specifies a "Connection Gene." Nodes are represented using the NNode class, which serves as both a genotypic and phenotypic representation of nodes. Genetic Representation of connections uses this special class because it calls for special operations better served by a specific genetic representation. A Gene object in this system specifies a link between two nodes along with an "innovation number" which tells when in the history of a population the gene first arose. This allows the system to track innovations and use those to determine which organisms are compatible (i.e. in the same species). A mutation_num gives a rough sense of how much mutation the gene has experienced since it originally appeared (Since it was first innovated). In the current implementation the mutation number is the same as the weight.

func NewGene

func NewGene(weight float64, in_node, out_node *network.NNode, recurrent bool, inov_num int64, mut_num float64) *Gene

Creates new Gene

func NewGeneCopy

func NewGeneCopy(g *Gene, trait *neat.Trait, in_node, out_node *network.NNode) *Gene

Construct a gene off of another gene as a duplicate

func NewGeneWithTrait

func NewGeneWithTrait(trait *neat.Trait, weight float64, in_node, out_node *network.NNode,
	recurrent bool, inov_num int64, mut_num float64) *Gene

Creates new Gene with Trait

func (*Gene) String

func (g *Gene) String() string

type Genome

type Genome struct {
	// The genome ID
	Id int
	// The parameters conglomerations
	Traits []*neat.Trait
	// List of NNodes for the Network
	Nodes []*network.NNode
	// List of innovation-tracking genes
	Genes []*Gene
	// List of MIMO control genes
	ControlGenes []*MIMOControlGene

	// Allows Genome to be matched with its Network
	Phenotype *network.Network
}

A Genome is the primary source of genotype information used to create a phenotype. It contains 3 major constituents:

  1. A Vector of Traits
  2. A List of NNodes pointing to a Trait from (1)
  3. A List of Genes with Links that point to Traits from (1)
  4. A List of MIMO Control Genes with Links to different genome modules

(1) Reserved parameter space for future use. (2) NNode specifications. (3) Is the primary source of innovation in the evolutionary Genome. (4) Control genes allows to receive inputs from multiple independent genome modules and output processed signal to the

multitude of output locations

Each Gene in (3) has a marker telling when it arose historically. Thus, these Genes can be used to speciate the population, and the list of Genes provide an evolutionary history of innovation and link-building.

func NewGenome

func NewGenome(id int, t []*neat.Trait, n []*network.NNode, g []*Gene) *Genome

Constructor which takes full genome specs and puts them into the new one

func NewModularGenome

func NewModularGenome(id int, t []*neat.Trait, n []*network.NNode, g []*Gene, mimoG []*MIMOControlGene) *Genome

Constructs new modular genome

func ReadGenome

func ReadGenome(ir io.Reader, id int) (*Genome, error)

Reads Genome from reader

func (*Genome) Extrons

func (g *Genome) Extrons() int

Return # of non-disabled genes

func (*Genome) Genesis

func (g *Genome) Genesis(net_id int) (*network.Network, error)

Generate a Network phenotype from this Genome with specified id

func (*Genome) IsEqual

func (g *Genome) IsEqual(og *Genome) (bool, error)

Tests if given genome is equal to this one genetically and phenotypically. This method will check that both genomes has the same traits, nodes and genes. If mismatch detected the error will be returned with mismatch details.

func (*Genome) String

func (g *Genome) String() string

Stringer

func (*Genome) Write

func (g *Genome) Write(w io.Writer) error

Writes this genome into provided writer

type GenomeEncoding

type GenomeEncoding byte

Defines format of Genome data encoding

const (
	// The plain text
	PlainGenomeEncoding GenomeEncoding = iota + 1
	// The rich text in YAML
	YAMLGenomeEncoding
)

type GenomeReader

type GenomeReader interface {
	// Reads one Genome record
	Read() (*Genome, error)
}

The interface to define genome reader

func NewGenomeReader

func NewGenomeReader(r io.Reader, encoding GenomeEncoding) (GenomeReader, error)

Creates reader for Genome data with specified encoding format.

type GenomeWriter

type GenomeWriter interface {
	// Writes Genome record
	WriteGenome(genome *Genome) error
}

The interface to define genome writer

func NewGenomeWriter

func NewGenomeWriter(w io.Writer, encoding GenomeEncoding) (GenomeWriter, error)

Creates genome writer with specified data encoding format

type Innovation

type Innovation struct {

	// Two nodes specify where the innovation took place
	InNodeId  int
	OutNodeId int
	// The number assigned to the innovation
	InnovationNum int64
	// If this is a new node innovation, then there are 2 innovations (links) added for the new node
	InnovationNum2 int64

	// If a link is added, this is its weight
	NewWeight float64
	// If a link is added, this is its connected trait index
	NewTraitNum int
	// If a new node was created, this is its node_id
	NewNodeId int

	// If a new node was created, this is the innovation number of the gene's link it is being stuck inside
	OldInnovNum int64

	// Flag to indicate whether its innovation for recurrent link
	IsRecurrent bool
	// contains filtered or unexported fields
}

This Innovation class serves as a way to record innovations specifically, so that an innovation in one genome can be compared with other innovations in the same epoch, and if they are the same innovation, they can both be assigned the same innovation number.

This class can encode innovations that represent a new link forming, or a new node being added. In each case, two nodes fully specify the innovation and where it must have occurred (between them).

func NewInnovationForLink(node_in_id, node_out_id int, innovation_num int64, weight float64, trait_id int) *Innovation

Constructor for new link case

func NewInnovationForNode

func NewInnovationForNode(node_in_id, node_out_id int, innovation_num1, innovation_num2 int64,
	newnode_id int, old_innov_num int64) *Innovation

Constructor for the new node case

func NewInnovationForRecurrentLink(node_in_id, node_out_id int, innovation_num int64, weight float64,
	trait_id int, recur bool) *Innovation

Constructor for a recur link

type MIMOControlGene

type MIMOControlGene struct {
	// The current innovation number for this gene
	InnovationNum int64
	// Used to see how much mutation has changed the link
	MutationNum float64
	// If true the gene is enabled
	IsEnabled bool

	// The control node with control/activation function
	ControlNode *network.NNode
	// contains filtered or unexported fields
}

The Multiple-Input Multiple-Output (MIMO) control Gene allows to create modular genomes, in which several groups of genes connected through single MIMO Gene and corresponding control function is applied to all inputs in order to produce outputs. This allows to build modular hierarchical genomes which can be considered as sum of constituent components and evolved as a whole and as a concrete parts simultaneously.

func NewMIMOGene

func NewMIMOGene(control_node *network.NNode, innov_num int64, mut_num float64, enabled bool) *MIMOControlGene

Creates new MIMO gene

func NewMIMOGeneCopy

func NewMIMOGeneCopy(g *MIMOControlGene, control_node *network.NNode) *MIMOControlGene

The copy constructor taking parameters from provided control gene for given control node

func (*MIMOControlGene) String

func (g *MIMOControlGene) String() string

The stringer

type Organism

type Organism struct {
	// A measure of fitness for the Organism
	Fitness float64
	// The error value indicating how far organism's performance is from ideal task goal, e.g. MSE
	Error float64
	// Win marker (if needed for a particular task)
	IsWinner bool

	// The Organism's phenotype
	Phenotype *network.Network
	// The Organism's genotype
	Genotype *Genome
	// The Species of the Organism
	Species *Species

	// Number of children this Organism may have
	ExpectedOffspring float64
	// Tells which generation this Organism is from
	Generation int

	// The utility data transfer object to be used by different GA implementations to hold additional data.
	// Implemented as ANY to allow implementation specific objects.
	Data *OrganismData

	// The flag to be used as utility value
	Flag int
	// contains filtered or unexported fields
}

Organisms are Genotypes (Genomes) and Phenotypes (Networks) with fitness information, i.e. the genotype and phenotype together.

func NewOrganism

func NewOrganism(fit float64, g *Genome, generation int) (org *Organism, err error)

Creates new organism with specified genome, fitness and given generation number

func (*Organism) CheckChampionChildDamaged

func (o *Organism) CheckChampionChildDamaged() bool

Method to check if this algorithm is champion child and if so than if it's damaged

func (*Organism) Dump

func (o *Organism) Dump() string

Dumps all organism's fields into string

func (*Organism) MarshalBinary

func (o *Organism) MarshalBinary() ([]byte, error)

Encodes this organism for wired transmission during parallel reproduction cycle

func (*Organism) String

func (o *Organism) String() string

func (*Organism) UnmarshalBinary

func (o *Organism) UnmarshalBinary(data []byte) error

Decodes organism received over the wire during parallel reproduction cycle

func (*Organism) UpdatePhenotype

func (o *Organism) UpdatePhenotype() (err error)

Regenerate the network based on a change in the genotype

type OrganismData

type OrganismData struct {
	// The implementation specific data object to be associated with organism
	Value interface{}
}

The object to associate implementation specific data with particular organism for various algorithm implementations

type Organisms

type Organisms []*Organism

Organisms is sortable list of organisms by fitness

func (Organisms) Len

func (f Organisms) Len() int

func (Organisms) Less

func (f Organisms) Less(i, j int) bool

func (Organisms) Swap

func (f Organisms) Swap(i, j int)

type ParallelPopulationEpochExecutor

type ParallelPopulationEpochExecutor struct {
	// contains filtered or unexported fields
}

The population epoch executor with parallel reproduction cycle

func (*ParallelPopulationEpochExecutor) NextEpoch

func (ex *ParallelPopulationEpochExecutor) NextEpoch(generation int, population *Population, context *neat.NeatContext) error

type Population

type Population struct {
	// Species in the Population. Note that the species should comprise all the genomes
	Species []*Species
	// The organisms in the Population
	Organisms []*Organism
	// The highest species number
	LastSpecies int
	// For holding the genetic innovations of the newest generation
	Innovations []*Innovation
	// An integer that when above zero tells when the first winner appeared
	WinnerGen int
	// The last generation played
	FinalGen int

	// Stagnation detector
	HighestFitness float64
	// The number of epochs when highest fitness was recorded for this population. If it was too long before
	// than delta coding will be applied to avoid population's fitness stagnation
	EpochsHighestLastChanged int

	/* Fitness Statistics */
	MeanFitness float64
	Variance    float64
	StandardDev float64
	// contains filtered or unexported fields
}

A Population is a group of Organisms including their species

func NewPopulation

func NewPopulation(g *Genome, context *neat.NeatContext) (*Population, error)

Construct off of a single spawning Genome

func NewPopulationRandom

func NewPopulationRandom(in, out, nmax int, recurrent bool, link_prob float64, context *neat.NeatContext) (*Population, error)

Special constructor to create a population of random topologies uses NewGenomeRand(new_id, in, out, n, nmax int, recurrent bool, link_prob float64) See the Genome constructor above for the argument specifications

func ReadPopulation

func ReadPopulation(ir io.Reader, context *neat.NeatContext) (pop *Population, err error)

Reads population from provided reader

func (*Population) Verify

func (p *Population) Verify() (bool, error)

Run verify on all Genomes in this Population (Debugging)

func (*Population) Write

func (p *Population) Write(w io.Writer)

Writes given population to a writer

func (*Population) WriteBySpecies

func (p *Population) WriteBySpecies(w io.Writer)

Writes given population by species

type PopulationEpochExecutor

type PopulationEpochExecutor interface {
	// Turnover the population to a new generation
	NextEpoch(generation int, population *Population, context *neat.NeatContext) error
}

Executes epoch's turnover for population of organisms

type SequentialPopulationEpochExecutor

type SequentialPopulationEpochExecutor struct {
	// contains filtered or unexported fields
}

The epoch executor which will run execution sequentially in single thread for all species and organisms

func (*SequentialPopulationEpochExecutor) NextEpoch

func (ex *SequentialPopulationEpochExecutor) NextEpoch(generation int, population *Population, context *neat.NeatContext) error

type Species

type Species struct {
	// The ID
	Id int
	// The age of the Species
	Age int
	// The maximal fitness it ever had
	MaxFitnessEver float64
	// How many child expected
	ExpectedOffspring int

	// Is it novel
	IsNovel bool

	// The organisms in the Species
	Organisms Organisms
	// If this is too long ago, the Species will goes extinct
	AgeOfLastImprovement int

	// Flag used for search optimization
	IsChecked bool
}

A Species is a group of similar Organisms. Reproduction takes place mostly within a single species, so that compatible organisms can mate.

func NewSpecies

func NewSpecies(id int) *Species

Construct new species with specified ID

func NewSpeciesNovel

func NewSpeciesNovel(id int, novel bool) *Species

Allows the creation of a Species that won't age (a novel one). This protects new Species from aging inside their first generation

func (Species) ComputeMaxAndAvgFitness

func (s Species) ComputeMaxAndAvgFitness() (max, avg float64)

Computes maximal and average fitness of species

func (Species) FindChampion

func (s Species) FindChampion() *Organism

Returns most fit organism for this species

func (Species) String

func (s Species) String() string

func (Species) Write

func (s Species) Write(w io.Writer)

Writes species to the specified writer

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL