evolution

package
v0.0.0-...-9aba028 Latest Latest
Warning

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

Go to latest
Published: Sep 21, 2020 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Index

Constants

View Source
const (
	MinAllowableGenerationsToTerminate  = 9
	TopologyRoundRobin                  = "TopologyRoundRobin"
	TopologyKRandom                     = "TopologyKRandom"
	TopologyHallOfFame                  = "TopologyHallOfFame"
	TopologySingleEliminationTournament = "TopologySET"
)
View Source
const (
	FitnessAbsolute                   = "FitnessAbsolute"
	FitnessThresholdedAntagonistRatio = "FitnessThresholdedAntagonistRatio"
	FitnessProtagonistThresholdTally  = "FitnessProtagonistThresholdTally"
	FitnessRatio                      = "FitnessRatio"
	FitnessMonoThresholdedRatio       = "FitnessMonoThresholdedRatio"
	FitnessDualThresholdedRatio       = "FitnessDualThresholdedRatio"

	DivByZeroIgnore           = "Ignore"
	DivByZeroSteadyPenalize   = "SteadyPenalization"
	DivByZeroPenalize         = "Penalize"
	DivByZeroSetSpecValueZero = "SetSpecValueZero"
)
View Source
const (
	IndividualAntagonist  = 0
	IndividualProtagonist = 1
)
View Source
const (
	ParentSelectionTournament           = "ParentSelectionTournament" // ID for Tournament Selection
	ParentSelectionElitism              = "ParentSelectionElitism"    //ID for elitism
	ParentSelectionFitnessProportionate = 2
)
View Source
const (
	MathErrorGeneral = 0
	MathErrorInvalid = 1
)
View Source
const (
	CrossoverSinglePoint = "CrossoverSinglePoint"
	CrossoverFixedPoint  = "CrossoverFixedPoint"
	CrossoverKPoint      = "CrossoverKPoint"
	CrossoverUniform     = "CrossoverUniform"
)
View Source
const (

	// StrategyDeleteNonTerminal will select a non-root non-terminal element from a given tree and delete it by
	// setting it to 0
	StrategyDeleteNonTerminal = "DeleteNonTerminalR"
	// StrategyDeleteMalicious randomly selects any element of a tree (
	// including the root) and convert it to a value of 0 potentially deleting all
	// genetic material if the root is selected
	StrategyDeleteMalicious = "DeleteMaliciousR"
	// StrategyDeleteTerminal will convert a terminal node to 0.
	StrategyDeleteTerminal = "DeleteTerminalR"
	// StrategyMutateNode randomly selects a non-terminal in a tree and changes its value to one of the available
	// nonterminals in the parameter list.
	// If the tree only contains a root that is a terminal it will ignore it.
	StrategyMutateNonTerminal = "MutateNonTerminalR"
	// StrategyMutateTerminal randomly selects a terminal in a tree and changes its value to one of the available
	// terminals in the parameter list.
	// If the tree only contains a root that is a terminal it will ignore it.
	StrategyMutateTerminal = "MutateTerminalR"
	// StrategyReplaceBranch takes a given tree and randomly selects a branch i.
	// e non-terminal and will swap it with a randomly generated tree of variable depth
	StrategyReplaceBranch  = "ReplaceBranchR"
	StrategyReplaceBranchX = "ReplaceBranchXR"
	//StrategyAddRandomSubTree is a generic strategy that adds a randomly generated subtree anywhere on a given tree
	//  If an add strategy encounters a 0 at the root, it will replace the 0.
	StrategyAddRandomSubTree = "AddRandomSubTreeR"
	// StrategyAddToLeaf is similar to AddSubTree,
	// however the SubTree will only be placed on a randomly selected leaf. It will not replace a non-terminal.
	// It can replace a root
	StrategyAddToLeaf  = "AddToLeafR"
	StrategyAddToLeafX = "AddToLeafX"
	// StrategyAddTreeWithMult will add a subTree with a root of multiplication to a given leaf node
	StrategyAddTreeWithMult = "AddTreeWithMult"
	// StrategyAddTreeWithMult will add a subTree with a root of subtract to a given leaf node
	StrategyAddTreeWithSub = "AddTreeWithSub"
	// StrategyAddTreeWithMult will add a subTree with a root of add to a given leaf node
	StrategyAddTreeWithAdd = "AddTreeWithAdd"
	StrategyAddTreeWithDiv = "AddTreeWithDiv"

	// ####################################################### DETERMINISTIC STRATEGIES #############################
	// StrategySkip performs no operations on the given subtree.
	StrategySkip = "SkipD"
	// StrategyFellTree destroys the tree and sets its root to 0 and kills it all.
	StrategyFellTree = "FellTreeD"
	StrategyMultXD   = "MultXD"
	StrategyAddXD    = "AddXD"
	StrategySubXD    = "SubXD"
	StrategyDivXD    = "DivXD"
)
View Source
const (
	SurvivorSelectionFitnessBased = "SurvivorSelectionFitnessBased"
	SurvivorSelectionRandom       = "SurvivorSelectionRandom"
)
View Source
const DeletionTypeMalicious = 1
View Source
const DeletionTypeSafe = 0
View Source
const (
	ProgressCountersEvolutionResult = 7
)

Variables

View Source
var Add = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const0 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const1 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const10 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const100 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const1000 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const10000 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const100000 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const2 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const3 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const4 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const5 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const6 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const7 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const8 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Const9 = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Epoch0 = Epoch{
	// contains filtered or unexported fields
}
View Source
var Epoch1 = Epoch{
	// contains filtered or unexported fields
}
View Source
var EpochNil = Epoch{}
View Source
var EvolutionEngineTest0 = EvolutionEngine{
	Parameters: EvolutionParams{},
}
View Source
var EvolutionEngineTest1 = EvolutionEngine{
	Parameters: EvolutionParams{},
}
View Source
var EvolutionEngineTestNil = EvolutionEngine{}
View Source
var (
	EvolutionaryStrategy = evolutionaryStrategy{}
)
View Source
var GenerationNil = Generation{}
View Source
var GenerationTest0 = Generation{

	GenerationID: "gen0",
	// contains filtered or unexported fields
}
View Source
var GenerationTest1 = Generation{

	GenerationID: "gen0",
	// contains filtered or unexported fields
}

GenerationTest1 1 less protagonist

View Source
var IndividualNilProgNil = Individual{
	Program:              &ProgNil,
	Kind:                 0,
	Id:                   "ANTAGONIST-",
	Age:                  0,
	HasCalculatedFitness: false,
}

IndividualNilProgNil

View Source
var IndividualProg0Kind0 = Individual{
	Program:                  &ProgX,
	Kind:                     0,
	Id:                       "ANTAGONIST-",
	Age:                      0,
	HasCalculatedFitness:     false,
	Strategy:                 []Strategy{StrategyMutateTerminal, StrategyDeleteNonTerminal, StrategyAddRandomSubTree},
	Fitness:                  []float64{},
	FitnessCalculationMethod: FitnessProtagonistThresholdTally,
	HasAppliedStrategy:       false,
}

IndividualProg0-Kind-0

View Source
var IndividualProg0Kind1 = Individual{
	Program:                  &ProgX,
	Kind:                     1,
	Id:                       "PROTAGONIST-",
	Age:                      0,
	HasCalculatedFitness:     false,
	Strategy:                 []Strategy{StrategyMutateTerminal, StrategyDeleteNonTerminal, StrategyAddRandomSubTree},
	Fitness:                  []float64{},
	FitnessCalculationMethod: FitnessProtagonistThresholdTally,
	HasAppliedStrategy:       false,
}

IndividualProg0-Kind-1

View Source
var IndividualProg1Kind1 = Individual{
	Program:                  &Prog1,
	Kind:                     1,
	Id:                       "PROTAGONIST-",
	Age:                      0,
	HasCalculatedFitness:     false,
	Strategy:                 []Strategy{StrategyMutateTerminal, StrategyDeleteNonTerminal, StrategyAddRandomSubTree},
	Fitness:                  []float64{},
	FitnessCalculationMethod: FitnessProtagonistThresholdTally,
	HasAppliedStrategy:       false,
}

IndividualProg1Kind1

View Source
var IndividualProgTreeT_NT_T_0 = Individual{
	Program:                  &ProgTreeT_NT_T_0,
	Kind:                     1,
	Id:                       "PROTAGONIST-",
	Age:                      0,
	HasCalculatedFitness:     false,
	Strategy:                 []Strategy{StrategyMutateTerminal, StrategyDeleteNonTerminal, StrategyAddRandomSubTree},
	Fitness:                  []float64{},
	FitnessCalculationMethod: FitnessProtagonistThresholdTally,
	HasAppliedStrategy:       false,
}

IndividualProgTreeT_NT_T_0

View Source
var IndividualProgTreeT_NT_T_1 = Individual{
	Program:                  &ProgTreeT_NT_T_1,
	Kind:                     1,
	Id:                       "PROTAGONIST-",
	Age:                      0,
	HasCalculatedFitness:     false,
	Strategy:                 []Strategy{StrategyMutateTerminal, StrategyDeleteNonTerminal, StrategyAddRandomSubTree},
	Fitness:                  []float64{},
	FitnessCalculationMethod: FitnessProtagonistThresholdTally,
	HasAppliedStrategy:       false,
}

IndividualProgTreeT_NT_T_4

View Source
var IndividualProgTreeT_NT_T_4 = Individual{
	Program:                  &ProgTreeT_NT_T_4,
	Kind:                     1,
	Id:                       "PROTAGONIST-",
	Age:                      0,
	HasCalculatedFitness:     false,
	Strategy:                 []Strategy{StrategyMutateTerminal, StrategyDeleteNonTerminal, StrategyAddRandomSubTree},
	Fitness:                  []float64{},
	FitnessCalculationMethod: FitnessProtagonistThresholdTally,
	HasAppliedStrategy:       false,
}

IndividualProgTreeT_NT_T_4

View Source
var IndividualProgTreeT_NT_T_NT_T_0 = Individual{
	Program:                  &ProgTreeT_NT_T_NT_T_0,
	Kind:                     1,
	Id:                       "PROTAGONIST-",
	Age:                      0,
	HasCalculatedFitness:     false,
	Strategy:                 []Strategy{StrategyMutateTerminal, StrategyDeleteNonTerminal, StrategyAddRandomSubTree},
	Fitness:                  []float64{},
	FitnessCalculationMethod: FitnessProtagonistThresholdTally,
	HasAppliedStrategy:       false,
}

IndividualProgTreeT_NT_T_NT_T_0

View Source
var IndividualProgTreeT_NT_T_NT_T_NT_T_0 = Individual{
	Program:                  &ProgTreeT_NT_T_NT_T_NT_T_0,
	Kind:                     1,
	Id:                       "PROTAGONIST-",
	Age:                      0,
	HasCalculatedFitness:     false,
	Strategy:                 []Strategy{StrategyMutateTerminal, StrategyDeleteNonTerminal, StrategyAddRandomSubTree},
	Fitness:                  []float64{},
	FitnessCalculationMethod: FitnessProtagonistThresholdTally,
	HasAppliedStrategy:       false,
}

IndividualProgTreeT_NT_T_NT_T_NT_T_0

View Source
var IndividualProgTreeT_NT_T_NT_T_NT_T_NT_T_1 = Individual{
	Program:                  &ProgTreeXXXX4,
	Kind:                     1,
	Id:                       "PROTAGONIST-",
	Age:                      0,
	HasCalculatedFitness:     false,
	Strategy:                 []Strategy{StrategyMutateTerminal, StrategyDeleteNonTerminal, StrategyAddRandomSubTree},
	Fitness:                  []float64{},
	FitnessCalculationMethod: FitnessProtagonistThresholdTally,
	HasAppliedStrategy:       false,
}

IndividualProgTreeT_NT_T_NT_T_NT_T_NT_T_1

View Source
var IndividualProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0Kind0 = Individual{
	Program:                  &ProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0,
	Kind:                     0,
	Id:                       "ANTAGONIST-",
	Age:                      0,
	HasCalculatedFitness:     false,
	Strategy:                 []Strategy{StrategyMutateTerminal, StrategyDeleteNonTerminal, StrategyAddRandomSubTree},
	Fitness:                  []float64{},
	FitnessCalculationMethod: FitnessProtagonistThresholdTally,
	HasAppliedStrategy:       false,
}

IndividualProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0Kind0-Kind-1

View Source
var IndividualProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0Kind1 = Individual{
	Program:                  &ProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0,
	Kind:                     1,
	Id:                       "PROTAGONIST-",
	Age:                      0,
	HasCalculatedFitness:     false,
	Strategy:                 []Strategy{StrategyMutateTerminal, StrategyDeleteNonTerminal, StrategyAddRandomSubTree},
	Fitness:                  []float64{},
	FitnessCalculationMethod: FitnessProtagonistThresholdTally,
	HasAppliedStrategy:       false,
}

IndividualProg0-Kind-1

View Source
var Mult = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Prog1 = Program{
	T:  TreeT_1(),
	ID: "Prog1",
}

Prog1-TreeT_1

View Source
var ProgBadTree = Program{
	T:  TreeBad(),
	ID: "BadTree",
}
View Source
var ProgNil = Program{
	T:  TreeNil(),
	ID: "ProgNil",
}

ProgNil-TreeNil

View Source
var ProgTreeT_NT_T_0 = Program{
	T:  TreeT_NT_T_0(),
	ID: "ProgTreeT_NT_T_0",
}

ProgTreeT_NT_T_0 | x*4

View Source
var ProgTreeT_NT_T_1 = Program{
	T:  TreeT_NT_T_1(),
	ID: "ProgTreeT_NT_T_0",
}

ProgTreeT_NT_T_0 + x+8

View Source
var ProgTreeT_NT_T_4 = Program{
	T:  TreeT_NT_T_4(),
	ID: "ProgTreeT_NT_T_4",
}

ProgTreeT_NT_T_4 = x * x

View Source
var ProgTreeT_NT_T_NT_T_0 = Program{
	T:  TreeT_NT_T_NT_T_0(),
	ID: "ProgTreeT_NT_T_NT_T_0",
}

ProgTreeT_NT_T_NT_T_0 | x - x * 4

View Source
var ProgTreeT_NT_T_NT_T_NT_T_0 = Program{
	T:  TreeT_NT_T_NT_T_NT_T_0(),
	ID: "ProgTreeT_NT_T_NT_T_NT_T_0",
}

ProgTreeT_NT_T_NT_T_NT_T_0 | 4 - 0 + 4 + 8

View Source
var ProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_0 = Program{
	T:  TreeT_NT_T_NT_T_NT_T_NT_T_NT_T_0(),
	ID: "ProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_0",
}

ProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_0

View Source
var ProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0 = Program{
	T:  TreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0(),
	ID: "ProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0",
}

ProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0

View Source
var ProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0 = Program{
	T:  TreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0(),
	ID: "ProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0",
}

ProgTreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0

View Source
var ProgTreeXXXX4 = Program{
	T:  TreeT_NT_T_NT_T_NT_T_NT_T_1(),
	ID: "ProgTreeXXXX4",
}

ProgTreeXXXX4 = x * x * x * x + 4

View Source
var ProgTreeXby5 = Program{
	T:  TreeXby5(),
	ID: "TreeXby5",
}

ProgTreeT_NT_T_0 | x*5

View Source
var ProgX = Program{
	T:  TreeT_X(),
	ID: "ProgX",
}

ProgX-TreeNil

View Source
var ProgXXXX = Program{
	T:  TreeXXXX(),
	ID: "ProgTreeT_NT_T_NT_T_NT_T_2",
}

ProgXXXX = x * x * x * x

View Source
var Sin = SymbolicExpression{/* contains filtered or unexported fields */}
View Source
var Spec0 = SpecMulti{
	EquationPairing{Independents: IndependentVariableMap{"x": 0}, Dependent: 0},
	EquationPairing{Independents: IndependentVariableMap{"x": 1}, Dependent: 0},
	EquationPairing{Independents: IndependentVariableMap{"x": 2}, Dependent: 0},
	EquationPairing{Independents: IndependentVariableMap{"x": 3}, Dependent: 0},
	EquationPairing{Independents: IndependentVariableMap{"x": 4}, Dependent: 0},
}

Spec0 x * 0 = y

View Source
var Sub = SymbolicExpression{/* contains filtered or unexported fields */}

NON-TERMINALS

View Source
var Tree3 = func() *DualTree {
	t := DualTree{}
	t.root = Sin.ToDualTreeNode(RandString(5))
	t.root.left = Sub.ToDualTreeNode(RandString(5))
	t.root.left.left = X1.ToDualTreeNode(RandString(5))
	t.root.left.right = Const4.ToDualTreeNode(RandString(5))
	return &t
}

Tree3 = Sin(4 - x)

View Source
var Tree4 = func() *DualTree {
	t := DualTree{}
	t.root = Sin.ToDualTreeNode(RandString(5))
	t.root.left = X1.ToDualTreeNode(RandString(5))
	return &t
}

Tree4 = Sin(x)

View Source
var Tree5 = func() *DualTree {
	t := DualTree{}
	t.root = Sin.ToDualTreeNode(RandString(5))
	return &t
}

Tree5 = Sin

View Source
var Tree6 = func() *DualTree {
	t := DualTree{}
	t.root = Add.ToDualTreeNode(RandString(5))
	t.root.left = X1.ToDualTreeNode(RandString(5))
	return &t
}

Tree6 = x +

View Source
var Tree7 = func() *DualTree {
	t := DualTree{}
	t.root = Add.ToDualTreeNode(RandString(5))
	return &t
}

Tree7 = +

View Source
var Tree8 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.left = X1.ToDualTreeNode(RandString(5))
	t.root.right = X1.ToDualTreeNode(RandString(5))
	return &t
}

Tree8 = x * x

View Source
var TreeBad = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	return &t
}
View Source
var TreeNil = func() *DualTree {
	t := DualTree{}
	return &t
}

TreeNil = 0

View Source
var TreeT_1 = func() *DualTree {
	t := DualTree{}
	t.root = Const0.ToDualTreeNode("0")
	return &t
}

TreeT_1 = 0

View Source
var TreeT_10 = func() *DualTree {
	t := DualTree{}
	t.root = Const10.ToDualTreeNode("0")
	return &t
}
View Source
var TreeT_100 = func() *DualTree {
	t := DualTree{}
	t.root = Const100.ToDualTreeNode("0")
	return &t
}
View Source
var TreeT_1000 = func() *DualTree {
	t := DualTree{}
	t.root = Const1000.ToDualTreeNode("0")
	return &t
}
View Source
var TreeT_10000 = func() *DualTree {
	t := DualTree{}
	t.root = Const10000.ToDualTreeNode("0")
	return &t
}
View Source
var TreeT_NT_T_0 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode("1")
	t.root.left = X1.ToDualTreeNode("2")
	t.root.right = Const4.ToDualTreeNode("3")
	return &t
}

TreeT_NT_T_0 = x * 4

View Source
var TreeT_NT_T_1 = func() *DualTree {
	t := DualTree{}
	t.root = Add.ToDualTreeNode("1234")
	t.root.left = X1.ToDualTreeNode("12345")
	t.root.right = Const8.ToDualTreeNode("456")
	return &t
}

TreeT_NT_T_1 = x + 8

View Source
var TreeT_NT_T_2 = func() *DualTree {
	t := DualTree{}
	t.root = Sub.ToDualTreeNode(RandString(5))
	t.root.left = Const4.ToDualTreeNode(RandString(5))
	t.root.right = Const8.ToDualTreeNode(RandString(5))
	return &t
}

TreeT_NT_T_2 = 4 - 8

View Source
var TreeT_NT_T_3 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.left = Const8.ToDualTreeNode(RandString(5))
	t.root.right = Const8.ToDualTreeNode(RandString(5))
	return &t
}

TreeT_NT_T_3 = 8 * 8

View Source
var TreeT_NT_T_4 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.left = X1.ToDualTreeNode(RandString(5))
	t.root.right = X1.ToDualTreeNode(RandString(5))
	return &t
}

TreeT_NT_T_4 = x * x

View Source
var TreeT_NT_T_5 = func() *DualTree {
	t := DualTree{}
	t.root = Sub.ToDualTreeNode("2")
	t.root.left = X1.ToDualTreeNode("3")
	t.root.right = X1.ToDualTreeNode("4")
	return &t
}

TreeT_NT_T_5 = x - x

View Source
var TreeT_NT_T_NT_T_0 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode("0")
	t.root.right = Const4.ToDualTreeNode("1")
	t.root.left = Sub.ToDualTreeNode("2")
	t.root.left.left = X1.ToDualTreeNode("3")
	t.root.left.right = X1.ToDualTreeNode("4")
	return &t
}

TreeT_NT_T_NT_T_0 = x - x * 4

View Source
var TreeT_NT_T_NT_T_1 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.right = Const4.ToDualTreeNode(RandString(5))
	t.root.left = Add.ToDualTreeNode(RandString(5))
	t.root.left.left = X1.ToDualTreeNode(RandString(5))
	t.root.left.right = Const8.ToDualTreeNode(RandString(5))
	return &t
}

TreeT_NT_T_NT_T_1 = x + 8 * 4

View Source
var TreeT_NT_T_NT_T_2 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.right = Const4.ToDualTreeNode(RandString(5))
	t.root.left = Sub.ToDualTreeNode(RandString(5))
	t.root.left.left = X1.ToDualTreeNode(RandString(5))
	t.root.left.right = Const0.ToDualTreeNode(RandString(5))
	return &t
}

TreeT_NT_T_NT_T_2 = x - 0 * 4

View Source
var TreeT_NT_T_NT_T_3 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode("0")
	t.root.right = Const0.ToDualTreeNode("2")
	t.root.left = Sub.ToDualTreeNode("1")
	t.root.left.left = X1.ToDualTreeNode("ll")
	t.root.left.right = Const0.ToDualTreeNode("32")
	return &t
}

TreeT_NT_T_NT_T_3 = x - 0 * 0

View Source
var TreeT_NT_T_NT_T_4 = func() *DualTree {
	t := DualTree{}
	t.root = Add.ToDualTreeNode(RandString(5))
	t.root.right = Const0.ToDualTreeNode(RandString(5))
	t.root.left = Sub.ToDualTreeNode(RandString(5))
	t.root.left.left = Const4.ToDualTreeNode(RandString(5))
	t.root.left.right = Const0.ToDualTreeNode(RandString(5))
	return &t
}

TreeT_NT_T_NT_T_4 = 4 - 0 + 0

View Source
var TreeT_NT_T_NT_T_NT_T_0 = func() *DualTree {
	t := DualTree{}
	t.root = Add.ToDualTreeNode(RandString(5))
	t.root.right = Add.ToDualTreeNode(RandString(5))
	t.root.right.left = Const4.ToDualTreeNode(RandString(5))
	t.root.right.right = Const8.ToDualTreeNode(RandString(5))

	t.root.left = Sub.ToDualTreeNode(RandString(5))
	t.root.left.left = Const4.ToDualTreeNode(RandString(5))
	t.root.left.right = Const0.ToDualTreeNode(RandString(5))
	return &t
}

TreeT_NT_T_NT_T_NT_T_0 = 4 - 0 + 4 + 8

View Source
var TreeT_NT_T_NT_T_NT_T_1 = func() *DualTree {
	t := DualTree{}
	t.root = Add.ToDualTreeNode(RandString(5))
	t.root.right = Add.ToDualTreeNode(RandString(5))
	t.root.right.left = Const4.ToDualTreeNode(RandString(5))
	t.root.right.right = Const8.ToDualTreeNode(RandString(5))

	t.root.left = Mult.ToDualTreeNode(RandString(5))
	t.root.left.left = X1.ToDualTreeNode(RandString(5))
	t.root.left.right = X1.ToDualTreeNode(RandString(5))
	return &t
}

TreeT_NT_T_NT_T_NT_T_1 = x * x + 4 + 8

View Source
var TreeT_NT_T_NT_T_NT_T_NT_T_0 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.right = Mult.ToDualTreeNode(RandString(5))
	t.root.right.left = X1.ToDualTreeNode(RandString(5))
	t.root.right.right = X1.ToDualTreeNode(RandString(5))

	t.root.left = Mult.ToDualTreeNode(RandString(5))
	t.root.left.right = X1.ToDualTreeNode(RandString(5))

	t.root.left.left = Mult.ToDualTreeNode(RandString(5))
	t.root.left.left.left = X1.ToDualTreeNode(RandString(5))
	t.root.left.left.right = X1.ToDualTreeNode(RandString(5))
	return &t
}

TreeT_NT_T_NT_T_NT_T_0 = x * x * x * x * x

View Source
var TreeT_NT_T_NT_T_NT_T_NT_T_1 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.right = Add.ToDualTreeNode(RandString(5))
	t.root.right.left = X1.ToDualTreeNode(RandString(5))
	t.root.right.right = Const4.ToDualTreeNode(RandString(5))

	t.root.left = Mult.ToDualTreeNode(RandString(5))
	t.root.left.right = X1.ToDualTreeNode(RandString(5))

	t.root.left.left = Mult.ToDualTreeNode(RandString(5))
	t.root.left.left.left = X1.ToDualTreeNode(RandString(5))
	t.root.left.left.right = X1.ToDualTreeNode(RandString(5))
	return &t
}

TreeT_NT_T_NT_T_NT_T_NT_T_1 = x * x * x * x + 4

View Source
var TreeT_NT_T_NT_T_NT_T_NT_T_NT_T_0 = func() *DualTree {
	t := DualTree{}
	t.root = Add.ToDualTreeNode(RandString(5))

	t.root.left = Add.ToDualTreeNode(RandString(5))
	t.root.left.left = Add.ToDualTreeNode(RandString(5))
	t.root.left.left.left = Const0.ToDualTreeNode(RandString(5))
	t.root.left.left.right = Const1.ToDualTreeNode(RandString(5))

	t.root.left.right = Add.ToDualTreeNode(RandString(5))
	t.root.left.right.left = Const2.ToDualTreeNode(RandString(5))
	t.root.left.right.right = Const3.ToDualTreeNode(RandString(5))

	t.root.right = Add.ToDualTreeNode(RandString(5))
	t.root.right.left = Const4.ToDualTreeNode(RandString(5))
	t.root.right.right = Const5.ToDualTreeNode(RandString(5))

	return &t
}

TreeT_NT_T_NT_T_NT_T_NT_T_NT_T_0 = 0 + 1 + 2 + 3 + 4 + 5

View Source
var TreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0 = func() *DualTree {
	t := DualTree{}
	t.root = Add.ToDualTreeNode(RandString(5))

	t.root.left = Add.ToDualTreeNode(RandString(5))
	t.root.left.left = Add.ToDualTreeNode(RandString(5))
	t.root.left.left.left = Const0.ToDualTreeNode(RandString(5))
	t.root.left.left.right = Const1.ToDualTreeNode(RandString(5))

	t.root.left.right = Add.ToDualTreeNode(RandString(5))
	t.root.left.right.left = Const2.ToDualTreeNode(RandString(5))
	t.root.left.right.right = Const3.ToDualTreeNode(RandString(5))

	t.root.right = Add.ToDualTreeNode(RandString(5))
	t.root.right.right = Const6.ToDualTreeNode(RandString(5))

	t.root.right.left = Add.ToDualTreeNode(RandString(5))
	t.root.right.left.left = Const4.ToDualTreeNode(RandString(5))
	t.root.right.left.right = Const5.ToDualTreeNode(RandString(5))
	return &t
}

TreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0 = 0 + 1 + 2 + 3 + 4 + 5 + 6

View Source
var TreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0 = func() *DualTree {
	t := DualTree{}
	t.root = Add.ToDualTreeNode(RandString(5))

	t.root.left = Add.ToDualTreeNode(RandString(5))
	t.root.left.left = Add.ToDualTreeNode(RandString(5))
	t.root.left.left.left = Const0.ToDualTreeNode(RandString(5))
	t.root.left.left.right = Const1.ToDualTreeNode(RandString(5))

	t.root.left.right = Add.ToDualTreeNode(RandString(5))
	t.root.left.right.left = Const2.ToDualTreeNode(RandString(5))
	t.root.left.right.right = Const3.ToDualTreeNode(RandString(5))

	t.root.right = Add.ToDualTreeNode(RandString(5))
	t.root.right.right = Add.ToDualTreeNode(RandString(5))
	t.root.right.right.left = Const6.ToDualTreeNode(RandString(5))
	t.root.right.right.right = Const7.ToDualTreeNode(RandString(5))

	t.root.right.left = Add.ToDualTreeNode(RandString(5))
	t.root.right.left.left = Const4.ToDualTreeNode(RandString(5))
	t.root.right.left.right = Const5.ToDualTreeNode(RandString(5))
	return &t
}

TreeT_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_NT_T_0 = 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7

View Source
var TreeT_X = func() *DualTree {
	t := DualTree{}
	t.root = X1.ToDualTreeNode("0")
	return &t
}

TreeT_X = x

View Source
var TreeVine_D3 = func() *DualTree {
	t := DualTree{}
	t.root = Sin.ToDualTreeNode(RandString(5))
	t.root.left = Sin.ToDualTreeNode(RandString(5))
	t.root.left.left = Sin.ToDualTreeNode(RandString(5))
	t.root.left.left.left = X1.ToDualTreeNode(RandString(5))
	return &t
}

TreeVine_D3 = sin(sin(sin(x)))

View Source
var TreeVine_D4 = func() *DualTree {
	t := DualTree{}
	t.root = Sin.ToDualTreeNode(RandString(5))
	t.root.left = Sin.ToDualTreeNode(RandString(5))
	t.root.left.left = Sin.ToDualTreeNode(RandString(5))
	t.root.left.left.left = Sin.ToDualTreeNode(RandString(5))
	t.root.left.left.left.left = X1.ToDualTreeNode(RandString(5))
	return &t
}

TreeVine_D4 = sin(sin(sin(sin(x)))))

View Source
var TreeVine_D5_R = func() *DualTree {
	t := DualTree{}
	t.root = Add.ToDualTreeNode(RandString(5))
	t.root.left = Sin.ToDualTreeNode(RandString(5))
	t.root.left.left = Sin.ToDualTreeNode(RandString(5))
	t.root.left.left.left = Sin.ToDualTreeNode(RandString(5))
	t.root.left.left.left.left = X1.ToDualTreeNode(RandString(5))

	t.root.right = Sin.ToDualTreeNode(RandString(5))
	t.root.right.right = Sin.ToDualTreeNode(RandString(5))
	t.root.right.right.right = Sin.ToDualTreeNode(RandString(5))
	t.root.right.right.right.right = Sin.ToDualTreeNode(RandString(5))
	t.root.right.right.right.right.right = X1.ToDualTreeNode(RandString(5))
	return &t
}

TreeVine_D5_R = It looks like triangle with depth 5 on the right side.

View Source
var TreeVine_D6_R = func() *DualTree {
	t := DualTree{}
	t.root = Add.ToDualTreeNode("0")
	t.root.left = Sin.ToDualTreeNode("1")
	t.root.left.left = Sin.ToDualTreeNode("2")
	t.root.left.left.left = Sin.ToDualTreeNode("3")
	t.root.left.left.left.left = X1.ToDualTreeNode("4")

	t.root.right = Sin.ToDualTreeNode("5")
	t.root.right.right = Sin.ToDualTreeNode("6")
	t.root.right.right.right = Sin.ToDualTreeNode("7")
	t.root.right.right.right.right = Sin.ToDualTreeNode("8")
	t.root.right.right.right.right.right = Sin.ToDualTreeNode("9")
	t.root.right.right.right.right.right.left = X1.ToDualTreeNode("10")
	return &t
}

TreeVine_D5_R = It looks like triangle with depth 6 on the right side.

View Source
var TreeXAddXMult4Sub9Mult0 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode("0")
	t.root.right = Const0.ToDualTreeNode("1")
	t.root.left = Sub.ToDualTreeNode("2")
	t.root.left.right = Const9.ToDualTreeNode("4")
	t.root.left.left = Add.ToDualTreeNode("43")
	t.root.left.left.left = X1.ToDualTreeNode("3f3")
	t.root.left.left.right = Mult.ToDualTreeNode("4sd3")
	t.root.left.left.right.left = X1.ToDualTreeNode("4fd3")
	t.root.left.left.right.right = Const4.ToDualTreeNode("4x3")
	return &t
}

TreeT_NT_T_NT_T_0 = (((x + (x * 4)) - 9) * 0)

View Source
var TreeXXXX = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.right = Mult.ToDualTreeNode(RandString(5))
	t.root.right.left = X1.ToDualTreeNode(RandString(5))
	t.root.right.right = X1.ToDualTreeNode(RandString(5))

	t.root.left = Mult.ToDualTreeNode(RandString(5))
	t.root.left.left = X1.ToDualTreeNode(RandString(5))
	t.root.left.right = X1.ToDualTreeNode(RandString(5))
	return &t
}

TreeXXXX = x * x * x * x

View Source
var TreeXby5 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode("1fas")
	t.root.left = X1.ToDualTreeNode("2ds")
	t.root.right = Const5.ToDualTreeNode("3dd")
	return &t
}

TreeXby5 = x * 5

View Source
var Tree_100000XXX = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.left = Mult.ToDualTreeNode(RandString(5))
	t.root.left.left = Const100000.ToDualTreeNode(RandString(5))
	t.root.left.right = X1.ToDualTreeNode(RandString(5))
	t.root.right = Mult.ToDualTreeNode(RandString(5))
	t.root.right.left = X1.ToDualTreeNode(RandString(5))
	t.root.right.right = X1.ToDualTreeNode(RandString(5))
	return &t
}
View Source
var Tree_X10 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.left = X1.ToDualTreeNode(RandString(5))
	t.root.right = Const10.ToDualTreeNode(RandString(5))
	return &t
}
View Source
var Tree_X100 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.left = X1.ToDualTreeNode(RandString(5))
	t.root.right = Const100.ToDualTreeNode(RandString(5))
	return &t
}
View Source
var Tree_X1000 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.left = X1.ToDualTreeNode(RandString(5))
	t.root.right = Const1000.ToDualTreeNode(RandString(5))
	return &t
}
View Source
var Tree_X10000 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.left = X1.ToDualTreeNode(RandString(5))
	t.root.right = Const10000.ToDualTreeNode(RandString(5))
	return &t
}
View Source
var Tree_X100000 = func() *DualTree {
	t := DualTree{}
	t.root = Mult.ToDualTreeNode(RandString(5))
	t.root.left = X1.ToDualTreeNode(RandString(5))
	t.root.right = Const100000.ToDualTreeNode(RandString(5))
	return &t
}
View Source
var X1 = SymbolicExpression{/* contains filtered or unexported fields */}

TERMINALS

Functions

func AggregateFitness

func AggregateFitness(individual Individual) (float64, error)

AggregateFitness simply adds all the Fitness values of a given individual to come up with a total number. If the Fitness array is nil or empty return MaxInt8 as values such as -1 or 0 have a differnt meaning

func AntagonistFitnessResolver

func AntagonistFitnessResolver(perfectTreeMap map[string]PerfectTree, antagonist *Individual,
	antagonistFitness float64, antagonistFitnessDelta float64)

func CalculateAverage

func CalculateAverage(items []float64) (float64, error)

CalculateAverage averages the fitness values for each individual

func CalculateAverageFitnessAverage

func CalculateAverageFitnessAverage(individuals []*Individual) (float64, error)

CalculateAverageFitnessAverage averages the fitness values for each individual

func CalculateCumulative

func CalculateCumulative(individuals []*Individual) (float64, error)

CalculateCumulative accumulates all the averaged fitness values each individual has.

func CalculateGenerationSize

func CalculateGenerationSize(params EvolutionParams) int

func CoalesceFitnessStatistics

func CoalesceFitnessStatistics(individual *Individual) (fitnessToBeAppendedToGenerationAvgFitness float64)

func ConvertStrategiesToString

func ConvertStrategiesToString(strategies []Strategy) (stringStrategies []string)

func CreateEpochID

func CreateEpochID(count int, generationId, antagonistId, protagonistId string) string

CreateEpochID generates a given epoch Id with some useful information

func DominantStrategy

func DominantStrategy(individual Individual) string

func DominantStrategyStr

func DominantStrategyStr(str string) string

func EvaluateMathematicalExpression

func EvaluateMathematicalExpression(expressionString string, independentVariables IndependentVariableMap) (float64,
	error)

EvaluateMathematicalExpression evaluates a valid expression using the given independentVar

func FitnessResolver

func FitnessResolver(perfectTreeMap map[string]PerfectTree, antagonist, protagonist *Individual,
	antagonistFitness float64, antagonistFitnessDelta float64, protagonistFitness float64, protagonistFitnessDelta float64)

func FixedPointCrossover

func FixedPointCrossover(individual Individual, individual2 Individual, params EvolutionParams) (Individual, Individual,
	error)

FixedPointCrossover will perform crossover on the strategies of a given set of individuals

func FormatStrategiesList

func FormatStrategiesList(strategies []Strategy) strings.Builder

func FormatStrategiesTotal

func FormatStrategiesTotal(strategies []Strategy) strings.Builder

func GenerateGenerationID

func GenerateGenerationID(count int, topology string) string

func GenerateIndividualID

func GenerateIndividualID(identifier string, individualKind int) string

func GenerateProgramID

func GenerateProgramID(count int) string

func GetMaxFitnessAndDelta

func GetMaxFitnessAndDelta(individual *Individual) (maxFit float64, maxDelta float64)

func GetTopIndividualInRun

func GetTopIndividualInRun(sortedGenerations []*Generation, isMoreFitnessBetter bool) (topAntagonist *Individual, topProtagonist *Individual, err error)

GetTopIndividualInRun returns the best protagonist and antagonist in the entire evolutionary process

func KPointCrossover

func KPointCrossover(parentA, parentB *Individual, kPoint int) (childA Individual, childB Individual, err error)

CrossoverSinglePoint performs a single-point crossover that is dictated by the crossover percentage float. Both parent chromosomes are split at the percentage section specified by crossoverPercentage

func KindToString

func KindToString(kind int) string

KindToString checks the Kind and returns the appropriate string representation

func MathPreorder

func MathPreorder(node *DualTreeNode, sb *strings.Builder)

func Mutate

func Mutate(outgoingParents []*Individual, children []*Individual, kind int,
	opts EvolutionParams) (parents []*Individual, childs []*Individual, err error)

func ProtagonistFitnessResolver

func ProtagonistFitnessResolver(perfectTreeMap map[string]PerfectTree, protagonist *Individual, protagonistFitness float64, protagonistFitnessDelta float64)

func RMSE

func RMSE(forecast, observed []float64) float64

RMSE (Root Mean Squared Error) Root Mean Square Error (RMSE) is the standard deviation of the residuals (prediction errors). Residuals are a measure of how far from the regression line data points are; RMSE is a measure of how spread out these residuals are. In other words, it tells you how concentrated the data is around the line of best fit. Root mean square error is commonly used in climatology, forecasting, and regression analysis to verify experimental results.

func RandString

func RandString(n int) string

func SinglePointCrossover

func SinglePointCrossover(parentA, parentB *Individual) (childA Individual,
	childB Individual,
	err error)

CrossoverSinglePoint performs a single-point crossover that is dictated by the crossover percentage float. Both parent chromosomes are split at the percentage section specified by crossoverPercentage

func StrategiesToString

func StrategiesToString(individual Individual) string

func StrategiesToStringArr

func StrategiesToStringArr(strategies []string) string

func StrategySwapper

func StrategySwapper(a []Strategy, b []Strategy, swapLength int, startIndex int) ([]Strategy, []Strategy)

StrategySwapper takes two slices containing variable length strategies. The swapLength must be smaller than the length of the largest, but less than the length of the smallest. A swap length of 0 will return the same arrays a and b untouched.

func StrategySwapperIgnorant

func StrategySwapperIgnorant(a []Strategy, b []Strategy, swapLength int, startIndex int) ([]Strategy, []Strategy)

StrategySwapperIgnorant will perform crossover regardless of size

func ThresholdedRatioFitness

func ThresholdedRatioFitness(spec SpecMulti, antagonist, protagonist *Program,
	divByZeroStrategy string) (antagonistFitness float64,
	protagonistFitness, antagonistFitnessDelta, protagonistFitnessDelta float64, err error)

ThresholdedRatioFitness is a means to calculate fitness that spurs the protagonists and antagonists to do their best. It works by applying a threshold criteria that is based on the incoming spec. A mono threshold is applied by setting the protagonist and antagonist threshold values to the same value, this is done automatically when you select the fitness strategy at the start of the evolutionary process. Both individuals have to fall on their respective side and either edge closer to delta-0 for the protagonist or delta-infitinite for the antagonist. If they happen to fall on opposite sides they attain at most -1 A dual threshold is used to punish both antagonist of protagonist for not performing as expected. // This fitness strategy works by comparing the average delta values of both protagonist and antagonist with a // specified threshold. Their deltas are not compared against each other as with other fitness strategies, // the thresholds act as markers of performance for each. // The porotagonist and antagonist each have their own threshold values that are embeded in the SpecMulti data // structure. Note this only compares the average and not the total deltas

func TruncShort

func TruncShort(s []Strategy) string

func UniformCrossover

func UniformCrossover(parentA, parentB *Individual) (childA Individual,
	childB Individual,
	err error)

CrossoverSinglePoint performs a single-point crossover that is dictated by the crossover percentage float. Both parent chromosomes are split at the percentage section specified by crossoverPercentage

func WriteGenerationToLog

func WriteGenerationToLog(e *EvolutionEngine, i int, elapsed time.Duration)

func WriteToDataFolder

func WriteToDataFolder(dataFolderPath string, fileName string, fileValue string, logChan chan evolog.Logger,
	errChan chan error)

func WriteToDataFolders

func WriteToDataFolders(folderPercentages []float64, currentGeneration, generationTotalSize int,
	params EvolutionParams)

Types

type Antagonist

type Antagonist Individual

type AvailableSymbolicExpressions

type AvailableSymbolicExpressions struct {
	//Constants []SymbolicExpression
	NonTerminals []SymbolicExpression
	Terminals    []SymbolicExpression
}

type AvailableVariablesAndOperators

type AvailableVariablesAndOperators struct {
	Constants []string `json:"constants"`
	Variables []string `json:"variables"`
	Operators []string `json:"operators"`
}

type AwareTree

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

type Bug

type Bug *Program

type DualTree

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

DualTree the binary search treeNode of Items

func GenerateRandomTree

func GenerateRandomTree(depth int, terminals []SymbolicExpression,
	nonTerminals []SymbolicExpression) (*DualTree, error)

GenerateRandomTree generates a given treeNode of a depth between 0 (i.e) root and (inclusive of) the depth specified. Assuming a binary structured treeNode. The number of terminals (T) is equal to 2^D where D is the depth. The number of NonTerminals (NT) is equal to 2^D - 1

func GenerateRandomTreeEnforceIndependentVariable

func GenerateRandomTreeEnforceIndependentVariable(depth int, independentVar SymbolicExpression,
	terminals []SymbolicExpression,
	nonTerminals []SymbolicExpression) (*DualTree, error)

GenerateRandomTreeEnforceIndependentVariable generates a given treeNode of a depth between 0 (i.e) root and (inclusive of) the depth specified. Assuming a binary structured treeNode. The number of terminals (T) is equal to 2^D where D is the depth. The number of NonTerminals (NT) is equal to 2^D - 1

func (*DualTree) AddEmptyToTreeRoot

func (bst *DualTree) AddEmptyToTreeRoot(subTree *DualTree) error

AddEmptyToTree is a conservative means of performing add and delete operations on trees that end up as single nodes. This function will add a 0 or subtract a 0 whenever an add operation encounters a single node

func (*DualTree) AddSubTree

func (bst *DualTree) AddSubTree(subTree *DualTree) error

StrategyAddRandomSubTree adds a given subtree to a treeNode.

func (*DualTree) AddToLeaf

func (bst *DualTree) AddToLeaf(tree DualTree) error

AddToLeaf is similar to AddSubTree, however the SubTree will only be placed on a randomly selected leaf. It will not replace a non-terminal

func (*DualTree) AttachSubTree

func (bst *DualTree) AttachSubTree(subTree *DualTree) error

AttachSubTree will take the current dual tree, make the incoming subTree's root the actual root, and attach the incoming leftmost node to the former root. So 3 + x where + is the root, if the incoming tree is x - 1, we set - to the new root and replace x with 3 + x in the previous tree, The result is ((3 + x) - 1) where - is not the new root.

func (DualTree) Clone

func (bst DualTree) Clone() (DualTree, error)

Clone will perform an O(N) deep clone of a treeNode and its items and return its copy.

func (*DualTree) ContainsNode

func (bst *DualTree) ContainsNode(treeNode *DualTreeNode) (bool, error)

ContainsNode checks to see if a treeNode contains a given node

func (*DualTree) ContainsSubTree

func (bst *DualTree) ContainsSubTree(subTree *DualTree) (bool, error)

ContainsSubTree checks to see if a treeNode contains part of a subTree

func (*DualTree) DeleteMalicious

func (bst *DualTree) DeleteMalicious() error

DeleteMalicious selects any element of a tree ( including the root) and convert it to a value of 0 potentially deleting all genetic material. It only affects terminals

func (*DualTree) DeleteNonTerminal

func (bst *DualTree) DeleteNonTerminal() error

DeleteNonTerminal will select a non-root non-terminal element from a given tree and delete it by setting it to 0. If the tree only contains a root it will ignore it.

func (*DualTree) DeleteSubTree

func (bst *DualTree) DeleteSubTree(deletionStrategy int) error

DeleteSubTree will delete a random branch or node of a subTree. Depending on the deletion Strategy 0 - DeleteSafe 1 - DeleteMalicious the Tree will be deleted in either conservative or aggressive ways If the Tree is a lone terminal - DeleteSafe will append a subtraction as well as copy of the value itself e.g. if the lone node is 3, the new Tree will become 3 - 3. Similarly if the node is x the new Tree will become x - x. This only occurs for lone nodes. If the Tree is not a lone terminal, but is of size 1 delete safe will turn the value of a terminal to zero. E.g. If a Tree represents 3 * 4, one of the terminals will be set to 0. The resulting may be 0 * 3 or 0 * 4. Trees that have a greater size than 1 can have actual branches deleted. A Tree like 3 + 4 * x may become 4 * x but never be converted to 0. This may have little impact on + or - operators. DeleteMalicious will follow the same semantics as deleteSafe except If the Tree is already a terminal it will convert the lone-terminal to a zero. DeleteMalicious can also reduce an entire Tree to zero if it chooses the root as a target to delete. This function will never return a nil Tree or a Tree with a nil root.

func (*DualTree) DeleteTerminal

func (bst *DualTree) DeleteTerminal() error

DeleteTerminal will select a non-root non-terminal element from a given tree and delete it by setting it to 0. If the tree only contains a root it will ignore it.

func (*DualTree) Depth

func (d *DualTree) Depth() (int, error)

Depth calculates the height of the treeNode. A treeNode with a nil root returns -1.

func (*DualTree) DepthAt

func (d *DualTree) DepthAt(depth int) ([]*DualTreeNode, error)

DepthAt returns a group of nodes AT the specified depth. No more no less.

func (*DualTree) DepthTo

func (d *DualTree) DepthTo(depth int) ([]*DualTreeNode, error)

DepthTo calculates the depth of the treeNode until the given set of nodes. All nodes traversed will be returned until that point (Not including). A depth value greater than the size of the treeNode will return the entire treeNode's nodes.

func (*DualTree) FellTree

func (bst *DualTree) FellTree() error

FellTree destroys the tree and sets its root to 0 and kills it all.

func (*DualTree) FromSymbolicExpressionSet2

func (bst *DualTree) FromSymbolicExpressionSet2(terminalSet []SymbolicExpression) error

* FromNodeTypes Creates a Tree from a list of NodeTypes

func (*DualTree) GetNode

func (bst *DualTree) GetNode(value string) (node *DualTreeNode, parent *DualTreeNode, err error)

GetNode returns the first node it encounters with the given value. It uses Inorder DFS to iterate through the treeNode, if it cannot locate an object it returns an error, if the treeNode is of size 1 i.e only containing the root, both parent and node will point to the root, in all other cases where size > 1, node and parent will be different granted the value can be found.

func (*DualTree) GetNonTerminalsAware

func (bst *DualTree) GetNonTerminalsAware() ([]AwareTree, error)

GetNonTerminalsAware is a utility function that returns a set of non-terminal nodes. In the event that the tree contains a lone terminal as its root. It will return an empty awareTree array. It is for the caller to understand that an empty awareTree array means there are no non-terminals within the tree and act appropriately

func (*DualTree) GetRandomSubTreeAtDepth

func (d *DualTree) GetRandomSubTreeAtDepth(depth int) (DualTree, error)

GetRandomSubTreeAtDepth will obtain a random subTree from a given treeNode. It assumes the depth you provide is the appropriate range as it WILL NOT check the depth and panic in case of a depth out of bounds. (This is done to prevent an extra redundant call to the depth method of treeNode if the user has already called it.

func (*DualTree) GetRandomSubTreeAtDepthAware

func (d *DualTree) GetRandomSubTreeAtDepthAware(depth int) (DualTree, error)

GetRandomSubTreeAtDepth will obtain a random subTree from a given treeNode. It assumes the depth you provide is the appropriate range as it WILL NOT check the depth and panic in case of a depth out of bounds. (This is done to prevent an extra redundant call to the depth method of treeNode if the user has already called it.

func (*DualTree) GetShortestBranch

func (bst *DualTree) GetShortestBranch(minAcceptableDepth int) (shortestNode *DualTreeNode,
	shortestNodeParent *DualTreeNode, shortestDepth int, err error)

GetShortestBranch returns the shortest branch in a given Tree. The minAcceptableDepth is used to accept a node on a Tree with a small enough acceptable depth that it can be used. This will prevent having to check each node. As with any Inorder DFS traversal, nodes placed furthest right are checked last. If the parent is nil and there is a nil error, assume the Tree itself only contains the root. You have to explicitly check this. This heavily skews to nodes on the left

func (*DualTree) GetTerminalsAware

func (bst *DualTree) GetTerminalsAware() ([]AwareTree, error)

GetTerminalsAware returns a slice of AwareTrees. The AwareTree will always have at least one value if no error is returned.

func (*DualTree) InOrderTraverse

func (bst *DualTree) InOrderTraverse(f func(node *DualTreeNode))

InOrderTraverse visits all nodes with in-order traversing

func (*DualTree) InOrderTraverseAware

func (bst *DualTree) InOrderTraverseAware(f func(node *DualTreeNode, parentNode *DualTreeNode))

InOrderTraverse visits all nodes with in-order traversing but remembers its parent. (A good child :D)

func (*DualTree) InOrderTraverseDepthAware

func (bst *DualTree) InOrderTraverseDepthAware(f func(node *DualTreeNode, parentNode *DualTreeNode, depth *int,
	shouldReturn *bool))

InOrderTraverse visits all nodes with in-order traversing but remembers its parent. (A good child :D)

func (*DualTree) MutateNonTerminal

func (bst *DualTree) MutateNonTerminal(nonTerminalSet []SymbolicExpression) error

MutateNonTerminal will mutate a terminal to another valid nonTerminal. Ensure set is nonTerminal set only otherwise arities will break. If the tree is a lone terminal at the root, it will be ignored and the program will exit NOTE ensure nonTerminalSet contains no duplicates

func (*DualTree) MutateTerminal

func (bst *DualTree) MutateTerminal(terminalSet []SymbolicExpression) error

MutateTerminal will mutate a terminal to another valid terminal if the terminalSet only contains a single item that is already in the treeNode and that treeNode element is of size 1 (root only). If both these elements are identical no change will occur

func (*DualTree) NonTerminals

func (d *DualTree) NonTerminals() ([]*DualTreeNode, error)

NonTerminals returns a list of non-terminal nodes

func (*DualTree) Print

func (bst *DualTree) Print()

Print prints a visual representation of the treeNode

func (*DualTree) Random

func (bst *DualTree) Random(terminalSet []SymbolicExpression, maxDepth int) error

func (*DualTree) RandomNonTerminal

func (bst *DualTree) RandomNonTerminal() (*DualTreeNode, error)

RandomNonTerminal locates a random non-terminal within a tree and returns the ref to the node.

func (*DualTree) RandomNonTerminalAware

func (bst *DualTree) RandomNonTerminalAware() (node *DualTreeNode, parent *DualTreeNode, err error)

RandomNonTerminalAware returns a random leaf along with their parent. If the Tree is of depth 0 -> Parent is always nil. It is the RandomNonTerminalAware responsibility to check for this.

func (*DualTree) RandomTerminal

func (bst *DualTree) RandomTerminal() (*DualTreeNode, error)

RandomTerminal locates a random leaf within a treeNode and returns the ref to the node.

func (*DualTree) RandomTerminalAware

func (bst *DualTree) RandomTerminalAware() (node *DualTreeNode, parent *DualTreeNode, err error)

RandomTerminalAware returns a random leaf along with their parent. If the Tree is of depth 0 -> Parent is always nil. It is the clients responsibility to check for this. The node value can never be nil on a valid tree if the error is nil

func (*DualTree) Replace

func (bst *DualTree) Replace(node *DualTreeNode, replacer DualTreeNode) (hobo DualTreeNode, parent *DualTreeNode,
	err error)

Replace replaces a node with replacer node. It DOES NOT Check to see if they are the same type. For simplicity a parent will never be nil if there is no error.

func (*DualTree) ReplaceBranch

func (bst *DualTree) ReplaceBranch(tree DualTree) error

ReplaceBranch takes a given tree and randomly selects a branch i. e non-terminal and will swap it with a randomly generated tree of variable depth. This includes the root

func (*DualTree) ReplaceStrict

func (bst *DualTree) ReplaceStrict(node *DualTreeNode, replacer DualTreeNode) (hobo DualTreeNode, parent *DualTreeNode,
	err error)

Replace replaces a node with replacer node. It DOES NOT Check to see if they are the same type,

func (*DualTree) Search

func (bst *DualTree) Search(key string) (node *DualTreeNode, parent *DualTreeNode, err error)

Search will use a node Id and linearly traverse the Tree using Inorder Depth First Search until it comes across the correct node. It will also return the parent of the given node. If the Tree only contains a root and the search key matches, then the node is set to the root and the parent is set to nil. In the event the given key is not found, no error will be returned, therefore the onus is on the user to verify that the returned node is not nil over and above typical error handling.

func (*DualTree) Size

func (bst *DualTree) Size() int

func (*DualTree) SoftDeleteSubTree

func (bst *DualTree) SoftDeleteSubTree() error

func (*DualTree) Terminals

func (d *DualTree) Terminals() ([]*DualTreeNode, error)

Terminals returns all the leaves in a given tree

func (*DualTree) ToMathematicalString

func (d *DualTree) ToMathematicalString() (string, error)

ToMathematicalString returns a mathematical representation of the treeNode after reading it using Inorder DFS

func (*DualTree) ToString

func (bst *DualTree) ToString() strings.Builder

Print prints a visual representation of the treeNode

func (*DualTree) ToSymbolicExpressionSet

func (bst *DualTree) ToSymbolicExpressionSet() ([]SymbolicExpression, error)

InOrderTraverse visits all nodes with in-order traversing

func (*DualTree) Validate

func (d *DualTree) Validate() error

type DualTreeNode

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

DualTreeNode represents a a treeNode with a maximum of two children. It is not technically a binary treeNode as it DOES not place any ordering on left and right children as binary trees prototypically do.

func Splitter

func Splitter(expressionSet []SymbolicExpression) ([]*DualTreeNode, error)

*

Splitter takes a set of symbolic expressions and breaks them out to a set of other symbolic expressions with the

remainder being passed back as the symbolicExpression. This will not check for empty expressionSets or expressionSets of len less than 3.

func (*DualTreeNode) ArityRemainder

func (d *DualTreeNode) ArityRemainder() int

ArityRemainder calculates the remaining available node connections based on arity for a given root node. This is used to balance the NonTerminals and the Terminals depending on their requirements.

func (DualTreeNode) Clone

func (d DualTreeNode) Clone() DualTreeNode

Clone performs an O(N) deep clone of a given DualTreeNode and returns a new DualTreeNode, granted no errors are present.

func (*DualTreeNode) IsEqual

func (b *DualTreeNode) IsEqual(t DualTreeNode) bool

IsEqual checks to see if all aspects of a DualTreeNode are equivalent. This includes value as well as pointers

func (*DualTreeNode) IsLeaf

func (d *DualTreeNode) IsLeaf() bool

IsLeaf checks to see if a given node is a leaf

func (*DualTreeNode) IsValEqual

func (d *DualTreeNode) IsValEqual(t DualTreeNode) bool

IsValEqual is a simple check to see if values of strings in the nodes are equal

func (*DualTreeNode) ToDualTree

func (d *DualTreeNode) ToDualTree() (DualTree, error)

ToDualTree takes a given node and returns a treeNode from it by following the path.

func (*DualTreeNode) ToSymbolicExpression

func (d *DualTreeNode) ToSymbolicExpression() (SymbolicExpression, error)

IsLeaf checks to see if a given node is a leaf

type Epoch

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

Epoch is defined as a coevolutionary step where protagonist and antagonist compete. For example an epoch could represent a distinct interaction between two parties. For instance a bug mutated program (antagonist) can be challenged a variety of times ( specified by {iterations}) by the tests (protagonist). The test will use up the strategies it contains and attempt to chew away at the antagonists Fitness, to maximize its own

func (*Epoch) Start

func (e *Epoch) Start(perfectTreeMap map[string]PerfectTree, params EvolutionParams) error

TopologyRoundRobin creates the Epoch process. This process applies the antagonist Strategy first, and then the protagonist Strategy second. It then appends the Fitness values to each individual in the epoch.

type EquationPairing

type EquationPairing struct {
	Independents         IndependentVariableMap
	Dependent            float64
	ProtagonistThreshold float64
	AntagonistThreshold  float64

	// AntagonistPenalization value to give the antagonist if it creates an invalid tree evaluation e.g. DivideByZero
	AntagonistPenalization float64
	// ProtagonistPenalization value to give the protagonist if it creates an invalid tree evaluation e.g. DivideByZero
	ProtagonistPenalization float64

	DivideByZeroPenalty float64
}

EquationPairing refers to a set dependent and independent values for a given equation. For example the equation x^2 + 1 has an equation pairing of {1, 0}, {2, 1}, {5, 2} for dependent and independent pairs respectively

func (*EquationPairing) ToString

func (e *EquationPairing) ToString() string

type EvolutionEngine

type EvolutionEngine struct {
	Generations []*Generation   `json:"generations"`
	Parameters  EvolutionParams `json:"parameters"`

	ProgressBar *uiprogress.Bar
	// contains filtered or unexported fields
}

func (*EvolutionEngine) EvaluateTerminationCriteria

func (engine *EvolutionEngine) EvaluateTerminationCriteria(generation *Generation,
	params EvolutionParams) (shouldTerminateEvolution bool)

EvaluateTerminationCriteria looks at the current state of the Generation and checks to see if the current termination criteria have been achieved. If so it returns true, if not the evolution can move on to the next step

func (*EvolutionEngine) Evolve

func (engine *EvolutionEngine) Evolve(params EvolutionParams) (*EvolutionResult, error)

func (*EvolutionEngine) InitializeGenerations

func (engine *EvolutionEngine) InitializeGenerations(params EvolutionParams) (antagonists []*Individual, protagonists []*Individual, err error)

InitializeGenerations starts the first generation as a building block for the evolutionary process. It will embedd the antagonists and protagonists created into its Generations slice at index [0]

func (*EvolutionEngine) RunGenerationStatistics

func (engine *EvolutionEngine) RunGenerationStatistics(currentGeneration *Generation)

func (*EvolutionEngine) ValidateGenerationTerminationMinimums

func (engine *EvolutionEngine) ValidateGenerationTerminationMinimums() (minimumTopProtagonistThreshold int,
	minimumMeanProtagonistInGenerationThreshold int)

type EvolutionParams

type EvolutionParams struct {
	Name string

	Topology Topology `json:"topology"`
	// StartIndividual - Output Only - This is set by the SpecParam Expression. Do not set it manually
	StartIndividual Program
	// Spec - Output Only - This is set by the SpecParam Expression. Do not set it manually
	Spec      SpecMulti `json:"spec"`
	SpecParam SpecParam `json:"specParam"`
	// MaxGenerations activates the ability for a variable number of generations before the simulation ends.
	// The value must be greater than 9 for the activation to begin, if not,
	// the simulation will default to GenerationsCount number of generations. Once this variable is set,
	// MinimumTopProtagonistMeanBeforeTerminate and ProtagonistMinGenAvgFit will come into effect. If no adequate solution is found,
	// MaxGenerations will terminate. This value should default to about 300.
	MaxGenerations int `json:"maxGenerationsCount",csv:"maxGenerationsCount"`
	// MinimumTopProtagonistMeanBeforeTerminate specifies the percentage of consecutive generations where the
	// ProtMinGenFitnessAvg has been hit by the best protaginist in the generation before the simulation can end.
	MinimumTopProtagonistMeanBeforeTerminate float64 `json:"minimumTopProtagonistMeanBeforeTerminate"`

	// MinimumGenerationMeanBeforeTerminate specifies the percentage of consecutive generations where the
	// ProtMinGenFitnessAvg has been hit by the average of all protagonists in the generation before the simulation can
	// end.
	MinimumGenerationMeanBeforeTerminate float64 `json:"minimumGenerationMeanBeforeTerminate"`

	// ProtagonistMinimumGenFitness specifies the average value of fitness of the best individual after a completed
	// generation. This individual must obtain this fitness value or greater e.g. an average of 0.75
	// for MinimumTopProtagonistMeanBeforeTerminate number of consecutive generations before the simulation can end.
	ProtagonistMinGenAvgFit float64 `json:"protagonistMinGenAvgFit"`
	GenerationsCount        int     `json:"generationCount",csv:"generationCount"`
	// EachPopulationSize represents the size of each protagonist or antagonist population.
	// This value must be even otherwise pairwise operations such as crossover will fail
	EachPopulationSize int  `json:"eachPopulationSize",csv:"eachPopulationSize"`
	EnableParallelism  bool `json:"enableParallelism",csv:"enableParallelism"`

	Strategies Strategies `json:"strategies",csv:"strategies"`

	FitnessStrategy FitnessStrategy `json:"fitnessStrategy",csv:"fitnessStrategy"`
	Reproduction    Reproduction    `json:"reproduction",csv:"reproduction"`
	Selection       Selection       `json:"selection",csv:"selection"`

	// FitnessCalculatorType allows user to select the fitness calculator.
	// The more complex the function 1 is better but slower. 0 for simple polynomials with single digit constants e.
	// g. x*x*x or x*x+4
	FitnessCalculatorType int `json:"fitnessCalculatorType"`
	// ShouldRunInteractiveTerminal ensures the interactive terminal is run at the end of the evolution that allows
	// users to query all individuals in all generations.
	ShouldRunInteractiveTerminal bool             `json:"shouldRunInteractiveTerminal"`
	StatisticsOutput             StatisticsOutput `json:"statisticsOutput"`
	// InternalCount - Output Only (Helps with file name assignments)
	InternalCount int

	EnableLogging bool `json:"-"`
	RunStats      bool `json:"-"`

	// FinalGeneration records if the simulation ended early by fulfilling the maxGen requirements.
	FinalGeneration       int    `json:"finalGeneration",csv:"finalGeneration"`
	FinalGenerationReason string `json:"finalGenerationReason",csv:"finalGenerationReason"`

	//Channels
	LoggingChan chan evolog.Logger `json:"-"`
	ErrorChan   chan error         `json:"-"`
	DoneChan    chan bool          `json:"-"`
	ParamFile   string             `json:"-"`

	//FolderPercentages help track progress when a certain percentage is reached
	FolderPercentages []float64
}

func (EvolutionParams) ToString

func (e EvolutionParams) ToString() string

type EvolutionProcess

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

* EvolutionProcess represents the state of an evolutionary process once the evolution engine starts

type EvolutionResult

type EvolutionResult struct {
	HasBeenAnalyzed     bool
	TopAntagonistInRun  Individual
	TopProtagonistInRun Individual
	FinalAntagonist     Individual
	FinalProtagonist    Individual

	Correlation    float64
	Covariance     float64
	CovarianceStd  float64
	CorrelationStd float64
	Generational   Generational

	ThoroughlySortedGenerations []*Generation
	OutputFile                  string

	Mutex sync.Mutex
}

func (*EvolutionResult) Analyze

func (e *EvolutionResult) Analyze(evolutionEngine *EvolutionEngine, generations []*Generation, isMoreFitnessBetter bool,
	params EvolutionParams) error

func (*EvolutionResult) Clean

func (e *EvolutionResult) Clean()

type FitnessStrategy

type FitnessStrategy struct {
	Type string `json:"type"`
	// AntagonistThresholdMultiplier is the multiplier applied to the antagonist delta when calculating fitness.
	// A large value means that antagonists have to attain a greater delta from the spec in order to gain adequate
	// fitness, conversely a smaller value gives the antagonists more slack to not manipulate the program excessively.
	// For good results set it to a value greater than that of the protagonist delta.
	// This value is only used when using DualThresholdedRatioFitness.
	AntagonistThresholdMultiplier float64 `json:"antagonistThresholdMultiplier"`

	// ProtagonistThresholdMultiplier is the multiplier applied to the protagonist delta when calculating fitness.
	// A large value means that protagonist can be less precise and gain adequate fitness,
	// conversely a smaller value gives the protagonist little room for mistake between its delta and that of the spec.
	// this value is used in both DualThresholdedRatioFitness and ThresholdedRatioFitness as a fitness value for
	// both antagonist and protagonists thresholds.
	ProtagonistThresholdMultiplier float64 `json:"protagonistThresholdMultiplier"`
}

type Generation

type Generation struct {
	Mutex        sync.Mutex
	GenerationID string
	Protagonists []*Individual //Protagonists in a given Generation
	Antagonists  []*Individual //Antagonists in a given Generation

	//Individuals
	BestAntagonist  Individual
	BestProtagonist Individual

	// Averages of all Antagonists and Protagonists in Generation
	Correlation float64
	Covariance  float64

	AntagonistAverage    float64
	AntagonistStdDev     float64
	AntagonistVariance   float64
	AntagonistAvgFitness []float64
	AntagonistSkew       float64
	AntagonistExKurtosis float64

	ProtagonistAverage    float64
	ProtagonistStdDev     float64
	ProtagonistVariance   float64
	ProtagonistSkew       float64
	ProtagonistExKurtosis float64
	ProtagonistAvgFitness []float64
	// contains filtered or unexported fields
}

TODO AGE TODO Calculate fitness average for GENERATIONS (seems off!)

func SortGenerationsThoroughly

func SortGenerationsThoroughly(generations []*Generation, isMoreFitnessBetter bool) ([]*Generation, error)

SortGenerationsThoroughly sorts each kind of individual in each generation for every generation. This allows for easy querying in later phases.

func SortGenerationsThoroughlyByAvgDelta

func SortGenerationsThoroughlyByAvgDelta(generations []*Generation, shouldAntagonistDeltaBig,
	shouldProtagonistDeltaBig bool) ([]*Generation, error)

SortGenerationsThoroughlyByAvgDelta sorts each kind of individual in each generation for every generation. This allows for easy querying in later phases.

func SortGenerationsThoroughlyByDelta

func SortGenerationsThoroughlyByDelta(generations []*Generation, shouldAntagonistDeltaBig,
	shouldProtagonistDeltaBig bool) ([]*Generation, error)

SortGenerationsThoroughlyByDelta sorts each kind of individual in each generation for every generation. This allows for easy querying in later phases.

func (*Generation) ApplyParentSelection

func (g *Generation) ApplyParentSelection(currentPopulation []*Individual) ([]*Individual, error)

ApplyParentSelection takes in a given Generation and returns a set of individuals once the preselected parent selection Strategy has been applied to the Generation. These individuals are ready to be taken to either a new Generation or preferably through survivor selection in the case you do not isEqual the population to grow in size.

func (*Generation) ApplyReproduction

func (g *Generation) ApplyReproduction(incomingParents []*Individual, kind int) (outgoingParents []*Individual,
	children []*Individual,
	err error)

ApplySurvivorSelection applies the preselected survivor selection Strategy. It DOES NOT check to see if the parent selection has already been applied, as in some cases evolutionary programs may choose to run without the parent selection phase. The onus is on the evolutionary architect to keep this consideration in mind.

func (*Generation) ApplySelection

func (g *Generation) ApplySelection(antagonists, protagonists []*Individual, errorChan chan error) (
	antagonistSurvivors []*Individual, protagonistSurvivors []*Individual)

ApplySelection applies all 3 selection methods, parent, reproduction and survivor to return a set of survivor antagonist and protagonists

func (*Generation) ApplySurvivorSelection

func (g *Generation) ApplySurvivorSelection(outgoingParents []*Individual,
	children []*Individual) ([]*Individual, error)

ApplySurvivorSelection applies the preselected survivor selection Strategy. It DOES NOT check to see if the parent selection has already been applied, as in some cases evolutionary programs may choose to run without the parent selection phase. The onus is on the evolutionary architect to keep this consideration in mind.

func (*Generation) CleansePopulations

func (g *Generation) CleansePopulations(params EvolutionParams)

func (*Generation) GenerateRandomIndividuals

func (g *Generation) GenerateRandomIndividuals(kind int, params EvolutionParams) ([]*Individual, error)

GenerateRandom creates a a random set of individuals based on the parameters passed into the evolution engine. To pass a tree to an individual pass it via the formal parameters and not through the evolution engine parameter section Antagonists are by default set with the StartIndividuals Program as their own program.

func (*Generation) InitializePopulation

func (g *Generation) InitializePopulation(params EvolutionParams) (antagonists []*Individual,
	protagonists []*Individual, err error)

initializePopulation randomly creates a set of antagonists and protagonists

func (*Generation) ToString

func (g *Generation) ToString() string

type Generational

type Generational struct {
	BestAntagonistInEachGenerationByAvgFitness  []Individual
	BestProtagonistInEachGenerationByAvgFitness []Individual

	CorrelationInEachGeneration []float64
	CovarianceInEachGeneration  []float64

	AntagonistAverageInEachGeneration    []float64
	AntagonistStdDevInEachGeneration     []float64
	AntagonistVarianceInEachGeneration   []float64
	AntagonistAvgFitnessInEachGeneration []float64
	AntagonistSkewInEachGeneration       []float64
	AntagonistExKurtosisInEachGeneration []float64

	ProtagonistAverageInEachGeneration    []float64
	ProtagonistStdDevInEachGeneration     []float64
	ProtagonistVarianceInEachGeneration   []float64
	ProtagonistSkewInEachGeneration       []float64
	ProtagonistExKurtosisInEachGeneration []float64
	ProtagonistAvgFitnessInEachGeneration []float64
}

Generational averages contain slices of length of the generations in a given run

type Generations

type Generations struct {
}

type HallOfFame

type HallOfFame struct {
	Engine *EvolutionEngine

	AntagonistArchive  []Individual
	ProtagonistArchive []Individual

	GenerationIntervals int
}

func (*HallOfFame) Evolve

func (s *HallOfFame) Evolve(params EvolutionParams, topology ITopology) (*EvolutionResult,
	error)

func (*HallOfFame) Topology

func (s *HallOfFame) Topology(currentGeneration *Generation,
	params EvolutionParams) (*Generation,
	error)

type IDualTree

type IDualTree interface {
	IDualTreeInsertable
	Get(index int) (*DualTreeNode, error)
	GetFirst(node DualTreeNode) (*DualTreeNode, error)
	Pop(index int) (*DualTreeNode, error)
	Delete(index int) error
	DeleteFirst(node DualTreeNode) error
	Swap(index int, node DualTreeNode, newNode DualTreeNode) error
	Traverse(traversalMethod string) []*DualTreeNode
}

IDualTree represents a complete behavior for a treeNode

type IDualTreeDeletable

type IDualTreeDeletable interface {
	Delete(index int) error
}

IDualTreeDeletable manages deletion behaviour

type IDualTreeGetFirstable

type IDualTreeGetFirstable interface {
	GetFirst(node DualTreeNode) (*DualTreeNode, error)
}

type IDualTreeGettable

type IDualTreeGettable interface {
	Get(index int) (*DualTreeNode, error)
}

type IDualTreeInsertable

type IDualTreeInsertable interface {
	Insert(node DualTreeNode, index int) error
}

type IDualTreePoppable

type IDualTreePoppable interface {
	Pop(index int) (*DualTreeNode, error)
}

type IDualTreeTraversable

type IDualTreeTraversable interface {
	Traverse(traversalMethod string) []*DualTreeNode
}

IDualTreeTraversable manages traversal behaviours

type IEvolve

type IEvolve interface {
	Evolve(params EvolutionParams, topology ITopology) (*EvolutionResult, error)
}

type ITopology

type ITopology interface {
	Topology(currentGeneration *Generation, params EvolutionParams) (*Generation, error)
}

type IndependentVariableMap

type IndependentVariableMap map[string]float64

type Individual

type Individual struct {
	Id                       string
	Parent                   *Individual
	Strategy                 []Strategy
	Fitness                  []float64
	Deltas                   []float64
	FitnessVariance          float64
	FitnessStdDev            float64
	HasAppliedStrategy       bool
	HasCalculatedFitness     bool
	FitnessCalculationMethod string
	Kind                     int
	BirthGen                 int
	Age                      int
	BestFitness              float64 // Best fitness from all epochs
	AverageFitness           float64 // Measures average fitness throughout epoch
	BestDelta                float64
	AverageDelta             float64
	NoOfCompetitions         int
	Mutex                    sync.Mutex

	Program *Program // The best program generated
}

func CleansePopulation

func CleansePopulation(individuals []*Individual, treeReplacer DualTree) ([]*Individual, error)

CleansePopulation removes the trees from the population and refits them with the starter Tree.

func CloneIndividualsLinkParent

func CloneIndividualsLinkParent(individuals []*Individual) (outgoing []*Individual, err error)

func Elitism

func Elitism(population []*Individual, isMoreFitnessBetter bool) ([]*Individual, error)

Elitism is an evolutionary process where only the top ( n) individuals based on eliteCount are selected based on their Fitness. In essence it ranks the individuals based on Fitness, then returns the top (n)

func FitnessBasedSurvivorSelection

func FitnessBasedSurvivorSelection(selectedParents, selectedChildren []*Individual,
	params EvolutionParams) ([]*Individual, error)

FitnessBasedSurvivorSelection returns a set of survivors proportionate to the survivor percentage. It orders some of the best parents and some of the best children based on the ratio

func FitnessProportionateSelection

func FitnessProportionateSelection(population []*Individual) ([]*Individual, error)

Fitness Proportionate Selection is one of the most popular ways of parent selection. In this every individual can become a parent with a probability which is proportional to its Fitness. Therefore, fitter individuals have a higher chance of mating and propagating their features to the next Generation. Therefore, such a selection Strategy applies a selection pressure to the more fit individuals in the population, evolving better individuals over time.

func GenerationalSurvivorSelection

func GenerationalSurvivorSelection(population *Generation) ([]*Individual, error)

GenerationalSurvivorSelection is a process where the entire input population gets replaced by their offspring. The returned individuals do not exist with their parents as they have been totally annihilated. These new individuals will go on into the next Generation

func GetNthPlaceIndividual

func GetNthPlaceIndividual(sortedIndividuals []*Individual, n int) (*Individual, error)

GetNthPlaceIndividual returns an individual in the nth place. N must be an index and not an actual position e.g. 0 is the first individual

func RandomSurvivorSelection

func RandomSurvivorSelection(selectedParents, selectedChildren []*Individual,
	params EvolutionParams) ([]*Individual, error)

RandomSurvivorSelection selects a random set of parents and a random set of children. The numbers are based on

func SortIndividuals

func SortIndividuals(individuals []*Individual, isMoreFitnessBetter bool) ([]*Individual, error)

SortIndividuals returns the Top N-1 individuals. In this application less is more, so they are sorted in ascending order, with smaller indices representing better individuals. It is for the user to specify the Kind of individual to pass in be it antagonist or protagonist.

func SortIndividualsByAvgDelta

func SortIndividualsByAvgDelta(individuals []*Individual, isMoreFitnessBetter bool) ([]*Individual, error)

SortIndividuals returns the Top N-1 individuals. In this application less is more, so they are sorted in ascending order, with smaller indices representing better individuals. It is for the user to specify the Kind of individual to pass in be it antagonist or protagonist.

func SortIndividualsByDelta

func SortIndividualsByDelta(individuals []*Individual, isMoreFitnessBetter bool) ([]*Individual, error)

SortIndividuals returns the Top N-1 individuals. In this application less is more, so they are sorted in ascending order, with smaller indices representing better individuals. It is for the user to specify the Kind of individual to pass in be it antagonist or protagonist.

func SteadyStateSurvivorSelection

func SteadyStateSurvivorSelection(population *Generation) ([]*Individual, error)

SteadyStateSurvivorSelection is a process where a select amount of individuals make it through. Some parents may make it through based on their Fitness or other compounding parameters. These new individuals will go on into the next Generation

func TournamentSelection

func TournamentSelection(population []*Individual, tournamentSize int) ([]*Individual, error)

TournamentSelection is a process whereby a random set of individuals from the population are selected, and the best in that sample succeed onto the next Generation

func (*Individual) ApplyAntagonistStrategy

func (individual *Individual) ApplyAntagonistStrategy(params EvolutionParams) error

ApplyAntagonistStrategy applies the AntagonistEquation strategies to program.

func (*Individual) ApplyProtagonistStrategy

func (individual *Individual) ApplyProtagonistStrategy(antagonistTree DualTree, params EvolutionParams) error

ApplyProtagonistStrategy applies the AntagonistEquation strategies to program.

func (*Individual) CalculateAntagonistThresholdedFitness

func (individual *Individual) CalculateAntagonistThresholdedFitness(params EvolutionParams) (antagonistFitness float64,
	delta float64, err error)

func (*Individual) CalculateProtagonistThresholdedFitness

func (individual *Individual) CalculateProtagonistThresholdedFitness(params EvolutionParams) (
	protagonistFitness float64,
	delta float64, err error)

func (Individual) Clone

func (individual Individual) Clone() (Individual, error)

func (Individual) CloneCleanse

func (individual Individual) CloneCleanse() (Individual, error)

CloneCleanse removes performance based information but keeps the strategy intact.

func (Individual) CloneWithTree

func (individual Individual) CloneWithTree(tree DualTree) Individual

func (*Individual) Mutate

func (individual *Individual) Mutate(availableStrategies []Strategy) error

Mutate will mutate the Strategy in a given individual

func (*Individual) ToString

func (individual *Individual) ToString() strings.Builder

type KRandom

type KRandom struct {
	Engine *EvolutionEngine
}

func (*KRandom) Evolve

func (s *KRandom) Evolve(params EvolutionParams, topology ITopology) (*EvolutionResult,
	error)

func (*KRandom) Topology

func (s *KRandom) Topology(currentGeneration *Generation,
	params EvolutionParams) (*Generation,
	error)

type ParentSelection

type ParentSelection struct {
	Type           string `json:"type",csv:"type"`
	TournamentSize int    `json:"tournamentSize",csv:"tournamentSize"`
}

type PerfectTree

type PerfectTree struct {
	Program          *Program
	BestFitnessValue float64
	BestFitnessDelta float64
}

type Program

type Program struct {
	ID string
	T  *DualTree
}

TODO generate AST treeNode from polynomial expression

func (*Program) ApplyStrategy

func (p *Program) ApplyStrategy(strategy Strategy, terminals []SymbolicExpression,
	nonTerminals []SymbolicExpression, depth int) (err error)

ApplyStrategy takes a given Strategy and applies a transformation to the given program. depth defines the exact depth the treeNode can evolve to given the transformation. Depth of a treeNode increases exponentially. So keep depths small e.g. 1,2,3 Ensure to place the independent variabel e.g X at the start of the SymbolicExpression terminals array. Otherwise there is less of a chance of having the independent variable propagate. The system is designed such that the first element of the terminals array will be the most prominent with regards to appearance.

func (Program) Clone

func (p Program) Clone() (Program, error)

func (Program) CloneWithTree

func (p Program) CloneWithTree(tree DualTree) Program

func (*Program) EvalMulti

func (p *Program) EvalMulti(independentVariables IndependentVariableMap, expressionString string) (float64,
	error)

Eval is a simple helper function that takes in an independent variable, uses the programs treeNode to compute the resultant value

type Protagonist

type Protagonist Individual

type Reproduction

type Reproduction struct {
	CrossoverStrategy string `json:"crossoverStrategy",csv:"crossoverStrategy"`
	// CrossoverPercentrage pertains to the amount of genetic material crossed-over. FOR SPX
	// This is a percentage represented as a float64. A value of 1 means all material is swapped.
	// A value of 0 means no material is swapped (which in effect are the same thing).
	// Avoid 0 or 1 use values in between
	CrossoverPercentage   float64 `json:"crossoverPercentage",csv:"crossoverPercentage"`
	ProbabilityOfMutation float64 `json:"probabilityOfMutation",csv:"probabilityOfMutation"`
	KPointCrossover       int     `json:"kPointCrossover",csv:"kPointCrossover"`
}

type RoundRobin

type RoundRobin struct {
	Engine *EvolutionEngine
}

func (*RoundRobin) Compete

func (r *RoundRobin) Compete(g *Generation) error

Compete gives protagonist and anatagonists the chance to compete. A competition involves an epoch, that returns the Individuals of the epoch.

func (*RoundRobin) Evolve

func (s *RoundRobin) Evolve(params EvolutionParams, topology ITopology) (*EvolutionResult,
	error)

func (RoundRobin) Topology

func (r RoundRobin) Topology(currentGeneration *Generation,
	params EvolutionParams) (*Generation,
	error)

type Selection

type Selection struct {
	Parent   ParentSelection   `json:"parentSelection",csv:"parentSelection"`
	Survivor SurvivorSelection `json:"survivorSelection",csv:"survivorSelection"`
}

type SingleEliminationTournamentTopology

type SingleEliminationTournamentTopology struct {
	Engine *EvolutionEngine
}

func (*SingleEliminationTournamentTopology) Evolve

func (*SingleEliminationTournamentTopology) Topology

func (s *SingleEliminationTournamentTopology) Topology(currentGeneration *Generation,
	params EvolutionParams) (*Generation,
	error)

type SpecMulti

type SpecMulti []EquationPairing

SpecMulti is the underlying data structre that contains the spec as well as threshold information

func GenerateSpecSimple

func GenerateSpecSimple(specParam SpecParam, fitnessStrategy FitnessStrategy) (SpecMulti,
	error)

GenerateSpecSimple assumes a single independent variable x with an unlimited count.

func (SpecMulti) ToString

func (spec SpecMulti) ToString() string

type SpecParam

type SpecParam struct {
	// SpecRange defines a range of variables on either side of the X axis. A range of 4 will include -2, -1,
	// 0 and 1.
	Range int `json:"range"`
	//Expression is the actual expression being tested.
	// It is the initial function that is converted to the startIndividual
	Expression string `json:"expression"`
	//OUTPUT
	ExpressionParsed               string `json:"expressionParsed"`
	Seed                           int    `json:"seed"`
	AvailableVariablesAndOperators AvailableVariablesAndOperators
	// AvailableSymbolicExpressions - Output Only
	AvailableSymbolicExpressions AvailableSymbolicExpressions
	DivideByZeroStrategy         string  `json:"divideByZeroStrategy",csv:"divideByZeroStrategy"`
	DivideByZeroPenalty          float64 `json:"divideByZeroPenalty",csv:"divideByZeroPenalty"`
}

type Statistics

type Statistics struct {
}

type StatisticsOutput

type StatisticsOutput struct {
	OutputPath string `json:"outputPath"`
	Name       string `json:"name"`
	OutputDir  string `json:"outputDir"`
}

type Strategable

type Strategable interface{ Apply(t *DualTree) }

type Strategies

type Strategies struct {
	//AvailableStrategies            []Strategy `json:"availableStrategies"`
	AntagonistAvailableStrategies  []Strategy `json:"antagonistAvailableStrategies"`
	ProtagonistAvailableStrategies []Strategy `json:"protagonistAvailableStrategies"`

	AntagonistStrategyCount  int `json:"antagonistStrategyCount"`
	ProtagonistStrategyCount int `json:"protagonistStrategyCount"`

	DepthOfRandomNewTrees int `json:"depthOfRandomNewTrees"`
}

type Strategy

type Strategy string

func GenerateRandomStrategy

func GenerateRandomStrategy(number int, availableStrategies []Strategy) []Strategy

GenerateRandomStrategy creates a random Strategy list that contains some or all of the availableStrategies. They are randomly selected and populated.

type SurvivorSelection

type SurvivorSelection struct {
	Type string `json:"type",csv:"type"`
	// SurvivorPercentage represents how many individulas in the parent vs child population should continue.
	// 1 means all parents move on. 0 means only children move on. Any number in betwee is a percentage value.
	// It cannot be greater than 1 or less than 0.
	SurvivorPercentage float64 `json:"survivorPercentage",csv:"survivorPercentage"`
}

type SymbolicExpression

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

func CreateBinaryNonTerminal

func CreateBinaryNonTerminal(value string) SymbolicExpression

func CreateNonTerminal

func CreateNonTerminal(arity int, value string) SymbolicExpression

func CreateTerminal

func CreateTerminal(value string) SymbolicExpression

func GenerateExpression

func GenerateExpression(expression string) ([]SymbolicExpression, error)

func GenerateNonTerminals

func GenerateNonTerminals(count int, symbolList []string) ([]SymbolicExpression, error)

func GenerateRandomSymbolicExpressionSet

func GenerateRandomSymbolicExpressionSet(size int) []SymbolicExpression

GenerateN generates a random SymbolicExpressionSet representing a valid mathematical expression. If size is less than 0, it reverts it to 0

func GenerateTerminals

func GenerateTerminals(count int, symbolList []string) ([]SymbolicExpression, error)

GenerateTerminals returns a set of count terminals from the symbol list. A count value less than 0 will return all symbols as terminals. Similarly a number greater than the length of the symbolList will return all the terminals.

func ParseString

func ParseString(expression string, validNonTerminals []string, validVariables []string) (terminals, nonTerminals,
	mathematicalExpression []SymbolicExpression,
	err error)

ParseString parses a given mathematical expression into a set of terminals and nonTerminals within the string. It assumes mathematical expressions in particular non-terminals have an arity of two and take in two arguments e. g. * / - + are some examples Todo: NEEDS MORE WORK

func ParseStringLiberal

func ParseStringLiberal(expression string) (terminals, nonTerminals,
	mathematicalExpression []SymbolicExpression,
	err error)

ParseStringLiberal parses a given mathematical expression into a set of terminals and nonTerminals within the string. It assumes mathematical expressions in particular non-terminals have an arity of two and take in two arguments e. g. * / - + are some examples

func (*SymbolicExpression) CreateBinaryNonTerminal

func (n *SymbolicExpression) CreateBinaryNonTerminal(value string)

func (*SymbolicExpression) CreateNonTerminal

func (n *SymbolicExpression) CreateNonTerminal(arity int, value string)

func (*SymbolicExpression) CreateTerminal

func (n *SymbolicExpression) CreateTerminal(value string)

func (*SymbolicExpression) ToDualTreeNode

func (n *SymbolicExpression) ToDualTreeNode(key string) *DualTreeNode

type SymbolicExpressionSet

type SymbolicExpressionSet []SymbolicExpression

SymbolicExpressionSet represents a mathematical expression broken into symbolic expressions. For Example x+1 will be broken into a SymbolicExpressionSet of size 3, containing both terminal and non terminal information

type Test

type Test *Program

type Topology

type Topology struct {
	Type               string  `json:"type"`
	KRandomK           int     `json:"kRandomK"`
	SETNoOfTournaments float64 `json:"SETNoOfTournaments"`
	// HoFGenerationInterval showcases the percentage of an evolutionary cycle that old individuals should be
	// introduced. A negative number introduces the previous winner from the old generation in every subsequent
	// generation
	HoFGenerationInterval float64 `json:"generationInterval"`
}

Jump to

Keyboard shortcuts

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