Module tutorial2
[hide private]
[frames] | no frames]

Source Code for Module tutorial2

  1  """ 
  2  tutorial2 
  3  ========= 
  4  Contains all parameters for the evolutionary run, grammar rules, constraints,  
  5  and specifics about the terminal and function set of the trees in tutorial2. 
  6  This example file gather all the settings for a simple polynomial regression 
  7  using this time 2 variables x and y, and adding random integer constants between 1 and 5, 
  8  and the following mathematical operators: '+','-','neg','*','^2'(or square). 
  9  We try to find the following polynomial: x^2+3y+4 
 10  from 5 sets of testing data (5 different values for x and y). 
 11  As Koza said, random constants are the "skeleton in Genetic Programming closet". 
 12  Using them will definitely slow down a search... 
 13  Any suggestions of current alternative strategies solving this problem would be  
 14  highly welcomed :) 
 15  Considering the constraints for building the trees, the root node will only have 
 16  one child, and there will be no need for ADF in the function and terminal set. 
 17  A typical way to run the tutorial would be to: 
 18      - modify the settings file so that: 
 19       
 20      >>>     #setup for running tutorial 2 
 21              functions = tutorial2.functions 
 22              crossover_mapping=tutorial2.crossover_mapping 
 23              nb_eval=tutorial2.nb_eval 
 24              ideal_results=tutorial2.GetIdealResultsData() 
 25              terminals =tutorial2.terminals 
 26              Strongly_Typed_Crossover_degree=tutorial2.Strongly_Typed_Crossover_degree 
 27              Substitute_Mutation=tutorial2.Substitute_Mutation 
 28              treeRules = tutorial2.treeRules 
 29              adfOrdered = tutorial2.adfOrdered 
 30              FitnessFunction = tutorial2.FitnessFunction 
 31       
 32      - run the evolution in the main method, and make sure that the root node parameter 
 33      only have one child.e.g. 
 34       
 35      >>>    import evolver 
 36      if __name__ == "__main__": 
 37      >>>    dbname=r'C:\pop_db' 
 38      >>>    evolver.EvolutionRun(2000,(0,1,'root'),2,8,'AddHalfNode',100, 0.00001 ,0.5,0.49,7,0.8,dbname,True) 
 39   
 40      This means that we define: 
 41      - a population size of 2000 individuals, 
 42      - a root node with 1 child 
 43      - a minimum tree depth of 2 
 44      - a maximum tree depth of 8 
 45      - the use of a Ramped half and Half Koza tree building method 
 46      - a maximum number of runs of 100 generations before we stop 
 47      - a stoping fitness criteria of 0.1 (if the fitness<=0.1, solution found) 
 48      - a crossover probability of 0.5 
 49      - a mutation probability of 0.49 
 50      - a reproduction probability of 0.01 (automatically deduced from the 2 previous values) 
 51      - the size of the tournament selection 
 52      - the probability of selecting the fitttest during tournament selection  
 53      - a database of name and path dbname 
 54      - a run done in verbose mode (printing the fittest element of each generation)  
 55            
 56  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 57  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 58  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 59  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 60  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 61  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
 62  THE SOFTWARE. 
 63   
 64  @author: by Mehdi Khoury 
 65  @version: 1.20 
 66  @copyright: (c) 2009 Mehdi Khoury under the mit license 
 67  http://www.opensource.org/licenses/mit-license.html 
 68  @contact: mehdi.khoury at gmail.com 
 69  """ 
 70   
 71  from treeutil import PostOrder_Search 
 72  from collections import deque 
 73  import psyco 
 74  import random 
 75  import math 
 76  import evalfitness 
 77   
 78  psyco.profile() 
 79   
 80   
 81  # first, we create result processing methods for each function: 
82 -def add(listElem):
83 try: 84 return listElem[0]+listElem[1] 85 except: 86 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 87 exit
88
89 -def sub(listElem):
90 try: 91 return listElem[0]-listElem[1] 92 except: 93 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 94 exit
95
96 -def neg(listElem):
97 try: 98 return 0-listElem[0] 99 except: 100 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 101 exit
102 103 104
105 -def multiply(listElem):
106 try: 107 return listElem[0]*listElem[1] 108 except: 109 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 110 exit
111
112 -def square(listElem):
113 try: 114 return listElem[0]*listElem[0] 115 except: 116 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 117 exit
118 119
120 -def rootBranch(x):
121 try: 122 return x 123 except: 124 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 125 exit
126 127 128 129 130 # then, we create a set of functions and associate them with the corresponding 131 # processing methods 132 functions = {'+':add, 133 '-':sub, 134 'neg':neg, 135 '*':multiply, 136 '^2':square, 137 'root':rootBranch 138 } 139 140 # we create the list of all possible values a variable can have in the learning examples 141 nb_eval=5 142 all_x=[] 143 all_y=[] 144 for i in xrange(nb_eval): 145 all_x.append(random.random()*10) 146 all_y.append(random.random()*10) 147 148 ideal_results=[] 149
150 -def GetIdealResultsData():
151 for nb in xrange(nb_eval): 152 ideal_results.append([all_x[nb]**2+(3*all_y[nb])+4]) 153 return ideal_results
154 155 156 157 # then, we create a mapping of terminals 158 # the variables will be given a value coming from a set of examples 159 # the constants will just be given as such or produced by a 160 # random producer 161 162 terminals = { 163 'x':all_x, 164 'y':all_y 165 } 166 # add a set of ephemeral random constants terminals depending on 167 # the number of random constants to be provided in the primitive set, 168 # and their range 169 # here we produce 5 random integer constants from ranging from 1 to 5 170 set_ERC=[] 171 for i in xrange(5): 172 terminals[':'+str(i+1)]=i 173 set_ERC.append((4,0,':'+str(i+1))) 174
175 -def FitnessFunction(my_tree):
176 return evalfitness.FinalFitness(evalfitness.EvalTreeForAllInputSets(my_tree,xrange(nb_eval)))
177 178 # the crossover mapping spec is empty in this case 179 crossover_mapping=[] 180 # default function set applicable by for branches: 181 defaultFunctionSet= [(1,2,'+'),(1,2,'*'),(1,2,'-'),(1,1,'neg'),(1,1,'^2')] 182 # default terminal set applicable by for branches: 183 defaultTerminalSet= [(3,0,'x'),(3,0,'y')] 184 defaultTerminalSet.extend(set_ERC) 185 186 treeRules = {'root':[(defaultFunctionSet,defaultTerminalSet)], 187 '+':[(defaultFunctionSet,defaultTerminalSet),(defaultFunctionSet,defaultTerminalSet)], 188 '*':[(defaultFunctionSet,defaultTerminalSet),(defaultFunctionSet,defaultTerminalSet)], 189 '^2':[(defaultFunctionSet,defaultTerminalSet)], 190 '-':[(defaultFunctionSet,defaultTerminalSet),(defaultFunctionSet,defaultTerminalSet)], 191 'neg':[([(1,2,'+'),(1,2,'*'),(1,2,'-'),(1,1,'^2')],defaultTerminalSet)] 192 } 193 194 Strongly_Typed_Crossover_degree=0 195 Substitute_Mutation=0 196 adfOrdered = False 197