@@ -287,34 +287,42 @@ def lrta_star_agent(a):
287287#______________________________________________________________________________
288288# Genetic Algorithm
289289
290- def genetic_search (problem , fitness_fn , ngen = 1000 , pmut = 0.0 , n = 20 ):
290+ def genetic_search (problem , fitness_fn , ngen = 1000 , pmut = 0.1 , n = 20 ):
291291 """Call genetic_algorithm on the appropriate parts of a problem.
292- This requires that the problem has a successor function that generates
293- reasonable states, and that it has a path_cost function that scores states.
294- We use the negative of the path_cost function, because costs are to be
295- minimized, while genetic-algorithm expects a fitness_fn to be maximized."""
296- states = [s for (a , s ) in problem .successor (problem .initial_state )[:n ]]
292+ This requires that the problem has a successor function that
293+ generates states that can mate and mutate, and that it has a value
294+ method that scores states."""
295+ states = [s for (a , s ) in problem .successor (problem .initial_state )]
297296 random .shuffle (states )
298- fitness_fn = lambda s : - problem .path_cost (0 , s , None , s )
299- return genetic_algorithm (states , fitness_fn , ngen , pmut )
297+ return genetic_algorithm (states [:n ], problem .value , ngen , pmut )
300298
301- def genetic_algorithm (population , fitness_fn , ngen = 1000 , pmut = 0.0 ):
299+ def genetic_algorithm (population , fitness_fn , ngen = 1000 , pmut = 0.1 ):
302300 """[Fig. 4.7]"""
303- def reproduce (p1 , p2 ):
304- c = random .randrange (len (p1 ))
305- return p1 [:c ] + p2 [c :]
306-
307301 for i in range (ngen ):
308302 new_population = []
309303 for i in len (population ):
310304 p1 , p2 = random_weighted_selections (population , 2 , fitness_fn )
311- child = reproduce ( p1 , p2 )
312- if random .uniform (0 ,1 ) > pmut :
305+ child = p1 . mate ( p2 )
306+ if random .uniform (0 , 1 ) < pmut :
313307 child .mutate ()
314308 new_population .append (child )
315309 population = new_population
316310 return argmax (population , fitness_fn )
317311
312+ class GAState :
313+ "Abstract class for individuals in a genetic algorithm."
314+ def __init__ (self , genes ):
315+ self .genes = genes
316+
317+ def mate (self , other ):
318+ "Return a new individual crossing self and other."
319+ c = random .randrange (len (self .genes ))
320+ return self .__class__ (self .genes [:c ] + other .genes [c :])
321+
322+ def mutate (self ):
323+ "Change a few of my genes."
324+ abstract
325+
318326def random_weighted_selection (seq , n , weight_fn ):
319327 """Pick n elements of seq, weighted according to weight_fn.
320328 That is, apply weight_fn to each element of seq, add up the total.
0 commit comments