ソースを参照

Fix some issues in crossbreed

Alexey Edelev 5 年 前
コミット
ade1c6d401

+ 23 - 14
neuralnetwork/genetic/genetic.go

@@ -3,7 +3,6 @@ package genetic
 import (
 	"fmt"
 	"log"
-	"math/rand"
 
 	"sort"
 
@@ -58,14 +57,24 @@ func (p *Population) crossbreedPopulation(results []*IndividalResult) {
 	})
 
 	etalons := int(float64(p.populationConfig.PopulationSize) * p.populationConfig.SelectionSize)
+	if etalons%2 != 0 {
+		etalons -= 1
+	}
+	etalonNetworks := make([]*neuralnetwork.NeuralNetwork, etalons)
+	for i := 1; i < etalons; i += 2 {
+		firstParentBase := results[i-1].Index
+		secondParentBase := results[i].Index
+		etalonNetworks[i-1] = p.Networks[firstParentBase].Copy()
+		etalonNetworks[i] = p.Networks[secondParentBase].Copy()
+	}
 	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()
+		firstParentBase := etalonNetworks[(i-1)%etalons]
+		secondParentBase := etalonNetworks[i%etalons]
+		firstParent := results[i-1].Index
+		secondParent := results[i].Index
+		fmt.Printf("Result value %v i %v firstParent %v secondParent %v\n", results[i].Result, i, firstParent, secondParent)
+		p.Networks[firstParent] = firstParentBase.Copy()
+		p.Networks[secondParent] = secondParentBase.Copy()
 		crossbreed(p.Networks[firstParent], p.Networks[secondParent], p.populationConfig.CrossbreedPart)
 		p.mutagen.Mutate(p.Networks[firstParent])
 		p.mutagen.Mutate(p.Networks[secondParent])
@@ -79,12 +88,12 @@ func crossbreed(firstParent, secondParent *neuralnetwork.NeuralNetwork, crossbre
 		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++ {
+		// rp := int(float64(r) * crossbreedPart)
+		// cp := int(float64(c) * crossbreedPart)
+		// r = int(rand.Uint32()) % r //(r-rp) + rp
+		// c = int(rand.Uint32()) % c //(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)

+ 3 - 3
neuralnetwork/genetic/mutagen/dummymutagen.go

@@ -8,10 +8,10 @@ import (
 )
 
 type DummyMutagen struct {
-	chance uint32
+	chance float64
 }
 
-func NewDummyMutagen(chance uint32) (rm *DummyMutagen) {
+func NewDummyMutagen(chance float64) (rm *DummyMutagen) {
 	rm = &DummyMutagen{
 		chance: chance,
 	}
@@ -22,7 +22,7 @@ func (rm *DummyMutagen) Mutate(network *neuralnetwork.NeuralNetwork) {
 	rand.Seed(time.Now().UnixNano())
 	for l := 1; l < network.LayerCount; l++ {
 		randomized := rand.Float64()
-		if randomized < (float64(rm.chance) / 100.0) {
+		if randomized < rm.chance {
 			r, c := network.Weights[l].Dims()
 			for o := 0; o < 10; o++ {
 				mutationRow := int(rand.Uint32()) % r

+ 1 - 1
neuralnetwork/main.go

@@ -12,7 +12,7 @@ func main() {
 	go rc.Run()
 	s := snakesimulator.NewSnakeSimulator()
 	s.StartServer()
-	p := genetic.NewPopulation(s, mutagen.NewDummyMutagen(50), genetic.PopulationConfig{PopulationSize: 500, SelectionSize: 0.05, CrossbreedPart: 0.2}, []int{24, 20, 20, 4})
+	p := genetic.NewPopulation(s, mutagen.NewDummyMutagen(50), genetic.PopulationConfig{PopulationSize: 500, SelectionSize: 0.05, CrossbreedPart: 0.2}, []int{8, 18, 18, 4})
 	for _, net := range p.Networks {
 		net.SetStateWatcher(rc)
 	}

+ 1 - 1
neuralnetwork/neuralnetwork/neuralnetwork.go

@@ -155,7 +155,7 @@ func (nn *NeuralNetwork) Copy() (outNN *NeuralNetwork) {
 		WGradient:                  make([]interface{}, nn.LayerCount),
 		gradientDescentInitializer: nn.gradientDescentInitializer,
 	}
-	for l := 1; l < nn.LayerCount; l++ {
+	for l := 1; l < outNN.LayerCount; l++ {
 		outNN.Biases[l] = mat.DenseCopyOf(nn.Biases[l])
 		outNN.Weights[l] = mat.DenseCopyOf(nn.Weights[l])
 		if outNN.gradientDescentInitializer != nil {

+ 117 - 110
neuralnetwork/snakesimulator/snakesimulator.go

@@ -57,42 +57,48 @@ func (s *SnakeSimulator) Verify(population *genetic.Population) (results []*gene
 	for index, inidividual := range population.Networks {
 		s.stats.Individual = uint32(index)
 		s.statsUpdateQueue <- true
-
-		rand.Seed(time.Now().UnixNano())
-		switch rand.Uint32() % 4 {
-		case 1:
-			s.snake = &Snake{
-				Points: []*Point{
-					&Point{X: 20, Y: 20},
-					&Point{X: 21, Y: 20},
-					&Point{X: 22, Y: 20},
-				},
-			}
-		case 2:
-			s.snake = &Snake{
-				Points: []*Point{
-					&Point{X: 22, Y: 20},
-					&Point{X: 21, Y: 20},
-					&Point{X: 20, Y: 20},
-				},
-			}
-		case 3:
-			s.snake = &Snake{
-				Points: []*Point{
-					&Point{X: 20, Y: 20},
-					&Point{X: 20, Y: 21},
-					&Point{X: 20, Y: 22},
-				},
-			}
-		default:
-			s.snake = &Snake{
-				Points: []*Point{
-					&Point{X: 20, Y: 22},
-					&Point{X: 20, Y: 21},
-					&Point{X: 20, Y: 20},
-				},
-			}
+		s.snake = &Snake{
+			Points: []*Point{
+				&Point{X: 19, Y: 20},
+				&Point{X: 20, Y: 20},
+				&Point{X: 21, Y: 20},
+			},
 		}
+		// rand.Seed(time.Now().UnixNano())
+		// switch rand.Uint32() % 4 {
+		// case 1:
+		// 	s.snake = &Snake{
+		// 		Points: []*Point{
+		// 			&Point{X: 20, Y: 20},
+		// 			&Point{X: 21, Y: 20},
+		// 			&Point{X: 22, Y: 20},
+		// 		},
+		// 	}
+		// case 2:
+		// 	s.snake = &Snake{
+		// 		Points: []*Point{
+		// 			&Point{X: 22, Y: 20},
+		// 			&Point{X: 21, Y: 20},
+		// 			&Point{X: 20, Y: 20},
+		// 		},
+		// 	}
+		// case 3:
+		// 	s.snake = &Snake{
+		// 		Points: []*Point{
+		// 			&Point{X: 20, Y: 20},
+		// 			&Point{X: 20, Y: 21},
+		// 			&Point{X: 20, Y: 22},
+		// 		},
+		// 	}
+		// default:
+		// 	s.snake = &Snake{
+		// 		Points: []*Point{
+		// 			&Point{X: 20, Y: 22},
+		// 			&Point{X: 20, Y: 21},
+		// 			&Point{X: 20, Y: 20},
+		// 		},
+		// 	}
+		// }
 
 		i := 0
 		s.stats.Move = 0
@@ -160,19 +166,20 @@ func (s *SnakeSimulator) Verify(population *genetic.Population) (results []*gene
 		}
 
 		results[index] = &genetic.IndividalResult{
-			Result: float64(len(s.snake.Points)-2) * float64(s.stats.Move),
-			// Result: float64(s.stats.Move),
-			Index: index,
+			// Result: float64(len(s.snake.Points)-2) * float64(s.stats.Move),
+			Result: float64(s.stats.Move),
+			Index:  index,
 		}
 	}
+
 	return
 }
 
 func (s *SnakeSimulator) GetHeadState() []float64 {
 	headX := float64(s.snake.Points[0].X)
 	headY := float64(s.snake.Points[0].Y)
-	tailX := float64(s.snake.Points[len(s.snake.Points)-1].X)
-	tailY := float64(s.snake.Points[len(s.snake.Points)-1].Y)
+	// tailX := float64(s.snake.Points[len(s.snake.Points)-1].X)
+	// tailY := float64(s.snake.Points[len(s.snake.Points)-1].Y)
 	// prevX := float64(s.snake.Points[1].X)
 	// prevY := float64(s.snake.Points[1].Y)
 	foodX := float64(s.field.Food.X)
@@ -210,10 +217,10 @@ func (s *SnakeSimulator) GetHeadState() []float64 {
 	tFood := float64(height)
 	bFood := float64(height)
 
-	tlFood := float64(diag)
-	trFood := float64(diag)
-	blFood := float64(diag)
-	brFood := float64(diag)
+	// tlFood := float64(diag)
+	// trFood := float64(diag)
+	// blFood := float64(diag)
+	// brFood := float64(diag)
 	tlWall := float64(0)
 	trWall := float64(0)
 	blWall := float64(0)
@@ -241,21 +248,21 @@ func (s *SnakeSimulator) GetHeadState() []float64 {
 		}
 	}
 
-	if math.Abs(foodY-headY) == math.Abs(foodX-headX) {
-		if foodX > headX {
-			if foodY > headY {
-				trFood = math.Abs(foodX-headX) * math.Sqrt2
-			} else {
-				brFood = math.Abs(foodX-headX) * math.Sqrt2
-			}
-		} else {
-			if foodY > headY {
-				tlFood = math.Abs(foodX-headX) * math.Sqrt2
-			} else {
-				blFood = math.Abs(foodX-headX) * math.Sqrt2
-			}
-		}
-	}
+	// if math.Abs(foodY-headY) == math.Abs(foodX-headX) {
+	// 	if foodX > headX {
+	// 		if foodY > headY {
+	// 			trFood = math.Abs(foodX-headX) * math.Sqrt2
+	// 		} else {
+	// 			brFood = math.Abs(foodX-headX) * math.Sqrt2
+	// 		}
+	// 	} else {
+	// 		if foodY > headY {
+	// 			tlFood = math.Abs(foodX-headX) * math.Sqrt2
+	// 		} else {
+	// 			blFood = math.Abs(foodX-headX) * math.Sqrt2
+	// 		}
+	// 	}
+	// }
 
 	if lWall > tWall {
 		tlWall = float64(tWall) * math.Sqrt2
@@ -305,68 +312,68 @@ func (s *SnakeSimulator) GetHeadState() []float64 {
 		brWall = float64(rWall) * math.Sqrt2
 	}
 
-	tTail := (headY - tailY)
-	if tTail < 0 {
-		tTail = height
-	}
-	bTail := (tailY - headY)
-	if bTail < 0 {
-		bTail = height
-	}
-	lTail := (headX - tailX)
-	if lTail < 0 {
-		tTail = width
-	}
-	rTail := (tailX - headX)
-	if lTail < 0 {
-		tTail = width
-	}
+	// tTail := (headY - tailY)
+	// if tTail < 0 {
+	// 	tTail = height
+	// }
+	// bTail := (tailY - headY)
+	// if bTail < 0 {
+	// 	bTail = height
+	// }
+	// lTail := (headX - tailX)
+	// if lTail < 0 {
+	// 	tTail = width
+	// }
+	// rTail := (tailX - headX)
+	// if lTail < 0 {
+	// 	tTail = width
+	// }
 
-	tlTail := float64(diag)
-	trTail := float64(diag)
-	blTail := float64(diag)
-	brTail := float64(diag)
-	if math.Abs(headY-tailY) == math.Abs(headX-tailX) {
-		if tailY > headY {
-			if tailX > headX {
-				trTail = math.Abs(tailX-headX) * math.Sqrt2
-			} else {
-				tlTail = math.Abs(tailX-headX) * math.Sqrt2
-			}
-		} else {
-			if tailX > headX {
-				brTail = math.Abs(tailX-headX) * math.Sqrt2
-			} else {
-				blTail = math.Abs(tailX-headX) * math.Sqrt2
-			}
-		}
-	}
+	// tlTail := float64(diag)
+	// trTail := float64(diag)
+	// blTail := float64(diag)
+	// brTail := float64(diag)
+	// if math.Abs(headY-tailY) == math.Abs(headX-tailX) {
+	// 	if tailY > headY {
+	// 		if tailX > headX {
+	// 			trTail = math.Abs(tailX-headX) * math.Sqrt2
+	// 		} else {
+	// 			tlTail = math.Abs(tailX-headX) * math.Sqrt2
+	// 		}
+	// 	} else {
+	// 		if tailX > headX {
+	// 			brTail = math.Abs(tailX-headX) * math.Sqrt2
+	// 		} else {
+	// 			blTail = math.Abs(tailX-headX) * math.Sqrt2
+	// 		}
+	// 	}
+	// }
 
 	return []float64{
 		lWall / width,
 		rWall / width,
 		tWall / height,
 		bWall / height,
-		(1.0 - lFood/width),
-		(1.0 - rFood/width),
-		(1.0 - tFood/height),
-		(1.0 - bFood/height),
+		// (1.0 - lFood/width),
+		// (1.0 - rFood/width),
+		// (1.0 - tFood/height),
+		// (1.0 - bFood/height),
 		tlWall / diag,
 		trWall / diag,
 		blWall / diag,
 		brWall / diag,
-		(1.0 - tlFood/diag),
-		(1.0 - trFood/diag),
-		(1.0 - blFood/diag),
-		(1.0 - brFood/diag),
-		tTail / height,
-		bTail / height,
-		lTail / width,
-		rTail / width,
-		tlTail / diag,
-		trTail / diag,
-		blTail / diag,
-		brTail / diag,
+		// (1.0 - tlFood/diag),
+		// (1.0 - trFood/diag),
+		// (1.0 - blFood/diag),
+		// (1.0 - brFood/diag),
+		// tTail / height,
+		// bTail / height,
+		// lTail / width,
+		// rTail / width,
+		// tlTail / diag,
+		// trTail / diag,
+		// blTail / diag,
+		// brTail / diag,
 	}
 }