def vectorial_delete_one_subtree(self, state): # here i make only crossovers between eqs1 resp. and eqs 2 prev_state = copy.deepcopy(state) game = Game(self.voc, prev_state) ast = game.convert_to_ast() rpn = prev_state.reversepolish #print('entering delete with', game.state.reversepolish, game.state.formulas) # throw away the last '1' (== halt) if exists: if rpn[-1] == 1: array = np.asarray(rpn[:-1]) else: array = np.asarray(rpn) start = 2 # get all topnodes of possible subtrees positions = np.where(array >= start)[0] if positions.size > 0: maxretries = 10 gotone = False count = 0 while gotone is False and count < maxretries: which = np.random.choice(positions) getnonleafnode = which + 1 # get the node operatornode = ast.from_ast_get_node(ast.topnode, getnonleafnode)[0] before_swap_rpn = ast.from_ast_to_rpn(operatornode) bfstate = State(self.voc, before_swap_rpn, self.calculus_mode) bef_game = Game(self.voc, bfstate) _, vec_number, _ = bef_game.from_rpn_to_critical_info() grandparent = operatornode.parent count += 1 if before_swap_rpn[ -1] in self.voc.arity2symbols and grandparent is not None: gotone = True count = 0 for child in grandparent.children: if child == operatornode: index = count count += 1 if gotone == False: return False, prev_state else: #print('le node selectionne est', ast.from_ast_to_rpn(operatornode)) #print('fils gauche', ast.from_ast_to_rpn(operatornode.children[0])) #print('fils droit', ast.from_ast_to_rpn(operatornode.children[1])) #print('ready:', before_swap_rpn, bef_game.state.formulas) vecs = [] for child in operatornode.children: rpnchild = ast.from_ast_to_rpn(child) #print('ici', rpnchild) statechild = State(self.voc, rpnchild, self.calculus_mode) gamechild = Game(self.voc, statechild) _, vec_number, _ = gamechild.from_rpn_to_critical_info() vecs.append(vec_number) #print('then vec numbers', vecs) if vecs == [0, 0]: if random.random() < 0.5: newnode = operatornode.children[0] #print('delete right') else: newnode = operatornode.children[1] #print('delete left') elif vecs == [0, 1]: newnode = operatornode.children[1] #print('delete left') elif vecs == [1, 0]: newnode = operatornode.children[0] #print('delete right') elif vecs == [1, 1] and before_swap_rpn[ -1] != self.voc.dot_number: #exclude dot product if random.random() < 0.5: newnode = operatornode.children[0] #print('delete right') else: newnode = operatornode.children[1] #print('delete left') else: #le cas du doot product return False, prev_state grandparent.children[index] = newnode # get the new reversepolish: newrpn = ast.from_ast_to_rpn(ast.topnode) # else cant delete tree else: return False, prev_state # returns the new states state = State(self.voc, newrpn, self.calculus_mode) #print('finally', state.reversepolish, state.formulas) #game = Game(self.voc, state) #game.from_rpn_to_critical_info() #print('bug?') return True, state
def vectorial_crossover(self, state1, state2): # here i make only crossovers between eqs1 resp. and eqs 2 prev_state1 = copy.deepcopy(state1) prev_state2 = copy.deepcopy(state2) game1 = Game(self.voc, prev_state1) game2 = Game(self.voc, prev_state2) ast1 = game1.convert_to_ast() ast2 = game2.convert_to_ast() rpn1 = prev_state1.reversepolish rpn2 = prev_state2.reversepolish # throw away the last '1' (== halt) if exists: if rpn1[-1] == 1: array1 = np.asarray(rpn1[:-1]) else: array1 = np.asarray(rpn1) if rpn2[-1] == 1: array2 = np.asarray(rpn2[:-1]) else: array2 = np.asarray(rpn2) # topnode has the max absolute label, so you dont want it/ you want only subtrees, hence the [:-1] # subtrees can be scalars == leaves, hence >= 2 start = 2 # + len(self.voc.arity0symbols) # get all topnodes of possible subtrees positions1 = np.where(array1 >= start)[0][:-1] positions2 = np.where(array2 >= start)[0][:-1] if positions1.size > 0 and positions2.size > 0: # choose two which1 = np.random.choice(positions1) which2 = np.random.choice(positions2) getnonleafnode1 = which1 + 1 getnonleafnode2 = which2 + 1 # get the nodes node1 = ast1.from_ast_get_node(ast1.topnode, getnonleafnode1)[0] node2 = ast2.from_ast_get_node(ast2.topnode, getnonleafnode2)[0] before_swap_rpn1 = ast1.from_ast_to_rpn(node1) before_swap_rpn2 = ast2.from_ast_to_rpn(node2) bfstate1 = State(self.voc, before_swap_rpn1, self.calculus_mode) bfstate2 = State(self.voc, before_swap_rpn2, self.calculus_mode) bef_game1 = Game(self.voc, bfstate1) bef_game2 = Game(self.voc, bfstate2) _, vec_number1, _ = bef_game1.from_rpn_to_critical_info() _, vec_number2, _ = bef_game2.from_rpn_to_critical_info() if vec_number1 == vec_number2: # swap parents and children == swap subtrees prev1 = node1.parent c = 0 for child in prev1.children: if child == node1: prev1.children[c] = node2 c += 1 c = 0 prev2 = node2.parent for child in prev2.children: if child == node2: prev2.children[c] = node1 c += 1 # get the new reversepolish: rpn1 = ast1.from_ast_to_rpn(ast1.topnode) rpn2 = ast2.from_ast_to_rpn(ast2.topnode) # but dont crossover at all if the results are eqs longer than maximal_size (see GP_QD) : if len(rpn1) > self.maximal_size or len( rpn2) > self.maximal_size: return False, prev_state1, prev_state2 else: #cant crossover vector and scalar return False, prev_state1, prev_state2 # else cant crossover else: return False, prev_state1, prev_state2 # returns the new states state1 = State(self.voc, rpn1, self.calculus_mode) state2 = State(self.voc, rpn2, self.calculus_mode) if self.usesimplif: state1 = game_env.simplif_eq(self.voc, state1) state2 = game_env.simplif_eq(self.voc, state2) # game1 = Game(self.voc, state1) # game1.simplif_eq() # state1 = game1.state # game2 = Game(self.voc, state2) # game2.simplif_eq() # state2 = game2.state game1 = Game(self.voc, state1) game2 = Game(self.voc, state2) #print('checkcrossovers enter with', game1.state.reversepolish) # print('checkcrossovers end with', game11.state.reversepolish) toreturn = [] # crossover can lead to true zero division thus : if self.voc.infinite_number in state1.reversepolish: toreturn.append(prev_state1) # print('fail') # also, if it returns too many nested functions, i dont want it (sort of parsimony) elif game1.getnumberoffunctions() > config.MAX_DEPTH: toreturn.append(prev_state1) # print('fail') else: toreturn.append(state1) # print('succes') if self.voc.infinite_number in state2.reversepolish: toreturn.append(prev_state2) # print('fail') elif game2.getnumberoffunctions() > config.MAX_DEPTH: toreturn.append(prev_state2) # print('fail') else: toreturn.append(state2) # print('succes') return True, toreturn[0], toreturn[1]