-
Notifications
You must be signed in to change notification settings - Fork 0
/
genetic.py
113 lines (70 loc) · 2.49 KB
/
genetic.py
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
# -*- coding: utf-8 -*-
"""
Created on Wed May 1 00:39:11 2019
@author: Faradars-pc2
"""
import random
import statistics
import time
import sys
class Chromosome:
Genes = None
Fitness = None
def __init__(self, genes, fitness):
self.Genes = genes
self.Fitness = fitness
def _generate_parent(length, geneSet, get_fitness):
genes = []
while len(genes) < length:
sampleSize = min(length - len(genes), len(geneSet))
genes.extend(random.sample(geneSet, sampleSize))
fitness = get_fitness(genes)
return Chromosome(genes, fitness)
def _mutate(parent, geneSet, get_fitness):
index = random.randrange(0, len(parent.Genes))
childGenes = parent.Genes[:]
newGene, alternate = random.sample(geneSet, 2)
childGenes[index] = alternate \
if newGene == childGenes[index] \
else newGene
fitness = get_fitness(childGenes)
return Chromosome(childGenes, fitness)
def get_improvement(new_child, generate_parent):
bestParent = generate_parent()
yield bestParent
while True:
child = new_child(bestParent)
if bestParent.Fitness > child.Fitness:
continue
if not child.Fitness > bestParent.Fitness:
bestParent = child
continue
yield child
bestParent = child
def get_best(get_fitness, targetLen, optimalFitness, geneSet, display):
random.seed()
def fnMutate(parent):
return _mutate(parent, geneSet, get_fitness)
def fnGenerateParent():
return _generate_parent(targetLen, geneSet, get_fitness)
for improvement in get_improvement(fnMutate, fnGenerateParent):
display(improvement)
if not optimalFitness > improvement.Fitness:
return improvement
class Benchmark:
@staticmethod
def run(function):
timings = []
stdout = sys.stdout
for i in range(100):
sys.stdout = None
startTime = time.time()
function()
seconds = time.time() - startTime
sys.stdout = stdout
timings.append(seconds)
mean = statistics.mean(timings)
if i < 10 or i % 10 == 9:
print("{0} {1:3.2f} {2:3.2f}".format( 1+i,
mean, statistics.stdev(timings, mean)
if i >1 else 0))