Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented SAFE coevolution method for solving maze navigation problem #7

Merged
merged 1 commit into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions data/safe.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#############################
# The SAFE population options
#############################
# Probability of mutating a single trait param
trait_param_mut_prob: 0.5
# Power of mutation on a single trait param
trait_mutation_power: 1.0
# The power of a link weight mutation
weight_mut_power: 2.5

# 3 global coefficients are used to determine the formula for computing the compatibility between 2 genomes.
# The formula is: disjoint_coeff * pdg + excess_coeff * peg + mutdiff_coeff * mdmg.
# See the Compatibility method in the Genome class for more info
# They can be thought of as the importance of disjoint Genes, excess Genes, and parametric difference between Genes of
# the same function, respectively.
disjoint_coeff: 1.0
excess_coeff: 1.0
mutdiff_coeff: 0.4

# This global tells compatibility threshold under which two Genomes are considered the same species
compat_threshold: 3.0
# How much does age matter? Gives a fitness boost up to some young age (niching). If it is 1, then young species get no fitness boost.
age_significance: 1.0
# Percent of average fitness for survival, how many get to reproduce based on survival_thresh * pop_size
survival_thresh: 0.2

# Probabilities of a non-mating reproduction
mutate_only_prob: 0.25
# Probability of genome trait mutation
mutate_random_trait_prob: 0.1
# Probability of link trait mutation
mutate_link_trait_prob: 0.1
# Probability of node trait mutation
mutate_node_trait_prob: 0.1
# Probability of link weight value mutation
mutate_link_weights_prob: 0.9
# Probability of enabling/disabling of specific link/gene
mutate_toggle_enable_prob: 0.0
# Probability of finding the first disabled gene and re-enabling it
mutate_gene_reenable_prob: 0.0
# Probability of adding new node
mutate_add_node_prob: 0.03
# Probability of adding new link between nodes
mutate_add_link_prob: 0.08
# Probability of making connections from disconnected sensors (input, bias type neurons)
mutate_connect_sensors: 0.5

# Probability of mating between different species
interspecies_mate_rate: 0.001
# Probability of mating this Genome with another Genome g. For every point in each Genome, where each Genome shares
# the innovation number, the Gene is chosen randomly from either parent. If one parent has an innovation absent in
# the other, the baby may inherit the innovation if it is from the more fit parent.
mate_multipoint_prob: 0.3
# Probability of mating like in multipoint, but instead of selecting one or the other when the innovation numbers match,
# it averages their weights.
mate_multipoint_avg_prob: 0.3
# Probability of mating similar to a standard single point CROSSOVER operator. Traits are averaged as in the previous two
# mating methods. A Gene is chosen in the smaller Genome for splitting. When the Gene is reached, it is averaged with
# the matching Gene from the larger Genome, if one exists. Then every other Gene is taken from the larger Genome.
mate_singlepoint_prob: 0.3

# Probability of mating without mutation
mate_only_prob: 0.2

# Probability of forcing selection of ONLY links that are naturally recurrent
recur_only_prob: 0.0

# The number of babies to stolen off to the champions
babies_stolen: 0
# The population size as a number of organisms
pop_size: 100
# Age when Species starts to be penalized
dropoff_age: 50
# Number of tries mutate_add_link will attempt to find an open link
newlink_tries: 50
# Tells to print population to file every n generations
print_every: 10

# The number of runs to average over in an experiment
num_runs: 100
# The number of epochs (generations) to execute training
num_generations: 100

# The epoch's executor type to apply [sequential, parallel]
epoch_executor: sequential

# The genome compatibility method to use [linear, fast]. The latter is best for bigger genomes
genome_compat_method: linear

# The log level
log_level: info

# The nodes activation functions list to choose from (activation function -> it's selection probability)
node_activators:
- SigmoidBipolarActivation 0.25
- GaussianBipolarActivation 0.35
- LinearAbsActivation 0.15
- SineActivation 0.25
27 changes: 27 additions & 0 deletions data/safeobjfuncstartgenes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# The objective function candidate start genome
genome:
id: 1
# The traits used in this genome
traits:
- {id: 1, params: [0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]}

# The neuron nodes list for this genome
nodes:
- {id: 1, trait_id: 0, type: BIAS, activation: LinearActivation}
# The input sensors
- { id: 2, trait_id: 0, type: INPT, activation: LinearActivation }
# The non-linear hidden control node
- { id: 3, trait_id: 0, type: HIDN, activation: SigmoidSteepenedActivation }
# The output nodes
# The a coefficient
- { id: 4, trait_id: 0, type: OUTP, activation: LinearActivation }
# The b coefficient
- { id: 5, trait_id: 0, type: OUTP, activation: LinearActivation }

# The connection genes
genes:
- {src_id: 1, tgt_id: 3, weight: 0.0, trait_id: 1, innov_num: 1, mut_num: 0, recurrent: false, enabled: true}
- {src_id: 2, tgt_id: 3, weight: 0.0, trait_id: 1, innov_num: 2, mut_num: 0, recurrent: false, enabled: true}
# Hidden-to-output
- {src_id: 3, tgt_id: 4, weight: 0.0, trait_id: 1, innov_num: 12, mut_num: 0, recurrent: false, enabled: true}
- {src_id: 3, tgt_id: 5, weight: 0.0, trait_id: 1, innov_num: 13, mut_num: 0, recurrent: false, enabled: true}
8 changes: 7 additions & 1 deletion examples/maze/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func mazeSimulationStep(env *Environment, phenotype *network.Network, netDepth i

// use the net's outputs to change heading and velocity of maze agent
if err := env.ApplyOutputs(phenotype.Outputs[0].Activation, phenotype.Outputs[1].Activation); err != nil {
neat.ErrorLog("Failed to apply outputs")
neat.ErrorLog(fmt.Sprintf("Failed to apply outputs: %s", err))
return err
}

Expand Down Expand Up @@ -196,3 +196,9 @@ func adjustSpeciesNumber(speciesCount, epochId, adjustFrequency, numberSpeciesTa
}
}
}

// NoveltyMetric the novelty metric function for maze simulation
var NoveltyMetric neatns.NoveltyMetric = func(x, y *neatns.NoveltyItem) float64 {
diff := histDiff(x.Data, y.Data)
return diff
}
8 changes: 1 addition & 7 deletions examples/maze/maze_ns.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@ import (
// The initial novelty threshold for Novelty Archive
const archiveThresh = 6.0

// the novelty metric function for maze simulation
var noveltyMetric neatns.NoveltyMetric = func(x, y *neatns.NoveltyItem) float64 {
diff := histDiff(x.Data, y.Data)
return diff
}

// NewNoveltySearchEvaluator allows creating maze solving agent based on Novelty Search optimization.
// It will use provided MazeEnv to run simulation of the maze environment. The numSpeciesTarget specifies the
// target number of species to maintain in the population. If the number of species differ from the numSpeciesTarget it
Expand Down Expand Up @@ -55,7 +49,7 @@ func (e *noveltySearchEvaluator) TrialRunStarted(trial *experiment.Trial) {
trialSim = mazeSimResults{
trialID: trial.Id,
records: new(RecordStore),
archive: neatns.NewNoveltyArchive(archiveThresh, noveltyMetric, opts),
archive: neatns.NewNoveltyArchive(archiveThresh, NoveltyMetric, opts),
}
}

Expand Down
2 changes: 1 addition & 1 deletion examples/maze/maze_obj.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (e *objectiveEvaluator) TrialRunStarted(trial *experiment.Trial) {
trialSim = mazeSimResults{
trialID: trial.Id,
records: new(RecordStore),
archive: neatns.NewNoveltyArchive(archiveThresh, noveltyMetric, neatns.DefaultNoveltyArchiveOptions()),
archive: neatns.NewNoveltyArchive(archiveThresh, NoveltyMetric, neatns.DefaultNoveltyArchiveOptions()),
}
}

Expand Down
Loading
Loading