-
Notifications
You must be signed in to change notification settings - Fork 0
/
pmx.py
92 lines (68 loc) · 2.61 KB
/
pmx.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
from random import randint
from chromosome import Chromosome
def _subsection(item):
L = list(range(0, len(item)-1))
left = randint(0, len(L) - 1)
right = randint(left + 1, len(L))
return left, right
def _get_replaced_item(left, right, child, gene, relation_map):
# Hit a base case
if gene not in relation_map:
return gene
mapped = relation_map[gene]
if mapped not in child[left:right]:
return mapped
else:
return _get_replaced_item(left, right, child, mapped, relation_map)
def _map(left, right, mother, father):
return dict(zip(father[left:right], mother[left:right]))
def _getIndex(item, child, left, right):
# Search left
for i in range(0, left):
if child[i] == item:
return i
# Search right
for i in range(right, len(child)):
if child[i] == item:
return i
def _swap_leftover_genes(left, right, mothers_child, fathers_child):
father_map = _map(left, right, mothers_child, fathers_child)
# Swap left versions
for i in range(0, left):
gene = fathers_child[i]
if gene not in father_map:
continue
mother_gene = _get_replaced_item(left, right, fathers_child, gene, father_map)
fathers_child[i] = mother_gene
m_index = _getIndex(mother_gene, mothers_child, left, right)
mothers_child[m_index] = gene
for i in range(right, len(fathers_child)):
gene = fathers_child[i]
if gene not in father_map:
continue
mother_gene = _get_replaced_item(left, right, fathers_child, gene, father_map)
fathers_child[i] = mother_gene
m_index = _getIndex(mother_gene, mothers_child, left, right)
mothers_child[m_index] = gene
return fathers_child, mothers_child
def _mate_one(pair):
mother, father = pair
left, right = _subsection(mother)
# Create copies (children) so we don't effect the original
mothers_child = list(mother.genes)
fathers_child = list(father.genes)
# Step 1, swap the sides
mothers_child[left:right] = father.genes[left:right]
fathers_child[left:right] = mother.genes[left:right]
# Step 2, deal with the leftovers
fathers_child, mothers_child = _swap_leftover_genes(left, right,
mothers_child, fathers_child)
child1_chrome = Chromosome(''.join(mothers_child))
child2_chrome = Chromosome(''.join(fathers_child))
return child1_chrome, child2_chrome
def mate(pairs):
people = []
for mother, father in pairs:
child1, child2 = _mate_one((mother, father))
people += [mother, father, child1, child2]
return people