-
Notifications
You must be signed in to change notification settings - Fork 0
/
mutation_operator.py
49 lines (36 loc) · 1.88 KB
/
mutation_operator.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
import copy
import random
from clash_checker import check_clash
from mutations import in_plane_rotation, out_of_plane_rotation, crank_shaft_rotation, kink_movement
def mutate(individuals_to_mutate, in_plane_prob, out_of_plane_prob, crank_prob, kink_prob, clash_limit):
mutated_individuals = list()
# cumulative probabilities
cumulative_probabilities = [in_plane_prob, in_plane_prob + out_of_plane_prob,
in_plane_prob + out_of_plane_prob + crank_prob,
in_plane_prob + out_of_plane_prob + crank_prob + kink_prob]
for individual in individuals_to_mutate:
mutant = copy.copy(individual[1])
clashed = 0
random_number = random.SystemRandom().uniform(0, 1.0)
# applies mutation until mutant does not show any clashes
while clash_limit != clashed:
# do in plane rotation
if random_number <= cumulative_probabilities[0]:
mutant = in_plane_rotation(mutant)
# do out of plane rotation
elif cumulative_probabilities[0] < random_number <= cumulative_probabilities[1]:
mutant = out_of_plane_rotation(mutant)
# do crank shaft mutation
elif cumulative_probabilities[1] < random_number <= cumulative_probabilities[2]:
mutant = crank_shaft_rotation(mutant)
# do kink movement
elif cumulative_probabilities[2] < random_number <= cumulative_probabilities[3]:
mutant = kink_movement(mutant)
# if clash occurred, try again to mutate individual
if check_clash(mutant):
mutant = copy.copy(individual[1])
clashed += 1
else:
break
mutated_individuals.append([individual[0], mutant])
return mutated_individuals