Converting integrate(ln(x-4)) Output - sympy

from sympy import *
from sympy.abc import x
integrate(ln(x-4))
Outputs:
𝑥log(𝑥−4)−𝑥−4log(𝑥−4)
Is there a way I can convert this to (x-4)*ln(x-4) - (x-4) or (x-4)*ln(x-4) + 4 -x

You can do it with a manual substitution using transform:
In [2]: I = Integral(ln(x - 4), x)
In [3]: I
Out[3]:
⌠
⎮ log(x - 4) dx
⌡
In [4]: I.transform(x - 4, y)
Out[4]:
⌠
⎮ log(y) dy
⌡
In [5]: I.transform(x - 4, y).doit()
Out[5]: y⋅log(y) - y
In [6]: I.transform(x - 4, y).doit().subs(y, x - 4)
Out[6]: -x + (x - 4)⋅log(x - 4) + 4
Alternatively you can just use collect:
In [7]: integrate(ln(x - 4))
Out[7]: x⋅log(x - 4) - x - 4⋅log(x - 4)
In [8]: integrate(ln(x - 4)).collect(log(x - 4))
Out[8]: -x + (x - 4)⋅log(x - 4)
This case misses the 4 but that's expected because antiderivatives are only uniquely defined up to an additive constant.

Related

Is this a bug of SymPy?

Why do we have a strange result with integration of expression by SymPy.
>>> from sympy import *
>>> from sympy import __version__
>>> __version__
'1.8'
>>> x = Symbol('x')
>>> f = (x**2 - Rational(1, 4))**2 * sqrt(1 - x**2); f
sqrt(1 - x**2)*(x**2 - 1/4)**2
>>> integrate(f, (x, -1, 1))
0
The integrand is strictly positive, this result is wrong.
However, dividing the interval (x, -1, 1) into (x, -1, 0) and (x, 0, 1), we have the correct.
>>> integrate(f, (x, -1, 0))
pi/64
>>> integrate(f, (x, 0, 1))
pi/64
Expanding the integrand, the result is also correct.
>>> g = f.expand(); g
x**4*sqrt(1 - x**2) - x**2*sqrt(1 - x**2)/2 + sqrt(1 - x**2)/16
>>> integrate(g, (x, -1, 1))
pi/32
This strange phenomenon has occurred since version 1.5 of SymPy.
>>> from sympy import *
>>> from sympy import __version__
>>> __version__
'1.4'
>>> x = Symbol('x')
>>> f = (x**2 - Rational(1, 4))**2 * sqrt(1 - x**2); f
sqrt(1 - x**2)*(x**2 - 1/4)**2
>>> integrate(f, (x, -1, 1))
pi/32
Is this a bug?
Discussion is continued to the following.
https://github.com/sympy/sympy/issues/22033?fbclid=IwAR3oPgk-sLipSDWe7lsRmqG_hpw0fEEgED5XU5K96IKDi-UnVyOzqQqjSYY
I'm not sure the code of integrate function, but I understand as follows.
The primitive function of f = (x**2 - Rational(1,4))**2 * sqrt(1 - x**2) is this.
>>> from sympy import *
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> x = Symbol('x')
>>> f = (x**2 - Rational(1,4))**2 * sqrt(1 - x**2)
>>> F = integrate(f).simplify(); F
Piecewise((-x**3*(1 - x**2)**(3/2)/6 + x*sqrt(1 - x**2)/32 + asin(x)/32, (x > -1) & (x < 1)))
>>> X = np.linspace(-1, 1, 1000)
>>> Y = np.vectorize(Lambda(x, F))(X)
>>> plt.plot(X, Y)
>>> plt.show()
This is correct.
However, in the definite integral with respect to a real number, another expression fr of xr is used as folows.
>>> xr = Symbol('xr', real=True)
>>> fr = (xr**2 - Rational(1,4))**2 * sqrt(1 - xr**2)
>>> Fr = integrate(fr).simplify()
>>> Fr
Piecewise((xr**4*sqrt(1 - xr**2)*Abs(xr)/6 - xr**2*sqrt(1 - xr**2)*Abs(xr)/6 + sqrt(1 - xr**2)*Abs(xr)/32 - asin(sqrt(1 - xr**2))/32, (xr > -1) & (xr < 1) & Ne(xr, 0)))
>>> Yr = np.vectorize(Lambda(xr, Fr))(X)
>>> plt.plot(X, Yr)
>>> plt.show()
This is incorrect.
I think that integration by substitution with y = x**2 is used inadequetly like this..
>>> y = Symbol('y')
>>> g = (y - Rational(1,4))**2 * sqrt(1 - y)/2/sqrt(y)
>>> G = integrate(g).simplify(); G
Piecewise((y**(5/2)*sqrt(1 - y)/6 - y**(3/2)*sqrt(1 - y)/6 + sqrt(y)*sqrt(1 - y)/32 - asin(sqrt(1 - y))/32, (y <= 1) & (y > 0)))
>>> Gr = G.subs(y, x**2).simplify(); Gr
Piecewise((sqrt(1 - x**2)*(x**2)**(5/2)/6 - sqrt(1 - x**2)*(x**2)**(3/2)/6 + sqrt(1 - x**2)*sqrt(x**2)/32 - asin(sqrt(1 - x**2))/32, (x > -1) & (x < 1) & Ne(x, 0)))
>>> Z = np.vectorize(Lambda(x, Gr))(X)
>>> plt.plot(X, Z)
>>> plt.show()
This function is same as Fr above.
However, I don't know why the well known integration by substitution with x = sin(t) isn't used.
>>> t = Symbol('t')
>>> h = (sin(t)**2 - Rational(1,4))**2 * cos(t)**2
>>> H = integrate(h).simplify()
>>> H = integrate(h)
>>> H
t*sin(t)**6/16 + 3*t*sin(t)**4*cos(t)**2/16 - t*sin(t)**4/16 + 3*t*sin(t)**2*cos(t)**4/16 - t*sin(t)**2*cos(t)**2/8 + t*sin(t)**2/32 + t*cos(t)**6/16 - t*cos(t)**4/16 + t*cos(t)**2/32 + sin(t)**5*cos(t)/16 - sin(t)**3*cos(t)**3/6 - sin(t)**3*cos(t)/16 - sin(t)*cos(t)**5/16 + sin(t)*cos(t)**3/16 + sin(t)*cos(t)/32
>>> H1 = H.subs(t, asin(x)).simplify(); H1
x**5*sqrt(1 - x**2)/6 - x**3*sqrt(1 - x**2)/6 + x*sqrt(1 - x**2)/32 + asin(x)/32
This is same as primitive function F of f above and has another expression.
>>> H2 = H.simplify().subs(t, asin(x)); H2
sin(6*asin(x))/192 + asin(x)/32
>>> plt.show()
Using this we are able to have the following correct definite integral of f over [-1, 1].
>>> H2.subs(x, 1) - H2.subs(x, -1)
pi/32

Adding an angle to a sum of trig functions

I have an expression which is the sum of some trig functions:
import sympy as sy
from sympy import cos,sin,pi
theta = sy.symbols('theta')
expr = 5*cos(theta) + sin(theta*2)+3*cos(3*theta)
I'd like to add a "phase shift" by pi/4 to each trig function:
sin(2*theta + pi/4) + 5*cos(theta + pi/4) + 3*cos(3*theta + pi/4)
How can this be achieved? Is there a way to walk the expression tree and do an insertion of pi/4?
There are many ways to do this. Here is one that uses pattern matching:
In [5]: expr
Out[5]: sin(2⋅θ) + 5⋅cos(θ) + 3⋅cos(3⋅θ)
In [6]: w = Wild('w')
In [7]: expr.replace(sin(w), sin(w+pi/4))
Out[7]:
⎛ π⎞
sin⎜2⋅θ + ─⎟ + 5⋅cos(θ) + 3⋅cos(3⋅θ)
⎝ 4⎠
In [8]: expr.replace(sin(w), sin(w+pi/4)).replace(cos(w), cos(w + pi/4))
Out[8]:
⎛ π⎞ ⎛ π⎞ ⎛ π⎞
sin⎜2⋅θ + ─⎟ + 5⋅cos⎜θ + ─⎟ + 3⋅cos⎜3⋅θ + ─⎟
⎝ 4⎠ ⎝ 4⎠ ⎝ 4⎠

Distance from a point to a line : output nan?

Thank you in advance and sorry for the bad English!
(ref)Distance from a point to a line < wikipedia
https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
from sympy import *
var('a b c x y x1 y1 x2 y2 x0 y0 co si tx ty d DH')
x1=0
y1=solve([a*x+b*y+c],[y])[y].subs({x:0})
x2=solve([a*x+b*y+c],[x])[x].subs({y:0})
y2=0
d=sqrt((x1-x2)**2+(y1-y2)**2)
v=solve([co*0-si*0+tx-x1,si*0+co*0+ty-y1,co*d-si*0+tx-x2,si*d+co*0+ty-y2],[co,si,tx,ty])
A=Matrix([
[v[co],-v[si],v[tx]],
[v[si], v[co],v[ty]],
[0 , 0, 1]
])
B=Matrix([
[x0],
[y0],
[ 1]
])
AinvB=A.inv()*B
DH=simplify(AinvB[1])
print(DH)
print(float(DH.subs({a:1,b:-1,c:10,x0:0,y0:11})))
print(float(DH.subs({a:1,b:-1,c: 0,x0:0,y0: 1})))
# -c*(a*x0 + b*y0 + c)/(a*b*sqrt(c**2*(a**2 + b**2)/(a**2*b**2)))
# -0.7071067811865476
# nan
The expression you generate is not always valid for all substituted values. In the case that gives nan your expression generates 0/0 which is nan.
>>> from sympy import S, fraction, Tuple
>>> eq=S('-c*(a*x0 + b*y0 + c)/(a*b*sqrt(c**2*(a**2 + b**2)/(a**2*b**2)))')
>>> n,d=fraction(eq)
>>> Tuple(n,d).subs(dict(a=1,b=-1,c=0,x0=0,y0=1))
(0, 0)
>>> _[0]/_[1]
nan
You might be interested in using SymPy's geometric objects to help with such calculations and (in this case) compare their expressions to what you generate by other means:
>>> from sympy.abc import b,m,x,y
>>> from sympy import Point, Line
>>> d=Point(x,y).distance(Line(m*x+b-y))
>>> d
sqrt((x-(-b*m+m*y+x)/(m**2+1))**2 + (y-(b+m**2*y+m*x)/(m**2+1))**2)
>>> d.subs(y, m*x+b).simplify()
0

Polynomial Coefficients from Sympy to Array

In the below code, L1 simplifies to the transfer function that I want:
import sympy as sy
z = sy.symbols('z')
L1 = sy.simplify(((z**2 - 0.5*z + 0.16) / (z-1)**2 ) - 1)
L1
After this, I manually enter the coefficients for the numerator and denominator as follow:
num = [1.5, -0.84]
den = [1., -2., 1.]
Is there a way to do this from code? I'm not sure how to convert the sympy result to something that I can work with again without manually creating the arrays num and den.
You can use as_numer_denom to get the numerator and denominator and then as_poly and coeffs to get the coefficients:
In [16]: import sympy as sy
...: z = sy.symbols('z')
...: L1 = sy.simplify(((z**2 - 0.5*z + 0.16) / (z-1)**2 ) - 1)
...: L1
Out[16]:
1.0⋅(1.5⋅z - 0.84)
────────────────────
2
1.0⋅z - 2.0⋅z + 1.0
In [17]: num, den = L1.as_numer_denom()
In [18]: num.as_poly(z).coeffs()
Out[18]: [1.5, -0.84]
In [19]: den.as_poly(z).coeffs()
Out[19]: [1.0, -2.0, 1.0]
Or to get the whole expression, you could do :
from sympy import *
z = symbols('z')
L1 = simplify(((z**2 - 0.5*z + 0.16) / (z-1)**2 ) - 1)
srepr(L1)
output:
"Mul(Float('1.0', precision=53), Add(Mul(Float('1.5', precision=53), Symbol('z')),
Float('-0.83999999999999997', precision=53)), Pow(Add(Mul(Float('1.0', precision=53),
Pow(Symbol('z'), Integer(2))), Mul(Integer(-1), Float('2.0', precision=53),
Symbol('z')), Float('1.0', precision=53)), Integer(-1)))"

Integral involving Bessel function

Is there any way to get sympy to perform this integral?
x=var('x')
L=var('L')
Q.positive(1/L)
integrate(besseli(1,x) * exp(-x**2/(4*L)-L),(x,0,inf))
Sympy just returns the integral:
Integral(exp(-L - x**2/(4*L))*besseli(1, x), (x, 0, +inf))
Mathematica does it:
Integrate[BesselI[1, x] Exp[-(x^2/(4 L)) - L], {x, 0, Infinity}]
Result:
ConditionalExpression[1 - E^-L, Re[1/L] > 0]
EDIT: using the answer provided below, a better way to perform this integral is:
L=var('L',real=True,positive=True)
x=var('x',real=True,positive=True)
integrate(besseli(1,x) * exp(-x**2/(4*L)-L),(x,0,oo))
The problem is that you are using inf, which I guess is Float('inf'). You want oo, the symbolic infinity. SymPy should probably be smarter about converting Float('inf') to oo.
In [1]: x=var('x')
In [2]: L=var('L')
In [3]: Q.positive(1/L)
Out[3]: Q.positive(1/L)
In [5]: integrate(besseli(1,x) * exp(-x**2/(4*L)-L),(x,0,oo))
Out[5]:
⎧ ⎛ L ⎞ -L │ ⎛ 1 ⎞│ π
⎪ ⎝ℯ - 1⎠⋅ℯ for │periodic_argument⎜─────────────, ∞⎟│ < ─
⎪ │ ⎝polar_lift(L) ⎠│ 2
⎪
⎪∞
⎪⌠
⎨⎮ 2
⎪⎮ x
⎪⎮ -L - ───
⎪⎮ 4⋅L
⎪⎮ ℯ ⋅besseli(1, x) dx otherwise
⎪⌡
⎩0
The original expression now works in SymPy because inf is automatically recast to oo:
>>> inf=float('inf')
>>> x=var('x')
>>> L=var('L')
>>> Q.positive(1/L)
Q.positive(1/L)
>>> integrate(besseli(1,x) * exp(-x**2/(4*L)-L),(x,0,inf))
Piecewise(
((exp(L) - 1)*exp(-L), Abs(arg(L)) < pi/2),
(Integral(exp(-L - x**2/(4*L))*besseli(1, x), (x, 0, oo)), True))