-
Notifications
You must be signed in to change notification settings - Fork 0
/
visualization.go
113 lines (106 loc) · 2.94 KB
/
visualization.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
package main
import (
"fmt"
"os"
"gonum.org/v1/plot"
"gonum.org/v1/plot/palette/moreland"
"gonum.org/v1/plot/plotter"
"gonum.org/v1/plot/vg"
)
const NumLoggedChromosomesPerIteration = 5
// Adapted from: https://medium.com/@balazs.dianiska/generating-heatmaps-with-go-83988b22c000
type plottable struct {
grid [][]int
width int
height int
}
func (p plottable) Dims() (c, r int) {
return p.width, p.height
}
func (p plottable) X(c int) float64 {
return float64(c)
}
func (p plottable) Y(r int) float64 {
return float64(r)
}
func (p plottable) Z(c, r int) float64 {
return float64(p.grid[c][r])
}
func (g *GeneticAlgorithm) VisualizeChromosomes(chromosomes []Chromosome, iteration int, dir string) error {
err := os.MkdirAll(dir, 0o755)
if err != nil {
return err
}
factoryFrequencies := make([][]int, g.scenario.width)
for i := range factoryFrequencies {
factoryFrequencies[i] = make([]int, g.scenario.height)
}
combinerFrequencies := make([][]int, g.scenario.width)
for i := range combinerFrequencies {
combinerFrequencies[i] = make([]int, g.scenario.height)
}
conveyorFrequencies := make([][]int, g.scenario.width)
for i := range conveyorFrequencies {
conveyorFrequencies[i] = make([]int, g.scenario.height)
}
mineFrequencies := make([][]int, g.scenario.width)
for i := range mineFrequencies {
mineFrequencies[i] = make([]int, g.scenario.height)
}
for _, c := range chromosomes {
for _, f := range c.factories {
f.Rectangle().ForEach(func(p Position) {
factoryFrequencies[p.x][g.scenario.height-1-p.y] += 1
})
}
for _, combiner := range c.combiners {
combiner.RectanglesEach(func(r Rectangle) {
r.ForEach(func(p Position) {
combinerFrequencies[p.x][g.scenario.height-1-p.y] += 1
})
})
}
for _, path := range c.paths {
for _, conveyor := range path.conveyors {
conveyor.Rectangle().ForEach(func(p Position) {
conveyorFrequencies[p.x][g.scenario.height-1-p.y] += 1
})
}
}
for _, mine := range c.mines {
mine.RectanglesEach(func(r Rectangle) {
r.ForEach(func(p Position) {
mineFrequencies[p.x][g.scenario.height-1-p.y] += 1
})
})
}
}
err = saveGrid(factoryFrequencies, fmt.Sprintf("%s/f_iteration_%d.png", dir, iteration))
if err != nil {
return err
}
err = saveGrid(combinerFrequencies, fmt.Sprintf("%s/com_iteration_%d.png", dir, iteration))
if err != nil {
return err
}
err = saveGrid(conveyorFrequencies, fmt.Sprintf("%s/con_iteration_%d.png", dir, iteration))
if err != nil {
return err
}
return saveGrid(mineFrequencies, fmt.Sprintf("%s/m_iteration_%d.png", dir, iteration))
}
func saveGrid(grid [][]int, path string) error {
width := len(grid)
height := len(grid[0])
plotData := plottable{
grid: grid,
width: width,
height: height,
}
p := plot.New()
pal := moreland.SmoothBlueRed().Palette(255)
hm := plotter.NewHeatMap(plotData, pal)
p.Add(hm)
p.HideAxes()
return p.Save(vg.Length(width)*vg.Inch*0.1, vg.Length(height)*vg.Inch*0.1, path)
}