diff --git a/pyevolve/Consts.py b/pyevolve/Consts.py index 1664405..8d114db 100644 --- a/pyevolve/Consts.py +++ b/pyevolve/Consts.py @@ -524,6 +524,9 @@ # Util Consts CDefBroadcastAddress = "255.255.255.255" nodeType = {"TERMINAL" : 0, "NONTERMINAL": 1} +nodeValueType = [ "", "i", "b", "f", "s" ] +# [ default, int, bool, float, string ] +CDefValueType = 0 CDefGPGenomes = [GTreeGP] diff --git a/pyevolve/Crossovers.py b/pyevolve/Crossovers.py index b73d9e4..37a4a4f 100644 --- a/pyevolve/Crossovers.py +++ b/pyevolve/Crossovers.py @@ -733,7 +733,10 @@ def GTreeGPCrossoverSinglePoint(genome, **args): if dadRandom.getType() == Consts.nodeType["TERMINAL"]: momRandom = gMom.getRandomNode(1) elif dadRandom.getType() == Consts.nodeType["NONTERMINAL"]: - momRandom = gMom.getRandomNode(2) + momRandom = gMom.getRandomNode(2, dadRandom.getOutType(), dadRandom.getInType()) + + if momRandom is None: + continue mD = gMom.getNodeDepth(momRandom) dD = gDad.getNodeDepth(dadRandom) diff --git a/pyevolve/DBAdapters.py b/pyevolve/DBAdapters.py index 7c76f24..d94ee55 100644 --- a/pyevolve/DBAdapters.py +++ b/pyevolve/DBAdapters.py @@ -26,7 +26,7 @@ import Statistics -class DBBaseAdapter: +class DBBaseAdapter(object): """ DBBaseAdapter Class - The base class for all DB Adapters If you want to create your own DB Adapter, you must subclass this @@ -121,7 +121,7 @@ def __init__(self, filename=Consts.CDefCSVFileName, identify=None, frequency = Consts.CDefCSVFileStatsGenFreq, reset=True): """ The creator of DBFileCSV Class """ - DBBaseAdapter.__init__(self, frequency, identify) + super(DBFileCSV, self).__init__(frequency, identify) self.csvmod = None @@ -211,7 +211,7 @@ def __init__(self, url, identify=None, frequency = Consts.CDefURLPostStatsGenFreq, post=True): """ The creator of the DBURLPost Class. """ - DBBaseAdapter.__init__(self, frequency, identify) + super(DBURLPost, self).__init__(frequency, identify) self.urllibmod = None self.url = url @@ -286,7 +286,7 @@ def __init__(self, dbname=Consts.CDefSQLiteDBName, identify=None, resetDB=False, commit_freq=Consts.CDefSQLiteStatsCommitFreq): """ The creator of the DBSQLite Class """ - DBBaseAdapter.__init__(self, frequency, identify) + super(DBSQLite, self).__init__(frequency, identify) self.sqlite3mod = None self.connection = None @@ -476,7 +476,7 @@ def insert(l): def __init__(self, url, identify=None, frequency = Consts.CDefXMLRPCStatsGenFreq): """ The creator of DBXMLRPC Class """ - DBBaseAdapter.__init__(self, frequency, identify) + super(DBXMLRPC, self).__init__(frequency, identify) self.xmlrpclibmod = None self.url = url @@ -538,7 +538,7 @@ class DBVPythonGraph(DBBaseAdapter): """ def __init__(self, identify=None, frequency = 20, genmax=False): - DBBaseAdapter.__init__(self, frequency, identify) + super(DBVPythonGraph, self).__init__(frequency, identify) self.genmax = genmax self.vtkGraph = None self.curveMin = None @@ -638,7 +638,7 @@ def __init__(self, user, passwd, host=Consts.CDefMySQLDBHost, port=Consts.CDefMy frequency=Consts.CDefMySQLStatsGenFreq, commit_freq=Consts.CDefMySQLStatsCommitFreq): """ The creator of the DBSQLite Class """ - DBBaseAdapter.__init__(self, frequency, identify) + super(DBMySQLAdapter, self).__init__(frequency, identify) self.mysqldbmod = None self.connection = None diff --git a/pyevolve/FunctionSlot.py b/pyevolve/FunctionSlot.py index 20b2b94..003aa00 100644 --- a/pyevolve/FunctionSlot.py +++ b/pyevolve/FunctionSlot.py @@ -17,7 +17,7 @@ import Util -class FunctionSlot: +class FunctionSlot(object): """ FunctionSlot Class - The function slot Example: diff --git a/pyevolve/G1DBinaryString.py b/pyevolve/G1DBinaryString.py index efe2c89..3e538e3 100644 --- a/pyevolve/G1DBinaryString.py +++ b/pyevolve/G1DBinaryString.py @@ -38,15 +38,14 @@ import Consts import Util -class G1DBinaryString(GenomeBase, G1DBase): +class G1DBinaryString(G1DBase): """ G1DBinaryString Class - The 1D Binary String chromosome Inheritance diagram for :class:`G1DBinaryString.G1DBinaryString`: .. inheritance-diagram:: G1DBinaryString.G1DBinaryString - This chromosome class extends the :class:`GenomeBase.GenomeBase` - and :class:`GenomeBase.G1DBase` classes. + This chromosome class extends the :class:`GenomeBase.G1DBase` class. Example: >>> genome = G1DBinaryString.G1DBinaryString(5) @@ -54,44 +53,11 @@ class G1DBinaryString(GenomeBase, G1DBase): :param length: the 1D Binary String size """ - - evaluator = None - """ This is the :term:`evaluation function` slot, you can add - a function with the *set* method: :: - - genome.evaluator.set(eval_func) - """ - - initializator = None - """ This is the initialization function of the genome, you - can change the default initializator using the function slot: :: - - genome.initializator.set(Initializators.G1DBinaryStringInitializator) - - In this example, the initializator :func:`Initializators.G1DBinaryStringInitializator` - will be used to create the initial population. - """ - - mutator = None - """ This is the mutator function slot, you can change the default - mutator using the slot *set* function: :: - - genome.mutator.set(Mutators.G1DBinaryStringMutatorSwap) - - """ - - crossover = None - """ This is the reproduction function slot, the crossover. You - can change the default crossover method using: :: - - genome.crossover.set(Crossovers.G1DBinaryStringXUniform) - """ - + __slots__ = [ "stringLength" ] def __init__(self, length=10): """ The initializator of G1DList representation """ - GenomeBase.__init__(self) - G1DBase.__init__(self, length) + super(G1DBinaryString, self).__init__(length) self.genomeList = [] self.stringLength = length self.initializator.set(Consts.CDefG1DBinaryStringInit) diff --git a/pyevolve/G1DList.py b/pyevolve/G1DList.py index 2fd60a5..8b9e3ab 100644 --- a/pyevolve/G1DList.py +++ b/pyevolve/G1DList.py @@ -37,15 +37,14 @@ from GenomeBase import GenomeBase, G1DBase import Consts -class G1DList(GenomeBase, G1DBase): +class G1DList(G1DBase): """ G1DList Class - The 1D List chromosome representation Inheritance diagram for :class:`G1DList.G1DList`: .. inheritance-diagram:: G1DList.G1DList - This chromosome class extends the :class:`GenomeBase.GenomeBase` - and :class:`GenomeBase.G1DBase` classes. + This chromosome class extends the :class:`GenomeBase.G1DBase` classes. **Examples** @@ -104,43 +103,10 @@ class G1DList(GenomeBase, G1DBase): """ - evaluator = None - """ This is the :term:`evaluation function` slot, you can add - a function with the *set* method: :: - - genome.evaluator.set(eval_func) - """ - - initializator = None - """ This is the initialization function of the genome, you - can change the default initializator using the function slot: :: - - genome.initializator.set(Initializators.G1DListInitializatorAllele) - - In this example, the initializator :func:`Initializators.G1DListInitializatorAllele` - will be used to create the initial population. - """ - - mutator = None - """ This is the mutator function slot, you can change the default - mutator using the slot *set* function: :: - - genome.mutator.set(Mutators.G1DListMutatorSwap) - - """ - - crossover = None - """ This is the reproduction function slot, the crossover. You - can change the default crossover method using: :: - - genome.crossover.set(Crossovers.G1DListCrossoverUniform) - """ - def __init__(self, size=10, cloning=False): """ The initializator of G1DList representation, size parameter must be specified """ - GenomeBase.__init__(self) - G1DBase.__init__(self, size) + super(G1DList, self).__init__(size) if not cloning: self.initializator.set(Consts.CDefG1DListInit) self.mutator.set(Consts.CDefG1DListMutator) diff --git a/pyevolve/G2DBinaryString.py b/pyevolve/G2DBinaryString.py index 1e9c997..ea3a785 100644 --- a/pyevolve/G2DBinaryString.py +++ b/pyevolve/G2DBinaryString.py @@ -57,44 +57,12 @@ class G2DBinaryString(GenomeBase): :param width: the number of columns """ - - evaluator = None - """ This is the :term:`evaluation function` slot, you can add - a function with the *set* method: :: - - genome.evaluator.set(eval_func) - """ - - initializator = None - """ This is the initialization function of the genome, you - can change the default initializator using the function slot: :: - - genome.initializator.set(Initializators.G2DBinaryStringInitializator) - - In this example, the initializator :func:`Initializators.G1DBinaryStringInitializator` - will be used to create the initial population. - """ - - mutator = None - """ This is the mutator function slot, you can change the default - mutator using the slot *set* function: :: - - genome.mutator.set(Mutators.G2DBinaryStringMutatorSwap) - - """ - - crossover = None - """ This is the reproduction function slot, the crossover. You - can change the default crossover method using: :: - - genome.crossover.set(Crossovers.G2DBinaryStringXUniform) - """ - + __slots__ = [ "height", "width", "genomeString" ] def __init__(self, height, width): """ The initializator of G2DBinaryString representation, height and width must be specified """ - GenomeBase.__init__(self) + super(G2DBinaryString ,self).__init__() self.height = height self.width = width diff --git a/pyevolve/G2DList.py b/pyevolve/G2DList.py index 5d143e2..5b134be 100644 --- a/pyevolve/G2DList.py +++ b/pyevolve/G2DList.py @@ -85,43 +85,12 @@ class G2DList(GenomeBase): :param width: the number of columns """ - - evaluator = None - """ This is the :term:`evaluation function` slot, you can add - a function with the *set* method: :: - - genome.evaluator.set(eval_func) - """ - - initializator = None - """ This is the initialization function of the genome, you - can change the default initializator using the function slot: :: - - genome.initializator.set(Initializators.G2DListInitializatorAllele) - - In this example, the initializator :func:`Initializators.G2DListInitializatorAllele` - will be used to create the initial population. - """ - - mutator = None - """ This is the mutator function slot, you can change the default - mutator using the slot *set* function: :: - - genome.mutator.set(Mutators.G2DListMutatorIntegerGaussian) - - """ - - crossover = None - """ This is the reproduction function slot, the crossover. You - can change the default crossover method using: :: - - genome.crossover.set(Crossovers.G2DListCrossoverSingleHPoint) - """ + __slots__ = [ "height", "width", "genomeList" ] def __init__(self, height, width, cloning=False): """ The initializator of G2DList representation, height and width must be specified """ - GenomeBase.__init__(self) + super(G2DList, self).__init__() self.height = height self.width = width diff --git a/pyevolve/GAllele.py b/pyevolve/GAllele.py index 87737eb..354b17b 100644 --- a/pyevolve/GAllele.py +++ b/pyevolve/GAllele.py @@ -12,7 +12,7 @@ class that holds the allele types) and all the import Consts import Util -class GAlleles: +class GAlleles(object): """ GAlleles Class - The set of alleles Example: @@ -101,7 +101,7 @@ def __repr__(self): return ret -class GAlleleList: +class GAlleleList(object): """ GAlleleList Class - The list allele type Example: @@ -171,7 +171,7 @@ def __repr__(self): ret += "\tAllele Options:\t %s\n\n" % (self.options,) return ret -class GAlleleRange: +class GAlleleRange(object): """ GAlleleRange Class - The range allele type Example: diff --git a/pyevolve/GPopulation.py b/pyevolve/GPopulation.py index a60c3ff..8ef8592 100644 --- a/pyevolve/GPopulation.py +++ b/pyevolve/GPopulation.py @@ -82,7 +82,7 @@ def multiprocessing_eval_full(ind): return ind -class GPopulation: +class GPopulation(object): """ GPopulation Class - The container for the population **Examples** diff --git a/pyevolve/GSimpleGA.py b/pyevolve/GSimpleGA.py index 379d092..c54a3cf 100644 --- a/pyevolve/GSimpleGA.py +++ b/pyevolve/GSimpleGA.py @@ -148,7 +148,7 @@ def FitnessStatsCriteria(ga_engine): return True return False -class GSimpleGA: +class GSimpleGA(object): """ GA Engine Class - The Genetic Algorithm Core Example: @@ -232,6 +232,7 @@ def __init__(self, genome, seed=None, interactiveMode=True): self.migrationAdapter = None self.time_init = None + self.max_time = None self.interactiveMode = interactiveMode self.interactiveGen = -1 self.GPMode = False @@ -556,6 +557,20 @@ def getDBAdapter(self): """ return self.dbAdapter + def setMaxTime(self, seconds): + """ Sets the maximun evolve time of the GA Engine + + :param seconds: maximum time in seconds + """ + self.max_time = seconds + + def getMaxTime(self): + """ Get the maximun evolve time of the GA Engine + + :rtype: True or False + """ + return self.max_time + def bestIndividual(self): """ Returns the population best individual @@ -572,7 +587,7 @@ def worstIndividual(self): """ return self.internalPop.worstRaw() - def __gp_catch_functions(self, prefix): + def __gp_catch_functions(self, prefix, arg_name="gp_function_set", out_type=0, in_type=0): """ Internally used to catch functions with some specific prefix as non-terminals of the GP core """ import __main__ as mod_main @@ -586,12 +601,12 @@ def __gp_catch_functions(self, prefix): op_len = addr.func_code.co_argcount except: continue - function_set[obj] = op_len + function_set[obj] = (op_len, out_type, in_type) if len(function_set) <= 0: Util.raiseException("No function set found using function prefix '%s' !" % prefix, ValueError) - self.setParams(gp_function_set=function_set) + self.setParams(**{arg_name: function_set}) def initialize(self): """ Initializes the GA Engine. Create and initialize population """ @@ -690,6 +705,10 @@ def step(self): self.currentGeneration += 1 + if self.max_time: + total_time = time() - self.time_init + if total_time > self.max_time: + return True return (self.currentGeneration == self.nGenerations) def printStats(self): @@ -749,9 +768,11 @@ def evolve(self, freq_stats=0): if self.getGPMode(): - gp_function_prefix = self.getParam("gp_function_prefix") - if gp_function_prefix is not None: - self.__gp_catch_functions(gp_function_prefix) + for index1, value_type1 in enumerate(Consts.nodeValueType): + for index2, value_type2 in enumerate(Consts.nodeValueType): + gp_function_prefix = self.getParam("gp%s%s_function_prefix" % (value_type1, value_type2)) + if gp_function_prefix is not None: + self.__gp_catch_functions(gp_function_prefix, "gp%s%s_function_set" % (value_type1, value_type2), index1, index2) self.initialize() self.internalPop.evaluate() diff --git a/pyevolve/GTree.py b/pyevolve/GTree.py index de4fa24..702f07a 100644 --- a/pyevolve/GTree.py +++ b/pyevolve/GTree.py @@ -34,6 +34,7 @@ ------------------------------------------------------------- """ import random +from random import choice as rand_choice from GenomeBase import GenomeBase, GTreeBase, GTreeNodeBase import Consts import Util @@ -49,7 +50,7 @@ ################################# -class GTree(GenomeBase, GTreeBase): +class GTree(GTreeBase): """ The GTree class - The tree chromosome representation Inheritance diagram for :class:`GTree.GTree`: @@ -58,42 +59,9 @@ class GTree(GenomeBase, GTreeBase): :param root_node: the root node of the tree """ - - evaluator = None - """ This is the :term:`evaluation function` slot, you can add - a function with the *set* method: :: - - genome.evaluator.set(eval_func) - """ - - initializator = None - """ This is the initialization function of the genome, you - can change the default initializator using the function slot: :: - - genome.initializator.set(Initializators.G1DListInitializatorAllele) - - In this example, the initializator :func:`Initializators.G1DListInitializatorAllele` - will be used to create the initial population. - """ - - mutator = None - """ This is the mutator function slot, you can change the default - mutator using the slot *set* function: :: - - genome.mutator.set(Mutators.G1DListMutatorSwap) - - """ - - crossover = None - """ This is the reproduction function slot, the crossover. You - can change the default crossover method using: :: - - genome.crossover.set(Crossovers.G1DListCrossoverUniform) - """ def __init__(self, root_node=None): - GenomeBase.__init__(self) - GTreeBase.__init__(self, root_node) + super(GTree, self).__init__(root_node) self.initializator.set(Consts.CDefGTreeInit) self.mutator.set(Consts.CDefGGTreeMutator) self.crossover.set(Consts.CDefGTreeCrossover) @@ -133,9 +101,10 @@ class GTreeNode(GTreeNodeBase): :param parent: the parent node, if root, this must be *None* """ + __slots__ = [ "node_data" ] def __init__(self, data, parent=None): - GTreeNodeBase.__init__(self, parent) + super(GTreeNode, self).__init__(parent) self.node_data = data def __repr__(self): @@ -261,12 +230,18 @@ class GTreeNodeGP(GTreeNodeBase): :param data: the node data :param type: the node type + :param out: the node output value type + :param in: the node input value type :param parent: the node parent """ - def __init__(self, data, node_type=0, parent=None): - GTreeNodeBase.__init__(self, parent) + __slots__ = [ "node_type", "node_data", "out_type", "in_type" ] + + def __init__(self, data, node_type=0, out_type=0, in_type=0, parent=None): + super(GTreeNodeGP, self).__init__(parent) self.node_type = node_type + self.out_type = out_type + self.in_type = in_type self.node_data = data def __repr__(self): @@ -282,9 +257,11 @@ def compare(self, other): if not isinstance(other, GTreeNodeGP): Util.raiseException("The other node used to compare is not a GTreeNodeGP class", TypeError) - if other.node_type == self.node_type: - if other.node_data == self.node_data: - return 0 + if other.node_type == self.node_type and \ + other.out_type == self.out_type and \ + other.in_type == self.in_type: + if other.node_data == self.node_data: + return 0 return -1 def setData(self, data): @@ -315,6 +292,36 @@ def getType(self): """ return self.node_type + def setOutType(self, out_type): + """Sets the node output value type + + :param node_type: the node output value type is type of Consts.nodeValueType + """ + self.out_type = out_type + + def getOutType(self): + """Get the node output value type + + :rtype: the node output value type is type of Consts.nodeValueType + """ + return self.out_type + + def setInType(self, in_type): + """Sets the node input value type + + :param node_type: the node input value type is type of Consts.nodeValueType + """ + self.in_type = in_type + + def getInType(self, index=0): + """Get the node input value type + + :rtype: the node input value type is type of Consts.nodeValueType + """ + if type(self.in_type) == list: + return self.in_type[index] + return self.in_type + def newNode(self, data): """Creates a new node and adds this node as children of current node @@ -332,10 +339,16 @@ def swapNodeData(self, node): """ tmp_data = self.node_data tmp_type = self.node_type + tmp_out_type = self.out_type + tmp_in_type = self.in_type self.setData(node.getData()) self.setType(node.getType()) + self.setInType(node.getInType()) + self.setOutType(node.getOutType()) node.setData(tmp_data) node.setType(tmp_type) + node.setInType(tmp_in_type) + node.setOutType(tmp_out_type) def copy(self, g): """ Copy the contents to the destination g @@ -345,6 +358,8 @@ def copy(self, g): GTreeNodeBase.copy(self, g) g.node_data = self.node_data g.node_type = self.node_type + g.out_type = self.out_type + g.in_type = self.in_type def clone(self): """ Return a new copy of the node @@ -355,7 +370,7 @@ def clone(self): self.copy(newcopy) return newcopy -class GTreeGP(GenomeBase, GTreeBase): +class GTreeGP(GTreeBase): """ The GTreeGP Class - The Genetic Programming Tree representation Inheritance diagram for :class:`GTree.GTreeGP`: @@ -364,9 +379,9 @@ class GTreeGP(GenomeBase, GTreeBase): :param root_node: the Root node of the GP Tree """ + def __init__(self, root_node=None, cloning=False): - GenomeBase.__init__(self) - GTreeBase.__init__(self, root_node) + super(GTreeGP, self).__init__(root_node) if not cloning: self.initializator.set(Consts.CDefGTreeGPInit) self.mutator.set(Consts.CDefGGTreeGPMutator) @@ -380,6 +395,22 @@ def __repr__(self): ret += "\tExpression: %s\n" % self.getPreOrderExpression() return ret + def getRandomNode(self, node_type=0, out_type=0, in_type=0): + """ Returns a random node from the Tree + + :param node_type: 0 = Any, 1 = Leaf, 2 = Branch + :param out_type: the type returned to the node's parent + :param in_type: the type returned from the node's children + :rtype: random node + """ + lists = (self.nodes_list, self.nodes_leaf, self.nodes_branch) + cho = lists[node_type] + if node_type == 2: + cho = [c for c in cho if c.getOutType() == out_type and c.getInType() == in_type] + if len(cho) <= 0: + return None + return rand_choice(cho) + def writeDotImage(self, filename): """ Writes a image representation of the individual @@ -473,21 +504,17 @@ def getSExpression(self, start_node=None): :rtype: a S-Expression representing the tree """ - str_buff = "" if start_node is None: start_node = self.getRoot() - str_buff += "%s " % start_node.getData() - - is_leaf = start_node.isLeaf() - if not is_leaf: - str_buff += "( " - for child_node in start_node.getChilds(): - str_buff += "%s " % child_node.getData() - str_buff += self.getSExpression(child_node) + str_buff = "%s " % start_node.getData() - if not is_leaf: + if not start_node.isLeaf(): + str_buff += "( " + for child_node in start_node.getChilds(): + str_buff += self.getSExpression(child_node) str_buff += " )" + return str_buff def getPreOrderExpression(self, start_node=None): @@ -667,7 +694,7 @@ def checkTerminal(terminal): else: return terminal -def buildGTreeGPGrow(ga_engine, depth, max_depth): +def buildGTreeGPGrow(ga_engine, depth, max_depth, out_type=0): """ Creates a new random GTreeGP root node with subtrees using the "Grow" method. @@ -676,16 +703,22 @@ def buildGTreeGPGrow(ga_engine, depth, max_depth): :max_depth: the maximum depth of the tree :rtype: the root node """ + if out_type == 0: + out_type = Consts.CDefValueType - gp_terminals = ga_engine.getParam("gp_terminals") + gp_terminals = ga_engine.getParam("gp%s_terminals" % Consts.nodeValueType[out_type]) assert gp_terminals is not None - gp_function_set = ga_engine.getParam("gp_function_set") - assert gp_function_set is not None + gp_function_set = {} + for value_type in Consts.nodeValueType: + temp_function_set = ga_engine.getParam("gp%s%s_function_set" % (Consts.nodeValueType[out_type], value_type)) + if temp_function_set is not None: + gp_function_set.update(temp_function_set) + assert len(gp_function_set) > 0 if depth == max_depth: random_terminal = checkTerminal(random.choice(gp_terminals)) - n = GTreeNodeGP(random_terminal, Consts.nodeType["TERMINAL"]) + n = GTreeNodeGP(random_terminal, Consts.nodeType["TERMINAL"], out_type) return n else: # Do not generate degenerative trees @@ -696,19 +729,19 @@ def buildGTreeGPGrow(ga_engine, depth, max_depth): random_node = random.choice(fchoice) if random_node in gp_terminals: - n = GTreeNodeGP(checkTerminal(random_node), Consts.nodeType["TERMINAL"]) + n = GTreeNodeGP(checkTerminal(random_node), Consts.nodeType["TERMINAL"], out_type) else: - n = GTreeNodeGP(random_node, Consts.nodeType["NONTERMINAL"]) + n = GTreeNodeGP(random_node, Consts.nodeType["NONTERMINAL"], out_type, gp_function_set[random_node][2]) if n.getType() == Consts.nodeType["NONTERMINAL"]: - for i in xrange(gp_function_set[n.getData()]): - child = buildGTreeGPGrow(ga_engine, depth+1, max_depth) + for i in xrange(gp_function_set[n.getData()][0]): + child = buildGTreeGPGrow(ga_engine, depth+1, max_depth, n.getInType(i)) child.setParent(n) n.addChild(child) return n -def buildGTreeGPFull(ga_engine, depth, max_depth): +def buildGTreeGPFull(ga_engine, depth, max_depth, out_type=0): """ Creates a new random GTreeGP root node with subtrees using the "Full" method. @@ -717,23 +750,30 @@ def buildGTreeGPFull(ga_engine, depth, max_depth): :max_depth: the maximum depth of the tree :rtype: the root node """ - gp_terminals = ga_engine.getParam("gp_terminals") + if out_type == 0: + out_type = Consts.CDefValueType + + gp_terminals = ga_engine.getParam("gp%s_terminals" % Consts.nodeValueType[out_type]) assert gp_terminals is not None - gp_function_set = ga_engine.getParam("gp_function_set") - assert gp_function_set is not None + gp_function_set = {} + for value_type in Consts.nodeValueType: + temp_function_set = ga_engine.getParam("gp%s%s_function_set" % (Consts.nodeValueType[out_type], value_type)) + if temp_function_set is not None: + gp_function_set.update(temp_function_set) + assert len(gp_function_set) > 0 if depth == max_depth: random_terminal = checkTerminal(random.choice(gp_terminals)) - n = GTreeNodeGP(random_terminal, Consts.nodeType["TERMINAL"]) + n = GTreeNodeGP(random_terminal, Consts.nodeType["TERMINAL"], out_type) return n else: random_oper = random.choice(gp_function_set.keys()) - n = GTreeNodeGP(random_oper, Consts.nodeType["NONTERMINAL"]) + n = GTreeNodeGP(random_oper, Consts.nodeType["NONTERMINAL"], out_type, gp_function_set[random_oper][2]) if n.getType() == Consts.nodeType["NONTERMINAL"]: - for i in xrange(gp_function_set[n.getData()]): - child = buildGTreeGPFull(ga_engine, depth+1, max_depth) + for i in xrange(gp_function_set[n.getData()][0]): + child = buildGTreeGPFull(ga_engine, depth+1, max_depth, n.getInType(i)) child.setParent(n) n.addChild(child) diff --git a/pyevolve/GenomeBase.py b/pyevolve/GenomeBase.py index 088da7e..0f4113e 100644 --- a/pyevolve/GenomeBase.py +++ b/pyevolve/GenomeBase.py @@ -14,41 +14,9 @@ from FunctionSlot import FunctionSlot import Util -class GenomeBase: +class GenomeBase(object): """ GenomeBase Class - The base of all chromosome representation """ - - evaluator = None - """ This is the :term:`evaluation function` slot, you can add - a function with the *set* method: :: - - genome.evaluator.set(eval_func) - """ - - initializator = None - """ This is the initialization function of the genome, you - can change the default initializator using the function slot: :: - - genome.initializator.set(Initializators.G1DListInitializatorAllele) - - In this example, the initializator :func:`Initializators.G1DListInitializatorAllele` - will be used to create the initial population. - """ - - mutator = None - """ This is the mutator function slot, you can change the default - mutator using the slot *set* function: :: - - genome.mutator.set(Mutators.G1DListMutatorSwap) - - """ - - crossover = None - """ This is the reproduction function slot, the crossover. You - can change the default crossover method using: :: - - genome.crossover.set(Crossovers.G1DListCrossoverUniform) - """ - + __slots__ = [ "evaluator", "initializator", "mutator", "crossover", "internalParams", "score", "fitness" ] def __init__(self): """Genome Constructor""" @@ -79,8 +47,8 @@ def getFitnessScore(self): def __repr__(self): """String representation of Genome""" - allSlots = self.allSlots = [ self.evaluator, self.initializator, - self.mutator, self.crossover ] + allSlots = [ self.evaluator, self.initializator, + self.mutator, self.crossover ] ret = "- GenomeBase\n" ret+= "\tScore:\t\t\t %.6f\n" % (self.score,) @@ -189,16 +157,20 @@ def clone(self): self.copy(newcopy) return newcopy -class G1DBase: +class G1DBase(GenomeBase): """ G1DBase Class - The base class for 1D chromosomes - + + This chromosome class extends the :class:`GenomeBase` classes. + :param size: the 1D list size .. versionadded:: 0.6 - Added te *G1DBase* class + Added the *G1DBase* class """ + __slots__ = [ "genomeSize", "genomeList" ] def __init__(self, size): + super(G1DBase, self).__init__() self.genomeSize = size self.genomeList = [] @@ -305,15 +277,16 @@ def setInternalList(self, lst): """ self.genomeList = lst -class GTreeNodeBase: +class GTreeNodeBase(object): """ GTreeNodeBase Class - The base class for the node tree genomes :param parent: the parent node of the node :param childs: the childs of the node, must be a list of nodes .. versionadded:: 0.6 - Added te *GTreeNodeBase* class + Added the *GTreeNodeBase* class """ + __slots__ = [ "parent", "childs" ] def __init__(self, parent, childs=None): self.parent = parent @@ -420,16 +393,20 @@ def clone(self): return newcopy -class GTreeBase: +class GTreeBase(GenomeBase): """ GTreeBase Class - The base class for the tree genomes - + + This chromosome class extends the :class:`GenomeBase` classes. + :param root_node: the root node of the tree .. versionadded:: 0.6 - Added te *GTreeBase* class + Added the *GTreeBase* class """ + __slots__ = [ "root_node", "tree_height", "nodes_list", "nodes_leaf", "nodes_branch" ] def __init__(self, root_node): + super(GTreeBase, self).__init__() self.root_node = root_node self.tree_height = None self.nodes_list = None diff --git a/pyevolve/Mutators.py b/pyevolve/Mutators.py index 8c275ac..e6ed1bd 100644 --- a/pyevolve/Mutators.py +++ b/pyevolve/Mutators.py @@ -954,9 +954,6 @@ def GTreeGPMutatorOperation(genome, **args): ga_engine = args["ga_engine"] - gp_terminals = ga_engine.getParam("gp_terminals") - assert gp_terminals is not None - gp_function_set = ga_engine.getParam("gp_function_set") assert gp_function_set is not None @@ -968,12 +965,16 @@ def GTreeGPMutatorOperation(genome, **args): rand_node = genome.getRandomNode() assert rand_node is not None if rand_node.getType() == Consts.nodeType["TERMINAL"]: + gp_terminals = ga_engine.getParam("gp%s_terminals" % Consts.nodeValueType[rand_node.getOutType()]) + if len(gp_terminals) == 0: continue term_operator = rand_choice(gp_terminals) else: - op_len = gp_function_set[rand_node.getData()] + op_len = gp_function_set[rand_node.getData()][0] + out_type = rand_node.getOutType() + in_type = rand_node.getInType() fun_candidates = [] for o, l in gp_function_set.items(): - if l==op_len: + if l[0] == op_len and l[1] == out_type and l[2] == in_type: fun_candidates.append(o) if len(fun_candidates) <= 0: @@ -986,12 +987,16 @@ def GTreeGPMutatorOperation(genome, **args): rand_node = genome.getRandomNode() assert rand_node is not None if rand_node.getType() == Consts.nodeType["TERMINAL"]: + gp_terminals = ga_engine.getParam("gp%s_terminals" % Consts.nodeValueType[rand_node.getOutType()]) + if len(gp_terminals) == 0: continue term_operator = rand_choice(gp_terminals) else: - op_len = gp_function_set[rand_node.getData()] + op_len = gp_function_set[rand_node.getData()][0] + out_type = rand_node.getOutType() + in_type = rand_node.getInType() fun_candidates = [] for o, l in gp_function_set.items(): - if l==op_len: + if l[0] == op_len and l[1] == out_type and l[2] == in_type: fun_candidates.append(o) if len(fun_candidates) <= 0: @@ -1035,7 +1040,7 @@ def GTreeGPMutatorSubtree(genome, **args): depth = genome.getNodeDepth(node) mutations += 1 - root_subtree = GTree.buildGTreeGPGrow(ga_engine, 0, max_depth-depth) + root_subtree = GTree.buildGTreeGPGrow(ga_engine, 0, max_depth-depth, node.getOutType()) node_parent = node.getParent() if node_parent is None: diff --git a/pyevolve/Network.py b/pyevolve/Network.py index f885bd7..c1781cc 100644 --- a/pyevolve/Network.py +++ b/pyevolve/Network.py @@ -59,7 +59,7 @@ class UDPThreadBroadcastClient(threading.Thread): """ def __init__(self, host, port, target_port): - threading.Thread.__init__(self) + super(UDPThreadBroadcastClient, self).__init__() self.host = host self.port = port self.targetPort = target_port @@ -138,7 +138,7 @@ class UDPThreadUnicastClient(threading.Thread): """ def __init__(self, host, port, pool_size=10, timeout=0.5): - threading.Thread.__init__(self) + super(UDPThreadUnicastClient, self).__init__() self.host = host self.port = port self.target = [] @@ -275,7 +275,7 @@ class UDPThreadServer(threading.Thread): """ def __init__(self, host, port, poolSize=10, timeout=3): - threading.Thread.__init__(self) + super(UDPThreadServer, self).__init__() self.recvPool = [] self.recvPoolLock = threading.Lock() self.bufferSize = 4096 diff --git a/pyevolve/Statistics.py b/pyevolve/Statistics.py index 037bb93..eca3347 100644 --- a/pyevolve/Statistics.py +++ b/pyevolve/Statistics.py @@ -7,7 +7,7 @@ generation. This class is used by the adapters and other statistics dump objects. """ -class Statistics: +class Statistics(object): """ Statistics Class - A class bean-like to store the statistics The statistics hold by this class are: diff --git a/pyevolve/Util.py b/pyevolve/Util.py index 8cfef96..b59b5bb 100644 --- a/pyevolve/Util.py +++ b/pyevolve/Util.py @@ -139,7 +139,7 @@ def importSpecial(name): raiseException("Cannot import module %s: %s" % (name, Consts.CDefImportList[name]), expt=ImportError) return imp_mod -class ErrorAccumulator: +class ErrorAccumulator(object): """ An accumulator for the Root Mean Square Error (RMSE) and the Mean Square Error (MSE) """ @@ -202,7 +202,7 @@ def getMSE(self): return (self.acc_square / float(self.acc_len)) -class Graph: +class Graph(object): """ The Graph class Example: