how to choose element from list based on probabilities?
Anton Vredegoor
anton at vredegoor.doge.nl
Fri Nov 14 23:57:17 CET 2003
Matthew Wilson <mwilson at sarcastic-horse.com> wrote:
>I have a list of very simple circle objects:
>
>class Circle:
> def __init__(self, x,y,r):
> self.center =(x,y)
> self.r = r
>
>I want to write a function that accepts a list of circle objects and
>then chooses one of the circles and returns that circle. The circles
>with the biggest areas should be the most likely to be chosen, but there
>should be some randomness.
>
>Subsequent calls to the function should not return the same circle.
Thanks for sharing this problem :-) Below is some not very well tested
code, maybe someone can get at a sample in a more interesting way.
Generating a set of *non-overlapping* circles of different sizes
fitting inside a rectangle may be the next problem?
Anton
from math import pi
from random import uniform
class Circle:
def __init__(self, x,y,r):
self.center = (x,y)
self.r = r
def getarea(self): return pi*self.r**2
area = property(getarea)
def randomcircleindex(circles):
"""area based choice"""
total = 0
treshold = uniform(0,sum([c.area for c in circles]))
for i,c in enumerate(circles) :
total += c.area
if total >= treshold: return i
def gencircles(maxc,maxr):
"""generate random circles with radius <= maxr,
fitting in a square ((0,0),(maxc,maxc)) """
while 1:
x = uniform(maxr,maxc-maxr)
y = uniform(maxr,maxc-maxr)
r = uniform(0,maxr)
yield Circle(x,y,r)
def samplecircles(circles,k):
"""area based sample"""
result = []
n = len(circles)
if k > n :
raise ValueError, 'sample larger than population'
L = circles[:]
for i in xrange(k):
j = randomcircleindex(L)
result.append( L.pop(j))
return result
def pprintcircle(c):
print "(%7.2f,%7.2f)" %c.center,
print "%7.2f %15.2f" %(c.r,c.area)
def test():
nc,maxr,maxc = 10,100,1000
g = gencircles(maxc,maxr)
circles = [g.next() for i in xrange(nc)]
#for c in circles: pprintcircle(c)
#print
selected = samplecircles(circles,10)
for c in selected: pprintcircle(c)
if __name__=='__main__':
test()
More information about the Python-list
mailing list