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  }