def get_bt_from_root(self): """ Returns bt string (actually a list) from py tree root by cleaning the ascii tree from py trees Not complete or beautiful by any means but works for many trees """ string = pt.display.ascii_tree(self.root) print(string) string = string.replace('[o] ', '') string = string.replace('\t', '') string = string.replace('-->', '') string = string.replace('Fallback', 'f(') string = string.replace('Sequence', 's(') bt = string.split('\n') bt = bt[:-1] #Remove empty element because of final newline prev_leading_spaces = 999999 for i in range(len(bt) - 1, -1, -1): leading_spaces = len(bt[i]) - len(bt[i].lstrip(' ')) bt[i] = bt[i].lstrip(' ') if leading_spaces > prev_leading_spaces: for _ in range( round((leading_spaces - prev_leading_spaces) / 4)): bt.insert(i + 1, ')') prev_leading_spaces = leading_spaces bt_obj = behavior_tree.BT(bt) bt_obj.close() return bt_obj.bt
def mutate_gene(genome, p_add, p_delete): """ Mutate only a single gene. """ if p_add < 0 or p_delete < 0: raise Exception("Mutation parameters must not be negative.") if p_add + p_delete > 1: raise Exception( "Sum of the mutation probabilities must be less than 1.") mutated_individual = behavior_tree.BT([]) max_attempts = 100 attempts = 0 while (not mutated_individual.is_valid() or mutated_individual.bt == genome) and attempts < max_attempts: mutated_individual.set(genome) index = random.randint(0, len(genome) - 1) mutation = random.random() # Delete node if mutation < p_delete: mutated_individual.delete_node(index) # Add node elif mutation < p_delete + p_add: mutated_individual.add_node(index) # Mutate node else: mutated_individual.change_node(index) #Close bt accordingly to the change mutated_individual.close() attempts += 1 if attempts >= max_attempts and (not mutated_individual.is_valid() or mutated_individual.bt == genome): mutated_individual = behavior_tree.BT([]) return mutated_individual.bt
def crossover_genome(genome1, genome2): """ Do crossover between genomes at random points """ bt1 = behavior_tree.BT(genome1) bt2 = behavior_tree.BT(genome2) offspring1 = behavior_tree.BT([]) offspring2 = behavior_tree.BT([]) if bt1.is_valid() and bt2.is_valid(): max_attempts = 100 attempts = 0 found = False while not found and attempts < max_attempts: offspring1.set(bt1.bt) offspring2.set(bt2.bt) cop1 = -1 cop2 = -1 if len(genome1) == 1: cop1 = 0 #Change whole tree else: while not offspring1.is_subtree(cop1): cop1 = random.randint(1, len(genome1) - 1) if len(genome2) == 1: cop2 = 0 #Change whole tree else: while not offspring2.is_subtree(cop2): cop2 = random.randint(1, len(genome2) - 1) offspring1.swap_subtrees(offspring2, cop1, cop2) attempts += 1 if offspring1.is_valid() and offspring2.is_valid(): found = True if not found: offspring1.set([]) offspring2.set([]) return offspring1.bt, offspring2.bt
def __init__(self, string, behaviors, state_machine=None, root=None): if root is not None: self.root = root string = self.get_bt_from_root() self.bt = behavior_tree.BT(string) self.depth = self.bt.depth() self.length = self.bt.length() self.state_machine = state_machine self.behaviors = behaviors if root is None: self.root, has_children = behaviors.get_node_from_string( string[0], state_machine) string.pop(0) else: has_children = False super().__init__(root=self.root) if has_children: self.create_from_string(string, self.root)
def random_genome(length): """ Returns a random genome """ bt = behavior_tree.BT([]) return bt.random(length)