-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtreeFactory.py
158 lines (128 loc) · 5.6 KB
/
treeFactory.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import random
from utils import Utils
class TreeFactory(Utils):
def __init__(self, state, fitness, config):
self.state = state
self.fitness = fitness
self.config = config
def denial_expression_with_probability(self):
if self.add_not():
self.state.get_not()
def _generate_operation(self, depth=1):
if depth > self.config.max_operations_depth or random.random() < (1 - self.config.complexity_of_operations):
operation_leaf = self.get_random_operation_leaf()
if operation_leaf == 'variable':
self.state.get_random_variable()
elif operation_leaf == 'constant':
self.state.get_random_const()
elif operation_leaf == 'input':
self.state.get_input()
else:
# Choose an arithmetic expression
self.state.get_random_operation()
self._generate_operation(depth + 1)
self._generate_operation(depth + 1)
def _generate_condition(self):
self.denial_expression_with_probability()
self.state.get_random_condition()
left_condition_leaf = self.get_random_condition_leaf()
right_condition_leaf = self.get_random_condition_leaf()
children = [left_condition_leaf, right_condition_leaf]
for child in children:
self.denial_expression_with_probability()
if child == 'operation':
self._generate_operation()
elif child == 'true':
self.state.get_true()
elif child == 'false':
self.state.get_false()
elif child == 'input':
self.state.get_input()
else:
raise Exception('Unknown condition leaf')
def _generate_logic(self, depth=1):
if depth > self.config.max_logic_depth or random.random() < (1 - self.config.complexity_of_logic):
self._generate_condition()
else:
self.denial_expression_with_probability()
self.state.get_random_logic()
self._generate_logic(depth + 1)
self._generate_logic(depth + 1)
def _generate_equation(self):
self.state.get_equation()
equation_type = self.get_random_equation_type()
if equation_type == 'input':
self.state.create_new_variable()
self.state.get_input()
return
random_number = random.randint(1, 100)
# Left side of the equation
if random_number < 50:
# Create new variable
self.state.create_new_variable()
else:
# Choose existing variable
self.state.get_random_variable()
# Right side of the equation
if equation_type == 'operation':
self._generate_operation()
elif equation_type == 'logic':
self._generate_logic()
def _generate_input(self):
self.state.create_new_variable()
self.state.get_input()
def _generate_while(self, depth):
self.state.get_while_loop()
self._generate_logic()
self.state.get_open_scope()
self._generate_block(depth)
self.state.get_close_scope()
def _generate_if(self, depth):
self.state.get_if_statement()
self._generate_logic()
self.state.get_open_scope()
self._generate_block(depth)
self.state.get_close_scope()
def _generate_output(self):
self.state.get_output()
self.state.get_random_variable()
def _generate_block(self, depth=1):
number_of_blocks = random.randint(self.config.min_blocks, self.config.max_blocks)
for _ in range(number_of_blocks):
block = self.get_random_block()
if block == 'equation':
self._generate_equation()
elif block == 'while':
# If max depth is reached, skip while loop
# because while loop creates a new block inside of it
if depth == self.config.max_blocks_depth:
continue
self._generate_while(depth + 1)
elif block == 'if':
# If max depth is reached, skip while loop
# because if creates a new block inside of it
if depth == self.config.max_blocks_depth:
continue
self._generate_if(depth + 1)
elif block == 'output':
self._generate_output()
# Create random number of variables with random values
def _generate_initial_variables(self):
for _ in range(random.randint(self.config.min_inital_vars, self.config.max_initial_vars)):
self.state.get_equation()
self.state.create_new_variable()
random_number = random.randint(1, 100)
if random_number < 50:
self.state.get_random_const()
else:
self.state.get_input()
def generate_population(self):
for i in range(self.config.population - 1):
self.state.init_new_indiv_state()
self._generate_initial_variables()
self._generate_block()
fitness = self.fitness.fitness_function(self.state.get_indiv_stack(i))
self.state.set_cur_indiv_fitness(fitness)
self.state.seed(['=', 'var0', '1','=', 'var1', 'input', 'if', '<', 'var1', '1000', '{', '=', 'var0', '0', '}', 'output','var0'], ['var0', 'var1'])
fitness = self.fitness.fitness_function(self.state.get_indiv_stack(self.state.current_indiv_index))
self.state.set_cur_indiv_fitness(fitness)