189 lines
3.9 KiB
Go
189 lines
3.9 KiB
Go
|
package gago
|
||
|
|
||
|
import (
|
||
|
"math"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
func TestNewIndividuals(t *testing.T) {
|
||
|
var rng = newRandomNumberGenerator()
|
||
|
for _, n := range []int{1, 2, 42} {
|
||
|
var indis = newIndividuals(n, NewVector, rng)
|
||
|
if len(indis) != n {
|
||
|
t.Error("newIndividuals didn't generate the right number of individuals")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestCloneIndividuals(t *testing.T) {
|
||
|
var (
|
||
|
rng = newRandomNumberGenerator()
|
||
|
indis = newIndividuals(20, NewVector, rng)
|
||
|
clones = indis.Clone(rng)
|
||
|
)
|
||
|
for _, indi := range indis {
|
||
|
for _, clone := range clones {
|
||
|
if &indi == &clone || indi.ID == clone.ID {
|
||
|
t.Error("Cloning did not work as expected")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestEvaluateIndividuals(t *testing.T) {
|
||
|
var indis = newIndividuals(10, NewVector, newRandomNumberGenerator())
|
||
|
for _, indi := range indis {
|
||
|
if indi.Evaluated {
|
||
|
t.Error("Individual shouldn't have Evaluated set to True")
|
||
|
}
|
||
|
}
|
||
|
indis.Evaluate()
|
||
|
for _, indi := range indis {
|
||
|
if !indi.Evaluated {
|
||
|
t.Error("Individual should have Evaluated set to True")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestMutateIndividuals(t *testing.T) {
|
||
|
var (
|
||
|
rng = newRandomNumberGenerator()
|
||
|
indis = newIndividuals(10, NewVector, rng)
|
||
|
)
|
||
|
indis.Evaluate()
|
||
|
indis.Mutate(1, rng)
|
||
|
for _, indi := range indis {
|
||
|
if indi.Evaluated {
|
||
|
t.Error("Individual shouldn't have Evaluated set to True")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestIndividualsSortByFitness(t *testing.T) {
|
||
|
var indis = newIndividuals(10, NewVector, newRandomNumberGenerator())
|
||
|
// Assign a fitness to each individual in decreasing order
|
||
|
for i := range indis {
|
||
|
indis[i].Fitness = float64(len(indis) - i)
|
||
|
}
|
||
|
indis.SortByFitness()
|
||
|
// Check fitnesses are in increasing order
|
||
|
for i := 1; i < len(indis); i++ {
|
||
|
if indis[i-1].Fitness > indis[i].Fitness {
|
||
|
t.Error("Individuals are not sorted")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestGetFitnesses(t *testing.T) {
|
||
|
var (
|
||
|
indis = Individuals{
|
||
|
Individual{Fitness: 0.0},
|
||
|
Individual{Fitness: 1.0},
|
||
|
Individual{Fitness: 2.0},
|
||
|
}
|
||
|
target = []float64{0.0, 1.0, 2.0}
|
||
|
fitnesses = indis.getFitnesses()
|
||
|
)
|
||
|
for i, fitness := range fitnesses {
|
||
|
if fitness != target[i] {
|
||
|
t.Error("getFitnesses didn't work as expected")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestFitMin(t *testing.T) {
|
||
|
var testCases = []struct {
|
||
|
indis Individuals
|
||
|
min float64
|
||
|
}{
|
||
|
{Individuals{
|
||
|
Individual{Fitness: 1.0},
|
||
|
}, 1.0},
|
||
|
{Individuals{
|
||
|
Individual{Fitness: 2.0},
|
||
|
Individual{Fitness: 1.0},
|
||
|
}, 1.0},
|
||
|
{Individuals{
|
||
|
Individual{Fitness: 1.0},
|
||
|
Individual{Fitness: -1.0},
|
||
|
}, -1.0},
|
||
|
}
|
||
|
for _, test := range testCases {
|
||
|
if test.indis.FitMin() != test.min {
|
||
|
t.Error("FitMin didn't work as expected")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestFitMax(t *testing.T) {
|
||
|
var testCases = []struct {
|
||
|
indis Individuals
|
||
|
max float64
|
||
|
}{
|
||
|
{Individuals{
|
||
|
Individual{Fitness: 1.0},
|
||
|
}, 1.0},
|
||
|
{Individuals{
|
||
|
Individual{Fitness: 2.0},
|
||
|
Individual{Fitness: 1.0},
|
||
|
}, 2.0},
|
||
|
{Individuals{
|
||
|
Individual{Fitness: 1.0},
|
||
|
Individual{Fitness: -1.0},
|
||
|
}, 1.0},
|
||
|
}
|
||
|
for _, test := range testCases {
|
||
|
if test.indis.FitMax() != test.max {
|
||
|
t.Error("FitMax didn't work as expected")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestFitAvg(t *testing.T) {
|
||
|
var testCases = []struct {
|
||
|
indis Individuals
|
||
|
mean float64
|
||
|
}{
|
||
|
{Individuals{
|
||
|
Individual{Fitness: 1.0},
|
||
|
}, 1.0},
|
||
|
{Individuals{
|
||
|
Individual{Fitness: 1.0},
|
||
|
Individual{Fitness: 2.0},
|
||
|
}, 1.5},
|
||
|
{Individuals{
|
||
|
Individual{Fitness: -1.0},
|
||
|
Individual{Fitness: 1.0},
|
||
|
}, 0.0},
|
||
|
}
|
||
|
for _, test := range testCases {
|
||
|
if test.indis.FitAvg() != test.mean {
|
||
|
t.Error("FitAvg didn't work as expected")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestFitStd(t *testing.T) {
|
||
|
var testCases = []struct {
|
||
|
indis Individuals
|
||
|
variance float64
|
||
|
}{
|
||
|
{Individuals{
|
||
|
Individual{Fitness: 1.0},
|
||
|
}, 0.0},
|
||
|
{Individuals{
|
||
|
Individual{Fitness: -1.0},
|
||
|
Individual{Fitness: 1.0},
|
||
|
}, 1.0},
|
||
|
{Individuals{
|
||
|
Individual{Fitness: -2.0},
|
||
|
Individual{Fitness: 2.0},
|
||
|
}, 4.0},
|
||
|
}
|
||
|
for _, test := range testCases {
|
||
|
if test.indis.FitStd() != math.Sqrt(test.variance) {
|
||
|
t.Error("FitStd didn't work as expected")
|
||
|
}
|
||
|
}
|
||
|
}
|