genetic.go 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package genetic
  2. import (
  3. "log"
  4. "sort"
  5. neuralnetwork "../neuralnetwork"
  6. )
  7. type PopulationConfig struct {
  8. PopulationSize int
  9. SelectionSize float64 // 0..1 persentage of success individuals to be used as parents for population
  10. CrossbreedPart float64 // 0..1 persentage of weights and biases to be exchanged beetween individuals while Crossbreed
  11. }
  12. type Population struct {
  13. populationConfig *PopulationConfig
  14. Networks []*neuralnetwork.NeuralNetwork
  15. verifier PopulationVerifier
  16. mutagen Mutagen
  17. }
  18. func NewPopulation(verifier PopulationVerifier, mutagen Mutagen, populationConfig PopulationConfig, sizes []int) (p *Population) {
  19. if populationConfig.PopulationSize%2 != 0 {
  20. return nil
  21. }
  22. p = &Population{
  23. populationConfig: &populationConfig,
  24. Networks: make([]*neuralnetwork.NeuralNetwork, populationConfig.PopulationSize),
  25. verifier: verifier,
  26. mutagen: mutagen,
  27. }
  28. for i := 0; i < populationConfig.PopulationSize; i++ {
  29. var err error
  30. p.Networks[i], err = neuralnetwork.NewNeuralNetwork(sizes, nil)
  31. if err != nil {
  32. log.Fatal("Could not initialize NeuralNetwork")
  33. }
  34. }
  35. return
  36. }
  37. func (p *Population) NaturalSelection(generationCount int) {
  38. for g := 0; g < generationCount; g++ {
  39. p.crossbreedPopulation(p.verifier.Verify(p))
  40. }
  41. }
  42. func (p *Population) crossbreedPopulation(results []*IndividalResult) {
  43. sort.Slice(results, func(i, j int) bool {
  44. return results[i].Result < results[j].Result
  45. })
  46. etalons := int(float64(p.populationConfig.PopulationSize) * p.populationConfig.SelectionSize)
  47. for i := 1; i < p.populationConfig.PopulationSize; i += 2 {
  48. firstParentBase := results[i%etalons].Index
  49. secondParentBase := results[(i-1)%etalons].Index
  50. firstParent := results[i].Index
  51. secondParent := results[i-1].Index
  52. p.Networks[firstParent] = p.Networks[firstParentBase].Copy()
  53. p.Networks[secondParent] = p.Networks[secondParentBase].Copy()
  54. crossbreed(p.Networks[firstParent], p.Networks[secondParent], p.populationConfig.CrossbreedPart)
  55. p.mutagen.Mutate(p.Networks[firstParent])
  56. p.mutagen.Mutate(p.Networks[secondParent])
  57. }
  58. }
  59. func crossbreed(firstParent, secondParent *neuralnetwork.NeuralNetwork, crossbreedPart float64) {
  60. for l := 1; l < firstParent.LayerCount; l++ {
  61. firstParentWeights := firstParent.Weights[l]
  62. secondParentWeights := secondParent.Weights[l]
  63. firstParentBiases := firstParent.Biases[l]
  64. secondParentBiases := secondParent.Biases[l]
  65. r, c := firstParentWeights.Dims()
  66. for i := 0; i < int(float64(r)*crossbreedPart); i++ {
  67. for j := 0; j < c; j++ {
  68. // Swap first half of weights
  69. w := firstParentWeights.At(i, j)
  70. firstParentWeights.Set(i, j, secondParentWeights.At(i, j))
  71. secondParentWeights.Set(i, j, w)
  72. }
  73. // Swap first half of biases
  74. b := firstParentBiases.At(i, 0)
  75. firstParentBiases.Set(i, 0, secondParentBiases.At(i, 0))
  76. secondParentBiases.Set(i, 0, b)
  77. }
  78. }
  79. }