-
Notifications
You must be signed in to change notification settings - Fork 0
/
mutator.py
89 lines (66 loc) · 2.76 KB
/
mutator.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
"""
"""
import random
import itertools
import functools
from utils import named_functions_interface_decorator
import mutator_functions as mutfunc
MUT_FUNC_FUNCTIONAL = (mutfunc.loop_transposition, mutfunc.io_change,
mutfunc.io_transposition, mutfunc.output_interleaving, mutfunc.output_separation,
mutfunc.group_transition, mutfunc.number_complementary)
MUT_FUNC_STRING = (mutfunc.transition, mutfunc.addition, mutfunc.deletion,
mutfunc.transposition, mutfunc.single_deletion,
mutfunc.single_addition, mutfunc.reversion)
@named_functions_interface_decorator
def named_functions() -> dict:
"""Return a mutator function."""
return {
'ALL': all_mutators(),
'FMT': function_mutators(),
'SMT': string_mutators(),
'NO': mutfunc.null_mutator,
}
def default_functions() -> tuple:
"""Return default mutation functions"""
return named_functions.as_tuple() + anonymous_functions()
def anonymous_functions() -> tuple:
"""Return mutation functions that have no name"""
return ()
def _apply_mutations_randomly(mutators, unit):
"""Apply randomly given mutators according to unit mutation rates"""
if random.random() < unit.mutation_rate:
random.choice(mutators)(unit)
while random.random() < unit.additional_mutation_rate:
random.choice(mutators)(unit) # one more time !
def no_mutators() -> callable:
"""Return a function that never mutate input unit."""
@functools.wraps(no_mutators)
def no_mutators_wrapped(unit): pass
return no_mutators_wrapped
def all_mutators() -> callable:
"""Return a function that mutate input unit using a randomly choosen
mutation method.
"""
methods = MUT_FUNC_FUNCTIONAL + MUT_FUNC_STRING
@functools.wraps(all_mutators)
def all_mutators_wrapped(unit):
_apply_mutations_randomly(methods, unit)
return all_mutators_wrapped
def function_mutators() -> callable:
"""Return a function that mutate input unit using a randomly choosen
mutation method oriented toward modification of functional parts.
"""
@functools.wraps(function_mutators)
def function_mutators_wrapped(unit):
_apply_mutations_randomly(MUT_FUNC_FUNCTIONAL, unit)
return function_mutators_wrapped
def string_mutators() -> tuple:
"""Return a function that mutate input unit using a randomly choosen
mutation method oriented toward modification of source code as a string.
These mutators works by modifying sequence, without any look into
the consequences of the change.
"""
@functools.wraps(string_mutators)
def string_mutators_wrapped(unit):
_apply_mutations_randomly(MUT_FUNC_STRING, unit)
return string_mutators_wrapped