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