-
Notifications
You must be signed in to change notification settings - Fork 2
/
crossovers.py
136 lines (107 loc) · 3.65 KB
/
crossovers.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from mingus.containers import *
from mingus.core import *
from mingus.midi import fluidsynth
import MusicGene
import random
def interleaved_single_pt_crossover(gene1, gene2):
if (random.randint(0,1)):
return single_pt_crossover(gene1, gene2)
else:
return interleave_crossover(gene1, gene2)
def double_pt_crossover(gene1, gene2):
# Most naive method - interleave bars
#print "Mating:"
#print "P1: " + gene1.print_track(gene1.track)
#print "P2: " + gene1.print_track(gene2.track)
assert(len(gene1.track) == len(gene2.track))
children = []
crossover = random.randint(0,len(gene1.track))
crossover_ = random.randint(crossover,len(gene1.track))
child = []
child_ = []
for i in xrange(len(gene1.track)):
note = gene1.track[i]
note_ = gene2.track[i]
if i < crossover or i > crossover_:
child.append(note)
child_.append(note_)
else:
child.append(note_)
child_.append(note)
children += [MusicGene.MusicGene(child), MusicGene.MusicGene(child_)]
return children
def crossover_bars(bar, bar_):
new_bar = Track()
new_bar_ = Track()
# Find notes which share a beat
shared_beats = []
for beat, duration, note in bar:
for beat_, duration_, note_ in bar_:
if beat == beat_: shared_beats.append(beat)
beat_crossover = random.choice(shared_beats)
i,j = 0,0
while(i < len(bar) or j < len(bar_)):
if i < len(bar): beat, duration, note = bar[i]
else: beat = 1
if j < len(bar_): beat_, duration_, note_ = bar_[j]
else: beat_ = 1
if i < len(bar) and beat < beat_crossover:
new_bar.add_notes(note, duration)
i += 1
elif j < len(bar_) and beat_ < beat_crossover:
new_bar_.add_notes(note_, duration_)
j += 1
if beat >= beat_crossover and beat_ >= beat_crossover:
if i < len(bar):
new_bar_.add_notes(note, duration)
i+=1
if j < len(bar_):
new_bar.add_notes(note_, duration_)
j+=1
assert(len(new_bar) == 1)
assert(len(new_bar_) == 1)
return new_bar[0], new_bar_[0]
def single_pt_crossover(gene1, gene2):
# Most naive method - interleave bars
#print "Mating:"
#print "P1: " + gene1.print_track(gene1.track)
#print "P2: " + gene1.print_track(gene2.track)
children = []
bar_crossover = random.randint(0,len(gene1.track))
child = Track()
child_ = Track()
len_ = len(gene1.track)
if len_ > len(gene2.track): len_ = len(gene2.track)
for i in xrange(len_):
bar = gene1.track[i]
bar_ = gene2.track[i]
if i < bar_crossover:
child.add_bar(bar)
child_.add_bar(bar_)
elif i > bar_crossover:
child.add_bar(bar_)
child_.add_bar(bar)
# At crossover
else:
new_bar, new_bar_ = crossover_bars(bar, bar_)
child.add_bar(new_bar)
child_.add_bar(new_bar_)
children.append(MusicGene.MusicGene(child))
children.append(MusicGene.MusicGene(child_))
return children
def interleave_crossover(gene1, gene2):
assert(len(gene1.track) == len(gene2.track))
children = []
child = []
child_ = []
for i in xrange(len(gene1.track)):
note = gene1.track[i]
note_ = gene2.track[i]
if i%2 == 0:
child.append(note)
child_.append(note_)
else:
child.append(note_)
child_.append(note)
children += [MusicGene.MusicGene(child), MusicGene.MusicGene(child_)]
return children