/
line_profile
603 lines (560 loc) · 41.6 KB
/
line_profile
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
Population Initialized w/ Parameters:
------------------------------ -------
Initial number of individuals: 1000
Initial size of individuals: 2
Max. number of generations: 100
Parallel fitness turned on: 0
Stagnation factor: 20
Percent of Elitism: 0.02
Percent of replication: 0.28
Percent of mating: 0.6
Percent of mutation: 0.1
Selective pressure: 2
------------------------------ -------
Initializing Population with Individuals composed of random Trees:
[****************100%******************] 1000 of 1000 complete
Current Population Status:
---------------------- ---------------
Current generation: 0
Number of individuals: 1000
Max fitness: 2.00604e+144
Average fitness: 9.63925e+143
Min fitness: 1.70399
---------------------- ---------------
[****************100%******************] 50 of 50 complete 50 generations
Wrote profile results to eguene_test.py.lprof
Timer unit: 1e-06 s
Total time: 55.2102 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Individual.py
Function: compute_gene_expression at line 36
Line # Hits Time Per Hit % Time Line Contents
==============================================================
36 @profile
37 def compute_gene_expression(self, error_function=None, target=None):
38 """compute gene expression by evaluating function stored in tree, and keep track of time"""
39
40 # evaluate function and time to compute
41 57594 48524 0.8 0.1 t0 = time.time()
42 57594 52483053 911.3 95.1 output = self.chromosomes.evaluate()
43 57594 50016 0.9 0.1 t1 = time.time()
44
45 # calculate error of result and time complexity
46 57594 2231178 38.7 4.0 error = error_function(output, target)
47 57594 49662 0.9 0.1 time_complexity = t1 - t0
48 57594 113280 2.0 0.2 physical_complexity = self.chromosomes.complexity
49
50 57594 234492 4.1 0.4 return np.array([error, time_complexity, physical_complexity])
Total time: 367.137 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Individual.py
Function: crossover at line 52
Line # Hits Time Per Hit % Time Line Contents
==============================================================
52 @profile
53 def crossover(self, spouse=None):
54 """randomly crossover two chromosomes"""
55
56 # create random crossover points
57 15000 198127 13.2 0.1 x1 = r.randint(0, self.size - 1)
58 15000 111850 7.5 0.0 x2 = r.randint(0, spouse.size - 1)
59
60 # clone parent chromosomes
61 15000 49372197 3291.5 13.4 c1 = cp.deepcopy(self.chromosomes)
62 15000 49561602 3304.1 13.5 c2 = cp.deepcopy(spouse.chromosomes)
63
64 # get nodes to cross
65 15000 12141864 809.5 3.3 c1n = c1.get_node(x1)
66 15000 12447661 829.8 3.4 c2n = c2.get_node(x2)
67
68 # transfer nodes
69 15000 120987352 8065.8 33.0 c1.set_node(x1, c2n)
70 15000 122270886 8151.4 33.3 c2.set_node(x2, c1n)
71
72 15000 45368 3.0 0.0 return (Individual(c1), Individual(c2))
Total time: 43.0822 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Individual.py
Function: mutate at line 74
Line # Hits Time Per Hit % Time Line Contents
==============================================================
74 @profile
75 def mutate(self, pruning=False):
76 """ alter a random node in chromosomes"""
77
78 # randomly select node to mutate
79 5000 54552 10.9 0.1 mpoint = r.randint(0, self.size - 1)
80
81 # mutate whole node by replacing children with random subtree
82 5000 5964 1.2 0.0 if r.random() >= 0.5:
83 2439 1069947 438.7 2.5 rand_tree = random_tree(2)
84 2439 17276 7.1 0.0 x2 = r.randint(0, rand_tree.node_num - 1)
85 2439 887038 363.7 2.1 node = rand_tree.get_node(x2)
86 2439 18046137 7399.0 41.9 self.chromosomes.set_node(mpoint, node)
87 # check and prune tree with new subtree for inefficiencies
88 2439 1795 0.7 0.0 if pruning:
89 self.chromosomes.prune()
90
91 # or just mutate node value based on current type
92 else:
93 2561 2078889 811.7 4.8 node = self.chromosomes.get_node(mpoint)
94 # constant
95 2561 3716 1.5 0.0 if node.value in CONSTS:
96 77 598 7.8 0.0 mutated_value = CONSTS[r.randint(0, len(CONSTS) - 1)]
97 # variable
98 2484 2483 1.0 0.0 elif node.value in VARIABLES:
99 985 7282 7.4 0.0 mutated_value = VARIABLES[r.randint(0, len(VARIABLES) - 1)]
100 # a unary operator
101 1499 1659 1.1 0.0 elif node.value in UNARIES:
102 365 2683 7.4 0.0 mutated_value = UNARIES[r.randint(0, len(UNARIES) - 1)]
103 # a binary operator
104 1134 1140 1.0 0.0 elif node.value in BINARIES:
105 886 7014 7.9 0.0 mutated_value = BINARIES[r.randint(0, len(BINARIES) - 1)]
106 # a n-ary operator
107 248 229 0.9 0.0 elif node.value in NARIES:
108 1 7 7.0 0.0 mutated_value = NARIES[r.randint(0, len(NARIES) - 1)]
109 # EPHEMERAL constant random ( 0:1, uniform -500:500, or normal -500:500 )
110 else:
111 247 1816 7.4 0.0 mutated_value = EPHEMERAL[r.randint(1, len(EPHEMERAL) - 1)]
112
113 # mutate node value (keeps children, if applicable)
114 2561 2324 0.9 0.0 node.value = mutated_value
115 2561 20889626 8156.8 48.5 self.chromosomes.set_node(mpoint, node)
Total time: 1.30891 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Node.py
Function: random_node at line 10
Line # Hits Time Per Hit % Time Line Contents
==============================================================
10 @profile
11 def random_node(max_level=20, min_level=1, current_level=0):
12 """create a random node that may contain random subnodes"""
13
14 69758 46080 0.7 3.5 if current_level == max_level:
15 36697 193055 5.3 14.7 rand_node = r.randint(0, 3)
16 # node = a constant
17 36697 23447 0.6 1.8 if rand_node == 0:
18 9286 82294 8.9 6.3 node = Node(CONSTS[r.randint(0, len(CONSTS) - 1)])
19 # node = EPHEMERAL constant random ( 0:1, uniform -500:500, or normal -500:500 )
20 27411 15415 0.6 1.2 elif rand_node == 1:
21 9291 83761 9.0 6.4 node = Node(EPHEMERAL[r.randint(1, len(EPHEMERAL) - 1)])
22 # node = EPHEMERAL constant random integer
23 18120 10041 0.6 0.8 elif rand_node == 2:
24 9065 37494 4.1 2.9 node = Node(EPHEMERAL[0])
25 # node = variable
26 9055 4952 0.5 0.4 elif rand_node == 3:
27 9055 79984 8.8 6.1 node = Node(VARIABLES[r.randint(0, len(VARIABLES) - 1)])
28 else:
29 33061 193445 5.9 14.8 rand_node = r.randint(4, 6) if current_level < min_level else r.randint(0, 6)
30 # node = a constant
31 33061 21842 0.7 1.7 if rand_node == 0:
32 1257 11631 9.3 0.9 node = Node(CONSTS[r.randint(0, len(CONSTS) - 1)])
33 # node = EPHEMERAL constant random ( 0:1, uniform -500:500, or normal -500:500 )
34 31804 18096 0.6 1.4 elif rand_node == 1:
35 1260 12033 9.6 0.9 node = Node(EPHEMERAL[r.randint(1, len(EPHEMERAL) - 1)])
36 # node = EPHEMERAL constant random integer
37 30544 17178 0.6 1.3 elif rand_node == 2:
38 1248 5820 4.7 0.4 node = Node(EPHEMERAL[0])
39 # node = variable
40 29296 16472 0.6 1.3 elif rand_node == 3:
41 1281 12368 9.7 0.9 node = Node(VARIABLES[r.randint(0, len(VARIABLES) - 1)])
42 # node = a unary operator
43 28015 15941 0.6 1.2 elif rand_node == 4:
44 9296 5634 0.6 0.4 node = Node(
45 9296 52010 5.6 4.0 UNARIES[r.randint(0, len(UNARIES) - 1)],
46 9296 18408 2.0 1.4 random_node(max_level, min_level, current_level + 1)
47 )
48 # node = a binary operator
49 18719 10825 0.6 0.8 elif rand_node == 5:
50 9358 5764 0.6 0.4 node = Node(
51 9358 52237 5.6 4.0 BINARIES[r.randint(0, len(BINARIES) - 1)],
52 9358 18560 2.0 1.4 random_node(max_level, min_level, current_level + 1),
53 9358 16219 1.7 1.2 random_node(max_level, min_level, current_level + 1)
54 )
55 # node = a n-ary operator
56 9361 5558 0.6 0.4 elif rand_node == 6:
57 9361 48750 5.2 3.7 nary_node_num = r.randint(2, 5)
58 9361 6338 0.7 0.5 if nary_node_num == 2:
59 2339 1378 0.6 0.1 node = Node(
60 2339 12821 5.5 1.0 NARIES[r.randint(0, len(NARIES) - 1)],
61 2339 4808 2.1 0.4 random_node(max_level - 1, current_level + 1),
62 2339 4184 1.8 0.3 random_node(max_level - 1, current_level + 1)
63 )
64 7022 4157 0.6 0.3 elif nary_node_num == 3:
65 2379 1467 0.6 0.1 node = Node(
66 2379 13328 5.6 1.0 NARIES[r.randint(0, len(NARIES) - 1)],
67 2379 4981 2.1 0.4 random_node(max_level - 1, current_level + 1),
68 2379 4264 1.8 0.3 random_node(max_level - 1, current_level + 1),
69 2379 4177 1.8 0.3 random_node(max_level - 1, current_level + 1)
70 )
71 4643 2812 0.6 0.2 elif nary_node_num == 4:
72 2317 1474 0.6 0.1 node = Node(
73 2317 12752 5.5 1.0 NARIES[r.randint(0, len(NARIES) - 1)],
74 2317 4820 2.1 0.4 random_node(max_level - 1, current_level + 1),
75 2317 4067 1.8 0.3 random_node(max_level - 1, current_level + 1),
76 2317 3981 1.7 0.3 random_node(max_level - 1, current_level + 1),
77 2317 4086 1.8 0.3 random_node(max_level - 1, current_level + 1)
78 )
79 2326 1386 0.6 0.1 elif nary_node_num == 5:
80 2326 1492 0.6 0.1 node = Node(
81 2326 12952 5.6 1.0 NARIES[r.randint(0, len(NARIES) - 1)],
82 2326 4893 2.1 0.4 random_node(max_level - 1, current_level + 1),
83 2326 4090 1.8 0.3 random_node(max_level - 1, current_level + 1),
84 2326 4053 1.7 0.3 random_node(max_level - 1, current_level + 1),
85 2326 3966 1.7 0.3 random_node(max_level - 1, current_level + 1),
86 2326 3994 1.7 0.3 random_node(max_level - 1, current_level + 1)
87 )
88 69758 40875 0.6 3.1 return node
Total time: 135.472 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Node.py
Function: set_nums at line 134
Line # Hits Time Per Hit % Time Line Contents
==============================================================
134 @profile
135 def set_nums(self, node_counter=-1, level_counter=0, leaf_count=-1, edge_count=-1):
136 """set node numbers (depth first)"""
137
138 # count this node
139 9397425 5750217 0.6 4.2 node_counter += 1
140 9397425 5783217 0.6 4.3 self.num = node_counter
141 9397425 5579282 0.6 4.1 self.level = level_counter
142 9397425 5001930 0.5 3.7 complexity = 0
143 9397425 4860208 0.5 3.6 node_count = 1
144
145 # traverse children if present or count as leaf node
146 9397425 6654512 0.7 4.9 if len(self.children) > 0:
147 5006054 2864732 0.6 2.1 level_counter += 1
148 5006054 3334264 0.7 2.5 edge_count += len(self.children)
149 5006054 2690022 0.5 2.0 height_count = 1
150 13535768 8411504 0.6 6.2 for c in self.children:
151 8529714 13978182 1.6 10.3 child_numbers = c.set_nums(node_counter, level_counter, leaf_count, edge_count)
152 8529714 5520393 0.6 4.1 node_counter, child_node_count, child_height, leaf_count, edge_count, child_complexity = child_numbers
153 8529714 7037516 0.8 5.2 height_count = max(height_count, child_height)
154 8529714 5352200 0.6 4.0 complexity += child_complexity
155 8529714 5018812 0.6 3.7 node_count += child_node_count
156 else:
157 4391371 2566912 0.6 1.9 leaf_count += 1
158 4391371 2342208 0.5 1.7 height_count = 0
159 4391371 2358320 0.5 1.7 edge_count = 0
160
161 # store counts of children below
162 9397425 6041168 0.6 4.5 self.height = height_count
163 9397425 5716379 0.6 4.2 self.node_num = node_count
164 9397425 5619873 0.6 4.1 self.leaf_num = leaf_count
165 9397425 5624333 0.6 4.2 self.edge_num = edge_count
166 9397425 5435134 0.6 4.0 complexity += node_count
167 9397425 5642917 0.6 4.2 self.complexity = complexity
168
169 9397425 6287522 0.7 4.6 return (node_counter, node_count, height_count + 1, leaf_count, edge_count, complexity)
Total time: 39.0693 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Population.py
Function: initialize at line 148
Line # Hits Time Per Hit % Time Line Contents
==============================================================
148 @profile
149 def initialize(self, seed=None):
150 """initialize a population based on seed or randomly"""
151
152 1 1433 1433.0 0.0 self.describe_init()
153 1 2 2.0 0.0 self.created = True
154 1 1 1.0 0.0 if seed:
155 print '\nUsing seed for inital population'
156 self.individuals = seed
157 else:
158 1 5 5.0 0.0 print '\nInitializing Population with Individuals composed of random Trees:'
159 1 21 21.0 0.0 pb = ProgressBar(self.init_population_size)
160 6595 9324 1.4 0.0 while len(self.individuals) < self.init_population_size:
161 # generate a random expression tree
162 6594 3033378 460.0 7.8 tree = random_tree(self.init_tree_size)
163 # prune inefficiencies from the tree
164 6594 5047 0.8 0.0 if self.pruning:
165 tree.prune()
166 # create an individual from this expression
167 6594 26916 4.1 0.1 individual = Individual(tree)
168 # check for genes
169 6594 35784991 5426.9 91.6 gene_expression = individual.compute_gene_expression(self.error_function, self.target)
170 # if there is some non-infinite error, add to the population
171 6594 26626 4.0 0.1 if not np.isinf(gene_expression[0]):
172 1000 1332 1.3 0.0 self.individuals.append(individual)
173 1000 33770 33.8 0.1 pb.animate(self.size)
174 1 10 10.0 0.0 print '\n'
175 1 146477 146477.0 0.4 self.describe_current()
Total time: 22.055 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Population.py
Function: calc_fitness at line 177
Line # Hits Time Per Hit % Time Line Contents
==============================================================
177 @profile
178 def calc_fitness(self):
179 """calculate the fitness of each individual."""
180
181 51 53 1.0 0.0 if self.parallel:
182 pool = Pool()
183 fitness = pool.map(par_fit, [(i, self.objective_function) for i in self.individuals])
184 pool.close()
185 pool.join()
186 self._fitness = np.array(fitness)
187
188 else:
189 51051 21401058 419.2 97.0 expression = np.array([i.compute_gene_expression(self.error_function, self.target) for i in self.individuals])
190 51 14535 285.0 0.1 expression_scale = np.array(np.ma.masked_invalid(expression).max(axis=0))
191 51 10605 207.9 0.0 max_expr = np.array(np.ma.masked_invalid(expression).max(axis=0)) / expression_scale
192 51 26523 520.1 0.1 mean_expr = np.array(np.ma.masked_invalid(expression).mean(axis=0)) / expression_scale
193 51 10858 212.9 0.0 min_expr = np.array(np.ma.masked_invalid(expression).min(axis=0)) / expression_scale
194
195 51 3241 63.5 0.0 self._fitness = self.objective_function(expression, expression_scale)
196 51 2149 42.1 0.0 mfit = np.ma.masked_invalid(self._fitness)
197
198 51 526513 10323.8 2.4 self.rank()
199 51 15676 307.4 0.1 self.history['fitness'].append((mfit.max(), mfit.mean(), mfit.min()))
200 51 218 4.3 0.0 self.history['error'].append((max_expr[0], mean_expr[0], min_expr[0]))
201 51 94 1.8 0.0 self.history['time'].append((max_expr[1], mean_expr[1], min_expr[1]))
202 51 86 1.7 0.0 self.history['complexity'].append((max_expr[2], mean_expr[2], min_expr[2]))
203 51 43437 851.7 0.2 self.history['most_fit'].append(self.most_fit())
Total time: 0.607102 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Population.py
Function: rank at line 205
Line # Hits Time Per Hit % Time Line Contents
==============================================================
205 @profile
206 def rank(self):
207 """create ranking of individuals"""
208 152 502151 3303.6 82.7 self.ranking = zip(self.fitness, self.individuals)
209 152 104951 690.5 17.3 self.ranking.sort()
Total time: 0.362354 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Population.py
Function: roulette at line 211
Line # Hits Time Per Hit % Time Line Contents
==============================================================
211 @profile
212 def roulette(self, number=None):
213 """select parent pairs based on roulette method (probability proportional to fitness)"""
214 200 187 0.9 0.1 number = number if number else self.size
215 200 155 0.8 0.0 selections = []
216
217 # unpack
218 200 180898 904.5 49.9 ranked_fitness, ranked_individuals = (list(i) for i in zip(*self.ranking))
219 200 17763 88.8 4.9 ranked_fitness = np.array(ranked_fitness)
220
221 # calculate weighted probability proportial to fitness
222 200 22986 114.9 6.3 fitness_probability = ranked_fitness / np.ma.masked_invalid(ranked_fitness).sum()
223 200 25621 128.1 7.1 cum_prob_dist = np.array(np.ma.masked_invalid(fitness_probability).cumsum())
224
225 # randomly select two individuals with weighted probability proportial to fitness
226 49200 114594 2.3 31.6 selections = [ranked_individuals[bisect.bisect(cum_prob_dist, r.random() * cum_prob_dist[-1])] for _ in xrange(number)]
227 200 150 0.8 0.0 return selections
Total time: 0.40706 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Population.py
Function: select at line 287
Line # Hits Time Per Hit % Time Line Contents
==============================================================
287 @profile
288 def select(self, number=None):
289 """select individuals thru various methods"""
290 200 406960 2034.8 100.0 selections = self.roulette(number)
291 200 100 0.5 0.0 return selections
Total time: 432.944 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Population.py
Function: create_generation at line 293
Line # Hits Time Per Hit % Time Line Contents
==============================================================
293 @profile
294 def create_generation(self):
295 """create the next generations, this is main function that loops"""
296
297 # determine fitness of current generations and log average fitness
298 50 21967429 439348.6 5.1 self.calc_fitness()
299
300 # rank individuals by fitness
301 50 38735 774.7 0.0 self.rank()
302
303 # create next generation
304 50 326 6.5 0.0 elite_num = int(round(self.size * self.elitism))
305 50 122 2.4 0.0 replicate_num = int(round(self.size * self.replication))
306 50 103 2.1 0.0 mate_num = int(round(self.size * self.mating))
307 50 103 2.1 0.0 mutate_num = int(round(self.size * self.mutation))
308 # split mate_num in half_size (2 parents = 2 children)
309 50 86 1.7 0.0 mate_num = int(round(mate_num/2.0))
310
311 # propogate elite
312 1050 1027 1.0 0.0 next_generation = [i[1] for i in self.ranking[-elite_num:]]
313
314 # replicate
315 50 93009 1860.2 0.0 next_generation.extend(self.select(replicate_num))
316
317 # crossover mate
318 50 180906 3618.1 0.0 parent_pairs = zip(self.select(mate_num), self.select(mate_num))
319 15050 367330554 24407.3 84.8 child_pairs = [p1.crossover(p2) for p1, p2 in parent_pairs]
320 45050 38227 0.8 0.0 children = [child for pair in child_pairs for child in pair]
321 50 330 6.6 0.0 next_generation.extend(children)
322
323 # mutate
324 50 135390 2707.8 0.0 mutants = self.select(mutate_num)
325 5050 5767 1.1 0.0 for m in mutants:
326 5000 43149318 8629.9 10.0 m.mutate(self.pruning)
327 50 222 4.4 0.0 next_generation.extend(mutants)
328
329 50 1726 34.5 0.0 self.individuals = next_generation[:self.size]
330
331 # clear cached values
332 50 608 12.2 0.0 self._fitness = np.array([])
333
334 # log generation
335 50 78 1.6 0.0 self.generation += 1
336
337 50 40 0.8 0.0 return None
Total time: 433.02 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Population.py
Function: run at line 339
Line # Hits Time Per Hit % Time Line Contents
==============================================================
339 @profile
340 def run(self, number_of_generations=None):
341 """run algorithm"""
342
343 1 1 1.0 0.0 number_of_generations = number_of_generations if number_of_generations else self.max_generations
344 1 26 26.0 0.0 pb = ProgressBar(number_of_generations)
345
346 51 380 7.5 0.0 while self.generation < number_of_generations and not self.stagnate:
347 50 433017162 8660343.2 100.0 self.create_generation()
348 50 2344 46.9 0.0 pb.animate(self.generation)
349
350 1 8 8.0 0.0 if self.stagnate:
351 print 'population became stagnate'
352 1 35 35.0 0.0 print self.generation, 'generations'
Total time: 4.06558 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Tree.py
Function: random_tree at line 14
Line # Hits Time Per Hit % Time Line Contents
==============================================================
14 @profile
15 def random_tree(max_level=20, min_level=1, current_level=0):
16 """generate a random tree of random nodes"""
17 9033 4065585 450.1 100.0 return Tree(random_node(max_level, min_level, current_level))
Total time: 52.1438 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Tree.py
Function: evaluate at line 60
Line # Hits Time Per Hit % Time Line Contents
==============================================================
60 @profile
61 def evaluate(self):
62 """evaluate expression stored in tree"""
63 57594 28572 0.5 0.1 try:
64 57594 52061494 903.9 99.8 result = np.array(eval(compile(self.__str__(), '', 'eval')))
65 2862 2187 0.8 0.0 except:
66 2862 5502 1.9 0.0 result = np.array(np.nan)
67 57594 46010 0.8 0.1 return result
Total time: 25.0918 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Tree.py
Function: get_node at line 69
Line # Hits Time Per Hit % Time Line Contents
==============================================================
69 @profile
70 def get_node(self, n=0):
71 """return a node from the tree"""
72
73 # search tree until node number is found and take sub tree
74 498880 393687 0.8 1.6 if self.nodes.num == n:
75 35000 22020193 629.1 87.8 return cp.deepcopy(self.nodes)
76 463880 349065 0.8 1.4 elif len(self.nodes.children) > 0:
77 629246 617983 1.0 2.5 for c in self.nodes.children:
78 463880 1309325 2.8 5.2 cn = Tree(c, subtree=True).get_node(n)
79 463880 252398 0.5 1.0 if cn:
80 143703 72783 0.5 0.3 return cn
81 else:
82 154811 76321 0.5 0.3 return None
Total time: 278.922 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Tree.py
Function: set_node at line 84
Line # Hits Time Per Hit % Time Line Contents
==============================================================
84 @profile
85 def set_node(self, n=0, node=None):
86 """set a node in the tree"""
87
88 # search tree until node number is found, and store sub tree
89 858678 577397 0.7 0.2 if self.nodes.num == n:
90 35000 31411 0.9 0.0 self.nodes = node
91 else:
92 1647356 3464874 2.1 1.2 self.nodes.children = tuple([Tree(c, subtree=True).set_node(n, node) for c in self.nodes.children])
93
94 # rebase the numbers of the Tree
95 858678 274443455 319.6 98.4 self.nodes.set_nums()
96 858678 405103 0.5 0.1 return self.nodes
Total time: 0 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Tree.py
Function: list_edges at line 98
Line # Hits Time Per Hit % Time Line Contents
==============================================================
98 @profile
99 def list_edges(self):
100 """get edges of tree"""
101
102 # get list of tuple edges between nodes e.g. [(n1,n2),(n1,n3)...]
103 edges = [(self.nodes.value, c.value if len(c.children) > 0 else c.value) for c in self.nodes.children]
104 children_nodes = [Tree(c, subtree=True).list_edges() for c in self.nodes.children if len(c.children) > 0]
105 for i in xrange(len(children_nodes)):
106 edges += children_nodes[i]
107 return edges
Total time: 0 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Tree.py
Function: list_nodes at line 109
Line # Hits Time Per Hit % Time Line Contents
==============================================================
109 @profile
110 def list_nodes(self):
111 """return nodes of tree"""
112
113 # get list of nodes
114 node_list = []
115 node_list.append(self.nodes.value)
116 # add children
117 node_list.extend([c.value for c in self.nodes.children if len(c.children) == 0])
118 # add children's children
119 grand_children = [Tree(c, subtree=True).list_nodes() for c in self.nodes.children if len(c.children) > 0]
120 node_list.extend([node for grand_child in grand_children for node in grand_child])
121
122 return node_list
Total time: 0 s
File: /Users/timothydavenport/GitHub/eugene/eugene/Tree.py
Function: prune at line 124
Line # Hits Time Per Hit % Time Line Contents
==============================================================
124 @profile
125 def prune(self):
126 """go thru nodes and remove or replace dead / constant branches (subtrees)"""
127
128 # create subtree
129 sub_tree = Tree(self.nodes, subtree=True)
130 # check if the tree contains a variable
131 contains_variable = any([n in VARIABLES for n in sub_tree.list_nodes()])
132 # evaluate subtree for inefficiencies
133 sub_eval = sub_tree.evaluate()
134 # check is evaluation exactly equals variable
135 equals_variable = [v for v in VARIABLES if (Tree(Node(v)).evaluate() == sub_eval).all()]
136
137 # if subtree of node does not contain variable, it must be constant
138 if not contains_variable:
139 self.nodes.value = sub_eval
140 self.nodes.children = ()
141 # if subtree contains a variable, but evaluates to exactly the variable, replace with variable
142 elif equals_variable:
143 self.nodes.value = equals_variable[0]
144 self.nodes.children = ()
145 # can't make more effiecient
146 else:
147 for child in self.nodes.children:
148 Tree(child, subtree=True).prune()
149
150 # rebase the numbers of the Tree
151 self.nodes.set_nums()
152 return self.nodes
Total time: 0.002627 s
File: /Users/timothydavenport/GitHub/eugene/tests/eguene_test.py
Function: error_and_complexity at line 21
Line # Hits Time Per Hit % Time Line Contents
==============================================================
21 @profile
22 def error_and_complexity(gene_expression, scale):
23 """user fitness function, weighted combination of error and complexity"""
24
25 51 221 4.3 8.4 weights = np.array([0.95, 0.025, 0.025])
26 51 1918 37.6 73.0 scaled_gene_expression = 1.0 / (gene_expression / scale)
27
28 51 488 9.6 18.6 return np.dot(scaled_gene_expression, weights)