-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
128 lines (119 loc) · 3.88 KB
/
main.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
122
123
124
125
126
127
128
package main
import (
"flag"
"log"
"math/rand"
"os"
"runtime/pprof"
"time"
)
// TODO: is this enough when running in docker?
const PercentTimeUsed = 90
const MaxFinishingTime = 2
func main() {
inputPtr := flag.String("input", "-", "Path to input scenario json")
outputPtr := flag.String("output", "-", "Path to output scenario json")
seedPtr := flag.Int64("seed", 0, "Seed for random number generator")
cpuProfilePtr := flag.String("cpuprofile", "", "Path to output cpu profile")
itersPtr := flag.Int("iters", 50, "Number of iterations to run. Use 0 for unlimited")
logChromosomesDirPtr := flag.String("logdir", "", "Directory to log top chromosomes in each iteration")
visualizeChromosomesDirPtr := flag.String("visualizedir", "", "Directory to visualize chromosomes in each iteration")
endOnOptimalPtr := flag.Bool("endonoptimal", false, "End when optimal solution is found")
exportPtr := flag.String("exporter", "scenario", "Export type, either \"scenario\" or \"solution\"")
flag.Parse()
if *inputPtr == "" || *outputPtr == "" {
flag.Usage()
os.Exit(1)
}
if *cpuProfilePtr != "" {
f, err := os.Create(*cpuProfilePtr)
if err != nil {
log.Fatal("could not create cpu profile file: ", err)
}
err = pprof.StartCPUProfile(f)
if err != nil {
log.Fatal("could not start cpu profiling: ", err)
}
defer pprof.StopCPUProfile()
}
var exporter Exporter
if *exportPtr == "scenario" {
exporter = ScenarioExporter{}
} else if *exportPtr == "solution" {
exporter = SolutionExporter{}
} else {
log.Fatal("unknown exporter ", *exportPtr)
}
scenario, _, err := ImportScenario(*inputPtr)
if err != nil {
log.Fatal("could not import scenario: ", err)
}
var seed int64
if *seedPtr != 0 {
seed = *seedPtr
} else {
seed = time.Now().UnixNano()
}
log.Println("using seed", seed)
rand.Seed(seed)
optimum, err := TheoreticalOptimum(scenario)
if err != nil {
log.Println("no theoretical optimum found")
} else {
log.Println("theoretical optimum", optimum)
}
chromosomeChannel := make(chan Chromosome)
doneChannel := make(chan bool)
geneticAlgorithm := GeneticAlgorithm{
scenario: scenario,
populationSize: 100,
iterations: *itersPtr,
moveObjectProbability: 0.18,
numMutatedChromosomes: 50,
numMutationsPerChromosome: 20,
numCrossovers: 10,
optimum: optimum,
chromosomeChannel: chromosomeChannel,
doneChannel: doneChannel,
logChromosomesDir: *logChromosomesDirPtr,
visualizeChromosomesDir: *visualizeChromosomesDirPtr,
}
go geneticAlgorithm.Run()
var timeChannel <-chan time.Time
if scenario.time != 0 {
buffer := time.Duration(scenario.time) * time.Second * (100 - PercentTimeUsed) / 100
if buffer > MaxFinishingTime*time.Second {
buffer = MaxFinishingTime * time.Second
}
deadline := time.Duration(scenario.time)*time.Second - buffer
timeChannel = time.After(deadline)
} else {
timeChannel = make(<-chan time.Time)
}
var chromosome Chromosome
done := false
for !done {
var newChromosome Chromosome
select {
case <-timeChannel:
log.Println("terminating: time is up")
done = true
case <-doneChannel:
log.Println("terminating: max iters reached")
done = true
case newChromosome = <-chromosomeChannel:
if newChromosome.fitness > chromosome.fitness || (newChromosome.fitness == chromosome.fitness && newChromosome.neededTurns < chromosome.neededTurns) {
chromosome = newChromosome
if optimum != NoOptimum && chromosome.fitness == optimum && endOnOptimalPtr != nil && *endOnOptimalPtr {
log.Println("terminating: optimal solution found")
done = true
}
}
}
}
log.Println("final fitness", chromosome.fitness, "turns", chromosome.neededTurns)
err = chromosome.CopyWithoutDisconnectedMines().Export(scenario, exporter, *outputPtr)
if err != nil {
log.Fatal("could not export solution: ", err)
}
}