github.com/yaricom/goNEAT@v0.0.0-20210507221059-e2110b885482/neat/genetics/species_test.go (about) 1 package genetics 2 3 import ( 4 "math/rand" 5 "testing" 6 "github.com/yaricom/goNEAT/neat" 7 "sort" 8 "bytes" 9 ) 10 11 func buildSpeciesWithOrganisms(id int) (*Species, error) { 12 gen := buildTestGenome(1) 13 14 sp := NewSpecies(id) 15 for i := 0; i < 3; i++ { 16 org, err := NewOrganism( float64(i + 1) * 5.0 * float64(id), gen, id) 17 if err != nil { 18 return nil, err 19 } 20 sp.addOrganism(org) 21 } 22 23 return sp, nil 24 } 25 26 func TestSpecies_Write(t *testing.T) { 27 sp, err := buildSpeciesWithOrganisms(1) 28 29 if err != nil { 30 t.Error(err) 31 return 32 } 33 34 out_buf := bytes.NewBufferString("") 35 sp.Write(out_buf) 36 } 37 38 // Tests Species adjustFitness 39 func TestSpecies_adjustFitness(t *testing.T) { 40 sp, err := buildSpeciesWithOrganisms(1) 41 42 if err != nil { 43 t.Error(err) 44 return 45 } 46 47 // Configuration 48 conf := neat.NeatContext{ 49 DropOffAge:5, 50 SurvivalThresh:0.5, 51 AgeSignificance:0.5, 52 } 53 sp.adjustFitness(&conf) 54 55 // test results 56 if sp.Organisms[0].isChampion != true { 57 t.Error("sp.Organisms[0].IsChampion", true, sp.Organisms[0].isChampion) 58 } 59 if sp.AgeOfLastImprovement != 1 { 60 t.Error("sp.AgeOfLastImprovement", 1, sp.AgeOfLastImprovement) 61 } 62 if sp.MaxFitnessEver != 15.0 { 63 t.Error("sp.MaxFitnessEver", 15.0, sp.MaxFitnessEver) 64 } 65 if sp.Organisms[2].toEliminate != true { 66 t.Error("sp.Organisms[2].ToEliminate", true, sp.Organisms[2].toEliminate) 67 } 68 } 69 70 // Tests Species countOffspring 71 func TestSpecies_countOffspring(t *testing.T) { 72 sp, err := buildSpeciesWithOrganisms(1) 73 if err != nil { 74 t.Error(err) 75 return 76 } 77 78 for i, o := range sp.Organisms { 79 o.ExpectedOffspring = float64(i) * 1.5 80 } 81 82 expectedOffspring, skim := sp.countOffspring(0.5) 83 sp.ExpectedOffspring = expectedOffspring 84 85 if sp.ExpectedOffspring != 5 { 86 t.Error("sp.ExpectedOffspring", 5, sp.ExpectedOffspring) 87 return 88 } 89 if skim != 0 { 90 t.Error("skim", 0, skim) 91 return 92 } 93 94 sp, err = buildSpeciesWithOrganisms(2) 95 if err != nil { 96 t.Error(err) 97 return 98 } 99 100 for i, o := range sp.Organisms { 101 o.ExpectedOffspring = float64(i) * 1.5 102 } 103 expectedOffspring, skim = sp.countOffspring(0.4) 104 sp.ExpectedOffspring = expectedOffspring 105 if sp.ExpectedOffspring != 4 { 106 t.Error("sp.ExpectedOffspring", 5, sp.ExpectedOffspring) 107 return 108 } 109 if skim != 0.9 { 110 t.Error("skim", 0.9, skim) 111 return 112 } 113 } 114 115 func TestSpecies_computeMaxFitness(t *testing.T) { 116 sp, err := buildSpeciesWithOrganisms(1) 117 if err != nil { 118 t.Error(err) 119 return 120 } 121 avg_check := 0.0 122 for _, o := range sp.Organisms{ 123 avg_check += o.Fitness 124 } 125 avg_check /= float64(len(sp.Organisms)) 126 127 max, avg := sp.ComputeMaxAndAvgFitness() 128 if max != 15.0 { 129 t.Error("sp.MaxFitness != 15.0", 15.0, max) 130 } 131 if avg != avg_check { 132 t.Error("sp.AvgFitness != avg_check", avg, avg_check) 133 } 134 } 135 136 func TestSpecies_findChampion(t *testing.T) { 137 sp, err := buildSpeciesWithOrganisms(1) 138 if err != nil { 139 t.Error(err) 140 return 141 } 142 143 champ := sp.findChampion() 144 if champ.Fitness != 15.0 { 145 t.Error("champ.Fitness != 15.0", champ.Fitness) 146 } 147 148 } 149 150 func TestSpecies_removeOrganism(t *testing.T) { 151 sp, err := buildSpeciesWithOrganisms(1) 152 if err != nil { 153 t.Error(err) 154 return 155 } 156 157 // test remove 158 size := len(sp.Organisms) 159 res, err := sp.removeOrganism(sp.Organisms[0]) 160 if res != true { 161 t.Error("res != true", res, err) 162 } 163 if err != nil { 164 t.Error("err != nil", err) 165 } 166 if size - 1 != len(sp.Organisms) { 167 t.Error("size - 1 != len(sp.Organisms)", size - 1, len(sp.Organisms)) 168 } 169 170 // test fail to remove 171 size = len(sp.Organisms) 172 gen := buildTestGenome(2) 173 org, err := NewOrganism(6.0, gen, 1) 174 if err != nil { 175 t.Error(err) 176 return 177 } 178 res, err = sp.removeOrganism(org) 179 if res == true { 180 t.Error("res == true", res, err) 181 } 182 if err == nil { 183 t.Error("err == nil", res, err) 184 } 185 if size != len(sp.Organisms) { 186 t.Error("size != len(sp.Organisms)", size, len(sp.Organisms)) 187 } 188 } 189 190 // Tests Species reproduce failure 191 func TestSpecies_reproduce_fail(t *testing.T) { 192 sp := NewSpecies(1) 193 194 sp.ExpectedOffspring = 1 195 196 babies, err := sp.reproduce(1, nil, nil, nil) 197 if babies != nil { 198 t.Error("babies != nil") 199 } 200 if err == nil { 201 t.Error("err == nil") 202 } 203 } 204 205 // Tests Species reproduce success 206 func TestSpecies_reproduce(t *testing.T) { 207 rand.Seed(42) 208 in, out, nmax, n := 3, 2, 15, 3 209 recurrent := false 210 link_prob := 0.8 211 212 // Configuration 213 conf := neat.NeatContext { 214 DropOffAge:5, 215 SurvivalThresh:0.5, 216 AgeSignificance:0.5, 217 PopSize:30, 218 CompatThreshold:0.6, 219 } 220 neat.LogLevel = neat.LogLevelInfo 221 222 gen := newGenomeRand(1, in, out, n, nmax, recurrent, link_prob) 223 pop, err := NewPopulation(gen, &conf) 224 if err != nil { 225 t.Error(err) 226 } 227 if pop == nil { 228 t.Error("pop == nil") 229 } 230 231 // Stick the Species pointers into a new Species list for sorting 232 sorted_species := make([]*Species, len(pop.Species)) 233 copy(sorted_species, pop.Species) 234 235 // Sort the Species by max original fitness of its first organism 236 sort.Sort(byOrganismOrigFitness(sorted_species)) 237 238 pop.Species[0].ExpectedOffspring = 11 239 240 babies, err := pop.Species[0].reproduce(1, pop, sorted_species, &conf) 241 if babies == nil { 242 t.Error("No reproduction", err) 243 } 244 if err != nil { 245 t.Error("err != nil", err) 246 } 247 248 if len(babies) != pop.Species[0].ExpectedOffspring { 249 t.Error("Wrong number of babies was created", len(babies)) 250 } 251 }