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) (nr)) 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)
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]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.