Source code for HyperGP.libs.representation.TGP

import copy
import random
import numpy as np

from HyperGP.base.prog_basic import Program
from ..states import ProgBuildStates
from ..utils import HalfAndHalf

prog_basic_list = np.arange(10000, dtype=np.int32)

[docs] class TGPIndv(Program): """ We provide the ``TGPIndv`` class to build the tree structure program Note: The encode list is a collection of pset elements without deep copy. """
[docs] def __init__(self, states=None, encode=None, module_states=None, **kwargs): """ Initialize the program Args: states(HyperGP.States): the states assign to a program. encode: generate a new ``TGPIndv`` with a given encode. kwargs: the attrs assign to a program. Returns: returns a new ``TGPIndv`` Examples: >>> from HyperGP.representation import TGPIndv >>> from HyperGP.states import States >>> ind = TGPIndv() Initialize with states and attrs: >>> ind = TGPIndv(states=States(elim_prob=1, rk=0), win_num=0) >>> print(ind.states) xxxxx >>> print(TGPIndv.win_num) xxxxx """ super().__init__(state=states, module_states=module_states, encode=encode, **kwargs)
# if states is not None: # if 'module_states' not in states and 'states' not in states: # super().__init__(state=states, **kwargs) # else: # super().__init__(**states, **kwargs) # else: # super().__init__(state=None, module_states=None, **kwargs) # if encode is not None: # self._encode = encode """""" def buildProgram(self, cond: ProgBuildStates, method=HalfAndHalf(), node_states=None): """ Build the program Args: cond(ProgBuildStates): The states needed to generate the program with given method, which will be used as uniform formal parameter of the generation method. method: the method to generate a encode list, with `cond` parameter as input. node_states: the states want . Returns: returns a new ``TGPIndv`` Examples: >>> from HyperGP.states import ProgBuildStates >>> prog_states = ProgBuildStates(pset=pset, depth_rg=[2, 6], len_limit=100) >>> ind.build(prog_states) >>> print(ind) xxxxxxx """ encode = method(cond, node_states) replace_array = np.array([elem for node in encode for elem in (node.idx if node.idx != -1 else node.val, node.arity, (0 if node.arity > 0 else 1) if node.idx != -1 else 2)], dtype=np.float32) self._pset_map = {(node.idx if node.arity > 0 else -(node.idx + 1)):node for node in encode if node.idx != -1 and (node.idx if node.arity > 0 else -(node.idx + 1)) not in self._pset_map} self._encode_array = replace_array # self.stateRegister(encode=root) self._encode = encode # def list(self, parent=False, childs=False): # if not parent and not childs: # return list(range(len(self._encode))) def list(self, parent=False, childs=False): """ Generate the preorder traversal list of the program Args: parent(bool): whether generate the parent list with the preorder traversal list. childs(bool): whether generate the child list with the preorder traversal list. Returns: Return the preorder traversal list. If parent or childs is true, then return a list: [preorder list, parent list if parent=True, child list if childs=True] Examples: >>> print(ind.list()) xxxxxx >>> print(ind.list(child=True)) xxxxxx >>> print(ind.list(parent=True, child=True)) xxxxxx """ if not parent and not childs: return prog_basic_list[:int(self._encode_array.shape[0] / 3)] pc_list = [] if parent: p_list = [[] for z in range(int(self._encode_array.shape[0] / 3))] cur_arity = [[0, self._encode_array[1]]] for i in range(0, len(self._encode_array[1:]), 3): i = int(i / 3 + 1) arity = self._encode_array[1 + i * 3] idx, _ = cur_arity[-1] cur_arity[-1][1] -= 1 p_list[i].append(idx) if cur_arity[-1][1] == 0: cur_arity.pop() if arity > 0: cur_arity.append([i, arity]) pc_list.append(p_list) if childs: c_list = [[] for z in range(int(self._encode_array.shape[0] / 3))] cur_arity = [[0, self._encode_array[1].arity]] for i in range(0, len(self._encode_array[1:]), 3): i = int(i / 3 + 1) arity = self._encode_array[1 + i * 3] idx, _ = cur_arity[-1] cur_arity[-1][1] -= 1 c_list[idx].append(i) if cur_arity[-1][1] == 0: cur_arity.pop() if arity > 0: cur_arity.append([i, arity]) pc_list.append(c_list) if len(cur_arity) != 0: raise ValueError("Something wrong when search childs in list()") # print(len(c_list), len(c_list[0]), len(c_list[1]), c_list[0], c_list[1]) return pc_list # def __getitem__(self, item): # # return [ for i in self.encode[item]] # return self.encode[item] # def __setitem__(self, key, value): # if isinstance(key, slice): # if key.start >= len(self): # raise IndexError("Invalid slice object (try to assign a %s" # " in a tree of size %d). Even if this is allowed by the" # " list object slice setter, this should not be done in" # " the PrimitiveTree context, as this may lead to an" # " unpredictable behavior for searchSubtree or evaluate." # % (key, len(self))) # total = value[0].arity # for node in value[1:]: # total += node.arity - 1 # if total != 0: # raise ValueError("Invalid slice assignation : insertion of" # " an incomplete subtree is not allowed in PrimitiveTree." # " A tree is defined as incomplete when some nodes cannot" # " be mapped to any position in the tree, considering the" # " primitives' arity. For instance, the tree [sub, 4, 5," # " 6] is incomplete if the arity of sub is 2, because it" # " would produce an orphan node (the 6).") # elif value.arity != self[key].arity: # raise ValueError("Invalid node replacement with a node of a" # " different arity.") # self.encode.__setitem__(key, value) def __deepcopy__(self, memo): new_ind = TGPIndv() return new_ind.make(self._encode_array, self.states, self._pset_map, memo) def copy(self): """ Returns a new ``TGPIndv`` with the same encode list and states. """ new_ind = TGPIndv.__new__(TGPIndv) # new_ind = TGPIndv() new_ind.update(self) # new_ind._encode_array, new_ind._pset_map = self._encode_array.copy(), self._pset_map return new_ind def __str__(self): def format(node, *args): if node.arity > 0: _args = ", ".join(map("{{{0}}}".format, range(node.arity))) seq = "{name}({args})".format(name=node.name, args=_args) return seq.format(*args) else: return str(node) string = "" stack = [] for node in self: stack.append((node, [])) while len(stack[-1][1]) == stack[-1][0].arity: prim, args = stack.pop() string = format(prim, *args) if len(stack) == 0: break stack[-1][1].append(string) return string
# # stack = [self.encode] # tstack = [] # while stack: # node = stack.pop() # tstack.append((node, [])) # if node.childs is not None: # stack.extend(node.childs) # while tstack[-1][0].arity == len(tstack[-1][1]): # f_node = tstack.pop() # if len(tstack) == 0: # return f_node[0].format(*f_node[1]) # tstack[-1][1].append(f_node[0].format(*f_node[1]))