Skip to content

Commit dafac5b

Browse files
committed
Moved random_weighted_selection to utils and rewrote it using bisect.
1 parent 50e8f0f commit dafac5b

File tree

2 files changed

+25
-23
lines changed

2 files changed

+25
-23
lines changed

search.py

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,8 @@ def genetic_algorithm(population, fitness_fn, ngen=1000, pmut=0.1):
367367
for i in range(ngen):
368368
new_population = []
369369
for i in len(population):
370-
p1, p2 = random_weighted_selections(population, 2, fitness_fn)
370+
fitnesses = map(fitness_fn, population)
371+
p1, p2 = weighted_sample_with_replacement(population, fitnesses, 2)
371372
child = p1.mate(p2)
372373
if random.uniform(0, 1) < pmut:
373374
child.mutate()
@@ -389,25 +390,6 @@ def mutate(self):
389390
"Change a few of my genes."
390391
abstract
391392

392-
def random_weighted_selection(seq, n, weight_fn):
393-
"""Pick n elements of seq, weighted according to weight_fn.
394-
That is, apply weight_fn to each element of seq, add up the total.
395-
Then choose an element e with probability weight[e]/total.
396-
Repeat n times, with replacement. """
397-
totals = []; runningtotal = 0
398-
for item in seq:
399-
runningtotal += weight_fn(item)
400-
totals.append(runningtotal)
401-
selections = []
402-
for s in range(n):
403-
r = random.uniform(0, totals[-1])
404-
for i in range(len(seq)):
405-
if totals[i] > r:
406-
selections.append(seq[i])
407-
break
408-
return selections
409-
410-
411393
#_____________________________________________________________________________
412394
# The remainder of this file implements examples for the search algorithms.
413395

@@ -885,7 +867,4 @@ def compare_graph_searchers():
885867
886868
>>> boggle_hill_climbing(list('ABCDEFGHI'), verbose=False)
887869
(['E', 'P', 'R', 'D', 'O', 'A', 'G', 'S', 'T'], 123)
888-
889-
>>> random_weighted_selection(range(10), 3, lambda x: x * x)
890-
[8, 9, 6]
891870
""")

utils.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,18 @@ def probability(p):
501501
"Return true with probability p."
502502
return p > random.uniform(0.0, 1.0)
503503

504+
def weighted_sample_with_replacement(seq, weights, n):
505+
"""Pick n samples from seq at random, with replacement, with the
506+
probability of each element in proportion to its corresponding
507+
weight."""
508+
totals = []
509+
for w in weights:
510+
totals.append(w + totals[-1] if totals else w)
511+
def sample():
512+
r = random.uniform(0, totals[-1])
513+
return seq[bisect.bisect(totals, r)]
514+
return [sample() for s in range(n)]
515+
504516
def num_or_str(x):
505517
"""The argument is a string; convert to a number if possible, or strip it.
506518
>>> num_or_str('42')
@@ -939,4 +951,15 @@ def fixup(test):
939951
>>> sl(a)
940952
['a', 'b', 'c', 'd', 'r', 'w', 'y', 'z']
941953
954+
>>> weighted_sample_with_replacement([], [], 0)
955+
[]
956+
>>> weighted_sample_with_replacement('a', [3], 2)
957+
['a', 'a']
958+
>>> weighted_sample_with_replacement('ab', [0, 3], 3)
959+
['b', 'b', 'b']
942960
"""
961+
962+
__doc__ += random_tests("""
963+
>>> weighted_sample_with_replacement(range(10), [x*x for x in range(10)], 3)
964+
[8, 9, 6]
965+
""")

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy