@@ -287,34 +287,42 @@ def lrta_star_agent(a):
287
287
#______________________________________________________________________________
288
288
# Genetic Algorithm
289
289
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 ):
291
291
"""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 )]
297
296
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 )
300
298
301
- def genetic_algorithm (population , fitness_fn , ngen = 1000 , pmut = 0.0 ):
299
+ def genetic_algorithm (population , fitness_fn , ngen = 1000 , pmut = 0.1 ):
302
300
"""[Fig. 4.7]"""
303
- def reproduce (p1 , p2 ):
304
- c = random .randrange (len (p1 ))
305
- return p1 [:c ] + p2 [c :]
306
-
307
301
for i in range (ngen ):
308
302
new_population = []
309
303
for i in len (population ):
310
304
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 :
313
307
child .mutate ()
314
308
new_population .append (child )
315
309
population = new_population
316
310
return argmax (population , fitness_fn )
317
311
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
+
318
326
def random_weighted_selection (seq , n , weight_fn ):
319
327
"""Pick n elements of seq, weighted according to weight_fn.
320
328
That is, apply weight_fn to each element of seq, add up the total.
0 commit comments