An algorithm for randomly generating integer partitions of a particular length, in Python?

后端 未结 3 1537
没有蜡笔的小新
没有蜡笔的小新 2021-01-05 10:58

I\'ve been using the random_element() function provided by SAGE to generate random integer partitions for a given integer (N) that are a particular

相关标签:
3条回答
  • 2021-01-05 11:33

    Finally, I have a definitively unbiased method that has a zero rejection rate. Of course, I've tested it to make sure the results are representative samples of entire feasible sets. It's very fast and totally unbiased. Enjoy.

    from sage.all import *
    import random
    

    First, a function to find the smallest maximum addend for a partition of n with s parts

    def min_max(n,s):
    
        _min = int(floor(float(n)/float(s)))
        if int(n%s) > 0:
            _min +=1
    
        return _min
    

    Next, A function that uses a cache and memoiziation to find the number of partitions of n with s parts having x as the largest part. This is fast, but I think there's a more elegant solution to be had. e.g., Often: P(N,S,max=K) = P(N-K,S-1) Thanks to ante (https://stackoverflow.com/users/494076/ante) for helping me with this: Finding the number of integer partitions given a total, a number of parts, and a maximum summand

    D = {}
    def P(n,s,x):
        if n > s*x or x <= 0: return 0
        if n == s*x: return 1
        if (n,s,x) not in D:
            D[(n,s,x)] = sum(P(n-i*x, s-i, x-1) for i in xrange(s))
        return D[(n,s,x)]
    

    Finally, a function to find uniform random partitions of n with s parts, with no rejection rate! Each randomly chosen number codes for a specific partition of n having s parts.

    def random_partition(n,s):
        S = s
        partition = []
        _min = min_max(n,S)
        _max = n-S+1
    
        total = number_of_partitions(n,S)
        which = random.randrange(1,total+1) # random number
    
        while n:
            for k in range(_min,_max+1):
                count = P(n,S,k)
                if count >= which:
                    count = P(n,S,k-1)
                    break
    
            partition.append(k)
            n -= k
            if n == 0: break
            S -= 1
            which -= count
            _min = min_max(n,S)
            _max = k
    
        return partition
    
    0 讨论(0)
  • 2021-01-05 11:35

    I ran into a similar problem when I was trying to calculate the probability of the strong birthday problem.

    First off, the partition function explodes when given only modest amount of numbers. You'll be returning a LOT of information. No matter which method you're using N = 10000 and S = 300 will generate ridiculous amounts of data. It will be slow. Chances are any pure python implementation you use will be equally slow or slower. Look to making a CModule.

    If you want to try python the approach I took as a combination of itertools and generators to keep memory usage down. I don't seem to have my code handy anymore, but here's a good impementation:

    http://wordaligned.org/articles/partitioning-with-python

    EDIT:

    Found my code:

    def partition(a, b=-1, limit=365):
      if (b == -1):
        b = a
      if (a == 2 or a == 3):
        if (b >= a and limit):
          yield [a]
        else:
          return
      elif (a > 3):
        if (a <= b):
          yield [a]
        c = 0
        if b > a-2:
          c = a-2
        else:
          c = b
        for i in xrange(c, 1, -1):
          if (limit):
            for j in partition(a-i, i, limit-1):
              yield [i] + j
    
    0 讨论(0)
  • 2021-01-05 11:37

    Simple approach: randomly assign the integers:

    def random_partition(n, s):
        partition = [0] * s
        for x in range(n):
            partition[random.randrange(s)] += 1
        return partition
    
    0 讨论(0)
提交回复
热议问题