I have the following calculation for sympy:
import sympy
q, r = sympy.symbols("q r")
equation = (((-q + r) - (q - r)) <= 0).simplify()
print(equation) # q >= r
equation = ((sympy.sqrt(2) * (-q + r) - sympy.sqrt(2) * (q - r)) <= 0).simplify()
print(equation) # q <= r
I don't see why the results should differ. What am I missing?
Edit
I am using version 1.5.1 of sympy and can see this on Python 3.6.6 and 3.7.7.
A fix for this is given here. It looks like gcd was assumed to behave like igcd (which gives a nonnegative value). But when dealing with non-integers, gcd currently can give a negative result, thus the error. So SymPy will either modify gcd and the simplify code will work or the simplification routine must account for the sign of the extracted gcd.
Related
I'm making a solver of cubic equations in Python that includes division of polynomials.
from sympy import symbols
# Coefficients
a = int(input("1st coef: "))
b = int(input("2nd coef: "))
c = int(input("3rd coef: "))
d = int(input("Const: "))
# Polynomial of x
def P(x):
return a*x**3 + b*x**2 + c*x + d
x = symbols('x')
# Find 1 root by Cardano
R = (3*a*c - b**2) / (9*a**2)
Q = (3*b**3 - 9*a*b*c + 27*a**2*d) / (54*a**3)
Delta = R**3 + Q**2
y = (-Q + sqrt(Delta))**(1/3) + (-Q - sqrt(Delta))**(1/3)
x_1 = y - b/(3*a)
# Division
P(x) / (x - x_1) = p(x)
print(p(x)) # Just a placeholder
The program returns an error: "cannot assign to operator" and highlights the P(x) after the # Division comment (worded poorly, yes, but I'm from Russia so idc).
What I tried doing was to assign a variable to a polynomial and then dividing:
z = P(x)
w = x - x_1
p = z / w
print(p)
But alas: it just returns a plain old quotient (a = 1, b = 4, c = -9, d = -36):
(x**3 + 4*x**2 - 9*x - 36)/(x - 2.94254537742264)
Does anyone out here knows what to do in this situation (not to mention the non-exact value of x_1: the roots of x^3+4x^2-9x-36=0 are 3, -4, and -3, no floaty-irrational-messy-ugly things in sight)?
tl;dr: Polynomial division confusion and non-exact roots
I am not sure what exactly your question is but here is an attempt at an answer
The line
P(x) / (x - x_1) = p(x)
is problematic for multiple reasons. First of all it's important to know that the = operator in python (and a lot of other modern programming languages) is an assignment operator. You seem to come from more of a math background, so consider it to be something like the := operator. The direction of this is always fixed, i.e. with a = b you are always assigning the value of b to the variable a. In your case you are basically assigning an expression the value of p which does not make much sense:
Python can't assign anything to an expression (At least not as far as I know)
p(x) is not yet defined
The second problem is that you are mixing python functions with math functions.
A python function looks something like this:
def some_function(some_parameter)
print("Some important Thing!: ", some_parameter)
some_return_value = 42
return some_return_value
It (can) take some variable(s) as input, do a bunch of things with them, and then (can) return something else. They are generally called with the bracket operator (). I.e. some_function(42) translates to execute some_function and substitute the first parameter with the value 42. An expression in sympy however is as far as python is concerned just an object/variable.
So basically you could have just written P = a*x**3 + b*x**2 + c*x + d. What your P(x) function is doing is basically taking the expression a*x**3 + b*x**2 + c*x + d, substituting x for whatever you have put in the brackets, and then giving it back in as a sympy expression. (It's important to understand, that the x in your P python function has nothing to do with the x you define later! Because of that, one usually tries to avoid such "false friends" in coding)
Also, a math function in sympy is really just an expression formed from sympy symbols. As far as sympy is concerned, the return value of the P function is a (mathematical) function of the symbols a,b,c,d and the symbol you put into the brackets. This is why, whenever you want to integrate or differentiate, you will need to specify by which symbol to do that.
So the line should have looked something like this.
p = P(x) / (x - x_1)
Or you leave replace the P(x) function with P = a*x**3 + b*x**2 + c*x + d and end up with
p = P / (x - x_1)
Thirdly if you would like to have the expression simplified you should take a look here (https://docs.sympy.org/latest/tutorial/simplification.html). There are multiple ways here of simplifying expressions, depending on what sort of expression you want as a result. To make for faster code sympy will only simplify your expression if you specifically ask for it.
You might however be disappointed with the results, as the line
y = (-Q + sqrt(Delta))**(1/3) + (-Q - sqrt(Delta))**(1/3)
will do an implicit conversion to floating point numbers, and you are going to end up with rounding problems. To blame is the (1/3) part which will evaluate to 0.33333333 before ever seeing sympy. One possible fix for this would be
y = (-Q + sqrt(Delta))**(sympy.Rational(1,3)) + (-Q - sqrt(Delta))**(sympy.Rational(1,3))
(You might need to add import sympy at the top)
Generally, it might be worth learning a bit more about python. It's a language that mostly tries to get out of your way with annoying technical details. This unfortunately however also means that things can get very confusing when using libraries like sympy, that heavily rely on stuff like classes and operator overloading. Learning a bit more python might give you a better idea about what's going on under the hood, and might make the distinction between python stuff and sympy specific stuff easier. Basically, you want to make sure to read and understand this (https://docs.sympy.org/latest/gotchas.html).
Let me know if you have any questions, or need some resources :)
I'm currently trying to implement the Newton-Raphson algorithm for some finance-based calculations.
I tried it in Python with a simple for loop, but I get this RuntimeWarning: divide by zero encountered in double_scalars and I also get no result of the approximation. I tried to fix it by checking every division on my own, but I found no step where Python should be forced to divide by a zero.
import numpy as np
import math as m
import scipy.stats as si
def totalvol_zero(M):
v_0 = m.sqrt(2 * abs(M))
return v_0
def C_prime(M,v):
C_prime = si.norm.cdf(M/v + v/2) - m.exp(-M)*si.norm.cdf(M/v - v/2)
return C_prime
def NR(M,C_prime_obs):
v_0 = totalvol_zero(M)
for k in range(0,7,1):
v_0 = v_0 - ((C_prime(M,v_0) - C_prime_obs)/(m.sqrt(1/(m.pi * 2))*m.exp(-0.5*((M/v_0 + v_0/2)**2))))
k += 1
return v_0
print(NR(2,2))
This may be a really easy error/typo for some of you because I am still a beginner in Python but at the moment I just don't see anything wrong in this code and can't explain why this warning appeared and why I don't get any value as result.
Edit:
Sorry, I forgot about M and v. They are just explicit formulas so I didn't thought that they are the cause of this problem.
def moneyness(S,K,d,r,t):
F = S * m.exp((r-d)*t)
M = m.log(F/K)
return M
def totalvol(sigma,t):
v = sigma * m.sqrt(t)
return v
These are the explicit expressions for M and v. M defines the moneyness of an option, while v is the total volatility of it. But because I didn't even express M and v in the for-loop like that, but used them just as numbers for the Newton-Raphson, I don't think they will help solve the problem.
C_prime_obs is a converted call price of an option. The value should be always positive but since I never divided by C_prime_obs, this doesn't change anything.
def GetE(x1, x2, k, x, z, N):
firstHeight = math.exp(((k/(2*math.pi*z)) * ((x-x1) ** 2))j)
My function gives me a syntax error on the line defining firstHeight. I believe it is to do with not being able to define a complex number with variables, as I have tried:
test = 2 + (k)j
and also recieved a syntax error. Does anyone know how to fix this?
math does not support complex numbers, for that you have cmath:
import math, cmath
cmath.exp(((k/(2*math.pi*z)) * ((x-x1) ** 2))*1j)
# (0.998966288513345+0.045457171204028084j)
Or you could use NumPy:
np.exp(((k/(2*np.pi*z)) * ((x-x1) ** 2))*1j)
#(0.998966288513345+0.045457171204028084j)
That, and also as #GreenCloakGuy points out, you can't use j to convert a non-literal into a complex number. You can instead use complex() or 1j
The j suffix can only be used in an imaginary literal, not with variables. To get a negative imaginary number from a variable, multiply the variable by -1j.
firstHeight = math.exp(((k/(2*math.pi*z)) * ((x-x1) ** 2)) * -1j)
test = 2 + k * -1j
beginner programmer here. I have been assigned to create a function 'Roots' that takes two parameters x and n(n has to be an integer) and then calculates all complex and real roots of the equation z^n=x. However, the only module/package I can use is math. Also, I have been told that the certain aspects of the following function 'Power_complex' play a big role into creating 'Roots':
def Power_complex(re, im, n): #calculates the n-th power of a complex number(lets call this a), where 're' is the real part and 'im' the imaginary part
import math
r=math.sqrt((re)**2+(im)**2) #calculates modulus
h=math.atan2(re,im) #calculates argument(angle)
ren=(r**n)*math.cos(h*n) #calculates the real part of a^n
imn=(r**n)*math.sin(h*n) #calculates the imaginary part of a^n
return ren, imn
print '(',re, '+', im, 'i',')','^',n,'=',ren,'+',imn,'i' #displays the result
Also, I need to somehow implement a for loop into 'Roots'.
I have been pondering over this for hours, but alas I really can't figure it out and am hoping one of you can help me out here.
BTW my python version is 2.7.10
The expression for the solutions is ( explained here ):
when
In the case that z^n is real, equal to the x in your question, then r = |x| and the angle is 0 or pi for positive and negative values, respectively.
So you make the modulus and argument as you have done, then make every solution corresponding to a value of k
z = [r**(1./n) * exp(1j * (theta + 2*pi*k) / n ) for k in range(n)]
This line uses a Python technique called list comprehension. An eqvivalent way of doing it (that you may be more familiar to) could be:
z = []
for k in range(n):
nthroot = r**(1./n) * exp( 1j * (theta + 2*pi*k) / n )
z.append(nthroot)
Printing them out could be done in the same fashion, using a for-loop:
for i in range(len(z)):
print "Root #%d = %g + i*%g" % (i, z[i].real, z[i].imag)
Note that the exp-function used must be from the module cmath (math can't handle complex numbers). If you are not allowed to use cmath, then I suggest you rewrite the expression for the solutions to the form without modulus and argument.
I am using the sympy library for python3, and I am handling equations, such as the following one:
a, b = symbols('a b', positive = True)
my_equation = Eq((2 * a + b) * (a - b) / 2, 0)
my_equations gets printed exactly as I have defined it ((2 * a + b) * (a - b) / 2 == 0, that is), and I am unable to reduce it even using simplify or similar functions.
What I am trying to achieve is simplifying the nonzero factors from the equation (2 * a + b and 1 / 2); ideally, I'd want to be able to simplify a - b as well, if I am sure that a != b.
Is there any way I can reach this goal?
The point is that simplify() is not capable (yet) of complex reasoning about assumptions. I tested it on Wolfram Mathematica's simplify, and it works. It looks like it's a missing feature in SymPy.
Anyway, I propose a function to do what you're looking for.
Define this function:
def simplify_eq_with_assumptions(eq):
assert eq.rhs == 0 # assert that right-hand side is zero
assert type(eq.lhs) == Mul # assert that left-hand side is a multipl.
newargs = [] # define a list of new multiplication factors.
for arg in eq.lhs.args:
if arg.is_positive:
continue # arg is positive, let's skip it.
newargs.append(arg)
# rebuild the equality with the new arguments:
return Eq(eq.lhs.func(*newargs), 0)
Now you can call:
In [5]: simplify_eq_with_assumptions(my_equation)
Out[5]: a - b = 0
You can easily adapt this function to your needs. Hopefully, in some future version of SymPy it will be sufficient to call simplify.