How to integrate expressions with sympy? - python

I have a problem integrating an expression:
I need to integrate all terms regardless of the variable,
the expression: -x + 2 * (x - 1)
Expected result: -x**2/2 + 2 * ((x - 1)**2) / 2
the code I'm using:
from sympy import *
x = symbols('x')
expr = - x + factor(2 * (x - 1))
int_1 = integrate(expr)
print(int_1)
generated result: x**2/2 - 2*x
I'm a python beginner...
Thank you!

If you check your result you will find it is the same as the original equation, so the answer is right:
>>> eq = -x + factor(2 * (x - 1))
>>> integrate(eq).diff()
x - 2
>>> eq.expand()
x - 2
This means that the result you got differed from the expected results by a constant and such cases are considered correct in terms of indefinite integration.
It looks like you already learned about autoexpansion (thus the use of factor to keep the 2 from distributing). What you may not realize, however, is that once you pass an expression to a routine it is not required to keep your expression in factored form. It looks like you were expecting that the x - 1 would be treated like x. We can simulate that as
>>> integrate(-x)+integrate(2*y).subs(y,x-1)
-x**2/2 + (x - 1)**2
Using y to represent x - 1 is ok in this case since the results only differ by a constant:
>>> (integrate(x-1) - integrate(y).subs(y ,x-1)).is_constant()
True
It will not, however, be true for all functions of x.

The problem is that you didn't pass any integration limits (from and to), so the only possible answer was the integrated formula.
If for example you want to integrate from 0 to inf, you need to pass this instead
from sympy import *
x = symbols('x')
expr = - x + factor(2 * (x - 1))
int_1 = integrate(expr, (x,0, float('inf')))
print(int_1)
replace 0 and/or float('inf') by any numbers you want to evaluate.

Related

python How to convert the input value into a mathematical function

How to convert an input value into a function!
x = int(input('Enter x value: '))
n = str(input('Enter n value: ')) #n= 2 * x ^ 2 - 2 * x + 2
def f(x,n):
return 2 * x ^ 2 - 2 * x + 2
Actually for what i understand, you don't need to input n.
x = int(input('Enter x value: '))
def f(x):
return 2*x**2 - 2*x+2
n = f(x)
Edit, after rereading others answer yes it probably wanted eval()
Just You can't write "2 * x ^ 2 - 2 * x + 2", the correct way is x**2 instead of x^2
You mean (?):
def f(x, n):
return n*x**2 - 2*x + 2
Or do you mean actually changing the operators?
The question as currently posed is mathematically impossible. You define x & n and are returning a function that you may or may not want to equate to n but its all defined entries.
Still guessing a little at the actual question, but if
y = input("Enter equation to evaluate")
and you expect y to be a quadratic, i.e.:
y = "a*x**b - c*x + d"
then you can get all them from:
import re
y1 = re.split('[* ]',y)
a = y1[0]
b = y1[3] #as there is a null ent between the ** we skip y1[2] and y[1] is 'x'
c = y1[5]
d = y1[8]
If you wanted the operators, then it gets a little harder to follow. So we'll cross that bridge if you do need them.
Or, as the others suggest, just use eval()!!
You could try to use eval.
x=int(input('...'))
n=input('...') # note that input returns a string
def f(x):
global n
return(eval(n))
I think,you are asking .
How to convert an input value into a mathmetical expression ?
If it is so !
use eval()
in python

Taylor series for log(x)

I'm trying to evaluate a Taylor polynomial for the natural logarithm, ln(x), centred at a=1 in Python. I'm using the series given on Wikipedia however when I try a simple calculation like ln(2.7) instead of giving me something close to 1 it gives me a gigantic number. Is there something obvious that I'm doing wrong?
def log(x):
n=1000
s=0
for i in range(1,n):
s += ((-1)**(i+1))*((x-1)**i)/i
return s
Using the Taylor series:
Gives the result:
EDIT: If anyone stumbles across this an alternative way to evaluate the natural logarithm of some real number is to use numerical integration (e.g. Riemann sum, midpoint rule, trapezoid rule, Simpson's rule etc) to evaluate the integral that is often used to define the natural logarithm;
That series is only valid when x is <= 1. For x>1 you will need a different series.
For example this one (found here):
def ln(x): return 2*sum(((x-1)/(x+1))**i/i for i in range(1,100,2))
output:
ln(2.7) # 0.9932517730102833
math.log(2.7) # 0.9932517730102834
Note that it takes a lot more than 100 terms to converge as x gets bigger (up to a point where it'll become impractical)
You can compensate for that by adding the logarithms of smaller factors of x:
def ln(x):
if x > 2: return ln(x/2) + ln(2) # ln(x) = ln(x/2 * 2) = ln(x/2) + ln(2)
return 2*sum(((x-1)/(x+1))**i/i for i in range(1,1000,2))
which is something you can also do in your Taylor based function to support x>1:
def log(x):
if x > 1: return log(x/2) - log(0.5) # ln(2) = -ln(1/2)
n=1000
s=0
for i in range(1,n):
s += ((-1)**(i+1))*((x-1)**i)/i
return s
These series also take more terms to converge when x gets closer to zero so you may want to work them in the other direction as well to keep the actual value to compute between 0.5 and 1:
def log(x):
if x > 1: return log(x/2) - log(0.5) # ln(x/2 * 2) = ln(x/2) + ln(2)
if x < 0.5: return log(2*x) + log(0.5) # ln(x*2 / 2) = ln(x*2) - ln(2)
...
If performance is an issue, you'll want to store ln(2) or log(0.5) somewhere and reuse it instead of computing it on every call
for example:
ln2 = None
def ln(x):
if x <= 2:
return 2*sum(((x-1)/(x+1))**i/i for i in range(1,10000,2))
global ln2
if ln2 is None: ln2 = ln(2)
n2 = 0
while x>2: x,n2 = x/2,n2+1
return ln2*n2 + ln(x)
The program is correct, but the Mercator series has the following caveat:
The series converges to the natural logarithm (shifted by 1) whenever −1 < x ≤ 1.
The series diverges when x > 1, so you shouldn't expect a result close to 1.
The python function math.frexp(x) can be used to advantage here to modify the problem so that the taylor series is working with a value close to one. math.frexp(x) is described as:
Return the mantissa and exponent of x as the pair (m, e). m is a float
and e is an integer such that x == m * 2**e exactly. If x is zero,
returns (0.0, 0), otherwise 0.5 <= abs(m) < 1. This is used to “pick
apart” the internal representation of a float in a portable way.
Using math.frexp(x) should not be regarded as "cheating" because it is presumably implemented just by accessing the bit fields in the underlying binary floating point representation. It isn't absolutely guaranteed that the representation of floats will be IEEE 754 binary64, but as far as I know every platform uses this. sys.float_info can be examined to find out the actual representation details.
Much like the other answer does you can use the standard logarithmic identities as follows: Let m, e = math.frexp(x). Then log(x) = log(m * 2e) = log(m) + e * log(2). log(2) can be precomputed to full precision ahead of time and is just a constant in the program. Here is some code illustrating this to compute the two similar taylor series approximations to log(x). The number of terms in each series was determined by trial and error rather than rigorous analysis.
taylor1 implements log(1 + x) = x1 - (1/2) * x2 + (1/3) * x3 ...
taylor2 implements log(x) = 2 * [t + (1/3) * t3 + (1/5) * t5 ...], where t = (x - 1) / (x + 1).
import math
import struct
_LOG_OF_2 = 0.69314718055994530941723212145817656807550013436025
def taylor1(x):
m, e = math.frexp(x)
log_of_m = 0
num_terms = 36
sign = 1
m_minus1_power = m - 1
for k in range(1, num_terms + 1):
log_of_m += sign * m_minus1_power / k
sign = -sign
m_minus1_power *= m - 1
return log_of_m + e * _LOG_OF_2
def taylor2(x):
m, e = math.frexp(x)
num_terms = 12
half_log_of_m = 0
t = (m - 1) / (m + 1)
t_squared = t * t
t_power = t
denominator = 1
for k in range(num_terms):
half_log_of_m += t_power / denominator
denominator += 2
t_power *= t_squared
return 2 * half_log_of_m + e * _LOG_OF_2
This seems to work well over most of the domain of log(x), but as x approaches 1 (and log(x) approaches 0) the transformation provided by x = m * 2e actually produces a less accurate result. So a better algorithm would first check if x is close to 1, say abs(x-1) < .5, and if so the just compute the taylor series approximation directly on x.
My answer is just using the Taylor series for In(x). I really hope this helps. It is simple and straight to the point.
enter image description here

Eliminate a variable to relate two functions in Python using SymPy

I have two equations that are parametrized by a variable "t". These look like:
X = p(t)
Y = q(t)
where p and q are polynomials in t. I want to use Python's SymPy library to eliminate the t variable and express Y = F(X) for some function X. I have tried using solve() in SymPy but this is not working too well. I know that Maple and Mathematica both have eliminate() functions that can accomplish this, but I wanted to know if Python might have a general function that does this.
Here is a lightly tested simple routine
def eliminate(eqs, z):
"""return eqs with parameter z eliminated from each equation; the first
element in the returned list will be the definition of z that was used
to eliminate z from the other equations.
Examples
========
>>> eqs = [Eq(2*x + 3*y + 4*z, 1),
... Eq(9*x + 8*y + 7*z, 2)]
>>> eliminate(eqs, z)
[Eq(z, -x/2 - 3*y/4 + 1/4), Eq(11*x/2 + 11*y/4 + 7/4, 2)]
>>> Eq(y,solve(_[1], y)[0])
Eq(y, -2*x + 1/11)
"""
from sympy.solvers.solveset import linsolve
Z = Dummy()
rv = []
for i, e in enumerate(eqs):
if z not in e.free_symbols:
continue
e = e.subs(z, Z)
if z in e.free_symbols:
break
try:
s = linsolve([e], Z)
if s:
zi = list(s)[0][0]
rv.append(Eq(z, zi))
rv.extend([eqs[j].subs(z, zi)
for j in range(len(eqs)) if j != i])
return rv
except ValueError:
continue
raise ValueError('only a linear parameter can be eliminated')
There is a more complex routine at this issue.
I refer to this example from the 'Scope' section of https://reference.wolfram.com/language/ref/Eliminate.html.
Eliminate[2 x + 3 y + 4 z == 1 && 9 x + 8 y + 7 z == 2, z]
>>> from sympy import *
>>> var('x y z')
(x, y, z)
>>> solve(2*x+3*y+4*z-1, z)
[-x/2 - 3*y/4 + 1/4]
>>> solve(9*x+8*y+7*z-2, z)
[-9*x/7 - 8*y/7 + 2/7]
>>> (-9*x/7 - 8*y/7 + Rational(2,7))-(-x/2 - 3*y/4 + Rational(1,4)).simplify()
-11*x/14 - 11*y/28 + 1/28
>>> 28*((-9*x/7 - 8*y/7 + Rational(2,7))-(-x/2 - 3*y/4 + Rational(1,4)).simplify())
-22*x - 11*y + 1
Solve each equation for z.
Subtract one expression for z from the other.
Note only that numeric fractions need to be coded — I've used Rational because I forget other methods — so that fractional arithmetic is used.
I multiply through to get rid of the denominators.
This approach will work only for the elimination of a single variable. I haven't considered the second and subsequent examples.
I hope this is useful.
Suppose you wanted to solve the equations for as a function of . This can be done by solving for both and :
solve(
[
Eq(z, sin(theta)),
Eq(z_o, cos(theta))
],
[z_o, theta],
dict=True
)
which yields
You can then throw away the result for and use the rest. This doesn't work for all situations - it requires that the intermediate variable be something that sympy could solve for directly.

How to get all the possible forms x=p(x) of equation f(x)=0

x**3-2*x-5=0
To the following forms [x = p(x)] where p(x) is continuously differentiable:
x=5/(x**2-2)
x=(2*x+5)**(1/3)
x=(x**3-5)/2
Given an expression, such as expr = x**3-2*x-5, assumed to be zero, one can form an equation x = p(x) in many ways. The simplest is to add x to both sides: Eq(x, expr + x).
This prints as one would expect: pprint(Eq(x, expr + x)):
3
x = x - x - 5
A couple of more interesting rewrites:
Iteration for Newton method: Eq(x, simplify(x - expr/diff(expr, x)))
3
2⋅x + 5
x = ────────
2
3⋅x - 2
Isolating the leading term on one side and taking a root:
p = poly(expr)
Eq(x, (LM(p) - expr)**(1/degree(p)))
3 _________
x = ╲╱ 2⋅x + 5
This is rough solution only..
from sympy import *
import numpy as np
var('x')
expr=sympify('x**3-2*x-5')
p = poly(expr);
p1=factor(p-(p).coeff_monomial(1))
for i in p1.args:
if (poly(i).is_monomial):
z=(np.prod([j for j in p1.args if j!=i]))
p2=(-(p).coeff_monomial(1)/z)**(1/degree(i));
v=i.coeff(x)
if p2:print(p2)
elif v:
p2=(-z/v)
print(p2)
for i in (p.all_terms())[:-1]:
if i[1]:
p3= ((i[1]*x**i[0][0]-expr)/i[1])**(1/Integer(i[0][0])) ;print(p3);
'''o
5/(x**2 - 2)
(2*x + 5)**(1/3)
x**3/2 - 5/2
'''

Python, square root function?

I have compiled multiple attempts at this and have failed miserably, some assistance would be greatly appreciated.
The function should have one parameter without using the print statement. Using Newton's method it must return the estimated square root as its value. Adding a for loop to update the estimate 20 times, and using the return statement to come up with the final estimate.
so far I have...
from math import *
def newton_sqrt(x):
for i in range(1, 21)
srx = 0.5 * (1 + x / 1)
return srx
This is not an assignment just practice. I have looked around on this site and found helpful ways but nothing that is descriptive enough.
This is an implementation of the Newton's method,
def newton_sqrt(val):
def f(x):
return x**2-val
def derf(x):
return 2*x
guess =val
for i in range(1, 21):
guess = guess-f(guess)/derf(guess)
#print guess
return guess
newton_sqrt(2)
See here for how it works. derf is the derivative of f.
I urge you to look at the section on Wikipedia regarding applying Newton's method to finding the square root of a number.
The process generally works like this, our function is
f(x) = x2 - a
f'(x) = 2x
where a is the number we want to find the square root of.
Therefore, our estimates will be
xn+1 = xn - (xn2 - a) / (2xn)
So, if your initial guess is x<sub>0</sub>, then our estimates are
x1 = x0 - (x02 - x) / (2x0)
x2 = x1 - (x12 - x) / (2x1)
x3 = x2 - (x22 - x) / (2x2)
...
Converting this to code, taking our initial guess to be the function argument itself, we would have something like
def newton_sqrt(a):
x = a # initial guess
for i in range(20):
x -= (x*x - a) / (2.0*x) # apply the iterative process once
return x # return 20th estimate
Here's a small demo:
>>> def newton_sqrt(a):
... x = a
... for i in range(20):
... x -= (x*x - a) / (2.0*x)
... return x
...
>>> newton_sqrt(2)
1.414213562373095
>>> 2**0.5
1.4142135623730951
>>>
>>> newton_sqrt(3)
1.7320508075688774
>>> 3**0.5
1.7320508075688772
In your code you are not updating x (and consequently srx) as you loop.
One problem is that x/1 is not going to do much and another is that since x never changes all the iterations of the loop will do the same.
Expanding on your code a bit, you could add a guess as a parameter
from math import *
def newton_sqrt(x, guess):
val = x
for i in range(1, 21):
guess = (0.5 * (guess + val / guess));
return guess
print newton_sqrt(4, 3) # Returns 2.0
You probably want something more like:
def newton_sqrt(x):
srx = 1
for i in range(1, 21):
srx = 0.5 * (srx + x/srx)
return srx
newton_sqrt(2.)
# 1.4142135623730949
This both: 1) updates the answer at each iteration, and 2) uses something much closer to the correct formula (ie, no useless division by 1).

Categories