I am using sympy to solve a very simple equation symbolically, but the solution I get for the variable is an empty matrix! Here is the code:
from sympy import *
x = Symbol('x')
l_x = Symbol('l_x')
x_min = -6
x_max = 6
precision_x = 10**8
solve(((x_max-x_min)/((2**l_x)-1))/precision_x, l_x)
print(l_x)
I tried some other simple equations such as:
solve(x**2 = 4, x)
And the later works perfectly; I just do not understand why the former one does not work!
The expression given to solve has an assumed rhs of 0 which no value of l_x can satisfy. Try something like this instead:
from sympy import *
q, r, s, t = symbols("q r s t")
eq = (q-r)/(2**s-1)/t
solve(eq-1,s)
The output is:
[log((q - r + t)/t)/log(2)]
to explicitly create an equation object with a non-zero rhs you can do something like:
solve(Eq(eq,1),s)
It is simple: your equation has no result.
The equation is 12/((2**l_x)-1))/1e8 = 0 and that has no solution.
See what y = 12/((2**x)-1))/1e8 looks like (copied from wolframalpha):
To compare, try solving e.g. 12/((2**l_x)-1))/1e8 = 1 instead:
>>> solve(((x_max-x_min)/((2**l_x)-1))/precision_x - 1, l_x)
[(-log(25000000) + log(25000003))/log(2)]
Works like a charm!
Related
How can I automatically write a 5th order expression using a for loop using sympy in Python?
For example, let the expression be: y = 2x^5 + 3x^4 + 17x^3 + x^2 - 8x +101
I have the coefficients in the 5th order expression as a list. You can think of it like [101,-8,1,17,3,2].
I want to create a 5th order expression using the elements of this list using sympy.
I would be very grateful if you could help with this.
from sympy import *
x = symbols("x")
coeff = [101,-8,1,17,3,2]
# create a list of exponents going from 0 to 5 (included)
expon = list(range(len(coeff)))
# create a list of polynomial terms using list-comprehension syntax
# and sum up the elements
expr = sum(c * x**e for c, e in zip(coeff, expon))
Edit to satisfy comment:
from sympy import *
x = symbols("x")
coeff = [101,-8,1,17,3,2]
# create a list of exponents going from 0 to 5 (included)
expon = list(range(len(coeff)))
terms = []
for c, e in zip(coeff, expon):
terms.append(c * x**e)
expr = sum(terms)
Poly can accept a list of coefficients and the generator directly. It expects them in order from high to low. If you want an Expr, not a Poly, you can append the as_expr() call:
>>> little_endian = [101,-8,1,17,3,2]
>>> Poly(reversed(little_endian), x).as_expr()
2*x**5 + 3*x**4 + 17*x**3 + x**2 - 8*x + 101
I'm new to sympy and I'm trying to use it to get the values of higher order Greeks of options (basically higher order derivatives). My goal is to do a Taylor series expansion. The function in question is the first derivative.
f(x) = N(d1)
N(d1) is the P(X <= d1) of a standard normal distribution. d1 in turn is another function of x (x in this case is the price of the stock to anybody who's interested).
d1 = (np.log(x/100) + (0.01 + 0.5*0.11**2)*0.5)/(0.11*np.sqrt(0.5))
As you can see, d1 is a function of only x. This is what I have tried so far.
import sympy as sp
from math import pi
from sympy.stats import Normal,P
x = sp.symbols('x')
u = (sp.log(x/100) + (0.01 + 0.5*0.11**2)*0.5)/(0.11*np.sqrt(0.5))
N = Normal('N',0,1)
f = sp.simplify(P(N <= u))
print(f.evalf(subs={x:100})) # This should be 0.5155
f1 = sp.simplify(sp.diff(f,x))
f1.evalf(subs={x:100}) # This should also return a float value
The last line of code however returns an expression, not a float value as I expected like in the case with f. I feel like I'm making a very simple mistake but I can't find out why. I'd appreciate any help.
Thanks.
If you define x with positive=True (which is implied by the log in the definition of u assuming u is real which is implied by the definition of f) it looks like you get almost the expected result (also using f1.subs({x:100}) in the version without the positive x assumption shows the trouble is with unevaluated polar_lift(0) terms):
import sympy as sp
from sympy.stats import Normal, P
x = sp.symbols('x', positive=True)
u = (sp.log(x/100) + (0.01 + 0.5*0.11**2)*0.5)/(0.11*sp.sqrt(0.5)) # changed np to sp
N = Normal('N',0,1)
f = sp.simplify(P(N <= u))
print(f.evalf(subs={x:100})) # 0.541087287864516
f1 = sp.simplify(sp.diff(f,x))
print(f1.evalf(subs={x:100})) # 0.0510177033783834
Apologies if this has been asked before, I’m a little stuck.
If I had two variables
a = 3x+4y
b = 2x+2y
How could I make it so that a+b = 5x+4y? The way I’ve been currently doing it is with numpy and the imaginary variable. However that doesn’t extend to more than one.
My current one variable code looks like this:
from numpy import *
a = 1+3j
b = 2+7j
Then I can just you the real and imag functions to get the appropriate coefficients.
Thanks
You can use Sympy.
from sympy import symbols
x = symbols('x')
y = symbols('y')
a = symbols('a')
b = symbols('b')
And define your equation using the python variables defined above
expr1 = 5*x + 4*y
expr2 = a + b
Im trying to build a constrained optimization calculator in python using the sympy module. The idea is that a user can enter two functions, "f" and "g", which then are put together to form the equation "L".
I want SymPy to give me the partial derivatives of x, y and lambda in "L", however my code does not seem to be working. When trying to get their partial derivatives i get the following results:
0
0
-x - 4*y + 500
I used x+100*y-y**2 as function 1 and x+4*y-500 and function 2.
Heres the code so far:
import sympy as sp
from sympy.parsing import sympy_parser
x, y = sp.symbols("x y", real=True)
lam = sp.symbols('lambda', real=True)
insert = input("Insert function 1:") #function 1
f = sympy_parser.parse_expr(insert) #transforming the function into a sympy expression
print(f)
insert2 = input("Insert function 2:") #function2
g = sympy_parser.parse_expr(insert2) #transforming function 2
L = f - lam*g #getting the equation "L"
xx = sp.diff(L, x) #partial derivative L'x
yy = sp.diff(L, y) #partial derivative L'y
ll = sp.diff(L, lam) #partial derivative L'lam
print(xx)
print(yy)
print(ll)
I have tried both the "parse_expr" and "simpify" commands to transform the functions input by the user from string to sympy expressions. I might be missing something else.
Your local x and y are real but those that the parser returns are vanilla, they have not assumptions. Since symbols match by name and assumptions, your input functions don't have (the same) x and y:
>>> f.has(x)
False
So either don't make your local symbols real
>>> var('x')
x
>>> f = sympy_parser.parse_expr(insert)
>>> f.has(x)
True
Or pass your local symbols to the parser so it can use them to build your functions:
>>> f = sympy_parser.parse_expr(insert, dict(x=x,y=y))
>>> f.has(x)
True
And once you are using the same symbols, the rest of your issues should move to a new level :-)
I want to do something like h = f(g(x)) and be able to differentiate h, like h.diff(x). For just one function like h = cos(x) this is in fact possible and the documentation makes it clear.
But for function compositions it is not so clear. If you have done this, kindly show me an example or link me to the relevant document.
(If Sympy can't do this, do you know of any other packages that does this, even if it is non-python)
thank you.
It seems that function composition works as you would expect in sympy:
import sympy
h = sympy.cos('x')
g = sympy.sin(h)
g
Out[245]: sin(cos(x))
Or if you prefer
from sympy.abc import x,y
g = sympy.sin('y')
f = g.subs({'y':h})
Then you can just call diff to get your derivative.
g.diff()
Out[246]: -sin(x)*cos(cos(x))
It's named compose; although, I can't find it in the docs.
from sympy import Symbol, compose
x = Symbol('x')
f = x**2 + 2
g = x**2 + 1
compose(f,g)
Out: x**4 + 2*x**2 + 4