Proving optimized function is still correct
Fernando Pérez
fperez528 at yahoo.com
Mon Nov 12 09:12:13 EST 2001
Huaiyu Zhu wrote:
> On Tue, 13 Nov 2001 16:55:48 GMT, Terry Reedy <tjreedy at home.com> wrote:
>>A recursive implementation like
[snip]
> Since m and n are symmetrical, one could also compare them and choose
> between space optimization vs recursion depth optimization.
The problem with all these forms is that they grow in execution time with the
parameters (though they are exact, if they use longs). Here's a constant-time
version, which is however limited to the range where the answer fits in a
float (I fixed some things from yesterday's version). For low values of m
this is expensive, but once m gets big it's immensely faster.
If one really needs speed, the ideal solution is probably a combination of a
good recursive solution for low m with this version for high m, and caching
of results for low (m,n) values if those are commonly needed.
from Numeric import *
#-----------------------------------------------------------------------------
def gammln(x):
"""Return the natural log of gamma(x)"""
cof = array([76.18009172947146,-86.50532032941677,
24.01409824083091,-1.231739572450155,
0.1208650973866179e-2,-0.5395239384953e-5],Float)
y = arange(x+1,x+7,typecode = Float)
tmp = x+5.5
tmp -= (x+0.5)*log(tmp)
ser = 1.000000000190015 + sum(cof/y)
return -tmp+log(2.5066282746310005*ser/x)
#-----------------------------------------------------------------------------
def bico(n,k):
"""Return binomial coefficient (n k)"""
return floor(0.5+exp(gammln(n+1.0)-gammln(k+1.0)-gammln(n-k+1.0)))
#-----------------------------------------------------------------------------
def combi_dist(m,n):
"""Return the number of combinations of m mutually distinguishable
elements in which each element may occur 0,1,2,...,n times in any
combination.
Constant time, uses floats."""
# this is just bico(m+n-1,n). Write it out explicitly for speed
nn = m+n-1
kk = n
return floor(0.5 +
exp(gammln(nn+1.0)-gammln(kk+1.0)-gammln(nn-kk+1.0)))
This bypasses the issue of explicitly building the factorials by computing
them through a gamma function (the implementation is from Numerical Recipes,
so not necessarily the best).
Cheers,
f
More information about the Python-list
mailing list