def trig_substitution_rule(integral):
integrand, symbol = integral
a = sympy.Wild('a', exclude=[0, symbol])
b = sympy.Wild('b', exclude=[0, symbol])
theta = sympy.Dummy("theta")
matches = integrand.find(a + b*symbol**2)
if matches:
for expr in matches:
match = expr.match(a + b*symbol**2)
a = match[a]
b = match[b]
a_positive = ((a.is_number and a > 0) or a.is_positive)
b_positive = ((b.is_number and b > 0) or b.is_positive)
x_func = None
if a_positive and b_positive:
# a**2 + b*x**2. Assume sec(theta) > 0, -pi/2 < theta < pi/2
x_func = (sympy.sqrt(a)/sympy.sqrt(b)) * sympy.tan(theta)
# Do not restrict the domain: tan(theta) takes on any real
# value on the interval -pi/2 < theta < pi/2 so x takes on
# any value
restriction = True
elif a_positive and not b_positive:
# a**2 - b*x**2. Assume cos(theta) > 0, -pi/2 < theta < pi/2
constant = sympy.sqrt(a)/sympy.sqrt(-b)
x_func = constant * sympy.sin(theta)
restriction = sympy.And(symbol > -constant, symbol < constant)
elif not a_positive and b_positive:
# b*x**2 - a**2. Assume sin(theta) > 0, 0 < theta < pi
constant = sympy.sqrt(-a)/sympy.sqrt(b)
x_func = constant * sympy.sec(theta)
restriction = sympy.And(symbol > -constant, symbol < constant)
if x_func:
# Manually simplify sqrt(trig(theta)**2) to trig(theta)
# Valid due to assumed domain restriction
substitutions = {}
for f in [sympy.sin, sympy.cos, sympy.tan,
sympy.sec, sympy.csc, sympy.cot]:
substitutions[sympy.sqrt(f(theta)**2)] = f(theta)
substitutions[sympy.sqrt(f(theta)**(-2))] = 1/f(theta)
replaced = integrand.subs(symbol, x_func).trigsimp()
replaced = replaced.subs(substitutions)
if not replaced.has(symbol):
replaced *= manual_diff(x_func, theta)
replaced = replaced.trigsimp()
secants = replaced.find(1/sympy.cos(theta))
if secants:
replaced = replaced.xreplace({
1/sympy.cos(theta): sympy.sec(theta)
})
substep = integral_steps(replaced, theta)
if not contains_dont_know(substep):
return TrigSubstitutionRule(
theta, x_func, replaced, substep, restriction,
integrand, symbol)
评论列表
文章目录