123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- package genetic
- import (
- "fmt"
- "log"
- "math/rand"
- "sort"
- neuralnetwork "../neuralnetwork"
- )
- type PopulationConfig struct {
- PopulationSize int
- SelectionSize float64 // 0..1 persentage of success individuals to be used as parents for population
- CrossbreedPart float64 // 0..1 persentage of weights and biases to be exchanged beetween individuals while Crossbreed
- }
- type Population struct {
- populationConfig *PopulationConfig
- Networks []*neuralnetwork.NeuralNetwork
- verifier PopulationVerifier
- mutagen Mutagen
- }
- func NewPopulation(verifier PopulationVerifier, mutagen Mutagen, populationConfig PopulationConfig, sizes []int) (p *Population) {
- if populationConfig.PopulationSize%2 != 0 {
- return nil
- }
- p = &Population{
- populationConfig: &populationConfig,
- Networks: make([]*neuralnetwork.NeuralNetwork, populationConfig.PopulationSize),
- verifier: verifier,
- mutagen: mutagen,
- }
- for i := 0; i < populationConfig.PopulationSize; i++ {
- var err error
- p.Networks[i], err = neuralnetwork.NewNeuralNetwork(sizes, nil)
- if err != nil {
- log.Fatal("Could not initialize NeuralNetwork")
- }
- }
- return
- }
- func (p *Population) NaturalSelection(generationCount int) {
- for g := 0; g < generationCount; g++ {
- p.crossbreedPopulation(p.verifier.Verify(p))
- }
- }
- func (p *Population) crossbreedPopulation(results []*IndividalResult) {
- sort.SliceStable(results, func(i, j int) bool {
- return results[i].Result > results[j].Result //Descent order best will be on top, worst in the bottom
- })
- etalons := int(float64(p.populationConfig.PopulationSize) * p.populationConfig.SelectionSize)
- for i := 1; i < p.populationConfig.PopulationSize; i += 2 {
- firstParentBase := results[i%etalons].Index
- secondParentBase := results[(i-1)%etalons].Index
- firstParent := results[i].Index
- secondParent := results[i-1].Index
- fmt.Printf("Result index %v value %v i %v\n", results[i].Index, results[i].Result, i)
- p.Networks[firstParent] = p.Networks[firstParentBase].Copy()
- p.Networks[secondParent] = p.Networks[secondParentBase].Copy()
- crossbreed(p.Networks[firstParent], p.Networks[secondParent], p.populationConfig.CrossbreedPart)
- p.mutagen.Mutate(p.Networks[firstParent])
- p.mutagen.Mutate(p.Networks[secondParent])
- }
- }
- func crossbreed(firstParent, secondParent *neuralnetwork.NeuralNetwork, crossbreedPart float64) {
- for l := 1; l < firstParent.LayerCount; l++ {
- firstParentWeights := firstParent.Weights[l]
- secondParentWeights := secondParent.Weights[l]
- firstParentBiases := firstParent.Biases[l]
- secondParentBiases := secondParent.Biases[l]
- r, c := firstParentWeights.Dims()
- rp := int(float64(r) * crossbreedPart)
- cp := int(float64(c) * crossbreedPart)
- r = int(rand.Uint32())%(r-rp) + rp
- c = int(rand.Uint32())%(c-cp) + cp
- // for i := 0; i < int(float64(r)*crossbreedPart); i++ {
- for i := 0; i < r; i++ {
- for j := 0; j < c; j++ {
- // Swap first half of weights
- w := firstParentWeights.At(i, j)
- firstParentWeights.Set(i, j, secondParentWeights.At(i, j))
- secondParentWeights.Set(i, j, w)
- }
- // Swap first half of biases
- b := firstParentBiases.At(i, 0)
- firstParentBiases.Set(i, 0, secondParentBiases.At(i, 0))
- secondParentBiases.Set(i, 0, b)
- }
- }
- }
|