-
Notifications
You must be signed in to change notification settings - Fork 1
/
model.go
121 lines (104 loc) · 2.99 KB
/
model.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package main
import (
"fmt"
"os"
"sync"
"time"
"github.com/dmarkham/goNEAT/experiments"
"github.com/dmarkham/goNEAT/neat"
"github.com/dmarkham/goNEAT/neat/genetics"
"github.com/hajimehoshi/ebiten"
)
type ModelEvaluator struct {
sync.Mutex
OutputPath string
g *Game
tick uint64
}
func (ex *ModelEvaluator) Draw(screen *ebiten.Image) error {
ex.Lock()
defer ex.Unlock()
if ex.g == nil {
return nil
}
ex.g.Draw(screen)
ex.tick = ex.g.steps
return nil
}
func (ex *ModelEvaluator) GenerationEvaluate(pop *genetics.Population, epoch *experiments.Generation, context *neat.NeatContext) error {
ex.Lock()
g := NewGame(pop)
ex.g = g
ex.Unlock()
for {
time.Sleep(time.Millisecond * 14)
ex.Lock()
err := g.Update()
ex.Unlock()
if err != nil {
break
}
}
// Evaluate each organism on a test
b := 0.0
for _, org := range pop.Organisms {
if org.Fitness > b {
b = org.Fitness
}
winner := org.IsWinner
if winner && (epoch.Best == nil || org.Fitness > epoch.Best.Fitness) {
epoch.Solved = true
epoch.WinnerNodes = len(org.Genotype.Nodes)
epoch.WinnerGenes = org.Genotype.Extrons()
epoch.WinnerEvals = context.PopSize*epoch.Id + org.Genotype.Id
epoch.Best = org
org.IsWinner = true
}
}
fmt.Printf("Generation: %v Best: %.06f Last Pop %.06f\n", epoch.Id, pop.HighestFitness, b)
epoch.FillPopulationStatistics(pop)
//fmt.Println("Best: ", pop.HighestFitness)
// Only print to file every print_every generations
if epoch.Solved || epoch.Id%context.PrintEvery == 0 {
pop_path := fmt.Sprintf("%s/gen_%d", experiments.OutDirForTrial(ex.OutputPath, epoch.TrialId), epoch.Id)
file, err := os.Create(pop_path)
if err != nil {
neat.ErrorLog(fmt.Sprintf("Failed to dump population, reason: %s\n", err))
} else {
pop.WriteBySpecies(file)
}
}
if b > .30 {
org := epoch.Best
orgPath := fmt.Sprintf("%s/%s_%.8f_%d-%d", experiments.OutDirForTrial(ex.OutputPath, epoch.TrialId),
"best", org.Fitness, org.Phenotype.NodeCount(), org.Phenotype.LinkCount())
file, err := os.Create(orgPath)
if err != nil {
neat.ErrorLog(fmt.Sprintf("Failed to dump best organism genome, reason: %s\n", err))
} else {
org.Genotype.Write(file)
neat.InfoLog(fmt.Sprintf("Generation #%d best %d dumped to: %s\n", epoch.Id, org.Genotype.Id, orgPath))
}
file.Close()
}
if epoch.Solved {
// print winner organism
for _, org := range pop.Organisms {
if org.IsWinner {
// Prints the winner organism to file!
orgPath := fmt.Sprintf("%s/%s_%.1f_%d-%d", experiments.OutDirForTrial(ex.OutputPath, epoch.TrialId),
"winner", org.Fitness, org.Phenotype.NodeCount(), org.Phenotype.LinkCount())
file, err := os.Create(orgPath)
if err != nil {
neat.ErrorLog(fmt.Sprintf("Failed to dump winner organism genome, reason: %s\n", err))
} else {
org.Genotype.Write(file)
neat.InfoLog(fmt.Sprintf("Generation #%d winner %d dumped to: %s\n", epoch.Id, org.Genotype.Id, orgPath))
}
break
}
}
return nil
}
return nil
}