当前位置: 动力学知识库 > 问答 > 编程问答 >

python - Symbolic definition of a binomial using SymPy

问题描述:

I am trying to symbolically define the Binomial function using Sympy.

My first attempt was as follows:

import numpy as np

import scipy.stats as st

import sklearn.linear_model as lm

import matplotlib.pyplot as plt

import sympy as sp

sp.interactive.printing.init_printing(use_latex=True)

n = sp.Symbol('n', integer=True, positive=True)

r = sp.Symbol('r', integer=True, positive=True)

theta = sp.Symbol('theta')

#Create the function symbolically

from sympy import factorial

cNkLambda= lambda n,r : (factorial(n))/ (factorial(r) *factorial(n- r))

binomLambda= lambda theta, n, r: cNkLambda(n,r)*((theta **r)*(1-theta)**(n-r))

print binomLambda (0.5, 10,5)

However, I realized I am not using any Sympy features here and nothing is evaluated symbolically.

In my second attempt, i removed the Lambda definition, so that the Symbolic function is correctly defined, however this results in an exception:

%reset -f

import numpy as np

import scipy.stats as st

import sklearn.linear_model as lm

import matplotlib.pyplot as plt

import sympy as sp

#from sympy import binomial

#from sympy import Symbol, Rational, factorial, binomial, expand_func

sp.interactive.printing.init_printing(use_latex=True)

n = sp.Symbol('n', integer=True, positive=True)

r = sp.Symbol('r', integer=True, positive=True)

theta = sp.Symbol('theta')

#Create the function symbolically

from sympy import factorial

cNkLambda= (factorial(n))/ (factorial(r) *factorial(n-r))

#cNkLambda_fied = sp.lambdify((n,r), cNkLambda, modules='numpy')

cNkLambda.evalf() # this works

binomLambda= cNkLambda(n,r)*((theta **r)*(1-theta)**(n-r))

#Convert it to a Numpy-callable function

#bin_likelihood = sp.lambdify((theta,r,n), binomLambda, modules='numpy')

#print binomLambda (0.5, 10,5)


TypeError Traceback (most recent call last)

in ()

23 cNkLambda.evalf() # this works

24

---> 25 binomLambda= cNkLambda(n,r)((theta r)(1-theta)(n-r))

26 # Convert it to a Numpy-callable function

27 #bin_likelihood = sp.lambdify((theta,r,n), binomLambda, modules='numpy')

TypeError: 'Mul' object is not callable

My question is: how to correctly define the function so that it is symbolic all the way through.

Edit 1:

Found this reference about this error: https://github.com/sympy/sympy/issues/8562, but I can not deduce where in my code I am doing the same.

Edit 2:

I updated the question,changed:

binomLambda= cNkLambda(n,r)*((theta **r)*(1-theta)**(n-r))

to :

binomLambda= cNkLambda*((theta **r)*(1-theta)**(n-r))

However now when I try to lamdify the symbolic function as follows:

binomLambda.subs({theta:0.5,r:5,n:10}) # this works

#Convert it to a Numpy-callable function

binomRealLambda = sp.lambdify((theta,r,n), binomLambda, modules='numpy')

print binomRealLambda(0.5,5,10)

This results in:

NameError Traceback (most recent call last)

in ()

27 binomRealLambda = sp.lambdify((theta,r,n), binomLambda, modules='numpy')

28

---> 29 print binomRealLambda(0.5,5,10)

/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/numpy/init.pyc in (_Dummy_46, _Dummy_47, _Dummy_48)

NameError: global name 'factorial' is not defined

Edit 3:

I got this fully working:

 #----------------------Symbolic beta-------------------------------#

a = sp.Symbol('a', integer=False, positive=True)

b = sp.Symbol('b', integer=False, positive=True)

mu = sp.Symbol('mu', integer=False, positive=True)

# Create the function symbolically

G = sp.gamma

# The normalisation factor

BetaNormSym = G(a + b)/(G(a)*G(b))

# The functional form

BetaFSym = mu**(a-1) * (1-mu)**(b-1)

BetaSym=BetaNormSym * BetaFSym

BetaSym.evalf() # this works

# Turn Beta into a function

BetaLambda = sp.Lambda((mu,a,b), BetaSym)

maths(r"\operatorname{Beta}(\mu|a,b) = ")

display(BetaSym)

BetaLambda(0.5,1,1)

BetaSym.subs({mu:0.5,a:1,b:1})

#----------------------Symbolic beta-------------------------------#

Thanks,

网友答案:

cNkLambda is a SymPy expression which is defined in terms of n and r. It's not a function, so do not call it with cNkLambda(n,r). binomLambda can then be defined by:

binomLambda = cNkLambda*((theta **r)*(1-theta)**(n-r))

In [18]: cNkLambda
Out[20]: 
     n!    

r!(n - r)!

In [22]: cNkLambda*((theta **r)*(1-theta)**(n-r))
Out[22]: 
 r         n - r   
 (- + 1)     n!

    r!(n - r)!    

To make a numeric function out of binomLambda, you could use sympy.lambdify. Note, however, that binomLambda uses factorials, and NumPy does not define a factorial function.

You could either call math.factorial or scipy.misc.factorial:

bin_likelihood = sy.lambdify((theta,r,n), binomLambda, modules='math')

or

bin_likelihood2 = sy.lambdify((theta,r,n), binomLambda,   
                              modules=[{'factorial':misc.factorial}])

For example,

import scipy.misc as misc
import numpy as np
import sympy as sy

sy.interactive.printing.init_printing(use_latex=True)

n = sy.Symbol('n', integer=True, positive=True)
r = sy.Symbol('r', integer=True, positive=True)
theta = sy.Symbol('theta')

cNkLambda=  (sy.factorial(n))/ (sy.factorial(r) * sy.factorial(n-r))
binomLambda = cNkLambda*((theta **r)*(1-theta)**(n-r))

bin_likelihood = sy.lambdify((theta,r,n), binomLambda, modules='math')
print(bin_likelihood(np.linspace(0,2*np.pi,4), 2, 5))
# [  0.00000000e+00  -5.74962672e+01  -5.68925055e+03  -5.82166577e+04]

bin_likelihood2 = sy.lambdify((theta,r,n), binomLambda,   
                              modules=[{'factorial':misc.factorial}])
print(bin_likelihood2(np.linspace(0,2*np.pi,4), 2, 5))
# [  0.00000000e+00  -5.74962672e+01  -5.68925055e+03  -5.82166577e+04]
分享给朋友:
您可能感兴趣的文章:
随机阅读: