Reputation: 185
Why does Sympy throw a Type error when I use the scipy.stats.norm
? How can I solve the equation?
from sympy import Eq, Symbol, solve, Piecewise
from scipy.stats import norm
import numpy as np
x = Symbol('x')
eqn = Eq((x-0.2)/0.3, norm.cdf((np.log(100/110) + x**2/2)/x))
print(solve(eqn))
Output:
TypeError: cannot determine truth value of Relational
Upvotes: 1
Views: 503
Reputation:
If you are looking for symbolic solutions, use symbolic functions: e.g., SymPy's log not NumPy's log. The normal CDF is also available from SymPy's stats module as cdf(Normal("x", 0, 1))
. The correct SymPy setup would be this:
from sympy import Eq, Rational, Symbol, log
from sympy.stats import cdf, Normal
eqn = Eq((x-Rational('0.2'))/Rational('0.3'), cdf(Normal("x", 0, 1))(log(Rational(100, 110)) + x**2/2)/x)
Notice that I put Rational('0.2')
where you had 0.2. The distinction between rationals and floats is important for symbolic math. The equation now looks good from the formal point of view:
Eq(10*x/3 - 2/3, (erf(sqrt(2)*(x**2/2 - log(11) + log(10))/2)/2 + 1/2)/x)
Unfortunately it also looks hopeless: there's no closed form solution for things like that, involving a transcendental function equated to a polynomial. Naturally, solve(eqn)
will fail. So all of the above does is demonstrate correct use of SymPy, but it doesn't change the fact that there is no symbolic solution.
To solve this numerically, do the opposite: drop the SymPy parts and import fsolve
from SciPy.
from scipy.stats import norm
from scipy.optimize import fsolve
import numpy as np
f = lambda x: (x-0.2)/0.3 - norm.cdf((np.log(100/110) + x**2/2)/x)
print(fsolve(f, 1)) # 1 is a random initial guess
The answer is 0.33622392.
Upvotes: 5