Skip to content

Commit 4dc3a72

Browse files
committed
#24 Individual modified to use subtrees instead of strings in some methods
1 parent 8dd9e16 commit 4dc3a72

File tree

2 files changed

+44
-55
lines changed

2 files changed

+44
-55
lines changed

MLC/Common/Lisp_Tree_Expr/Lisp_Tree_Expr.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ def get_root_node(self):
5959
def get_expanded_tree_as_string(self):
6060
return '(root ' + self._root.to_string() + ')'
6161

62+
def __str__(self):
63+
return self.get_expanded_tree_as_string()
64+
6265
def get_simplified_tree_as_string(self):
6366
return self._simplified_tree
6467

MLC/individual/Individual.py

Lines changed: 41 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ def generate(self, value=None, individual_type=None):
142142

143143
def mutate(self, mutation_type=MutationType.ANY):
144144
try:
145-
new_value = self.__mutate_tree(self.get_value(), mutation_type)
145+
new_value = self.__mutate_tree(Lisp_Tree_Expr(self.get_value()), mutation_type)
146146
new_individual = Individual()
147147
new_individual.generate(new_value)
148148
return new_individual
@@ -156,7 +156,7 @@ def crossover(self, other_individual):
156156
[NEW_IND1,NEW_IND2,FAIL]=CROSSOVER(MLCIND1,MLCIND2,MLC_PARAMETERS)
157157
"""
158158
try:
159-
new_value_1, new_value_2 = self.__crossover_tree(self.get_value(), other_individual.get_value())
159+
new_value_1, new_value_2 = self.__crossover_tree(Lisp_Tree_Expr(self.get_value()), Lisp_Tree_Expr(other_individual.get_value()))
160160

161161
new_ind1 = Individual()
162162
new_ind1.generate(new_value_1)
@@ -313,18 +313,13 @@ def __generate_indiv_regressive_tree(self, value, indiv_type=None):
313313

314314
return new_value
315315

316-
def __crossover_tree(self, value_1, value_2):
316+
def __crossover_tree(self, expression_tree_1, expression_tree_2):
317317
"""
318318
Extract a subtree out of a tree, extract a correct subtree out of
319-
another tree (with depth that can fit into maxdepth). Then interchange
320-
the two subtrees inputs:
321-
322-
:param value_1: first tree (lisp ascii expression)
323-
:param value_2: second tree (lisp ascii expression)
324-
returned by set_GP_parameters.m
325-
:return:
326-
m1: first new tree (lisp ascii expression) %
327-
m2: second new tree (lisp ascii expression)
319+
another tree (with depth that can fit into maxdepth).
320+
Then interchange the two subtrees inputs:
321+
322+
:return: (first new tree, second new tree) as strings
328323
"""
329324
maxtries = self._config.getint("GP", "maxtries")
330325
mutmindepth = self._config.getint("GP", "mutmindepth")
@@ -333,14 +328,11 @@ def __crossover_tree(self, value_1, value_2):
333328
correct = False
334329
count = 0
335330

336-
tmp_value_1 = value_1
337-
tmp_value_2 = value_2
338-
339331
while not correct and count < maxtries:
340332
try:
341333
# Extracting subtrees
342-
value_1, sm1, n = self.__extract_subtree(tmp_value_1, mutmindepth, maxdepth, maxdepth)
343-
value_2, sm2, _ = self.__extract_subtree(tmp_value_2, mutmindepth, n, maxdepth - n + 1)
334+
value_1, sm1, n = self.__extract_subtree(expression_tree_1, mutmindepth, maxdepth, maxdepth)
335+
value_2, sm2, _ = self.__extract_subtree(expression_tree_2, mutmindepth, n, maxdepth - n + 1)
344336
correct = True
345337

346338
except TreeException, ex:
@@ -359,7 +351,7 @@ def __crossover_tree(self, value_1, value_2):
359351

360352
return value_1, value_2
361353

362-
def __mutate_tree(self, value, mutation_type):
354+
def __mutate_tree(self, expression_tree, mutation_type):
363355
mutmindepth = self._config.getint("GP", "mutmindepth")
364356
maxdepth = self._config.getint("GP", "maxdepth")
365357
sensor_spec = self._config.getboolean("POPULATION", "sensor_spec")
@@ -372,50 +364,45 @@ def __mutate_tree(self, value, mutation_type):
372364
mutation_type = mutation_types[int(np.floor(rand_number * len(mutation_types)))]
373365

374366
if mutation_type in [Individual.MutationType.REMOVE_SUBTREE_AND_REPLACE, Individual.MutationType.SHRINK]:
367+
new_individual_value = None
375368
preevok = False
376369
while not preevok:
377370
# remove subtree and grow new subtree
378371
try:
379-
value, _, _ = self.__extract_subtree(value, mutmindepth, maxdepth, maxdepth)
380-
except TreeException:
381-
pass
372+
subtree, _, _ = self.__extract_subtree(expression_tree, mutmindepth, maxdepth, maxdepth)
373+
if mutation_type == Individual.MutationType.REMOVE_SUBTREE_AND_REPLACE:
374+
next_individual_type = 0
375+
else:
376+
next_individual_type = 4
382377

383-
if mutation_type == Individual.MutationType.REMOVE_SUBTREE_AND_REPLACE:
384-
value = self.__generate_indiv_regressive_tree(value, 0)
385-
else:
386-
value = self.__generate_indiv_regressive_tree(value, 4)
378+
new_individual_value = self.__generate_indiv_regressive_tree(subtree, next_individual_type)
387379

388-
if value:
389-
if sensor_spec:
390-
config_sensor_list = sorted(self._config.get_list('POPULATION', 'sensor_list'))
391-
else:
392-
config_sensor_list = range(sensors-1, -1, -1)
380+
if new_individual_value:
381+
if sensor_spec:
382+
config_sensor_list = sorted(self._config.get_list('POPULATION', 'sensor_list'))
383+
else:
384+
config_sensor_list = range(sensors - 1, -1, -1)
385+
386+
for i in range(len(config_sensor_list)):
387+
new_individual_value = new_individual_value.replace("z%d" % i, "S%d" % config_sensor_list[i])
393388

394-
for i in range(len(config_sensor_list)):
395-
value = value.replace("z%d" % i, "S%d" % config_sensor_list[i])
389+
except TreeException:
390+
pass
396391

397-
preevok = True
398-
# if gen_param.preevaluation
399-
# eval(['peval=@' gen_param.preev_function ';']);
400-
# f=peval;
401-
# preevok=feval(f,m);
402-
# end
403-
else:
404-
preevok = True
392+
preevok = True
405393

406-
if not value:
394+
if not new_individual_value:
407395
raise TreeException("Subtree cannot be generated")
408396

409-
return value
397+
return new_individual_value
410398

411399
elif mutation_type == Individual.MutationType.REPARAMETRIZATION:
412-
return self.__reparam_tree(value)
400+
return self.__reparam_tree(expression_tree)
413401

414402
elif mutation_type == Individual.MutationType.HOIST:
415403
controls = self._config.getint("POPULATION", "controls")
416404
prob_threshold = 1 / float(controls)
417405

418-
expression_tree = Lisp_Tree_Expr(value)
419406
cl = [stree.to_string() for stree in expression_tree.get_root_node()._nodes]
420407

421408
changed = False
@@ -427,7 +414,7 @@ def __mutate_tree(self, value, mutation_type):
427414
if (MatlabEngine.rand() < prob_threshold) or (k == controls and not changed):
428415

429416
try:
430-
_, sm, _ = self.__extract_subtree('(root '+cl[nc - 1]+')', mutmindepth+1, maxdepth, maxdepth+1)
417+
_, sm, _ = self.__extract_subtree(Lisp_Tree_Expr('(root '+cl[nc - 1]+')'), mutmindepth+1, maxdepth, maxdepth+1)
431418
cl[nc - 1] = sm
432419
changed = True
433420

@@ -439,8 +426,7 @@ def __mutate_tree(self, value, mutation_type):
439426
else:
440427
raise NotImplementedError("Mutation type %s not implemented" % mutation_type)
441428

442-
def __extract_subtree(self, m, mindepth, subtreedepthmax, maxdepth):
443-
expression_tree = Lisp_Tree_Expr(m)
429+
def __extract_subtree(self, expression_tree, mindepth, subtreedepthmax, maxdepth):
444430
candidates = []
445431
for node in expression_tree.internal_nodes():
446432
if mindepth <= node.get_depth() <= maxdepth:
@@ -450,28 +436,28 @@ def __extract_subtree(self, m, mindepth, subtreedepthmax, maxdepth):
450436
if not candidates:
451437
raise TreeException("No subtrees to extract from '%s' "
452438
"with mindepth=%s, maxdepth=%s, subtreedepthmax=%s" %
453-
(m, mindepth, maxdepth, subtreedepthmax))
439+
(expression_tree, mindepth, maxdepth, subtreedepthmax))
454440

455441
candidates.sort(key=lambda x: x.get_expr_index(), reverse=False)
456442
n = int(np.ceil(MatlabEngine.rand() * len(candidates))) - 1
457443
extracted_node = candidates[n]
458444
index = extracted_node.get_expr_index()
459-
new_value = m[:index] + m[index:].replace(extracted_node.to_string(), '@', 1)
445+
old_value = expression_tree.get_expanded_tree_as_string()
446+
new_value = old_value[:index] + old_value[index:].replace(extracted_node.to_string(), '@', 1)
460447
return new_value, extracted_node.to_string(), extracted_node.get_subtreedepth()
461448

462-
def __reparam_tree(self, value):
449+
def __reparam_tree(self, tree_expression):
463450
def leaf_value_generator():
464451
leaf_value = (MatlabEngine.rand() - 0.5) * 2 * self._range
465452
return "%0.*f" % (self._precision, leaf_value)
466453

467-
return self.__change_const_tree(value, leaf_value_generator)
454+
return self.__change_const_tree(tree_expression, leaf_value_generator)
468455

469-
def __change_const_tree(self, expression, leaf_value_generator):
470-
expression_tree = Lisp_Tree_Expr(expression)
471-
for leaf in expression_tree.leaf_nodes():
456+
def __change_const_tree(self, tree_expression, leaf_value_generator):
457+
for leaf in tree_expression.leaf_nodes():
472458
if not leaf.is_sensor():
473459
leaf._arg = leaf_value_generator()
474-
return expression_tree.get_expanded_tree_as_string()
460+
return tree_expression.get_expanded_tree_as_string()
475461

476462
def __str__(self):
477463
return "value: %s\n" % self.get_value() + \

0 commit comments

Comments
 (0)