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

Source Code for Module tutorial5

  1  """ 
  2  tutorial5 
  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 tutorial5. 
  6  In this example, we evolve hybrid system: a model containing discrete values  
  7  and logic operators and numerical operations. 
  8  More specifically, we will evolve if_then_else types rules that will determine  
  9  the application of different polynomials... 
 10  from 20 sets of testing data (20 different values for x and y). 
 11  Considering the constraints for building the trees, the root node will have 
 12  3 children, and these will be ordered ADF defining branches (we simply won't use ADF terminals nodes) 
 13  describing the structure of the if then else statement. 
 14  The solution found should be the equivalent of this expression: 
 15  if x>y then cos(x) else sin(y) 
 16     
 17  A typical way to run the tutorial would be to: 
 18      - modify the settings file so that:  
 19       
 20      >>>     # setup for running tutorial 5 
 21              functions = tutorial5.functions 
 22              crossover_mapping=tutorial5.crossover_mapping 
 23              nb_eval=tutorial5.nb_eval 
 24              ideal_results=tutorial5.GetIdealResultsData() 
 25              terminals =tutorial5.terminals 
 26              Strongly_Typed_Crossover_degree=tutorial5.Strongly_Typed_Crossover_degree 
 27              Substitute_Mutation=tutorial5.Substitute_Mutation 
 28              treeRules = tutorial5.treeRules 
 29              adfOrdered = tutorial5.adfOrdered 
 30              FitnessFunction = tutorial5.FitnessFunction 
 31       
 32      - use a different fitness function for the evaluation of a hybrid system (we 
 33      use both discrete and continuous values now!) 
 34      We create 1 new fitness function: 
 35           - FinalFitness3 is a modification of FinalFitness that take as input 
 36           sets of If Then Else types of trees and return the sum of their fitnesses. 
 37           These fitness functions are called in 3 different places. We need to update 
 38           the code that call them. 
 39           These fitness functions are called in FitnessFunction in the tutorial5 module.  
 40            
 41           >>>    def FitnessFunction(my_tree): 
 42           >>>        return evalfitness.FinalFitness3(evalfitness.EvalTreeForAllInputSets(my_tree,xrange(nb_eval))) 
 43            
 44      - run the evolution in the main method, and make sure that the root node parameter 
 45      only have three children.e.g. 
 46       
 47      >>>    import evolver 
 48      if __name__ == "__main__": 
 49      >>>    dbname=r'C:\pop_db' 
 50      >>>    evolver.EvolutionRun(2000,(0,3,'root'),3,8,'AddHalfNode',100, 0.00001 ,0.5,0.49,7,0.8,dbname,True) 
 51   
 52      This means that we define: 
 53      - a population size of 2000 individuals, 
 54      - a root node with 3 children 
 55      - a minimum tree depth of 3 (because the constraints of the tree would not work for a depth <3) 
 56      - a maximum tree depth of 8 
 57      - the use of a Ramped half and Half Koza tree building method 
 58      - a maximum number of runs of 100 generations before we stop 
 59      - a stoping fitness criteria of 0.1 (if the fitness<=0.1, solution found) 
 60      - a crossover probability of 0.5 
 61      - a mutation probability of 0.49 
 62      - a reproduction probability of 0.01 (automatically deduced from the 2 previous values) 
 63      - the size of the tournament selection 
 64      - the probability of selecting the fitttest during tournament selection  
 65      - a database of name and path dbname 
 66      - a run done in verbose mode (printing the fittest element of each generation)   
 67            
 68  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 69  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 70  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 71  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 72  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 73  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
 74  THE SOFTWARE. 
 75   
 76  @author: by Mehdi Khoury 
 77  @version: 1.20 
 78  @copyright: (c) 2009 Mehdi Khoury under the mit license 
 79  http://www.opensource.org/licenses/mit-license.html 
 80  @contact: mehdi.khoury at gmail.com 
 81  """ 
 82   
 83  from treeutil import PostOrder_Search 
 84  from collections import deque 
 85  import psyco 
 86  import random 
 87  import math 
 88  import evalfitness 
 89   
 90  psyco.profile() 
 91   
 92   
 93   
94 -def equal_(listElem):
95 try: 96 if listElem[0]==listElem[1]: 97 return True 98 else: 99 return False 100 except: 101 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 102 exit
103
104 -def superior_(listElem):
105 try: 106 if listElem[0]>listElem[1]: 107 return True 108 else: 109 return False 110 except: 111 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 112 exit
113
114 -def inferior_(listElem):
115 try: 116 if listElem[0]<listElem[1]: 117 return True 118 else: 119 return False 120 except: 121 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 122 exit
123
124 -def and_(listElem):
125 try: 126 if listElem[0] and listElem[1]: 127 return True 128 else: 129 return False 130 except: 131 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 132 exit
133
134 -def or_(listElem):
135 try: 136 if listElem[0] or listElem[1]: 137 return True 138 else: 139 return False 140 except: 141 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 142 exit
143 144 145 146 # first, we create result processing methods for each function:
147 -def add(listElem):
148 try: 149 return listElem[0]+listElem[1] 150 except: 151 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 152 exit
153
154 -def sub(listElem):
155 try: 156 return listElem[0]-listElem[1] 157 except: 158 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 159 exit
160
161 -def neg(listElem):
162 try: 163 return 0-listElem[0] 164 except: 165 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 166 exit
167 168 169
170 -def multiply(listElem):
171 try: 172 return listElem[0]*listElem[1] 173 except: 174 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 175 exit
176
177 -def square(listElem):
178 try: 179 return listElem[0]*listElem[0] 180 except: 181 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 182 exit
183
184 -def cos(listElem):
185 try: 186 return math.cos(listElem[0]) 187 except: 188 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 189 exit
190
191 -def sin(listElem):
192 try: 193 return math.sin(listElem[0]) 194 except: 195 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 196 exit
197
198 -def if_(x):
199 try: 200 return x 201 except: 202 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 203 exit
204
205 -def then_(x):
206 try: 207 return x 208 except: 209 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 210 exit
211
212 -def else_(x):
213 try: 214 return x 215 except: 216 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 217 exit
218
219 -def rootBranch(x):
220 try: 221 return x 222 except: 223 raise WrongValues, "Wrong values sent to function node.\nCan't get result" 224 exit
225 226 # then, we create a set of functions and associate them with the corresponding 227 # processing methods 228 functions = {'+':add, 229 '-':sub, 230 'neg':neg, 231 '*':multiply, 232 '^2':square, 233 'cos':cos, 234 'sin':sin, 235 '=':equal_, 236 '>':superior_, 237 '<':inferior_, 238 'and':and_, 239 'or':or_, 240 'if':if_, 241 'then':then_, 242 'else':else_, 243 'root':rootBranch 244 } 245 246 # we create the list of all possible values a variable can have in the learning examples 247 nb_eval=20 248 all_x=[] 249 all_y=[] 250 for i in xrange(nb_eval): 251 all_x.append(random.random()*10) 252 all_y.append(random.random()*10) 253 # then, we create a mapping of terminals 254 # the variables will be given a value coming from a set of examples 255 # the constants will just be given as such or produced by a 256 # random producer 257 terminals = { 258 'x':all_x, 259 'y':all_y 260 } 261 262 # ideal polynomial to find 263 ideal_results=[]
264 -def GetIdealResultsData():
265 for nb in xrange(nb_eval): 266 #ideal_results.append([all_x[nb]**3-all_x[nb]+math.cos(all_x[nb])]) 267 if all_x[nb]>all_y[nb]: 268 ideal_results.append([math.cos(all_x[nb])]) 269 else: 270 ideal_results.append([math.sin(all_y[nb])]) 271 return ideal_results
272 273
274 -def FitnessFunction(my_tree):
275 return evalfitness.FinalFitness3(evalfitness.EvalTreeForAllInputSets(my_tree,xrange(nb_eval)))
276 277 278 crossover_mapping=[] 279 280 # default function set applicable by for branches: 281 defaultFunctionSet= [(1,2,'+'),(1,2,'*'),(1,1,'^2'),(1,2,'-'),(1,1,'cos'),(1,1,'sin'),(1,1,'neg')] 282 # default terminal set applicable by for branches: 283 defaultTerminalSet= [(3,0,'x'),(3,0,'y')] 284 treeRules = {'root':[([(2,1,'if')],[]),([(2,1,'then')],[]),([(2,1,'else')],[])], 285 'if':[([(1,2,'and'),(1,2,'or'),(1,2,'>'),(1,2,'<'),(1,2,'=')],[])], 286 'then':[(defaultFunctionSet,defaultTerminalSet)], 287 'else':[(defaultFunctionSet,defaultTerminalSet)], 288 'and':[([(1,2,'and'),(1,2,'or'),(1,2,'>'),(1,2,'<'),(1,2,'=')],[]),([(1,2,'and'),(1,2,'or'),(1,2,'>'),(1,2,'<'),(1,2,'=')],[])], 289 'or':[([(1,2,'and'),(1,2,'or'),(1,2,'>'),(1,2,'<'),(1,2,'=')],[]),([(1,2,'and'),(1,2,'or'),(1,2,'>'),(1,2,'<'),(1,2,'=')],[])], 290 '=':[(defaultFunctionSet,defaultTerminalSet),(defaultFunctionSet,defaultTerminalSet)], 291 '>':[(defaultFunctionSet,defaultTerminalSet),(defaultFunctionSet,defaultTerminalSet)], 292 '<':[(defaultFunctionSet,defaultTerminalSet),(defaultFunctionSet,defaultTerminalSet)], 293 '+':[(defaultFunctionSet,defaultTerminalSet),(defaultFunctionSet,defaultTerminalSet)], 294 '*':[(defaultFunctionSet,defaultTerminalSet),(defaultFunctionSet,defaultTerminalSet)], 295 '^2':[(defaultFunctionSet,defaultTerminalSet),(defaultFunctionSet,defaultTerminalSet)], 296 '-':[(defaultFunctionSet,defaultTerminalSet),(defaultFunctionSet,defaultTerminalSet)], 297 'neg':[([(1,2,'+'),(1,2,'*'),(1,2,'-'),(1,1,'cos'),(1,1,'sin')],defaultTerminalSet)], 298 'cos':[([(1,2,'+'),(1,2,'*'),(1,2,'-'),(1,1,'sin'),(1,1,'neg')],defaultTerminalSet)], 299 'sin':[([(1,2,'+'),(1,2,'*'),(1,2,'-'),(1,1,'cos'),(1,1,'neg')],defaultTerminalSet)] 300 } 301 302 Strongly_Typed_Crossover_degree=0 303 Substitute_Mutation=0 304 adfOrdered = True 305