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

Source Code for Module tutorial3

  1  """ 
  2  tutorial3 
  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 tutorial3. 
  6  This example file gather all the settings for a 'multiple' polynomial regression. 
  7  We want to evolve a system of ordered polynomial equations by using the 
  8  mathematical operators: '+','*' and the ADF: ADF1 and ADF2, in the said order. 
  9  an ADF2 branch could then call for an ADF1 terminal, but not the opposite.   
 10  We try to find the following model being shaped as a system of polynomials:  
 11   
 12  |ADF1=x+y 
 13   
 14  |ADF2=ADF1^3 
 15   
 16  from 30 sets of testing data (30 different values for x and y). 
 17  This means the each tree has to be evaluated for every different example, 
 18  so 30 times. There is an alternative solution which we will see in the next tutorial, 
 19  where instead of evaluating a tree 30 times, we will input an array of 30 data in the 
 20  variable leafs of the tree. 
 21  Considering the constraints for building the trees, the root node will have 2 children ADF1 and ADF2 (in order), 
 22  and ADF2 must be able to reuse ADF1 as a terminal... 
 23  A typical way to run the tutorial would be to: 
 24      - modify the settings file so that: 
 25       
 26      >>>     # setup for running tutorial 3 
 27              functions = tutorial3.functions 
 28              crossover_mapping=tutorial3.crossover_mapping 
 29              nb_eval=tutorial3.nb_eval 
 30              ideal_results=tutorial3.GetIdealResultsData() 
 31              terminals =tutorial3.terminals 
 32              Strongly_Typed_Crossover_degree=tutorial3.Strongly_Typed_Crossover_degree 
 33              Substitute_Mutation=tutorial3.Substitute_Mutation 
 34              treeRules = tutorial3.treeRules 
 35              adfOrdered = tutorial3.adfOrdered 
 36              FitnessFunction = tutorial3.FitnessFunction 
 37       
 38      - run the evolution in the main method, and make sure that the root node parameter 
 39      only have two children.e.g. 
 40       
 41      >>>    import evolver 
 42      if __name__ == "__main__": 
 43      >>>    dbname=r'C:\pop_db' 
 44      >>>    evolver.EvolutionRun(2000,(0,2,'root'),2,8,'AddHalfNode',100, 0.00001 ,0.5,0.49,7,0.8,dbname,True) 
 45   
 46      This means that we define: 
 47      - a population size of 2000 individuals, 
 48      - a root node with 2 children 
 49      - a minimum tree depth of 2 
 50      - a maximum tree depth of 8 
 51      - the use of a Ramped half and Half Koza tree building method 
 52      - a maximum number of runs of 100 generations before we stop 
 53      - a stoping fitness criteria of 0.1 (if the fitness<=0.1, solution found) 
 54      - a crossover probability of 0.5 
 55      - a mutation probability of 0.49 
 56      - a reproduction probability of 0.01 (automatically deduced from the 2 previous values) 
 57      - the size of the tournament selection 
 58      - the probability of selecting the fitttest during tournament selection  
 59      - a database of name and path dbname 
 60      - a run done in verbose mode (printing the fittest element of each generation)  
 61         
 62  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 63  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 64  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 65  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 66  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 67  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
 68  THE SOFTWARE. 
 69   
 70  @author: by Mehdi Khoury 
 71  @version: 1.20 
 72  @copyright: (c) 2009 Mehdi Khoury under the mit license 
 73  http://www.opensource.org/licenses/mit-license.html 
 74  @contact: mehdi.khoury at gmail.com 
 75  """ 
 76   
 77   
 78  import psyco 
 79  import random 
 80  import math 
 81  from treeutil import PostOrder_Search 
 82  from collections import deque 
 83  import evalfitness 
 84   
 85  psyco.profile() 
 86   
 87  # first, we create result processing methods for each function: 
88 -def add(listElem):
89 try: 90 return listElem[0]+listElem[1] 91 except: 92 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 93 exit
94 95
96 -def multiply(listElem):
97 try: 98 return listElem[0]*listElem[1] 99 except: 100 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 101 exit
102
103 -def adfBranch(x):
104 try: 105 return x 106 except: 107 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 108 exit
109
110 -def rootBranch(x):
111 try: 112 return x 113 except: 114 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 115 exit
116 117 # then, we create a set of functions and associate them with the corresponding 118 # processing methods 119 functions = {'+':add, 120 '*':multiply, 121 'adf2_+':add, 122 'adf2_*':multiply, 123 'adf1':adfBranch, 124 'adf2':adfBranch, 125 'root':rootBranch 126 } 127 # when swapping subtrees during crossover, we can transform the following branches: 128 # + can be transformed into ADF2_+, and so on... 129 crossover_mapping=[('+','adf2_+'),('adf2_+','+'),('*','adf2_*'),('adf2_*','*')] 130 131 132 # we create the list of all possible values a variable can have in the learning examples 133 nb_eval=30 134 all_x=[] 135 all_y=[] 136 for i in xrange(nb_eval): 137 all_x.append(random.random()*10) 138 all_y.append(random.random()*10) 139 140 141 142 ideal_results=[] 143
144 -def GetIdealResultsData():
145 for nb in xrange(nb_eval): 146 ideal_results.append([all_x[nb]+all_y[nb],(all_x[nb]+all_y[nb])**3]) 147 return ideal_results
148 # then, we create a mapping of terminals 149 # the variables will be given a value coming from a set of examples 150 # the constants will just be given as such or produced by a 151 # random producer 152 terminals = { 153 'x':all_x, 154 'y':all_y 155 } 156 157 #MaxDepth=5 158 Strongly_Typed_Crossover_degree=1 159
160 -def FitnessFunction(my_tree):
161 return evalfitness.FinalFitness(evalfitness.EvalTreeForAllInputSets(my_tree,xrange(nb_eval)))
162 163 # default function set applicable by for branches: 164 defaultFunctionSet= [(1,2,'+'),(1,2,'*')] 165 # default terminal set applicable by for branches: 166 defaultTerminalSet= [(3,0,'x'),(3,0,'y')] 167 Adf2DefaultFunctionSet= [(1,2,'adf2_+'),(1,2,'adf2_*')] 168 Adf2DefaultTerminalSet= [(3,0,'x'),(3,0,'y'),(5,0,'adf1')] 169 treeRules = {'root':[ ([(2,1,'adf1')],[]) , ([(2,1,'adf2')],[]) ], 170 'adf1':[(defaultFunctionSet,defaultTerminalSet)], 171 'adf2':[(Adf2DefaultFunctionSet,Adf2DefaultTerminalSet)], 172 '+':[(defaultFunctionSet,defaultTerminalSet),(defaultFunctionSet,defaultTerminalSet)], 173 '*':[(defaultFunctionSet,defaultTerminalSet),(defaultFunctionSet,defaultTerminalSet)], 174 'adf2_+':[(Adf2DefaultFunctionSet,Adf2DefaultTerminalSet),(Adf2DefaultFunctionSet,Adf2DefaultTerminalSet)], 175 'adf2_*':[(Adf2DefaultFunctionSet,Adf2DefaultTerminalSet),(Adf2DefaultFunctionSet,Adf2DefaultTerminalSet)], 176 } 177 178 Strongly_Typed_Crossover_degree=1 179 Substitute_Mutation=0 180 adfOrdered = True 181