naneat

package module
v0.0.0-...-116bf7b Latest Latest
Warning

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

Go to latest
Published: Feb 10, 2020 License: MIT Imports: 25 Imported by: 0

README

NaNEAT?

GoDoc Build Status

삿대질

NaNEAT is a NEAT library made from scratch that's mostly for my own use. It is multi-threaded, and designed that way to become one day to be extended to a horizontally scalable microservice.

NEAT

NEAT (Neuro-Evolution of Augmenting Topologies) is a genetic algorithm developed by Dr. Kenneth O. Stanley in 2002. Being based on the neuroevolution technique which evolves both topology and weights of an artificial neural network, NEAT starts out with a population of minimal structures and adds structure as necessary in order to minimize the number of parameters being searched. This allows the network topology to grow only as it benefits the solution, and through its learning process the structure of the neural network complexifies.

Installation

go get -v github.com/nanitefactory/naneat

Empirical Proofs

Learns to play Metal Slug 3

Metal Slug 3

Video: https://www.youtube.com/watch?v=rjrheRsWXR4

Solves XOR Problem

XOR-Test

Example

In order to conduct the XOR test implemented in this package, test run func naneat.TestMain(*testing.M).

go test -run TestMain

And the code below initiates a NEAT context that runs with 3 agents.

conf := naneat.NewConfigurationSimple(1, 2, 1)
experimenter := naneat.New(conf)

agent1, agent2, agent3 := naneat.NewAgent(), naneat.NewAgent(), naneat.NewAgent()
experimenter.RegisterMeasurer(agent1)
experimenter.RegisterMeasurer(agent2)
experimenter.RegisterMeasurer(agent3)

go experimenter.Run()

(Further detail of that sample is included in the standard test code in this package.)

Features

  • Cross-platform throughout desktop environments; Windows, Linux and macOS.
  • The library may not depend on a particular programming language to use.
  • Entire codebase is written in Go which makes it lightweight and easier to maintain.
  • The experiment process is fully visualizable with faiface/pixel.
  • Can save/load the state serialized in JSON.
  • Offers a plain easy interface designed to be multi-threaded and may be said, horizontally scalable.

Todo

  • Performance evaluations
  • More tests and benchmarks
  • Documentation

References

License

MIT

Documentation

Overview

Package naneat offers an extensive implementation of NEAT (Neuro-Evolution of Augmenting Topologies).

Godoc

Doc is under constructions...

Notes:

  • Currently most of struct members are public - fields are no reason exported - in this package. Use them at your own risk. (Though, we'd better to use methods to access fields in most cases than to expose them directly.)
  • The nil slices are disallowed in any struct. Constructors may initialize them to empty slices.
  • It is strongly recommended to use constructors (func New~) to create any struct instance rather than just having it with composite literals.
  • asdfasdf

Index

Constants

View Source
const (
	// Defines the range of a value an axon outputs, (domain of activation)
	// which (state) is right before it gets multiplied by the synaptic weight of its axon.
	// NeuralValue is designed to be in range of [-128, +128].
	// The reason is because we might lose our precisions if the value was too small.
	// Also this is not to be confused with the signed byte integer range of [-128, +127].
	NeuralValueMin   NeuralValue = -128.0
	NeuralValueMax   NeuralValue = +128.0
	NeuralValueMid   NeuralValue = 0.0   // Denotes the neutral neural value.
	NeuralValueWidth NeuralValue = 256.0 // Const def of Abs(Min) + Abs(Max).
	// Constant of the Nth neural layer.
	LayerLevelInit int = -1 // An integer smaller than the smallest value of the layer N.
)

Constants regarding the neural node's inputs & outputs.

View Source
const (
	NVKindExceptional = iota // catch me
	NVKindNeutral
	NVKindNegative
	NVKindPositive
)

const Neutral, Negative, and Positive of NeuralValueKind.

View Source
const (
	NeglectedNode    = iota // invalid && unhandled (initial value of int set by default)
	InputNodeBias           // valid && handled
	InputNodeNotBias        // valid && handled
	OutputNode              // valid && handled
	HiddenNode              // valid && handled
	ExceptionalNode         // invalid && handled
)

const InputNode, OutputNode, and HiddenNode for NodeGene.

View Source
const NumKindChance = 8

NumKindChance must tell the number of M-Rate members in a ChanceGene. Unit-test with NumKindChance.

The purpose of this is to force a kind of dependency test all over the code and prevent bugs there. So this works as a filter bottlenecking possible mistakes.

Variables

This section is empty.

Functions

func And

func And(bools ...bool) bool

And gate of booleans.

func Avg

func Avg(nums ...float64) float64

Avg takes multiple numbers as its parameters then returns the average of those.

func BoundAdjust

func BoundAdjust(
	bound pixel.Rect,
	paddingTop, paddingRight,
	paddingBottom, paddingLeft float64,
) pixel.Rect

BoundAdjust returns the border without (inside) padding.

func GCD

func GCD(numbers ...int) int

GCD returns the greatest common divisor of all given integers.

func Gaussian

func Gaussian(mean, deviation float64) float64

Gaussian returns a random number N in a given normal distribution. Don't forget the good old `N(0, 1)` which gets us the standard normal distribution.

func PosBoxesOf

func PosBoxesOf(bound pixel.Rect, fromLeftToRight, fromTopToBottom bool, widthBox, heightBox float64) []pixel.Vec

PosBoxesOf returns all the positions of all boxes in a given rectangular bound, aligned in a linear order. This could be useful for positioning the input nodes of the neural network actor. Args `widthBox` and `heightBox` should be exact otherwise outbound-errors.

func PosPixelsOf

func PosPixelsOf(bound pixel.Rect, fromLeftToRight, fromTopToBottom bool) []pixel.Vec

PosPixelsOf returns all the positions of all pixels in a given rectangular bound, aligned in a linear order. This could be useful for positioning the input nodes of the neural network actor.

func RelativeDifferenceNormalized

func RelativeDifferenceNormalized(a, b float64) float64

RelativeDifferenceNormalized returns a value in [0, 1]; a percentage that tells how different two given numbers are.

Idea: https://en.wikipedia.org/wiki/Relative_change_and_difference http://mathcentral.uregina.ca/QQ/database/QQ.09.06/s/carolyn1.html It tells us to divide the absolute distance by the average of the two given numbers. (The formula of this function is of my own - I just felt like this would work. `Divide by Sum(a, b)` makes more sense to me than `divide by Max(a, b)` or `divide by Avg(a, b)` because `Divide by Sum(a, b)` limits the range of its outcome to [0, 1] and the others are not.)

func Roulette

func Roulette(ratio ...float64) (iPick int)

Roulette accepts weights of a ratio as its parameters, and returns a weighted random index number in [0, len(ratio)).

func Sum

func Sum(nums ...float64) float64

Sum takes multiple numbers as its parameters then returns the sum of those. (Duh.)

Types

type Agent

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

Agent is a Measurer: Agent implements Measurer interface.

func NewAgent

func NewAgent() *Agent

NewAgent is a constructor.

func (*Agent) Close

func (a *Agent) Close()

Close all channels of this agent.

Effects of closing channels:

  • Channels are closed.
  • The other goroutine is notified of the fact that the data flow was shut quite tough.
  • Possible memory leaks are prevented in case our GC is working so lazy.

func (*Agent) IsWorking

func (a *Agent) IsWorking() bool

IsWorking when this agent as a supplier thinks it is working, not when the consumer thinks it is. The consumer might use this method.

func (*Agent) Measure

func (a *Agent) Measure(brains []*NeuralNetwork) (fitness float64)

Measure blocks the thread. The consumer might use this method.

func (*Agent) MeasureAsync

func (a *Agent) MeasureAsync(brains []*NeuralNetwork) (messenger Swallow, err error)

MeasureAsync does not block the thread. The consumer uses this method.

func (*Agent) Receive

func (a *Agent) Receive() (brains []*NeuralNetwork)

Receive blocks the thread. The supplier uses this method.

func (*Agent) Send

func (a *Agent) Send(fitness float64)

Send blocks the thread. The supplier uses this method.

func (*Agent) String

func (a *Agent) String() string

String callback of Agent implements Measurer.

type Ark

type Ark struct {
	ReferenceByUUID map[uuid.UUID]*NodeGene
	Classes         []*Species
	TopFitness      float64
	Generation      int
	Innovation      int
	NicheCount      int
	Config          Configuration
	InputGenes      []*NodeGene
	OutputGenes     []*NodeGene
}

Ark JSON export of Universe. Backup state data.

func NewArkFromFile

func NewArkFromFile(filepath string) (*Ark, error)

NewArkFromFile loads one universe state from a JSON file. Data in.

func (*Ark) New

func (pack *Ark) New() (ret Experimenter, err error)

New is the coolest constructor where everything starts.

func (*Ark) NewUniverse

func (pack *Ark) NewUniverse() (retUniv *Universe, err error)

NewUniverse is a constructor. Data out.

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

Banner implements Actor and HUD.

func (*Banner) Draw

func (ban *Banner) Draw(t pixel.Target)

Draw implements Drawer.

func (*Banner) PosOnScreen

func (ban *Banner) PosOnScreen(width, height float64)

PosOnScreen implements HUD. Async.

func (*Banner) Self

func (ban *Banner) Self() *Banner

Self returns this object as a struct.

func (*Banner) Update

func (ban *Banner) Update(_ float64)

Update implements Updater.

func (*Banner) UpdateDesc

func (ban *Banner) UpdateDesc(desc string)

UpdateDesc queues an update to the text of this. This function falls through when this Actor is working too busy.

type BannerActor

type BannerActor interface {
	Self() *Banner
	visual.HUD
}

BannerActor implements Actor and HUD.

func NewBanner

func NewBanner(isAnchoredTop, isAnchoredRight bool) BannerActor

NewBanner is a constructor.

type ChanceGene

type ChanceGene struct {
	// It is strongly recommended to use getter methods to retrieve these fields if possible.
	// IsEnabled() and Unpack() are/should be the only getter methods the struct provides.
	// That design simply simplifies stuff and may prevent lots of errors in the future.
	Enabled       bool    // What tells either the local(dynamic) M-Rate enabled or not.
	AddNode       float64 // Add-node structural mutation chance in percentage. (local M-Rate)
	AddLink       float64 // Add-link between non-bias nodes structural mutation chance in percentage. (local M-Rate)
	AddBias       float64 // Add-link to bias structural mutation chance in percentage. (local M-Rate)
	PerturbWeight float64 // Synaptic weight mutation chance in percentage. (local M-Rate)
	NullifyWeight float64 // Mutation chance of synaptic weight becoming zero. (local M-Rate)
	TurnOn        float64 // Enable-gene mutation chance in percentage. (local M-Rate)
	TurnOff       float64 // Disable-gene mutation chance in percentage. (local M-Rate)
	Bump          float64 // Bump-enable mutation chance in percentage. (local M-Rate)
}

ChanceGene (an alias for DiceGene here) is a set of mutation probabilities for a Chromosome. This allows our searching algorithm (the genetic algorithm) to have different exploration-exploitation ability in different stage of the search process. Also in case such dynamic mutation rate is not preferred, ChanceGene provides a way that it can be disabled to have constant probabilities given by hyper parameters.

func NewChanceGene

func NewChanceGene(enabled bool, addNode, addLink, addBias, perturbWeight, nullifyWeight, turnOn, turnOff, bump float64) *ChanceGene

NewChanceGene is a constructor.

func NewChanceGeneDisabled

func NewChanceGeneDisabled() *ChanceGene

NewChanceGeneDisabled is a constructor.

func NewChanceGeneEnabled

func NewChanceGeneEnabled(addNode, addLink, addBias, nullifyWeight, perturbWeight, turnOn, turnOff, bump float64) *ChanceGene

NewChanceGeneEnabled is a constructor.

func (*ChanceGene) Copy

func (diceGene *ChanceGene) Copy() *ChanceGene

Copy is a constructor. A deep copy of this object is returned.

func (*ChanceGene) IsEnabled

func (diceGene *ChanceGene) IsEnabled() bool

IsEnabled tells either the local(dynamic) M-Rate is enabled or not.

func (*ChanceGene) Perturb

func (diceGene *ChanceGene) Perturb(mean, deviation float64)

Perturb mutates this dice-gene's weight with a random, normally distributed Gaussian noise. The way this works is similar to that of the LinkGene's.

Parameters:

  • `mean` - What tells how bias this operation is.
  • `deviation` - That defines how various a distribution is.

func (*ChanceGene) String

func (diceGene *ChanceGene) String() string

String callback of ChanceGene.

func (*ChanceGene) Unpack

func (diceGene *ChanceGene) Unpack() (addNode, addLink, addBias, perturbWeight, nullifyWeight, turnOn, turnOff, bump float64)

Unpack returns all the chance values (defined probabilities; rates) of this dice-gene, regardless of whether it's enabled or not.

The purpose of this is to force a kind of dependency-test all over the code and prevent bugs there. So this works as a filter bottlenecking possible mistakes.

I use this method whenever two or more of the members of this struct are needed to be read at a time, because in those places the way this function works reduced lots of errors.

type Chromosome

type Chromosome struct {
	LinkGenes   []*LinkGene // Hidden nodes are inferred out of this. Sort by innov.
	IONodeGenes []*NodeGene `json:"-"` // This does not contain hidden nodes. Inputs and Outputs only.
	DiceGene    *ChanceGene
}

Chromosome is a part of Genome the struct type. This encodes an NN and thus is a factory of a neural network. Chromosome may implement the genetic scheme of NEAT; a linear representation of network connectivity where its sequence alignment is significant.

func NewChromosome

func NewChromosome(links []*LinkGene, ioNodes []*NodeGene, dice *ChanceGene) (chrome *Chromosome, err error)

NewChromosome is a constructor. Arg links, nodes, and dice can be nil to set them empty by default.

Parameters

  • `links`: Link-genes. The innovation number must not overlap with any. A link may be connected to the Input, Hidden, or Output nodes.
  • `nodes`: Node-genes. Only Input/Output nodes are allowed. Hidden nodes etc. are forbidden.
  • `dice`: A set of mutation probabilities.

func (*Chromosome) AddLinkGenes

func (chrome *Chromosome) AddLinkGenes(pleasePassInDeepCopiesHere ...*LinkGene)

AddLinkGenes (gene) to this Chromosome. This does not verify the added gene(s) for its efficiency. You could test it with (*Chromosome).IsValidLinks().

func (*Chromosome) Bump

func (chrome *Chromosome) Bump()

Bump re-enables the oldest disabled structure a single gene represents. (It's like bringing up a post in message board terms.) Time complexity is O(N). If there ain't one disabled then this operation does nothing other than consuming some time searching for it.

func (*Chromosome) Copy

func (chrome *Chromosome) Copy() (*Chromosome, error)

Copy is a constructor. Deep-copies everything of this chromosome except node-genes.

func (*Chromosome) Genetics

func (chrome *Chromosome) Genetics() (linkGenesByInnovation map[Innovation]*LinkGene, sizeLinkGenes int, innovationLatest Innovation)

Genetics provides the essentials of this chromosome's genetics; all the link-gene stuff that is.

Returns:

  • `linkGenesByInnovation`: A map of all link genes available in this Chromosome.
  • `sizeLinkGenes`: The normalize size factor for the compatibility distance measure. Refer to (*Chromosome).SizeBuilding().
  • `innovationLatest`: The biggest (latest) innovation number this chromosome has. This is a historical bound used to divide unmatched genes into disjoint and excess.

func (*Chromosome) IsDiceEnabled

func (chrome *Chromosome) IsDiceEnabled() bool

IsDiceEnabled tells if this chromosome has its own dynamic mutation rate other than the fixed probability.

func (*Chromosome) IsValid

func (chrome *Chromosome) IsValid() bool

IsValid tests this chromosome.

func (*Chromosome) IsValidForDice

func (chrome *Chromosome) IsValidForDice() bool

IsValidForDice tests the dice of this chromosome.

func (chrome *Chromosome) IsValidForLinks() bool

IsValidForLinks tests links of this chromosome.

func (*Chromosome) IsValidForNodes

func (chrome *Chromosome) IsValidForNodes() bool

IsValidForNodes tests nodes of this chromosome.

func (*Chromosome) NewNeuralNetwork

func (chrome *Chromosome) NewNeuralNetwork() (network *NeuralNetwork, err error)

NewNeuralNetwork (verbed) from a Chromosome.

func (*Chromosome) NewNeuralNetworkProto

func (chrome *Chromosome) NewNeuralNetworkProto(
	includeDisabledLinks, includeNonBiasInputNodes, includeBiasNodes bool,
) (proto *NeuralNetworkProto, err error)

NewNeuralNetworkProto gets us a topological analysis of the network.

func (*Chromosome) NodeGenesByUUID

func (chrome *Chromosome) NodeGenesByUUID(fillMe map[uuid.UUID]*NodeGene) (filledOut map[uuid.UUID]*NodeGene)

NodeGenesByUUID returns a map of all node genes available in this Chromosome. The parameter can be nil.

func (*Chromosome) SizeBuilding

func (chrome *Chromosome) SizeBuilding() (sizeTopologicalInnovation int)

SizeBuilding returns the number of all link genes this genetic encoder has. This allows us to measure the scale of structural innovations a topology gets made up with.

func (*Chromosome) Sort

func (chrome *Chromosome) Sort()

Sort of Chromosome sorts slice(s) of a chromosome itself. For nodes, the order is important for inputs & outputs. The link genes are sorted in ascending order of the innovation number.

func (*Chromosome) String

func (chrome *Chromosome) String() string

String callback of Chromosome.

type Configuration

type Configuration struct {
	// Label for the universe
	ExperimentName string
	// Max number of creatures
	SizePopulation int
	// The percentage bottom which percentage of organisms in a species is culled off every epoch.
	// The range of this value is [0, 1].
	PercentageCulling float64
	// The Nth generation the stagnant species is going to face its extermination. xD
	// The species not improving over this much of generations will get penalized.
	// Negative value for this means infinity.
	MaxCntArmageddon int // Age threshold to dropoff. Rotten species are not allowed to reproduce.
	// If the top fitness of the entire universe does not improve for more than this much of generations,
	// only the top two species are allowed to reproduce, refocusing the search into the most promising spaces.
	// Negative value for this means infinity.
	MaxCntApocalypse int // Threshold to the universe's stagnancy.
	// If false, entire population of a species besides the champion is replaced by their offsprings at each reproduce procedure.
	// If true, there are un-culled organisms in species: reproducible organisms are saved and lives on to next generation.
	IsProtectiveElitism   bool
	IsFitnessRemeasurable bool // If true, the fitness of every organism that's already measured gets remeasured in the measuring stage of each generation.
	// Ratio of different reproduction methods performed upon breeding species
	ScaleCrossoverMultipointRnd  int // Sexual reproduction 1
	ScaleCrossoverMultipointAvg  int // Sexual reproduction 2
	ScaleCrossoverSinglepointRnd int // Sexual reproduction 3
	ScaleCrossoverSinglepointAvg int // Sexual reproduction 4
	ScaleFission                 int // Asexual breeding (Binary fission)
	// Base of M-Rate (ChanceGene)
	ChanceIsMutational  bool    // Genetic(dynamic) or constant.
	ChanceAddNode       float64 // Add-Node mutation chance.
	ChanceAddLink       float64 // Add-Link mutation chance only for non-bias nodes.
	ChanceAddBias       float64 // Add-Link mutation chance only for bias.
	ChancePerturbWeight float64 // Synaptic weight mutation chance.
	ChanceNullifyWeight float64 // Mutation chance of synaptic weight becoming zero.
	ChanceTurnOn        float64 // Enable mutation chance.
	ChanceTurnOff       float64 // Disable mutation chance.
	ChanceBump          float64 // Bump mutation chance.
	// What defines the synaptic weight mutation.
	// This is a size factor determining the deviation of a Gaussian distribution.
	TendencyPerturbWeight float64 // The mean(offset). Set to 0.0 by default.
	TendencyPerturbDice   float64 // The mean(offset). Set by default to a very small positive value.
	StrengthPerturbWeight float64 // Adjusted deviation. Synaptic weight is perturbed by this percent of it.
	StrengthPerturbDice   float64 // Adjusted deviation. Mutational rate is perturbed by this percent of it.
	// Measuring the compatibility distance
	CompatThreshold           float64 // The line separating species.
	CompatIsNormalizedForSize bool    // The characterizing variables of disjointedness and excess get expressed in normalized percent, or, rather in the absolute which ignores the size of two genetic encoders.
	CompatCoeffDisjoint       float64 // The maximum disjointedness when expressed in normalized percent or simply a multiplier to the number of disjoint genes a chromosome has.
	CompatCoeffExcess         float64 // The maximum excessiveness when expressed in normalized percent or simply a multiplier to the number of excessive genes a chromosome has.
	CompatCoeffWeight         float64 // The maximum or simply a multiplier regarding the mutational difference of weights.
	CompatCoeffChance         float64 // The maximum or simply a multiplier regarding the mutational difference of chance gene's.
	// Seeds of genetics (Genome/Chromosome)
	NumChromosomes   int // The number of Chromosome-s for a single Genome. The number of NNs a single Organism consists of.
	NumBiases        int // The number of biases.
	NumNonBiasInputs int // The number of input nodes. This doesn't count for biases.
	NumOutputs       int // The number of output nodes.
}

Configuration stores the universe's constants. A set of hyper parameters.

func NewConfiguration

func NewConfiguration() *Configuration

NewConfiguration is a constructor. This simply creates an empty object. Feel free to edit what's returned however you'd like.

func NewConfigurationSimple

func NewConfigurationSimple(nNet, nIn, nOut int) *Configuration

NewConfigurationSimple is a constructor. It returns what's filled up with a default setting.

A set of params I used to test with:

  • nNet = 2
  • nIn = 38 * 28
  • nOut = 7

func (*Configuration) BirthRatioSimplified

func (config *Configuration) BirthRatioSimplified() (
	weightCrossoverMultipointRnd,
	weightCrossoverMultipointAvg,
	weightCrossoverSinglepointRnd,
	weightCrossoverSinglepointAvg,
	weightFission,
	weightSterile float64,
)

BirthRatioSimplified returns the breeding methods ratio in smallest integers.

func (*Configuration) New

func (config *Configuration) New() Experimenter

New is where everything starts.

These two are the same:

  • func New(config *Configuration) Experimenter
  • func (config *Configuration) New() Experimenter

func (*Configuration) NewUniverse

func (config *Configuration) NewUniverse() *Universe

NewUniverse is a constructor.

type Experimenter

type Experimenter interface {
	Self() *Universe
	Status() UniverseStatusGetter
	RegisterMeasurer(agent Measurer)
	UnregisterMeasurer(agent Measurer)
	Run() error
	Shutdown()
	IsPumping() bool
}

Experimenter exposes a set of user-friendly methods. Facade of this library.

func New

func New(config *Configuration) Experimenter

New is where everything starts.

These two are the same:

  • func New(config *Configuration) Experimenter
  • func (config *Configuration) New() Experimenter

type Genome

type Genome struct {
	Chromes []*Chromosome // Each of these chromosomes is for a network.
}

Genome represents a genotype of a single living organism, from which, in general meaning, we can derive a neural network as a phenotype. This Genome designed here in specific can encode of multiple neural networks taking a separate set of inputs for each.

func NewGenome

func NewGenome(chromes []*Chromosome) (g *Genome, err error)

NewGenome is a constructor. Arg chromes can be nil to set by default.

func (*Genome) Chromosomes

func (g *Genome) Chromosomes() []*Chromosome

Chromosomes returns a list of all chromosomes of this genome. The slice returned is an original reference not a copy.

func (*Genome) Copy

func (g *Genome) Copy() (ret *Genome, err error)

Copy is a constructor.

func (*Genome) ForEachMatchingChromosome

func (g *Genome) ForEachMatchingChromosome(
	matchedPartner *Genome,
	forEachGeneticAnalysis func(
		i int,
		chrome1 *Chromosome,
		linkGenes1 map[Innovation]*LinkGene,
		nLinkGenes1 int, historical1 Innovation,
		chrome2 *Chromosome,
		linkGenes2 map[Innovation]*LinkGene,
		nLinkGenes2 int, historical2 Innovation,
	) error,
) error

ForEachMatchingChromosome of two genomes. Use this method to line up chromosomes of a genome beside one another. Genetic recombination may happen upon each genetic analysis of homologous chromosomes. The callback provides parental chromosomes that pair up with each other. This function returns error if each genome has a distinct number of chromosomes. Mandatory: All arguments are required and cannot be nil parameter.

func (*Genome) IsValid

func (g *Genome) IsValid() bool

IsValid tests this genome.

func (*Genome) Length

func (g *Genome) Length() int

Length returns the number of chromosomes this genome consist of.

func (*Genome) NewOrganism

func (g *Genome) NewOrganism(breed *Species, fitness float64, isMeasured bool) (o *Organism, err error)

NewOrganism is born. A constructor. The returned organism inherits the reference of this genome.

func (*Genome) NewOrganismSimple

func (g *Genome) NewOrganismSimple() (o *Organism, err error)

NewOrganismSimple is a constructor. The return is a default organism unmeasured and nil breed.

func (*Genome) NewPhenotype

func (g *Genome) NewPhenotype() (phenome []*NeuralNetwork, err error)

NewPhenotype from this genotype.

func (*Genome) NodeGenesByUUID

func (g *Genome) NodeGenesByUUID(fillMe map[uuid.UUID]*NodeGene) (filledOut map[uuid.UUID]*NodeGene)

NodeGenesByUUID returns a map of all node genes available in this Genome. The parameter can be nil.

func (*Genome) String

func (g *Genome) String() string

String of Genome.

type ImageConverter

type ImageConverter struct {
}

ImageConverter converts images.

func ImageMan

func ImageMan() ImageConverter

ImageMan is a getter and what returned from it is considered a public singleton object.

func (ImageConverter) FromColorsToImage

func (ImageConverter) FromColorsToImage(colors []color.Color, width, height int) *image.NRGBA

FromColorsToImage converts a color.Color list to an image.NRGBA.

func (ImageConverter) FromGraysToImage

func (ImageConverter) FromGraysToImage(colors []color.Gray, width, height int) *image.Gray

FromGraysToImage converts a color.Gray list to an image.Gray.

func (ImageConverter) FromImageGrayToNeuralValues

func (ImageConverter) FromImageGrayToNeuralValues(img *image.Gray) []NeuralValue

FromImageGrayToNeuralValues converts an image.Gray to a NeuralNeNeuralValueuralValueInput list. The return could be considered a list of inputs.

func (ImageConverter) FromImageNRGBAToNeuralValues

func (ImageConverter) FromImageNRGBAToNeuralValues(img *image.NRGBA) []NeuralValue

FromImageNRGBAToNeuralValues converts an image.NRGBA to a NeuralValue list. The return could be considered a list of inputs.

func (ImageConverter) FromImageNRGBAToRGBAs

func (ImageConverter) FromImageNRGBAToRGBAs(img *image.NRGBA) []color.RGBA

FromImageNRGBAToRGBAs converts an image.NRGBA to a premultiplied color.RGBA list.

func (ImageConverter) FromImageToColors

func (ImageConverter) FromImageToColors(img image.Image) []color.Color

FromImageToColors converts an image.Image to a color.Color list.

func (ImageConverter) FromImageToList

func (ImageConverter) FromImageToList(img image.Image, onGivenXY func(x, y int) interface{}) []interface{}

FromImageToList combined with `(image.Image).At(x, y)` can convert an `image.Image` to a list(slice).

func (ImageConverter) FromNRGBAsToImage

func (ImageConverter) FromNRGBAsToImage(colors []color.NRGBA, width, height int) *image.NRGBA

FromNRGBAsToImage converts a color.NRGBA list to an image.NRGBA.

type Innovation

type Innovation int64

Innovation is the historical marker known as `innovation number`. The innovation number is unique for each of structural innovations under a NEAT context. It basically is considered an integer starting from zero but could be used in other way depending on the context.

type LinkGene

type LinkGene struct {
	Topo struct {
		Innov Innovation // The innovation number; an identifier of the topological innovation, not a link-gene.
		From  *NodeGene  // Where this link is from. (in-node)
		To    *NodeGene  // Where this link is connected to. (out-node)
	}
	Weight float64 // Synaptic weight in neural network.
	// The 'Enabled' flag in a link gene.
	// It only determines whether this link gene's trait as a neural edge is expressed in a neural network or not.
	// Besides the crossover, this becomes false only when the link is split in half. But the link gene is still valid then,
	// even though having this false disallows the link gene itself to be instantiated to the neural edge.
	Enabled bool // Kinda like the gene's dominant or recessive.
}

LinkGene is a gene that encodes of something like synapses, axons and dendrites, etc. Abstracted as simple as possible.

func NewLinkGene

func NewLinkGene(innov Innovation, from, to *NodeGene, weight float64, enabled bool) *LinkGene

NewLinkGene is a constructor.

func (*LinkGene) Copy

func (linkGene *LinkGene) Copy() *LinkGene

Copy is a constructor. A deep copy of this object is returned.

func (*LinkGene) MarshalJSON

func (linkGene *LinkGene) MarshalJSON() ([]byte, error)

MarshalJSON of json.Marshaler interface. References are lost marshaling into JSON but the UUIDs.

func (*LinkGene) Perturb

func (linkGene *LinkGene) Perturb(mean, deviation float64)

Perturb mutates this link gene's weight with a random, normally distributed Gaussian noise. The size of this perturbation - regarding the standard deviation of a Gaussian distribution - is given by the parameter.

Parameters:

  • `mean` - What tells how bias this operation is.
  • `deviation` - That defines how various a distribution is.

func (*LinkGene) String

func (linkGene *LinkGene) String() string

String callback of LinkGene.

func (*LinkGene) UnmarshalJSON

func (linkGene *LinkGene) UnmarshalJSON(jsonLinkGeneMarshal []byte) (err error)

UnmarshalJSON of json.Unmarshaler interface. Notice that all references will point to dummy objects.

type LinkGeneMarshal

type LinkGeneMarshal struct {
	Topo struct {
		Innov Innovation
		From  uuid.UUID
		To    uuid.UUID
	}
	Weight  float64
	Enabled bool
}

LinkGeneMarshal is JSON export of LinkGene. We use this struct because of the LinkGene's references. (members of pointer type)

func (*LinkGeneMarshal) ToLinkGene

func (lgm *LinkGeneMarshal) ToLinkGene(referenceByUUID map[uuid.UUID]*NodeGene) *LinkGene

ToLinkGene from LinkGeneMarshal. The parameter can be nil. When there's a field of reference type not provided with any actual reference, this function would allocate a dummy object of that UUID and populate it.

type Measurer

type Measurer interface {
	// Notice the side effect of this method as an impure function that
	// with fitness it returns it might also update the state of our NN.
	MeasureAsync(organism []*NeuralNetwork) (postman Swallow, err error)
	String() string
}

Measurer is a consumer interface for what measures an organism's fitness. It could be an emulator thread or a network server or any test case. Implement it however you'd like.

type NRGBA

type NRGBA color.NRGBA

NRGBA extends `color.NRGBA`. NRGBA is a pixel converter converting `color.NRGBA`. Get this from `PixelConverter()`.

func PixelConverter

func PixelConverter(c color.NRGBA) NRGBA

PixelConverter is a factory and a utility for processing inputs.

func (NRGBA) ToGrayscaleColor

func (c NRGBA) ToGrayscaleColor() color.Gray

ToGrayscaleColor converts an NRGBA to a struct Gray.

func (NRGBA) ToGrayscaleFloat

func (c NRGBA) ToGrayscaleFloat() float64

ToGrayscaleFloat converts an NRGBA to a plain grayscale value. The alpha is ignored.

func (NRGBA) ToGrayscaleNRGBA

func (c NRGBA) ToGrayscaleNRGBA() color.NRGBA

ToGrayscaleNRGBA converts a colorful NRGBA to a grayscale NRGBA pixel. The alpha is preserved.

func (NRGBA) ToGrayscaleRGBA

func (c NRGBA) ToGrayscaleRGBA() color.RGBA

ToGrayscaleRGBA converts an NRGBA to a premultiplied grayscale RGBA pixel.

func (NRGBA) ToNeuralValue

func (c NRGBA) ToNeuralValue() NeuralValue

ToNeuralValue converts an NRGBA to a grayscale naneat input.

func (NRGBA) ToRGBA

func (c NRGBA) ToRGBA() color.RGBA

ToRGBA converts an NRGBA to a premultiplied RGBA pixel.

type NeuralEdge

type NeuralEdge struct {
	graph.Edge
	Gene *LinkGene
}

NeuralEdge is a neural connection in the neural network.

func (*NeuralEdge) IsValid

func (neuralEdge *NeuralEdge) IsValid() bool

IsValid tells whether this edge is valid or not.

func (*NeuralEdge) NeuralNodeFrom

func (neuralEdge *NeuralEdge) NeuralNodeFrom() *NeuralNode

NeuralNodeFrom this neural edge.

func (*NeuralEdge) NeuralNodeTo

func (neuralEdge *NeuralEdge) NeuralNodeTo() *NeuralNode

NeuralNodeTo this neural edge.

func (*NeuralEdge) String

func (neuralEdge *NeuralEdge) String() string

String callback of NeuralEdge.

func (*NeuralEdge) ToGene

func (neuralEdge *NeuralEdge) ToGene() *LinkGene

ToGene is a getter returning a gene of this NeuralEdge.

func (*NeuralEdge) Weight

func (neuralEdge *NeuralEdge) Weight() float64

Weight of this synaptic link.

type NeuralEdges

type NeuralEdges struct {
	graph.Edges
}

NeuralEdges is a NeuralEdge iterator.

Usage:

for neuralEdges.Next() {
	neuralEdge := neuralEdges.NeuralEdge()
	// do whatever
}

func (*NeuralEdges) NeuralEdge

func (edges *NeuralEdges) NeuralEdge() *NeuralEdge

NeuralEdge returns the NeuralEdge of this iterator.

Usage:

for neuralEdges.Next() {
	neuralEdge := neuralEdges.NeuralEdge()
	// do whatever
}

func (*NeuralEdges) String

func (edges *NeuralEdges) String() string

String callback of this NeuralEdges.

func (*NeuralEdges) ToSlice

func (edges *NeuralEdges) ToSlice() []*NeuralEdge

ToSlice of this NeuralEdges.

type NeuralNetwork

type NeuralNetwork struct {
	// Inheritance. (super class)
	*simple.DirectedGraph

	// Nodes in order.
	InputNodes  []*NeuralNode
	OutputNodes []*NeuralNode

	// Phonebooks.
	NodeByGene map[*NodeGene]*NeuralNode // Nodes indexed by NodeGene. // private use (member could be unexported)
	EdgeByGene map[*LinkGene]*NeuralEdge // Edges indexed by LinkGene. // private use (member could be unexported)

	// Counts up whenever a node is added to this network.
	// Always equal to the number of nodes this neural network has.
	NumBiasNodes   int
	NumInputNodes  int // including biases
	NumHiddenNodes int
	NumOutputNodes int
	// NumLayers 0 by default.
	// This updates only when the layer level is evaluated.
	NumLayers int

	// Set to false when the values are being updated or yet updated.
	IsEvaluatedWell bool
}

NeuralNetwork is a part of an artificial brain structure of an individual living organism. The basic form of it should be evaluatable and be constructed with valid structures only. The data structure of a neural network is represented as a DAG(Directed Acyclic Graph). All neural nodes in a valid neural network is connected directly or undirectly to both Inputs and Outputs layer but just except for those input nodes and output nodes. It is strongly recommended not to access any of these members directly outside this package, unless you understand what those really are. Otherwise use this struct's methods and its constructor instead.

func (*NeuralNetwork) AddNewNeuralEdge

func (network *NeuralNetwork) AddNewNeuralEdge(from, to graph.Node, gene *LinkGene) (err error)

AddNewNeuralEdge creates a neural edge and adds it to this network. It replaces this network's previous edge connected from from to to if there is any. Returns an error if the IDs of the from and to are equal.

func (*NeuralNetwork) AddNewNeuralNode

func (network *NeuralNetwork) AddNewNeuralNode(gene *NodeGene) (node *NeuralNode)

AddNewNeuralNode creates a unique identifiable neural node within this neural network, along with that node's genetics. Returns the node added to this network.

func (*NeuralNetwork) Clear

func (network *NeuralNetwork) Clear() (nodes []*NeuralNode, err error)

Clear values of all neural nodes of this NeuralNetwork. Sets IsEvaluated to false. This function returns the topological sort of this graph.

func (*NeuralNetwork) Evaluate

func (network *NeuralNetwork) Evaluate(inputs []NeuralValue) (outputs []NeuralNode, err error)

Evaluate of a NeuralNetwork performs a feedforward of a network. The list (slice) returned by this function keeps copies of all output nodes, from which we get the output values of a network evaluated.

func (*NeuralNetwork) FindEdgeByGene

func (network *NeuralNetwork) FindEdgeByGene(gene *LinkGene) *NeuralEdge

FindEdgeByGene finds (returns) a NeuralEdge in this NeuralNetwork by the NeuralEdge's LinkGene, costing only constant time complexity. Returns nil if not present. Each NeuralEdge in a NeuralNetwork is/should be matched to a single LinkGene.

func (*NeuralNetwork) FindNodeByGene

func (network *NeuralNetwork) FindNodeByGene(gene *NodeGene) *NeuralNode

FindNodeByGene finds (returns) a NeuralNode in this NeuralNetwork by the NeuralNode's NodeGene, costing only constant time complexity. Returns nil if not present. Each NeuralNode in a NeuralNetwork is/should be matched to a single NodeGene.

func (*NeuralNetwork) GetInputNodes

func (network *NeuralNetwork) GetInputNodes() []*NeuralNode

GetInputNodes returns a copy slice of InputNodes. The ptrs a slice returned here holds are to originals not to copies.

func (*NeuralNetwork) GetOutputNodes

func (network *NeuralNetwork) GetOutputNodes() []*NeuralNode

GetOutputNodes returns a copy slice of OutputNodes. The ptrs a slice returned here holds are to originals not to copies.

func (*NeuralNetwork) IsEvaluated

func (network *NeuralNetwork) IsEvaluated() bool

IsEvaluated tells whether neural values of this neural network has been evaluated or not.

func (*NeuralNetwork) NLayers

func (network *NeuralNetwork) NLayers() int

NLayers returns the number of layers in this network.

func (*NeuralNetwork) NeuralEdge

func (network *NeuralNetwork) NeuralEdge(from, to graph.Node) *NeuralEdge

NeuralEdge returns the neural edge from from to to. The return can be nil.

func (*NeuralNetwork) NeuralEdges

func (network *NeuralNetwork) NeuralEdges() *NeuralEdges

NeuralEdges returns all neural edges of this neural network.

Usage:

neuralEdges := network.NeuralEdges()
for neuralEdges.Next() {
	neuralEdge := neuralEdges.NeuralEdge()
	// do whatever
}

func (*NeuralNetwork) NeuralNodesFrom

func (network *NeuralNetwork) NeuralNodesFrom(from graph.Node) *NeuralNodes

NeuralNodesFrom of this neural network returns all nodes that can be reached directly from the from node. The returned nodes are what our axons linked to.

Usage:

neuralNodes := network.NeuralNodesFrom(from)
for neuralNodes.Next() {
	neuralNode := neuralNodes.NeuralNode()
	// do whatever
}

func (*NeuralNetwork) NeuralNodesTo

func (network *NeuralNetwork) NeuralNodesTo(to graph.Node) *NeuralNodes

NeuralNodesTo returns all nodes in this neural network that can directly reach to the to node. The returned nodes are those that our dendrites are receiving signals from.

Usage:

neuralNodes := network.NeuralNodesTo(to)
for neuralNodes.Next() {
	neuralNode := neuralNodes.NeuralNode()
	// do whatever
}

func (*NeuralNetwork) NewNeuralEdge

func (network *NeuralNetwork) NewNeuralEdge(from, to graph.Node, gene *LinkGene) *NeuralEdge

NewNeuralEdge creates an edge linked between nodes given as arguments, the from and the to. The gene must be enabled to create a valid evaluatable network. This edge is not valid until it is added to the NeuralNetwork that created it. You might want to use AddNewNeuralEdge() instead.

func (*NeuralNetwork) NewNeuralNode

func (network *NeuralNetwork) NewNeuralNode(gene *NodeGene) *NeuralNode

NewNeuralNode is a basic constructor for a NeuralNode. The node created here inherits a NodeGene. The returned node's identifier is not valid, until the node is added to the NeuralNetwork that created it. You might want to use AddNewNeuralNode() instead.

func (*NeuralNetwork) RemoveNeuralNode

func (network *NeuralNetwork) RemoveNeuralNode(gene *NodeGene) error

RemoveNeuralNode deletes a neural node of this network, as well as any neural edges attached to it. This does the inverse of AddNewNeuralNode(). Returns an error if the neural node to be removed is not present in this neural network.

func (*NeuralNetwork) Sort

func (network *NeuralNetwork) Sort() (nodes []*NeuralNode, err error)

Sort does the topological sort of this graph, (often abbreviated to topo-sort) so that you can iterate over all the nodes of a neural network in a feedforward order. The order is *similar* to that of BFS. The topological sort can also be used as a cycle detection of the graph. This sort is stable, as it follows the sequence alignment of the genetic encoder (chromosome) as well. The returned list; slice is a copy and holds the actual (pointing not to a copy) pointers to all the neural nodes of this network.

func (*NeuralNetwork) TraverseBackward

func (network *NeuralNetwork) TraverseBackward(
	node *NeuralNode,
	onNodeVisit func(nodeVisit *NeuralNode),
	visited map[*NeuralNode]struct{},
)

TraverseBackward DFSes a parent-tree(reverse-subtree) of a node.

Parameters:

  • `node`: The node where you want to start DFSing.
  • `onNodeVisit`: Callback on each node visit. It's allowed to be nil.
  • `visited`: DFS context. This argument cannot be nil. The function panics when it is.

func (*NeuralNetwork) TraverseForward

func (network *NeuralNetwork) TraverseForward(
	node *NeuralNode,
	onNodeVisit func(nodeVisit *NeuralNode),
	visited map[*NeuralNode]struct{},
)

TraverseForward DFSes a subtree of a node.

Parameters:

  • `node`: The node where you want to start DFSing.
  • `onNodeVisit`: Callback on each node visit. It's allowed to be nil.
  • `visited`: DFS context. This argument cannot be nil. The function panics when it is.

type NeuralNetworkActor

type NeuralNetworkActor interface {
	visual.Actor
	Self() *NeuralNetworkVisual // Itf to struct.
	Bound() pixel.Rect
	PosOutNodes() []pixel.Vec
	Channel() chan []NeuralNode
}

NeuralNetworkActor is a neural network as an actor.

func NewNeuralNetworkActor

func NewNeuralNetworkActor(
	network *NeuralNetwork, nSizeBufChan int,
	bound pixel.Rect, paddingTop, paddingRight, paddingBottom, paddingLeft float64,
	radiusNode, thicknessLink float64,
	fromRightToLeft, fromTopToBottom, isBoundVisible,
	isInputNodeVisible, isHiddenNodeVisible, isOutputNodeVisible, isTxtVisible bool,
	posInputNodes, posOutputNodes []pixel.Vec,
) (nna NeuralNetworkActor, err error)

NewNeuralNetworkActor is a constructor.

Arguments recommendation:

  • `16.0` for `radiusNode`.
  • `4.0` for `thicknessLink`.
  • `1.0` strongly recommended for `nSizeBufChan`.
  • `nil` for `posInputNodes`.
  • `nil` for `posOutputNodes`.

type NeuralNetworkProto

type NeuralNetworkProto struct {
	*NeuralNetwork
}

NeuralNetworkProto is a subclass of NeuralNetwork. It can provide a rough topological analysis of a neural network that might be constructed with incomplete structures so we can get an idea how it should/can be mutated and etc. How it really is different from NeuralNetwork is dynamically (at runtime) defined by a constructor.

func (*NeuralNetworkProto) AddNewNeuralEdge

func (nnp *NeuralNetworkProto) AddNewNeuralEdge(from, to graph.Node, gene *LinkGene) (err error)

AddNewNeuralEdge of NeuralNetworkProto is an override. The only difference with its super is that this method allows this neural network to be constructed with disabled link genes.

func (*NeuralNetworkProto) FromTo

func (nnp *NeuralNetworkProto) FromTo(topoNodes []*NeuralNode, fromNode *NeuralNode) (toNode *NeuralNode)

FromTo finds a random `toNode` where `fromNode` is connected to. The return can be nil if none is found.

func (*NeuralNetworkProto) GetNeuralNetwork

func (nnp *NeuralNetworkProto) GetNeuralNetwork() *NeuralNetwork

GetNeuralNetwork is a getter.

func (*NeuralNetworkProto) NewNeuralEdge

func (nnp *NeuralNetworkProto) NewNeuralEdge(from, to graph.Node, gene *LinkGene) *NeuralEdge

NewNeuralEdge of NeuralNetworkProto is an override. The only difference with its super is that this method allows this neural network to be constructed with disabled link genes.

func (nnp *NeuralNetworkProto) RandomNicePlaceForNewAcyclicLink() (fromNode, toNode *NeuralNode, err error)

RandomNicePlaceForNewAcyclicLink gets a random nice place where a new link can be put without creating a cycle in this graph. So we can ensure that the graph stays a DAG after insertion of a link in between two existing nodes. The returns are the two existing nodes of this graph a new link can bridge from and to. This function does a bit of calculations for finding the nice place. Time complexity is guessed O(V*E). To test this out, you may connect the two returned nodes and perform a topological sort of the graph to see if there is a cycle.

func (*NeuralNetworkProto) ToFrom

func (nnp *NeuralNetworkProto) ToFrom(topoNodes []*NeuralNode, toNode *NeuralNode) (fromNode *NeuralNode)

ToFrom finds a random `fromNode` that connects to `toNode`. The return can be nil if none is found.

type NeuralNetworkVisual

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

NeuralNetworkVisual implements the Actor interface. 해당 클래스(NNV)는 채널을 통해 신경원(NeuralNode)들의 값 사본의 리스트를 받아서 그리는 일을 한다. 별도의 쓰레드에서 전달되는 값을 매 비주얼라이저 프레임의 시작시에 채널에서 끄집어내어 읽어보고 확인된 변경사항만 다시 그린다. NNV의 기본 정의는 그림일 뿐이며 NN그래프를 상속 받지는 않는다. NNV의 인스턴스는 NN그래프에 대한 의존성이 없고 독립적이다. 생성시점에서 NN그래프를 한 번 인자로 받고 그 모양을 분석해서 그림을 그리기는 하지만 그렇다고 해서 이 타입의 인스턴스가 해당 객체를 소유하지는 않는다는 이야기다. 채널에 대해서는, 채널의 버퍼가 크면 안정적이지만 그에 따라 딜레이 때의 비주얼라이저(NNV)와 공급자(NN-Evaluater) 간의 시간차도 커진다는 점을 염두에 두자. 채널의 크기는 단지 1이면 족하다.

func (*NeuralNetworkVisual) Bound

func (nnv *NeuralNetworkVisual) Bound() pixel.Rect

Bound returns the bound of this. You get the size and its offset as well.

func (*NeuralNetworkVisual) Channel

func (nnv *NeuralNetworkVisual) Channel() chan []NeuralNode

Channel returns the channel this actor gets all the data from.

func (*NeuralNetworkVisual) Draw

func (nnv *NeuralNetworkVisual) Draw(t pixel.Target)

Draw obligatorily invoked by Visualizer on mainthread.

func (*NeuralNetworkVisual) PosOutNodes

func (nnv *NeuralNetworkVisual) PosOutNodes() []pixel.Vec

PosOutNodes returns positions vectors of all output nodes.

func (*NeuralNetworkVisual) Self

Self of this returns itself as a struct.

func (*NeuralNetworkVisual) Update

func (nnv *NeuralNetworkVisual) Update(dt float64)

Update obligatorily invoked by Visualizer on mainthread.

type NeuralNode

type NeuralNode struct {
	Identifier int64 // What identifies this node, given by the network this node belongs to. This ID is only unique within a graph.
	*NodeGene        // Genetics it inherits from.
	// Use only for the memoization of dynamic programming.
	Value NeuralValue // The value this single node holds(outputs).
	// The Nth layer of the neural network this node is located in.
	// N, where N is an integer >= 0, which denotes how the layer is closer to the output layer.
	// E.g. LayerLevel 0 points to the input layer of the neural network.
	LayerLevel int
	// This is set false by default and always true for outputs nodes recognized by a neural network,
	// otherwise it tells if this input/hidden node's synaptic influence can reach to the output layer or not.
	IsValidBackward bool
	// This is set false by default and always true for inputs nodes recognized by a neural network,
	// otherwise it tells if this output/hidden node's synaptic influence can reach to the input layer or not.
	IsValidForward bool
}

NeuralNode of an individual living organism. Use (*NeuralNetwork).NewNeuralNode() to create a new instance. NeuralNode is also considered graph.Node.

func (*NeuralNode) ClearAll

func (neuralNode *NeuralNode) ClearAll()

ClearAll resets all memos of this.

func (*NeuralNode) ClearLevel

func (neuralNode *NeuralNode) ClearLevel()

ClearLevel resets the layer level of this.

func (*NeuralNode) ClearValue

func (neuralNode *NeuralNode) ClearValue()

ClearValue resets the value of this.

func (*NeuralNode) Evaluate

func (neuralNode *NeuralNode) Evaluate(input NeuralValue) (output NeuralValue)

Evaluate the value of NeuralNode. The return gets stored (memoized) in this;self;receiver as well.

func (*NeuralNode) EvaluateWithoutActivation

func (neuralNode *NeuralNode) EvaluateWithoutActivation(input NeuralValue) (output NeuralValue)

EvaluateWithoutActivation of NeuralNode. The return gets stored (memoized) in this;self;receiver as well.

func (*NeuralNode) Gene

func (neuralNode *NeuralNode) Gene() *NodeGene

Gene of this NeuralNode.

func (*NeuralNode) ID

func (neuralNode *NeuralNode) ID() int64

ID of NeuralNode implements the graph.Node interface, so that the node can be added to a simple.DirectedGraph with its unique identifier.

func (*NeuralNode) IsEvaluated

func (neuralNode *NeuralNode) IsEvaluated() bool

IsEvaluated tells whether this NeuralNode's value has been updated or not.

func (*NeuralNode) IsInactive

func (neuralNode *NeuralNode) IsInactive() bool

IsInactive is not the inversion of this node's IsEvaluated(). This function tells if this node has been evaluated as inactive.

func (*NeuralNode) IsValid

func (neuralNode *NeuralNode) IsValid() bool

IsValid tells whether this node has been validated in a neural network. Returns true if this node is an input/output node recognized by a neural network, or it at least has a path (direct or not) open to both the output layer and the input layer.

func (*NeuralNode) Level

func (neuralNode *NeuralNode) Level() (level int, err error)

Level returns the Nth layer this node is located in its network. N is an integer >= 0, which denotes how the layer is closer to the output layer. E.g. Level 0 points to the input layer of the neural network. Returns error when the value is determined as uninitialized(invalid or not evaluated). The returned N could be bigger than the N that points to the output layer, which case is not considered an error.

func (*NeuralNode) Output

func (neuralNode *NeuralNode) Output() (value NeuralValue, err error)

Output returns the value this neuron's axon outputs. Returns error when the value is determined as uninitialized(invalid or not evaluated).

func (*NeuralNode) SetLevel

func (neuralNode *NeuralNode) SetLevel(layerLevel int)

SetLevel memoizes the Nth layer this node is located in its network.

func (*NeuralNode) String

func (neuralNode *NeuralNode) String() string

String callback of NeuralNode.

type NeuralNodes

type NeuralNodes struct {
	graph.Nodes
}

NeuralNodes is a NeuralNode iterator.

Usage:

for neuralNodes.Next() {
	neuralNode := neuralNodes.NeuralNode()
	// do whatever
}

func (*NeuralNodes) NeuralNode

func (nodes *NeuralNodes) NeuralNode() *NeuralNode

NeuralNode returns the NeuralNode of this iterator.

Usage:

for neuralNodes.Next() {
	neuralNode := neuralNodes.NeuralNode()
	// do whatever
}

func (*NeuralNodes) String

func (nodes *NeuralNodes) String() string

String callback of this NeuralNodes.

func (*NeuralNodes) ToSlice

func (nodes *NeuralNodes) ToSlice() []*NeuralNode

ToSlice of this NeuralNodes.

type NeuralValue

type NeuralValue float64

NeuralValue is the value an axon outputs, which is *about* to be multiplied by the synaptic weight of its axon. Or it may also be considered the input a neural node receives, summing up all those outputs multiplied by their weights. Note that NeuralValue as an input and as an output are two totally different things. In/Out should be distinguishable from each other. NeuralValue as an input can go outside the range of an output which is the domain of our activation function.

func Activation

func Activation(x NeuralValue) (y NeuralValue)

Activation function is that of a node which takes the sum of weighted inputs as its argument, then returns a value a neural node holds(outputs). The function is defined statically here for the efficiency.

func NV

func NV(from float64) (to NeuralValue)

NV is a shorthand for `NeuralValue()`.

  • NV(): NeuralValue from float64.
  • NVU(): NeuralValue from uint8.
  • NVS(): NeuralValue from int8.

Note that `NeuralValue()` may perform slightly faster than `NV()` by like 0.02ns - that at least on my laptop. `NeuralValue()` is a static type cast without any cost whilst `NV()` being a function that runs at runtime.

func NVS

func NVS(from int8) (to NeuralValue)

NVS is a shorthand for `NeuralValueFromInt8()`.

  • NV(): NeuralValue from float64.
  • NVU(): NeuralValue from uint8.
  • NVS(): NeuralValue from int8.

func NVU

func NVU(from uint8) (to NeuralValue)

NVU is a shorthand for `NeuralValueFromUint8()`.

  • NV(): NeuralValue from float64.
  • NVU(): NeuralValue from uint8.
  • NVS(): NeuralValue from int8.

func NeuralValueFromInt8

func NeuralValueFromInt8(from int8) (to NeuralValue)

NeuralValueFromInt8 converts a raw int8 value to a NeuralValue.

Interpreted:

  • int8(-128) <---> int8(+127)
  • NV(-128.0) <---> NV(+128.0)
  • 空; nil; NaN <==> NV(NeuralValueMid) --> NVKindNeutral
  • int8(nil) <==> NV(0.0)
  • int8(NaN) <==> NV(0.0)
  • int8(0) <==> NV(1.0)
  • int8(+127) <==> NV(128.0)
  • int8(-128):MaxNegative:float64(NeuralValueMin) == int8(+127):MaxPositive:float64(NeuralValueMax)

func NeuralValueFromUint8

func NeuralValueFromUint8(from uint8) (to NeuralValue)

NeuralValueFromUint8 converts a raw uint8 value to a NeuralValue.

Interpreted:

  • uint8(0) <---> uint8(255)
  • uint8(255) == uint8(math.MaxUint8)
  • uint8(0) <---> uint8(math.MaxUint8)
  • float64(NeuralValueMin) <---> float64(NeuralValueMax)
  • float64(NeuralValueMin):uint8(0) <---> uint8(math.MaxUint8):float64(NeuralValueMax)
  • float64(NeuralValueMin):MaxNegative:uint8(0) == float64(NeuralValueMax):MaxPositive:uint8(math.MaxUint8)
  • uint8(0):MaxNegative:float64(NeuralValueMin) == uint8(math.MaxUint8):MaxPositive:float64(NeuralValueMax)

func Ramp

func Ramp(x NeuralValue) (y NeuralValue)

Ramp is a kind of rectifier and a pseudo-activation.

func Sigmoid

func Sigmoid(x NeuralValue) (y NeuralValue)

Sigmoid our classic differentiable activation function.

Formula:

y = 256/(1+Exp(-x*1.0)) - 128

func (NeuralValue) Concentration

func (nv NeuralValue) Concentration() (diluteness uint8, err error)

Concentration of this NeuralValue. Inverse operation of `NeuralValueFromUint8()`. The return is a concentration; uint8 diluteness in range [0x0, 0xFF] equal to [0, 255]; what tells whether this neural value is more closer to the positive side or to the negative side. This function also tests the range of this neural value. An error is returned iif the result is overflowed/underflowed.

func (NeuralValue) Float64

func (nv NeuralValue) Float64() float64

Float64 of this NeuralValue. This method is defined for convenience, although it performs a bit slower than the type cast. `(NeuralValue).Float64()` is less performant than the `float64(NeuralValue)` static type cast which almost has the same effect.

func (NeuralValue) IsEvaluated

func (nv NeuralValue) IsEvaluated() bool

IsEvaluated tests if this neural value as an *output* is in its valid range.

Returns:

  • True if the value is within the range, that's a necessary condition for the value to be an output value, thus considered equivalent to that of a neural value filtered out of the activation, while not being a sufficient condition to be an output. So it could be an input or an output but at least not a complete raw input.
  • False if outside the range, or this value is turned out to be NaN; which means that the value is in the initial state of a neural node and is so unevaluated.

func (NeuralValue) Kind

func (nv NeuralValue) Kind() NeuralValueKind

Kind tells the kind of this NeuralValue and also tests if it is in its valid range while doing so.

Returns:

  • NVKindPositive: (NV-Mid, NV-Max]
  • NVKindNegative: [NV-Min, NV-Mid)
  • NVKindNeutral: [NV-Mid, NV-Mid]
  • NVKindExceptional: Outside [NV-Min, NV-Max]

func (NeuralValue) Strength

func (nv NeuralValue) Strength() (strength uint8, err error)

Strength returns a uint8 in range [0x0, 0xFF] equal to [0, 255], which denotes how strong this negative/positive signal is. 0 is returned if this neural value is determined neither negative nor positive kind. An error is returned iif this neural value is not in its range valid. The function panics upon runtime error.

type NeuralValueKind

type NeuralValueKind int

NeuralValueKind enum for Neutral, Negative, and Positive.

type Niche

type Niche int64

Niche is an identifier and a historical marker for species. This is unique for each of species under a NEAT context. And the bigger the number is, the later the Niche is. It basically is considered an integer starting from zero but could be used in other way depending on the context.

func (Niche) String

func (niche Niche) String() string

String callback of Niche.

type NodeGene

type NodeGene struct {
	UUID uuid.UUID // Having this member might help identifying this specific gene.
	Name string    // An optional label; nickname for this.
	Type int       // An index. InputNode, HiddenNode, or OutputNode. There are constants defined for this.
	Idx  int       // Optional. Determines the order of NodeGenes in a chromosome, followed by the Type.
}

NodeGene is not a node what's in the NN. This just encodes information about how a possible instantiated node might look like.

func NewNodeGene

func NewNodeGene(name string, kind int, index int) *NodeGene

NewNodeGene is a constructor.

func (*NodeGene) IsValid

func (nodeGene *NodeGene) IsValid() bool

IsValid validates this NodeGene.

func (*NodeGene) NewNodeGene

func (nodeGene *NodeGene) NewNodeGene() *NodeGene

NewNodeGene is a constructor. What returned is a new identifiable object resembling this object.

func (*NodeGene) SetName

func (nodeGene *NodeGene) SetName(nickname string)

SetName alias for this. Replaces the previous one if it already has its name.

func (*NodeGene) String

func (nodeGene *NodeGene) String() string

String callback of NodeGene.

func (*NodeGene) TypeInInt

func (nodeGene *NodeGene) TypeInInt() int

TypeInInt returns the node type as an int. There are constants defined for this. See def const InputNode, OutputNode, and HiddenNode for NodeGene.

func (*NodeGene) TypeInString

func (nodeGene *NodeGene) TypeInString() string

TypeInString returns the node type as a string.

type Organism

type Organism struct {
	Genotype   *Genome
	Phenotype  []*NeuralNetwork
	Breed      *Species
	Fitness    float64 // private. Do not access this directly without a public method.
	IsMeasured bool    // private. Do not access this directly without a public method.
}

Organism is an individual living thing born to compete with others.

func (*Organism) Copy

func (o *Organism) Copy() (daughter *Organism, err error)

Copy is a constructor. Notice: this method is no use in GA. The returned daughter is a genetic copy of this organism unspeciated, unevaluated, and unmeasured. This does not mutate the organism so you might want to use (*Genome).Copy() instead.

func (*Organism) GenoType

func (o *Organism) GenoType() *Genome

GenoType returns the genotype of this organism. Uppercase T of this function name is to avoid naming conflicts. :P

func (*Organism) GetFitness

func (o *Organism) GetFitness() (fitness float64, err error)

GetFitness is a getter. Returns error when the fitness of this organism is yet measured.

func (*Organism) IsFitnessMeasured

func (o *Organism) IsFitnessMeasured() bool

IsFitnessMeasured returns true iff an organism is already measured, no not for being measured. Returns false when this organism needs its fitness evaluated.

func (*Organism) IsSpeciated

func (o *Organism) IsSpeciated() bool

IsSpeciated of this organism.

func (*Organism) MarshalJSON

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

MarshalJSON of json.Marshaler interface.

func (*Organism) PhenoType

func (o *Organism) PhenoType() []*NeuralNetwork

PhenoType returns the phenotype of this organism. Uppercase T of this function name is to avoid naming conflicts. :P

func (*Organism) Species

func (o *Organism) Species() *Species

Species returns the breed of this organism. Returns nil when this creature is yet classified.

func (*Organism) String

func (o *Organism) String() string

String callback of Organism.

func (*Organism) Unbreed

func (o *Organism) Unbreed()

Unbreed this organism. This method is different from Unspeciate().

  • Unspeciate() **calls** the species the organism is in to dislink(unassociate;unrelate) the two. `o.Species().Unspeciate(o)`
  • Unbreed() is **called** by the species the organism is in to safely access the struct's field. `o.Breed = nil`

This function is a callback. Generally you don't want to use this.

func (*Organism) UnmarshalJSON

func (o *Organism) UnmarshalJSON(jsonOrganismMarshal []byte) (err error)

UnmarshalJSON of json.Unmarshaler interface. The organism is unspeciated.

func (*Organism) Unspeciate

func (o *Organism) Unspeciate() error

Unspeciate this single organism. This method is different from Unbreed().

  • Unspeciate() **calls** the species the organism is in to dislink(unassociate;unrelate) the two. `o.Species().Unspeciate(o)`
  • Unbreed() is **called** by the species the organism is in to safely access the struct's field. `o.Breed = nil`

This function results in calling Unbreed() and so is preferred over the other most of the times. Also this operation may take up to O(N) time searching a given organism. Consider using (*Species).Cull() or (*Universe).RemoveSpecies() instead if you just want a massacre.

func (*Organism) UpdateFitness

func (o *Organism) UpdateFitness(fitness float64)

UpdateFitness is a setter with a positive side effect.

type OrganismMarshal

type OrganismMarshal struct {
	Genotype   *Genome
	Fitness    float64
	IsMeasured bool
}

OrganismMarshal is JSON export of Organism.

type Species

type Species struct {
	ID      Niche       // Identifier of the habitat of this species.
	Livings []*Organism // Creatures of this species.
	// What tracks for the N how long this species has been stagnant.
	// This species has been stagnant over N generations in a row.
	// It's named stagnancy instead of stagnation for it sounding not like an economics vocabulary.
	Stagnancy int
	// We keep track of this so we can evaluate Stagnancy of this Species in each epoch.
	TopFitness float64
}

Species is a classification of living organisms in our simulated world.

func NewSpecies

func NewSpecies(id Niche, livings []*Organism) *Species

NewSpecies is a constructor. Arg livings can be nil to set by default.

func (*Species) AddOrganisms

func (s *Species) AddOrganisms(orgs ...*Organism)

AddOrganisms (organism) in this Species. This updates the organism(s) added as well.

func (*Species) AverageFitness

func (s *Species) AverageFitness() (averageFitness float64, err error)

AverageFitness of this species. This returns an error when it turns out that there is at least one organism with its fitness unevaluated in this species.

func (*Species) Champion

func (s *Species) Champion() *Organism

Champion of this species. Returns nil if there is no organism in this species.

func (*Species) Cull

func (s *Species) Cull(percentage float64) (segregated []*Organism)

Cull off bottom `percentage` percent of organisms. The range of `percentage` is [0, 1]. This function returns all organisms culled off of this zoo.

func (*Species) CullToSinglePopulation

func (s *Species) CullToSinglePopulation() (segregated []*Organism)

CullToSinglePopulation culls off all creatures but the champion of this species. The species must consist of one population at least. Otherwise this function panics.

func (*Species) EvaluateGeneration

func (s *Species) EvaluateGeneration() (stagnancy int, topFitness float64, err error)

EvaluateGeneration checks and updates the stagnancy of this species. This returns the updated stagnancy, and the top fitness of this species evaluated. An error is returned when the fitness of the champion is yet evaluated.

func (*Species) Niche

func (s *Species) Niche() Niche

Niche is a getter returning this species' identifier that could also be considered the habitat of creatures of this species.

func (*Species) OrganismRandom

func (s *Species) OrganismRandom() *Organism

OrganismRandom returns an organism chosen randomly of this species. The return won't and shouldn't be nil.

func (*Species) RandomOrganisms

func (s *Species) RandomOrganisms(n int) (creatures []*Organism)

RandomOrganisms returns N organisms randomly chosen from this species. The given parameter N must be less than or equal to the number of organisms of this species. Otherwise this function returns nil.

func (*Species) Size

func (s *Species) Size() int

Size returns the number of organisms in this species. Population of this species.

func (*Species) Sort

func (s *Species) Sort()

Sort sorts organisms of this species by their fitness, in descending order.

func (*Species) String

func (s *Species) String() string

String callback of Species.

func (*Species) Unspeciate

func (s *Species) Unspeciate(o *Organism) (expelled bool)

Unspeciate kicks out only a single organism of this species. Consider using (*Species).Cull() instead if you want a massacre. This operation takes O(N) time searching a given organism. The return is about whether it was successful or not.

type Subscribed

type Subscribed struct {
	// Measurer receives an NN to be evaluated.
	S Swallow   // Channel assigned to a Measurer.
	O *Organism // The creature being measured by a Measurer.
}

Subscribed of a Measurer.

func NewSubscribed

func NewSubscribed(mailFrom Swallow, mailTo *Organism) *Subscribed

NewSubscribed is a constructor.

func (*Subscribed) String

func (subbed *Subscribed) String() string

String callback of this.

type Swallow

type Swallow <-chan float64

Swallow is a bird that will deliver our fortune. Or it's a channel our organism's fitness is transferred over.

type Universe

type Universe struct {
	// Static info relates to all creations and destructions.
	Config Configuration // Constants.
	// Trivial runtime settings.
	ChStopSign chan chan struct{} // Private used only for the Shutdown().
	IsRunning  bool               // What tells whether this universe is actually running or not.
	MutexRun   sync.Mutex         // Sync tool used only for Experimenter implementations. For IsRunning bool.
	// Interface to talk to other possible modules.
	Agents      map[Measurer]*Subscribed // A set of agents measuring fitnesses of our creatures.
	MutexAgents sync.Mutex               // Sync tool used only for Experimenter implementations.
	// Regarding space we have in this universe.
	Livings      map[*Organism]struct{} // A set of all creatures available in this universe.
	Classes      []*Species             // Biological category of creatures.
	TopFitness   float64                // Of an organism in this universe.
	MutexLivings sync.Mutex             // Sync tool used only for Experimenter implementations.
	MutexClasses sync.Mutex             // Sync tool used only for Experimenter implementations.
	// Regarding time how far we've been through.
	// These can only go forward and there is no way for them to be winded back besides resetting the whole universe.
	// So what's not necessary at all: Any method that would decrement any of these global (innovation/historical) number.
	Generation int // The Nth generation. We could say the age of this universe is N generation old.
	Innovation int // The innovation number, which should be/is global throughout this universe.
	NicheCount int // This is a counter that tells exactly how many of niches have appeared since the creation of this universe. Niche is an identifier historical and unique for each of species in this universe.
	// The ancestor of all creatures born and raised in this universe.
	InputGenes  []*NodeGene
	OutputGenes []*NodeGene
}

Universe is NEAT context in the highest level, which gets you an access to all available training data of a training session. It is strongly recommended not to access any of these members directly outside this package, unless you understand what those really are. Otherwise use this struct's methods and its constructor instead.

func (*Universe) AddOrganism

func (univ *Universe) AddOrganism(o *Organism) (err error)

AddOrganism to this universe. The organism does not get speciated here. The parameter should not be nil and it should be new in this universe.

func (*Universe) AddSpecies

func (univ *Universe) AddSpecies(s *Species) error

AddSpecies to this universe. The parameter should not be nil.

func (*Universe) AdjAvgFitnessesOfSpecies

func (univ *Universe) AdjAvgFitnessesOfSpecies() (sumFitAvgAdj float64, fitAvgsAdj []float64)

AdjAvgFitnessesOfSpecies evaluates adjusted average-fitnesses of all competing species. Adjusted here only means that those values are made non-negative. The order for iSpecies is preserved.

func (*Universe) AdjTopFitnessesOfSpecies

func (univ *Universe) AdjTopFitnessesOfSpecies() (sumFitTopAdj float64, fitTopsAdj []float64)

AdjTopFitnessesOfSpecies evaluates adjusted top-fitnesses of all competing species. Adjusted here only means that those values are made non-negative. The order for iSpecies is preserved.

func (*Universe) AncestorGenes

func (univ *Universe) AncestorGenes() (inputs []*NodeGene, outputs []*NodeGene, err error)

AncestorGenes is a getter returning a copy slice of all ancestral node-genes in this universe. The slices returned are new; newly constructed with the contents that reference to those original objects.

func (*Universe) BiasGenes

func (univ *Universe) BiasGenes() []*NodeGene

BiasGenes returns genes for bias input nodes. This should be thread-safe. The returned slice is newly constructed and, comes with its contents that reference to original objects.

func (*Universe) Breeds

func (univ *Universe) Breeds() []*Species

Breeds is a getter thread-safely returning all species present in this universe. The returned slice is newly constructed and, comes with its contents that reference to original objects.

func (*Universe) ChanceDiff

func (univ *Universe) ChanceDiff(dice1, dice2 *ChanceGene) (
	addNode, addLink, addBias, perturbWeight, nullifyWeight, turnOn, turnOff, bump float64,
)

ChanceDiff returns mutational differences between two die.

func (*Universe) ChanceDiffInPercent

func (univ *Universe) ChanceDiffInPercent(dice1, dice2 *ChanceGene) (
	addNode, addLink, addBias, perturbWeight, nullifyWeight, turnOn, turnOff, bump float64,
)

ChanceDiffInPercent returns mutational differences between two die, normalized to [0, 1].

func (*Universe) Compatible

func (univ *Universe) Compatible(g1 *Genome, g2 *Genome) (isFertile bool, incompatibility float64, err error)

Compatible checks if two genomes are compatible for crossover and in addition returns a measure of how distant two genomes are. Those genome parameters can be given in any order. This is where the compatibility distance gets in in order to speciate different organisms.

The compatibility distance gives a measure of compatibility between two Genomes, by computing a linear combination of 3 characterizing variables of their compatibility. The 3 variables represent: PERCENT DISJOINT GENES, PERCENT EXCESS GENES, and MUTATIONAL DIFFERENCE WITHIN MATCHING GENES. So the formula for compatibility is: `th <= c1*pdg + c2*peg + c3*mdmg`. The 3 coefficients are global system parameters. (NEAT context of Universe here.) For the mutational difference, the weight of a gene can give a rough sense of how much mutation the gene has experienced since it originally appeared.

This function returns an error if given parameters are not valid.

func (*Universe) CrossoverMultipoint

func (univ *Universe) CrossoverMultipoint(o1, o2 *Organism, isAvgNotRnd bool) (offspring *Genome, err error)

CrossoverMultipoint mates two fitness-measured organisms. The return is their new obvious child, with mixed up genes, inheriting all the structural innovation from the dominant(more-fit) of either parents. This allows the topologies to grow incrementally maintaining their minimal structure, helping those evolving structures to find out a better solution whilst keeping themselves as small as possible. This operation alone can interbreed two organisms of different species, as it doesn't care the compatibility distance of them.

- - -

Parameters:

  • `o1`, `o2`: The parents. (can be given in any order)
  • `isAvgNotRnd`: This option determines the mating method either the matching genes are average weighted or are randomly chosen from either of the parents.

Returns:

  • `offspring`: The baby as a genetic encoder.
  • `err`: Not nil if any kind of invalid value was found.

- - -

Multipoint mating methods:

  1. `Rnd`; For every point in each chromosome where each chromosome shares the innovation number, the gene is chosen randomly from either parent. If one parent has an innovation absent in the other, the baby always inherits the innovation from the more fit parent.

  2. `Avg`; Instead of selecting one or the other when the innovation numbers match, this averages the weight at each matching gene.

- - -

func (*Universe) CrossoverSinglepoint

func (univ *Universe) CrossoverSinglepoint(g1, g2 *Genome, isAvgNotRnd bool) (offspring *Genome, err error)

CrossoverSinglepoint mates two organisms. This method does not require the fitnesses to be measured. The return is their new child. A single point is chosen in the smaller chromosome to split and cross with the bigger one. Genes to the left of that point in the smaller chromosome is connected to the other where every single gene is taken from the larger chromosome. This operation alone can interbreed two organisms of different species, as it doesn't care the compatibility distance of the parents.

- - -

Singlepoint mating methods:

  1. `Avg`; The gene at crosspoint is averaged with the matching gene from the larger, iif there is one.
  2. `Rnd`; The gene is randomly chosen from either of the parents' that's not absent.

Parameters:

  • `g1`, `g2`: The parents. (can be given in any order)
  • `isAvgNotRnd`: This option determines the mating method either the crosspoint gene is average weighted or is randomly chosen from either of the parents.

Returns:

  • `offspring`: The baby genome.
  • `err`: Not nil if any kind of invalid value was found.

- - -

func (*Universe) GetInputGenes

func (univ *Universe) GetInputGenes() []*NodeGene

GetInputGenes is a getter. This should be thread-safe. The returned slice is newly constructed and, comes with its contents that reference to original objects.

func (*Universe) GetOutputGenes

func (univ *Universe) GetOutputGenes() []*NodeGene

GetOutputGenes is a getter. This should be thread-safe. The returned slice is newly constructed and, comes with its contents that reference to original objects.

func (*Universe) GetSpeciesOrderedByProminence

func (univ *Universe) GetSpeciesOrderedByProminence() (sortByProminence []*Species, err error)

GetSpeciesOrderedByProminence returns a copy slice of all available classes in this universe. This method is used to tell the champion species of this universe. The returned slice here is in...

  • 1) descending order of the top fitness of each species,
  • 2) ascending order of the stagnancy of each species,
  • 3) descending order of the average fitness of each species,
  • 4) and ascending order of the number that denotes how early the niche of each species has appeared in this universe.

`univ.MutexClasses` is required in order to get this operation guarantee the thread-safety as it accesses `univ.Classes` directly. This function panics if there are one or more organisms have not been measured.

func (*Universe) HasSpecies

func (univ *Universe) HasSpecies(s *Species) bool

HasSpecies in this universe. This takes linear time O(N) searching for a species in a list.

func (*Universe) Info

func (univ *Universe) Info() (
	conf Configuration, topFitness float64,
	population, numSpecies, generation, innovation, nicheCount int,
)

Info peeks this universe's basic status. This should be thread-safe. The return is a nice summarized set of basic informative infomations.

Usage:

_, topFitness, population, numSpecies, generation, innovation, nicheCount := univ.Info()

func (*Universe) IsPumping

func (univ *Universe) IsPumping() bool

IsPumping thread-safely tells if this universe is running or not.

func (*Universe) Measurers

func (univ *Universe) Measurers() (ret map[Measurer]*Subscribed)

Measurers thread-safely returns all registered measurers and their work details we might want to take a look at. The returned map is a copy but its contents are pointers to original objects.

func (*Universe) Mutate

func (univ *Universe) Mutate(g *Genome)

Mutate a genome under this universe's context. To avoid confusion make sure that you don't mutate an existing organism's genome. It is strongly recommended that you get a copy of a genome you want to mutate before this.

func (*Universe) MutateAddBias

func (univ *Universe) MutateAddBias(chrome *Chromosome) error

MutateAddBias creates a link that connects to a bias.

func (*Universe) MutateAddLinkNoBias

func (univ *Universe) MutateAddLinkNoBias(chrome *Chromosome) error

MutateAddLinkNoBias creates a structural innovation between existing non-bias nodes.

func (*Universe) MutateAddNode

func (univ *Universe) MutateAddNode(chrome *Chromosome)

MutateAddNode of a genetic encoder creates a structural innovation. This splits a link resulting in two links and a node. The function will panic if nil parameter is provided. In theory this shouldn't raise any error as long as the Mutate-Add-Link operation works fine.

func (*Universe) MutateBump

func (univ *Universe) MutateBump(chrome *Chromosome)

MutateBump re-enables the oldest disabled gene. This method is only an alias for `(*Chromosome).Bump()`.

Mutations that fiddle around with the enable flag of genes:

  1. Re-enable the oldest disabled gene. (BUMP)
  2. Toggle on or off randomly at a rate.

func (*Universe) MutateDice

func (univ *Universe) MutateDice(chrome *Chromosome)

MutateDice noises all the dynamic chances of a genetic encoder Gaussian distributed. The way this works is similar to the weight mutation.

func (*Universe) MutateEnableOnOff

func (univ *Universe) MutateEnableOnOff(chrome *Chromosome)

MutateEnableOnOff of a genetic encoder mutates(toggles) the link-enable flag of one randomly chosen gene. Toggle genes from enable on to enable off or vice versa.

Mutations that fiddle around with the enable flag of genes:

  1. Re-enable the oldest disabled gene. (BUMP)
  2. Toggle on or off randomly at a rate.

func (*Universe) MutateNullifyWeight

func (univ *Universe) MutateNullifyWeight(chrome *Chromosome)

MutateNullifyWeight gives a chance for synaptic weights to become zero.

func (*Universe) MutatePerturbWeight

func (univ *Universe) MutatePerturbWeight(chrome *Chromosome)

MutatePerturbWeight noises all the weights of a genetic encoder Gaussian distributed.

func (*Universe) NewArk

func (univ *Universe) NewArk() *Ark

NewArk of this universe.

func (*Universe) NewChanceGeneBasic

func (univ *Universe) NewChanceGeneBasic() *ChanceGene

NewChanceGeneBasic is a constructor.

func (*Universe) NewChanceGeneMix

func (univ *Universe) NewChanceGeneMix(vParent1, vParent2 ChanceGene, isAvgNotRnd bool) *ChanceGene

NewChanceGeneMix is a constructor. All parameters are mandatory and should not be nil. This function panics otherwise. The return is the result of a crossover. nil is returned if there is a logical error.

func (*Universe) NewChromosome

func (univ *Universe) NewChromosome(linkGenes []*LinkGene) (*Chromosome, error)

NewChromosome is a constructor.

func (*Universe) NewChromosomeBasic

func (univ *Universe) NewChromosomeBasic() (*Chromosome, error)

NewChromosomeBasic is a constructor.

func (*Universe) NewGenomeBasic

func (univ *Universe) NewGenomeBasic() (g *Genome, err error)

NewGenomeBasic is a constructor.

func (*Universe) NewInnovation

func (univ *Universe) NewInnovation() (innovation *Innovation)

NewInnovation pulls out a new historical marker from this (current) NEAT context. The return is an identifiable innovation number, which is unique in this universe and is considered a component of the LinkGene.

func (*Universe) NewLinkGene

func (univ *Universe) NewLinkGene(from, to *NodeGene, weight float64, enabled bool) *LinkGene

NewLinkGene is a constructor. The link gene comes with a historical marker unique in this universe. (an identifiable innovation number)

func (*Universe) NewLinkGeneFromLinkGene

func (univ *Universe) NewLinkGeneFromLinkGene(vParent LinkGene) (daughter *LinkGene)

NewLinkGeneFromLinkGene is a constructor. The link gene comes with an identifiable innovation number. The rest of its fields are filled up with the parent's.

Parameter:

  • `vParent`: The parent as value.

func (*Universe) NewLinkGeneSimple

func (univ *Universe) NewLinkGeneSimple(from, to *NodeGene, enabled bool) *LinkGene

NewLinkGeneSimple is a constructor. The link gene comes with an identifiable innovation number. A perturbed random weight is assigned to the gene created.

func (*Universe) NewLinkGeneSimpleFromLinkGene

func (univ *Universe) NewLinkGeneSimpleFromLinkGene(vParent LinkGene) (daughter *LinkGene)

NewLinkGeneSimpleFromLinkGene is a constructor. The link gene comes with an identifiable innovation number. A perturbed random weight is assigned to the gene created. The rest of its fields are filled up with the parent's.

Parameter:

  • `vParent`: The parent as value.

func (*Universe) NewNiche

func (univ *Universe) NewNiche() (habitat *Niche)

NewNiche returns an identifiable niche that's unique in this universe. Niche is considered a component of the Species.

func (*Universe) NewNodeGeneBasic

func (univ *Universe) NewNodeGeneBasic() *NodeGene

NewNodeGeneBasic is a constructor. The return is a new unique identifiable hidden node.

func (*Universe) NewOrganismBasic

func (univ *Universe) NewOrganismBasic() (o *Organism, err error)

NewOrganismBasic is a constructor. This returns a basic mutant that's unmeasured and unrelated with any species.

func (*Universe) NewOrganismBrood

func (univ *Universe) NewOrganismBrood(s *Species, nChildren int) (children []*Organism, err error)

NewOrganismBrood returns N new offsprings (re)produced from a designated species, where N is given by the parameter `nChildren` >= 1. The hermaphroditism is strongly avoided unless there is only one creature left in the species. This function can return error for bad genetics issue. Panics upon runtime violation.

func (*Universe) NewSpecies

func (univ *Universe) NewSpecies(livings []*Organism) *Species

NewSpecies is a constructor. This creates a species with its unique identifier.

func (*Universe) NewSpeciesBasic

func (univ *Universe) NewSpeciesBasic() *Species

NewSpeciesBasic is a constructor. This simply creates an empty species with its own niche.

func (*Universe) NodeGenesByUUID

func (univ *Universe) NodeGenesByUUID(fillMe map[uuid.UUID]*NodeGene) (filledOut map[uuid.UUID]*NodeGene)

NodeGenesByUUID returns a map of all node genes available in this Universe. The parameter can be nil.

func (*Universe) NonBiasInputGenes

func (univ *Universe) NonBiasInputGenes() []*NodeGene

NonBiasInputGenes returns genes for non-bias input nodes. This should be thread-safe. The returned slice is newly constructed and, comes with its contents that reference to original objects.

func (*Universe) Organisms

func (univ *Universe) Organisms() []*Organism

Organisms is a getter thread-safely returning all organisms present in this universe. The returned slice is newly constructed and, comes with its contents that reference to original objects.

func (*Universe) PerturbChanceGene

func (univ *Universe) PerturbChanceGene(perturbed *ChanceGene)

PerturbChanceGene perturbs the weight of a dice-gene, in a strength constant and statically defined in this universe.

func (*Universe) PerturbLinkGene

func (univ *Universe) PerturbLinkGene(perturbed *LinkGene)

PerturbLinkGene perturbs the weight of a link-gene, in a strength defined in the dice. Argument dice is allowed to be nil. The other arguments are not.

func (*Universe) RegisterMeasurer

func (univ *Universe) RegisterMeasurer(agent Measurer)

RegisterMeasurer to this universe.

func (*Universe) RemoveClasses

func (univ *Universe) RemoveClasses(indicesSpecies ...int) (
	removed []*Species, segregated [][]*Organism, err error,
)

RemoveClasses of this universe. It means extinction of species. This unspeciates all creatures of those species taking only constant time for each, and returns them (unspeciated) so they can be killed or respeciated or recycled however etc.

func (*Universe) RemoveOrganism

func (univ *Universe) RemoveOrganism(o *Organism) error

RemoveOrganism of this universe. This unspeciates the organism. The time complexity is O(1), except for the case the organism is speciated, for which this operation takes linear time O(N) searching it as an element in a species in order to unspeciate it.

func (*Universe) Run

func (univ *Universe) Run() error

Run this universe. Entry point to our GA. *This* procedure of *this* universe can be run only one at a time. Otherwise it meets the only condition this can error. Give this blocking synchronous function a thread or a goroutine.

func (*Universe) Save

func (univ *Universe) Save(filename string) (err error)

Save this universe to a JSON file.

func (*Universe) Self

func (univ *Universe) Self() *Universe

Self implements the Experimenter interface.

func (*Universe) Shutdown

func (univ *Universe) Shutdown()

Shutdown stops running this universe. This blocks the routine this method is being called upon until the universe stops. Falls through if the universe isn't currently running (at the time this function gets called).

func (*Universe) SortSpecies

func (univ *Universe) SortSpecies() bool

SortSpecies of this universe.

func (*Universe) Speciate

func (univ *Universe) Speciate(o *Organism) (err error)

Speciate an unspeciated organism. This relates both organism and species.

func (*Universe) SpeciesRandom

func (univ *Universe) SpeciesRandom() *Species

SpeciesRandom returns a random species in this universe.

func (*Universe) Status

func (univ *Universe) Status() UniverseStatusGetter

Status implements the Experimenter interface.

func (*Universe) TellSpecies

func (univ *Universe) TellSpecies(o *Organism) (ret *Species, err error)

TellSpecies of an organism without touching it. This returns the closest species of that organism. If it turns out that there are two or more species of the same compatibility distance available in this universe, the return is the more earlier in the list in which species are sorted. This function returns error if the organism's genome is told corrupted.

func (*Universe) UnregisterMeasurer

func (univ *Universe) UnregisterMeasurer(agent Measurer)

UnregisterMeasurer to this universe.

type UniverseStatusGetter

type UniverseStatusGetter interface {
	Info() (
		conf Configuration, topFitness float64,
		population, numSpecies, generation, innovation, nicheCount int,
	)
	Measurers() (ret map[Measurer]*Subscribed)
	Breeds() []*Species
	Organisms() []*Organism
	BiasGenes() []*NodeGene
	NonBiasInputGenes() []*NodeGene
	GetInputGenes() []*NodeGene
	GetOutputGenes() []*NodeGene
}

UniverseStatusGetter exposes a set of thread-safe universe state getters.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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