def integrate(expr, a, b): # ∫ₐᵇ f(x) dx = [F(x)]ₐᵇ try: anti = antiderivative(expr) except: return simpson(mathparser.parse(expr), a, b) left = nest(anti, Constant(b), 'x') right = nest(anti, Constant(a), 'x') return simplify.evaluate(left) - simplify.evaluate(right)
def parts(u, dv): du = derivatives.main(u) v = antiderivative(dv, variable, limit) ddu = derivatives.main(du) ddv = derivatives.main(dv) if func in (BinaryOp(left = ddu, op = '⋅', right = dv), BinaryOp(left = dv, op = '⋅', right = ddu)): return BinaryOp( left = BinaryOp( left = BinaryOp( left = u, op = '⋅', right = v ), op = '-', right = BinaryOp( left = du, op = '⋅', right = dv ) ), op = '÷', right = Constant(2) ) vdu = simplify.simplify( antiderivative( BinaryOp( left = du, op = '⋅', right = v ), variable, limit ) ) return BinaryOp( left = BinaryOp( left = u, op = '⋅', right = v ), op = '-', right = vdu )
def simpson(f, a, b, n = 1 << 16): delta = (b - a) / n total = 0 for i in range(n+1): x_i = a + i * delta if i in (0, n): m = 1 elif i % 2 == 1: m = 4 elif i % 2 == 0: m = 2 f_x = nest(f, Constant(x_i), 'x') total += simplify.evaluate(f_x) * m return total * (delta / 3)
def simplify(tree): if isinstance(tree, BinaryOp): if isinstance(tree.left, Constant) and isinstance( tree.right, Constant): a = eval('{} {} {}'.format(tree.left.value, CMDS[tree.op], tree.right.value)) if isinstance(a, float) and a.is_integer(): a = int(a) return Constant(a) if tree.op == '⋅': if ONE in (tree.left, tree.right) or fONE in (tree.left, tree.right): if tree.left in (ONE, fONE): return simplify(tree.right) if tree.right in (ONE, fONE): return simplify(tree.left) if ZERO in (tree.left, tree.right) or fZERO in (tree.left, tree.right): return ZERO if MINUSONE in (tree.left, tree.right) or fMINUSONE in (tree.left, tree.right): if tree.left in (MINUSONE, fMINUSONE): return UnaryOp('Prefix', op='-', operand=simplify(tree.right)) if tree.right in (MINUSONE, fMINUSONE): return UnaryOp('Prefix', op='-', operand=simplify(tree.left)) if isnum(tree.left): return simplify_numbers(tree, 'left', '⋅') if isnum(tree.right): return simplify_numbers(tree, 'right', '⋅') if tree.left == tree.right: return UnaryOp('Postfix', op='²', operand=tree.left) if isinstance(tree.left, UnaryOp): if tree.left.op == '-' and tree.right == tree.left.operand: return UnaryOp('Prefix', op='-', operand=UnaryOp('Postfix', op='²', operand=tree.right)) if isinstance(tree.right, UnaryOp): if tree.right.op == '-' and tree.left == tree.right.operand: return UnaryOp('Prefix', op='-', operand=UnaryOp('Postfix', op='²', operand=tree.left)) if mathparser.isexp( tree.right.op) and tree.left == tree.right.operand: newpow = mathparser.make_power( mathparser.normalise(tree.right.op) + 1) return UnaryOp('Postfix', op=newpow, operand=tree.left) if tree.op == '+': if ZERO in (tree.left, tree.right) or fZERO in (tree.left, tree.right): if tree.left in (ZERO, fZERO): return simplify(tree.right) if tree.right in (ZERO, fZERO): return simplify(tree.left) if tree.op in ('÷', '/'): if tree.right in (ONE, fONE): return simplify(tree.left) if tree.right in (MINUSONE, fMINUSONE): return UnaryOp('Prefix', op='-', operand=simplify(tree.left)) if tree.left in (ZERO, fZERO): return ZERO if tree.left == tree.right: return ONE if isnum(tree.left) and isnum(tree.right): val = tree.left.value / tree.right.value if tree.op == '/': val = int(val) return Constant(val) if tree.op == '%': if tree.right in (ONE, MINUSONE, fONE, fMINUSONE): return ZERO if tree.left in (ZERO, fZERO): return ZERO if tree.op == '-': if tree.right in (ZERO, fZERO): return simplify(tree.left) if tree.op == '*': if tree.left in (ZERO, fZERO): return ZERO if tree.left in (ONE, fONE): return ONE if tree.right in (ZERO, fZERO): return ONE if tree.right in (ONE, fONE): return simplify(tree.left) if tree.right in SINGLE_DIGITS: return UnaryOp('Postfix', op=SUPERSCRIPT[int(tree.right.value)], operand=simplify(tree.left)) simp_tree = BinaryOp(simplify(tree.left), tree.op, simplify(tree.right)) return simp_tree if isinstance(tree, UnaryOp): if mathparser.isexp(tree.op) and isinstance(tree.operand, Constant): if isinstance(tree.operand.value, mathparser.NUMBER): return Constant(tree.operand.value**mathparser.normalise( tree.op)) return tree simp_tree = UnaryOp(tree.pos, tree.op, simplify(tree.operand)) return simp_tree return tree
import math import operator import re import mathparser from mathparser import BinaryOp, UnaryOp, Variable, Constant MINUSONE = Constant(-1) ZERO = Constant(0) ONE = Constant(1) TWO = Constant(2) fMINUSONE = Constant(-1.0) fZERO = Constant(0.0) fONE = Constant(1.0) fTWO = Constant(2.0) SINGLE_DIGITS = [] for i in range(10): SINGLE_DIGITS.append(Constant(i)) SINGLE_DIGITS.append(Constant(float(i))) SUPERSCRIPT = '⁰¹²³⁴⁵⁶⁷⁸⁹' CMDS = { '⋅': '*', '÷': '/', '+': '+', '-': '-', '*': '**', '/': '//',
def antiderivative(func, variable = 'x', limit = 1 << 12): def parts(u, dv): du = derivatives.main(u) v = antiderivative(dv, variable, limit) ddu = derivatives.main(du) ddv = derivatives.main(dv) if func in (BinaryOp(left = ddu, op = '⋅', right = dv), BinaryOp(left = dv, op = '⋅', right = ddu)): return BinaryOp( left = BinaryOp( left = BinaryOp( left = u, op = '⋅', right = v ), op = '-', right = BinaryOp( left = du, op = '⋅', right = dv ) ), op = '÷', right = Constant(2) ) vdu = simplify.simplify( antiderivative( BinaryOp( left = du, op = '⋅', right = v ), variable, limit ) ) return BinaryOp( left = BinaryOp( left = u, op = '⋅', right = v ), op = '-', right = vdu ) if not limit: raise Exception('Unable to find antiderivative in time') limit -= 1 if isinstance(func, str): if func in standard_integrals: return standard_integrals[func] func = mathparser.parse(func) if func in derivatives.standard_derivatives.values(): for key, value in derivatives.standard_derivatives.items(): if value == func: return mathparser.parse(key + '({})'.format(variable)) if isinstance(func, Constant): Ifunc = mathparser.parse('{}{}'.format(func.value, variable)) if isinstance(func, Variable): if is_x(func, variable): Ifunc = mathparser.parse('{}²÷2'.format(variable)) else: Ifunc = mathparser.parse('{}{}'.format(func.name, variable)) if isinstance(func, UnaryOp): if func.pos == 'Prefix': if func.op in standard_integrals and is_x(func.operand, variable): return nest(standard_integrals[func.op], Variable(variable), 'x') if is_axb(func.operand, variable): if func.op in '√∛': # Power rule with fractional powers # ∫(ax+b)ⁿ dx = ∫uⁿ du÷a, u = ax+b, du = a dx # = u*(n+1)÷(a(n+1)) # = (ax+b)*(n+1) ÷ (a(n+1)) f = func.operand n = 1 / ('√∛'.index(func.op) + 2) a = derivatives.main(f).value Ifunc = BinaryOp( left = BinaryOp( left = f, op = '*', right = Constant(n+1) ), op = '÷', right = Constant(a*(n+1)) ) else: # Basic u-substitution # ∫f(ax+b) dx = ∫f(u) du÷a, u = ax+b, du = a dx fu = UnaryOp('Prefix', op = func.op, operand = Variable('u')) Ifu = nest(antiderivative(fu, 'u', limit), Variable(variable), 'u') a = derivatives.main(func.operand) Ifunc = BinaryOp( left = nest(Ifu, func.operand, variable), op = '÷', right = a ) if func.op == '-': return UnaryOp('Prefix', op = '-', operand = antiderivative(func.operand)) if func.pos == 'Postfix': if derivatives.REGEX['exponent'].search(func.op): n = mathparser.normalise(func.op) f = func.operand if is_axb(f, variable): # Power rule # ∫(ax+b)ⁿ dx = ∫uⁿ du÷a, u = ax+b, du = a dx # = u*(n+1)÷(a(n+1)) # = (ax+b)*(n+1) ÷ (a(n+1)) a = derivatives.main(f).value Ifunc = BinaryOp( left = BinaryOp( left = f, op = '*', right = Constant(n+1) ), op = '÷', right = Constant(a*(n+1)) ) else: # Generalised power rule # ∫f(x)ⁿ dx if is_trig(f): # Integration by reduction formula if is_x(f.operand, variable): Ifunc = reduce_trig(f, n, variable, limit) elif is_axb(f.operand, variable): fu = UnaryOp('Prefix', op = f.op, operand = Variable('u')) Ifu = nest(antiderivative(fu, 'u', limit), Variable(variable), 'u') a = derivatives.main(func.operand) Ifunc = BinaryOp( left = nest(Ifu, func.operand, variable), op = '÷', right = a ) if isinstance(func, BinaryOp): f = func.left op = func.op g = func.right df = derivatives.main(f) dg = derivatives.main(g) if op in '+-': # Addition rule # ∫f(x)±g(x) dx = ∫f(x) dx ± ∫g(x) dx If = antiderivative(f, variable, limit = limit) Ig = antiderivative(g, variable, limit = limit) Ifunc = BinaryOp( left = If, op = op, right = Ig ) if op == '⋅': if isinstance(f, Constant): # Constant product rule # ∫af(x) dx = a∫f(x) dx Ig = antiderivative(g, variable, limit = limit) Ifunc = BinaryOp( left = f, op = '⋅', right = Ig ) elif inspect(func, f, g, variable) or inspect(func, g, f, variable): # Integration by inspection # ∫f'(g(x))g'(x) dx = f(g(x)) if inspect(func, g, f, variable): df, dg = g, f else: df, dg = f, g f = antiderivative( UnaryOp( df.pos, op = df.op, operand = Variable('u') ), 'u', limit) g = df.operand d_g = derivatives.main(g) consts = [] while dg != d_g and is_const_prod(dg, d_g): if isinstance(d_g.left, Constant): consts.append(d_g.left.value) d_g = d_g.right prod = 1 for v in consts: prod *= v prod = Constant(1/prod) Ifunc = BinaryOp( left = prod, op = '⋅', right = nest(f, g, 'u') ) elif is_power(f) and is_power(g): if is_trig(f.operand) and is_trig(g.operand): m = mathparser.normalise(f.op) n = mathparser.normalise(g.op) f = f.operand g = g.operand if is_trig(f.left) and is_trig(g.left): m = f.right.value n = g.right.value f = f.left g = g.left # Product of exponentiated trig # ∫f(x)ᵐ⋅g(x)ⁿ dx if is_x(f.operand, variable) and is_x(g.operand, variable): Ifunc = reduce_trig_prod(f, g, m, n, 1, 0, variable, limit) elif is_ax(f.operand, variable) and is_ax(g.operand, variable) and f.operand == g.operand: a = f.operand.left.value Ifunc = reduce_trig_prod(f, g, m, n, a, 0, variable, limit) elif is_axb(f.operand, variable) and is_axb(g.operand, variable) and f.operand == g.operand: if isinstance(f.operand.right, Constant): a = f.operand.left.left.value b = f.operand.right.value else: a = f.operand.right.left.value b = f.operand.left.value Ifunc = reduce_trig_prod(f, g, m, n, a, b, variable, limit) else: # Integration by parts # ∫u dv = uv - ∫v du # ∫f(x)g(x) dx = f(x)∫g(x) dx - ∫(∫g(x) dx)f'(x) dx try: Ifunc = parts(f, g) except: Ifunc = parts(g, f) if op == '*': if is_axb(f, variable) and isinstance(g, Constant): if g.value != -1: # Power rule # ∫(ax+b)ⁿ dx = ∫uⁿ du÷a, u = ax+b, du = a dx # = u*(n+1)÷(a(n+1)) # = (ax+b)*(n+1) ÷ (a(n+1)) a = df.value n = g.value Ifunc = BinaryOp( left = BinaryOp( left = f, op = '*', right = Constant(n+1) ), op = '÷', right = Constant(a*(n+1)) ) if g.value == -1: # Log rule # ∫(ax+b)⁻¹ dx = ∫u⁻¹ du÷a, u = ax+b, du = a dx # = ln(u)÷a # = ln(ax+b)÷a a = df Ifunc = BinaryOp( left = UnaryOp( 'Prefix', op = 'ln', operand = f ), op = '÷', right = a ) if isinstance(f, Constant) and is_axb(g, variable): # Exponential rule # ∫c*(ax+b) dx = c*b∫c*(ax) dx # = (c*(ax+b)) ÷ (aln(c)) a = dg c = f Ifunc = BinaryOp( left = func, op = '÷', right = BinaryOp( left = a, op = '⋅', right = UnaryOp( 'Prefix', op = 'ln', operand = c ) ) ) if is_trig(f) and isinstance(g, Constant): # Integration by reduction formula n = g.value if is_x(f.operand, variable): Ifunc = reduce_trig(f, n, variable, limit) elif is_axb(f.operand, variable): fu = UnaryOp('Prefix', op = f.op, operand = Variable('u')) Ifu = nest(antiderivative(fu, 'u', limit), Variable(variable), 'u') a = derivatives.main(func.operand) Ifunc = BinaryOp( left = nest(Ifu, func.operand, variable), op = '÷', right = a ) if op == '÷': if isinstance(simplify.simplify(f), Constant): f = simplify.simplify(f) if isinstance(simplify.simplify(g), Constant): g = simplify.simplify(g) if isinstance(f, Constant): if ( isinstance(g, UnaryOp) and \ g.pos == 'Postfix' and \ derivatives.REGEX['exponent'].search(g.op) ) or ( isinstance(g, UnaryOp) and \ g.pos == 'Prefix' and \ g.op in '√∛' ): # ∫c÷f(x)ⁿ dx = ∫cf(x)⁻ⁿ if g.pos == 'Postfix': n = mathparser.normalise(g.op) else: n = 1 / ('√∛'.index(g.op) + 2) if is_axb(g.operand, variable): # ∫c÷(ax+b)ⁿ dx if n != -1: # Power rule with negative power # ∫c÷(ax+b)ⁿ dx = c∫(ax+b)⁻ⁿ dx # = c(ax+b)*(1-n) ÷ (a(1-n)) a = derivatives.main(g.operand).value Ifunc = BinaryOp( left = f, op = '⋅', right = BinaryOp( left = BinaryOp( left = g.operand, op = '*', right = Constant(1-n) ), op = '÷', right = Constant(a*(1-n)) ) ) if n == -1: # Log rule # ∫c÷(ax+b) dx = c∫1÷(ax+b) dx # = cln(ax+b)÷a a = derivatives.main(g.operand) Ifunc = BinaryOp( left = f, op = '⋅', right = BinaryOp( left = UnaryOp( 'Prefix', op = 'ln', operand = g.operand ), op = '÷', right = a ) ) if is_axb(g, variable): # ∫c÷(ax+b) dx = c∫1÷(ax+b) dx # = cln(ax+b)÷a a = dg Ifunc = BinaryOp( left = f, op = '⋅', right = BinaryOp( left = UnaryOp( 'Prefix', op = 'ln', operand = g ), op = '÷', right = a ) ) if isinstance(g, Constant): # ∫f(x)÷a dx = ∫f(x) dx÷a Ifunc = BinaryOp( left = simplify.simplify(antiderivative( f, variable, limit )), op = '÷', right = g ) if is_poly(f, variable) and is_poly(g, variable): print('>', f, g) try: return Ifunc except: raise Exception('Unable to find antiderivative')
def reduce_trig_prod(f, g, m, n, a, b, variable, limit): # ∫f(ax+b)ᵐ⋅g(ax+b)ⁿ dx if m == 0: return reduce_trig(g, n, variable, limit) if n == 0: return reduce_trig(f, m, variable, limit) if m == 1: return antiderivative( BinaryOp( left = f, op = '⋅', right = BinaryOp( left = g, op = '*', right = n ) ), variable, limit ) if n == 1: return antiderivative( BinaryOp( left = g, op = '⋅', right = BinaryOp( left = f, op = '*', right = m ) ), variable, limit ) # ₋₂ ⁺⁻¹ axb = mathparser.parse('{}{}+{}'.format(a, variable, b)) if (f.op == 'sin' and g.op == 'cos') or (f.op == 'csc' and g.op == 'cot'): # csc(ax+b)ᵐ⋅cot(ax+b)ⁿ = sin(ax+b)ᵐ⁺ⁿ⋅cos(ax+b)ⁿ # # ∫sin(ax+b)ᵐ⋅cos(ax+b)ⁿ dx # = (-sinᵐ⁻¹(ax+b)⋅cosⁿ⁺¹(ax+b) ÷ a + (m-1)⋅∫sin(ax+b)ᵐ⁻²⋅cos(ax+b)ⁿ dx) ÷ (m+n) if f.op == 'csc' and g.op == 'cot': m += n I = antiderivative( BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = 'sin', operand = axb ), op = '*', right = Constant(m-2) ), op = '⋅', right = BinaryOp( left = UnaryOp( 'Prefix', op = 'cos', operand = axb ), op = '*', right = Constant(n) ) ), variable, limit ) return BinaryOp( left = BinaryOp( left = BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = '-', operand = BinaryOp( left = UnaryOp( 'Prefix', op = 'sin', operand = axb ), op = '*', right = Constant(m-1) ) ), op = '⋅', right = BinaryOp( left = UnaryOp( 'Prefix', op = 'cos', operand = axb ), op = '*', right = Constant(n+1) ) ), op = '÷', right = Constant(a) ), op = '+', right = BinaryOp( left = Constant(m-1), op = '⋅', right = I ) ), op = '÷', right = Constant(m+n) ) if (f.op == 'sin' and g.op in ('sec', 'tan')) or (f.op == 'tan' and g.op == 'sec'): # sin(ax+b)ᵐ⋅tan(ax+b)ⁿ = sin(ax+b)ᵐ⁺ⁿ⋅sec(ax+b)ⁿ # tan(ax+b)ᵐ⋅sec(ax+b)ⁿ = sin(ax+b)ᵐ⋅sec(ax+b)ᵐ⁺ⁿ # # ∫sin(ax+b)ᵐ⋅sec(ax+b)ⁿ dx # = ∫sin(ax+b)ᵐ÷cos(ax+b)ⁿ dx # = (-sinᵐ⁻¹(ax+b)⋅secⁿ⁻¹(ax+b) ÷ a + (m-1)⋅∫sin(ax+b)ᵐ⁻²⋅sec(ax+b)ⁿ dx) ÷ (m-n) if g.op == 'tan': m += n if f.op == 'tan': n += m I = antiderivative( BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = 'sin', operand = axb ), op = '*', right = Constant(m-2) ), op = '⋅', right = BinaryOp( left = UnaryOp( 'Prefix', op = 'sec', operand = axb ), op = '*', right = Constant(n) ) ), variable, limit ) return BinaryOp( left = BinaryOp( left = BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = '-', operand = BinaryOp( left = UnaryOp( 'Prefix', op = 'sin', operand = axb ), op = '*', right = Constant(m-1) ) ), op = '⋅', right = BinaryOp( left = UnaryOp( 'Prefix', op = 'sec', operand = axb ), op = '*', right = Constant(n-1) ) ), op = '÷', right = Constant(a) ), op = '+', right = BinaryOp( left = Constant(m-1), op = '⋅', right = I ) ), op = '÷', right = Constant(m-n) ) if f.op in ('csc', 'cot') and g.op == 'cos': # cot(ax+b)ᵐ⋅cos(ax+b)ⁿ = csc(ax+b)ᵐ⋅cos(ax+b)ᵐ⁺ⁿ # # ∫csc(ax+b)ᵐ⋅cos(ax+b)ⁿ dx # = ∫cos(ax+b)ⁿ÷sin(ax+b)ᵐ dx # = (cosⁿ⁻¹(ax+b)⋅cscᵐ⁻¹(ax+b) ÷ a + (n-1)⋅∫csc(ax+b)ᵐ⋅cos(ax+b)ⁿ⁻² dx) ÷ (n-m) if f.op == 'cot': n += m I = antiderivative( BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = 'csc', operand = axb ), op = '*', right = Constant(m) ), op = '⋅', right = BinaryOp( left = UnaryOp( 'Prefix', op = 'cos', operand = axb ), op = '*', right = Constant(n-2) ) ), variable, limit ) return BinaryOp( left = BinaryOp( left = BinaryOp( left = BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = 'cos', operand = axb ), op = '*', right = Constant(n-1) ), op = '⋅', right = BinaryOp( left = UnaryOp( 'Prefix', op = 'csc', operand = axb ), op = '*', right = Constant(m-1) ) ), op = '÷', right = Constant(a) ), op = '+', right = BinaryOp( left = Constant(n-1), op = '⋅', right = I ) ), op = '÷', right = Constant(n-m) ) if f.op == 'csc' and g.op == 'sec': # ∫csc(ax+b)ᵐ⋅sec(ax+b)ⁿ dx # = ∫1÷(sin(ax+b)ᵐ⋅cos(ax+b)ⁿ) dx # = (-csc(ax+b)ᵐ⁻¹⋅sec(ax+b)ⁿ⁻¹ ÷ a + (m+n-2)⋅∫csc(ax+b)ᵐ⁻²⋅sec(ax+b)ⁿ dx) ÷ (m-1) I = antiderivative( BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = 'csc', operand = axb ), op = '*', right = Constant(m-2) ), op = '⋅', right = BinaryOp( left = UnaryOp( 'Prefix', op = 'sec', operand = axb ), op = '*', right = Constant(n) ) ), variable, limit ) return BinaryOp( left = BinaryOp( left = BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = '-', operand = BinaryOp( left = UnaryOp( 'Prefix', op = 'csc', operand = axb ), op = '*', right = Constant(m-1) ) ), op = '⋅', right = BinaryOp( left = UnaryOp( 'Prefix', op = 'sec', operand = axb ), op = '*', right = Constant(n-1) ) ), op = '÷', right = Constant(a) ), op = '+', right = BinaryOp( left = Constant(m+n-2), op = '⋅', right = I ) ), op = '÷', right = Constant(m-1) ) return reduce_trig_prod(g, f, n, m, a, b, variable, limit)
def reduce_trig(f, n, variable, limit): # Trig integration by reduction formula if n == 0: return Variable(variable) if n == 1: return antiderivative(f, variable, limit) if f.op == 'sin': # ∫sin(x)ⁿ dx = (-sinⁿ⁻¹(x)⋅cos(x) + (n-1)∫sin(x)ⁿ⁻² dx) ÷ n Ifunc = BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = '-', operand = BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = 'sin', operand = Variable(variable) ), op = '*', right = Constant(n-1) ), op = '⋅', right = UnaryOp( 'Prefix', op = 'cos', operand = Variable(variable) ) ) ), op = '+', right = BinaryOp( left = Constant(n-1), op = '⋅', right = antiderivative( BinaryOp( left = UnaryOp( 'Prefix', op = 'sin', operand = Variable(variable) ), op = '*', right = Constant(n-2) ), variable, limit ) ) ), op = '÷', right = Constant(n) ) if f.op == 'cos': # ∫cos(x)ⁿ dx = (sin(x)⋅cosⁿ⁻¹(x) + (n-1)∫cos(x)ⁿ⁻² dx) ÷ n Ifunc = BinaryOp( left = BinaryOp( left = BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = 'cos', operand = Variable(variable) ), op = '*', right = Constant(n-1) ), op = '⋅', right = UnaryOp( 'Prefix', op = 'sin', operand = Variable(variable) ) ), op = '+', right = BinaryOp( left = Constant(n-1), op = '⋅', right = antiderivative( BinaryOp( left = UnaryOp( 'Prefix', op = 'cos', operand = Variable(variable) ), op = '*', right = Constant(n-2) ), variable, limit ) ) ), op = '÷', right = Constant(n) ) if f.op == 'tan': # ∫tan(x)ⁿ dx = tanⁿ⁻¹(x) ÷ (n-1) - ∫tan(x)ⁿ⁻² dx Ifunc = BinaryOp( left = BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = 'tan', operand = Variable(variable) ), op = '*', right = Constant(n-1) ), op = '÷', right = Constant(n-1) ), op = '-', right = antiderivative( BinaryOp( left = UnaryOp( 'Prefix', op = 'tan', operand = Variable(variable) ), op = '*', right = Constant(n-2) ), variable, limit ) ) if f.op == 'sec': # ∫sec(x)ⁿ dx = (sin(x)⋅secⁿ⁻¹(x) + (n-2)∫sec(x)ⁿ⁻² dx) ÷ (n-1) Ifunc = BinaryOp( left = BinaryOp( left = BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = 'sec', operand = Variable(variable) ), op = '*', right = Constant(n-1) ), op = '⋅', right = UnaryOp( 'Prefix', op = 'sin', operand = Variable(variable) ) ), op = '+', right = BinaryOp( left = Constant(n-2), op = '⋅', right = antiderivative( BinaryOp( left = UnaryOp( 'Prefix', op = 'sec', operand = Variable(variable) ), op = '*', right = Constant(n-2) ), variable, limit ) ) ), op = '÷', right = Constant(n-1) ) if f.op == 'csc': # ∫csc(x)ⁿ dx = (cos(x)⋅cscⁿ⁻¹(x) + (n-2)∫csc(x)ⁿ⁻² dx) ÷ (n-1) Ifunc = BinaryOp( left = BinaryOp( left = BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = 'csc', operand = Variable(variable) ), op = '*', right = Constant(n-1) ), op = '⋅', right = UnaryOp( 'Prefix', op = 'cos', operand = Variable(variable) ) ), op = '+', right = BinaryOp( left = Constant(n-2), op = '⋅', right = antiderivative( BinaryOp( left = UnaryOp( 'Prefix', op = 'csc', operand = Variable(variable) ), op = '*', right = Constant(n-2) ), variable, limit ) ) ), op = '÷', right = Constant(n-1) ) if f.op == 'cot': # ∫cot(x)ⁿ dx = cotⁿ⁻¹(x) ÷ (n-1) - ∫cot(x)ⁿ⁻² dx Ifunc = BinaryOp( left = BinaryOp( left = BinaryOp( left = UnaryOp( 'Prefix', op = 'cot', operand = Variable(variable) ), op = '*', right = Constant(n-1) ), op = '÷', right = Constant(n-1) ), op = '-', right = antiderivative( BinaryOp( left = UnaryOp( 'Prefix', op = 'cot', operand = Variable(variable) ), op = '*', right = Constant(n-2) ), variable, limit ) ) return Ifunc