# 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()

```