1""" 2Utility functions for Rubi integration. 3 4See: http://www.apmaths.uwo.ca/~arich/IntegrationRules/PortableDocumentFiles/Integration%20utility%20functions.pdf 5""" 6from sympy.external import import_module 7matchpy = import_module("matchpy") 8from sympy import (Basic, E, polylog, N, Wild, WildFunction, factor, gcd, Sum, 9 S, I, Mul, Integer, Float, Dict, Symbol, Rational, Add, hyper, symbols, 10 sqf_list, sqf, Max, factorint, factorrat, Min, sign, E, Function, collect, 11 FiniteSet, nsimplify, expand_trig, expand, poly, apart, lcm, And, Pow, pi, 12 zoo, oo, Integral, UnevaluatedExpr, PolynomialError, Dummy, exp as sym_exp, 13 powdenest, PolynomialDivisionFailed, discriminant, UnificationFailed, appellf1) 14from sympy.core.exprtools import factor_terms 15from sympy.core.sympify import sympify 16from sympy.functions import (log as sym_log, sin, cos, tan, cot, csc, sec, 17 sqrt, erf, gamma, uppergamma, polygamma, digamma, 18 loggamma, factorial, zeta, LambertW) 19from sympy.functions.elementary.complexes import im, re, Abs 20from sympy.functions.elementary.hyperbolic import acosh, asinh, atanh, acoth, acsch, asech, cosh, sinh, tanh, coth, sech, csch 21from sympy.functions.elementary.integers import floor, frac 22from sympy.functions.elementary.trigonometric import atan, acsc, asin, acot, acos, asec, atan2 23from sympy.functions.special.elliptic_integrals import elliptic_f, elliptic_e, elliptic_pi 24from sympy.functions.special.error_functions import fresnelc, fresnels, erfc, erfi, Ei, expint, li, Si, Ci, Shi, Chi 25from sympy.functions.special.hyper import TupleArg 26from sympy.logic.boolalg import Or 27from sympy.polys.polytools import Poly, quo, rem, total_degree, degree 28from sympy.simplify.simplify import fraction, simplify, cancel, powsimp 29from sympy.utilities.decorator import doctest_depends_on 30from sympy.utilities.iterables import flatten, postorder_traversal 31from random import randint 32 33 34class rubi_unevaluated_expr(UnevaluatedExpr): 35 """ 36 This is needed to convert `exp` as `Pow`. 37 sympy's UnevaluatedExpr has an issue with `is_commutative`. 38 """ 39 @property 40 def is_commutative(self): 41 from sympy.core.logic import fuzzy_and 42 return fuzzy_and(a.is_commutative for a in self.args) 43 44_E = rubi_unevaluated_expr(E) 45 46 47class rubi_exp(Function): 48 """ 49 sympy's exp is not identified as `Pow`. So it is not matched with `Pow`. 50 Like `a = exp(2)` is not identified as `Pow(E, 2)`. Rubi rules need it. 51 So, another exp has been created only for rubi module. 52 53 Examples 54 ======== 55 56 >>> from sympy import Pow, exp as sym_exp 57 >>> isinstance(sym_exp(2), Pow) 58 False 59 >>> from sympy.integrals.rubi.utility_function import rubi_exp 60 >>> isinstance(rubi_exp(2), Pow) 61 True 62 63 """ 64 @classmethod 65 def eval(cls, *args): 66 return Pow(_E, args[0]) 67 68class rubi_log(Function): 69 """ 70 For rule matching different `exp` has been used. So for proper results, 71 `log` is modified little only for case when it encounters rubi's `exp`. 72 For other cases it is same. 73 74 Examples 75 ======== 76 77 >>> from sympy.integrals.rubi.utility_function import rubi_exp, rubi_log 78 >>> a = rubi_exp(2) 79 >>> rubi_log(a) 80 2 81 82 """ 83 @classmethod 84 def eval(cls, *args): 85 if args[0].has(_E): 86 return sym_log(args[0]).doit() 87 else: 88 return sym_log(args[0]) 89 90if matchpy: 91 from matchpy import Arity, Operation, CustomConstraint, Pattern, ReplacementRule, ManyToOneReplacer 92 from sympy.integrals.rubi.symbol import WC 93 from matchpy import is_match, replace_all 94 95 class UtilityOperator(Operation): 96 name = 'UtilityOperator' 97 arity = Arity.variadic 98 commutative = False 99 associative = True 100 101 Operation.register(rubi_log) 102 Operation.register(rubi_exp) 103 104 A_, B_, C_, F_, G_, a_, b_, c_, d_, e_, f_, g_, h_, i_, j_, k_, l_, m_, \ 105 n_, p_, q_, r_, t_, u_, v_, s_, w_, x_, z_ = [WC(i) for i in 'ABCFGabcdefghijklmnpqrtuvswxz'] 106 a, b, c, d, e = symbols('a b c d e') 107 108 109Int = Integral 110 111 112def replace_pow_exp(z): 113 """ 114 This function converts back rubi's `exp` to general sympy's `exp`. 115 116 Examples 117 ======== 118 119 >>> from sympy.integrals.rubi.utility_function import rubi_exp, replace_pow_exp 120 >>> expr = rubi_exp(5) 121 >>> expr 122 E**5 123 >>> replace_pow_exp(expr) 124 exp(5) 125 126 """ 127 z = S(z) 128 if z.has(_E): 129 z = z.replace(_E, E) 130 return z 131 132def Simplify(expr): 133 expr = simplify(expr) 134 return expr 135 136def Set(expr, value): 137 return {expr: value} 138 139def With(subs, expr): 140 if isinstance(subs, dict): 141 k = list(subs.keys())[0] 142 expr = expr.xreplace({k: subs[k]}) 143 else: 144 for i in subs: 145 k = list(i.keys())[0] 146 expr = expr.xreplace({k: i[k]}) 147 return expr 148 149def Module(subs, expr): 150 return With(subs, expr) 151 152def Scan(f, expr): 153 # evaluates f applied to each element of expr in turn. 154 for i in expr: 155 yield f(i) 156 157def MapAnd(f, l, x=None): 158 # MapAnd[f,l] applies f to the elements of list l until False is returned; else returns True 159 if x: 160 for i in l: 161 if f(i, x) == False: 162 return False 163 return True 164 else: 165 for i in l: 166 if f(i) == False: 167 return False 168 return True 169 170def FalseQ(u): 171 if isinstance(u, (Dict, dict)): 172 return FalseQ(*list(u.values())) 173 174 return u == False 175 176def ZeroQ(*expr): 177 if len(expr) == 1: 178 if isinstance(expr[0], list): 179 return list(ZeroQ(i) for i in expr[0]) 180 else: 181 182 return Simplify(expr[0]) == 0 183 else: 184 return all(ZeroQ(i) for i in expr) 185 186def OneQ(a): 187 if a == S(1): 188 return True 189 return False 190 191def NegativeQ(u): 192 u = Simplify(u) 193 if u in (zoo, oo): 194 return False 195 if u.is_comparable: 196 res = u < 0 197 if not res.is_Relational: 198 return res 199 return False 200 201def NonzeroQ(expr): 202 return Simplify(expr) != 0 203 204 205def FreeQ(nodes, var): 206 if isinstance(nodes, list): 207 return not any(S(expr).has(var) for expr in nodes) 208 else: 209 nodes = S(nodes) 210 return not nodes.has(var) 211 212def NFreeQ(nodes, var): 213 """ Note that in rubi 4.10.8 this function was not defined in `Integration Utility Functions.m`, 214 but was used in rules. So explicitly its returning `False` 215 """ 216 return False 217 # return not FreeQ(nodes, var) 218 219def List(*var): 220 return list(var) 221 222def PositiveQ(var): 223 var = Simplify(var) 224 if var in (zoo, oo): 225 return False 226 if var.is_comparable: 227 res = var > 0 228 if not res.is_Relational: 229 return res 230 return False 231 232def PositiveIntegerQ(*args): 233 return all(var.is_Integer and PositiveQ(var) for var in args) 234 235def NegativeIntegerQ(*args): 236 return all(var.is_Integer and NegativeQ(var) for var in args) 237 238def IntegerQ(var): 239 var = Simplify(var) 240 if isinstance(var, (int, Integer)): 241 return True 242 else: 243 return var.is_Integer 244 245def IntegersQ(*var): 246 return all(IntegerQ(i) for i in var) 247 248def _ComplexNumberQ(var): 249 i = S(im(var)) 250 if isinstance(i, (Integer, Float)): 251 return i != 0 252 else: 253 return False 254 255def ComplexNumberQ(*var): 256 """ 257 ComplexNumberQ(m, n,...) returns True if m, n, ... are all explicit complex numbers, else it returns False. 258 259 Examples 260 ======== 261 262 >>> from sympy.integrals.rubi.utility_function import ComplexNumberQ 263 >>> from sympy import I 264 >>> ComplexNumberQ(1 + I*2, I) 265 True 266 >>> ComplexNumberQ(2, I) 267 False 268 269 """ 270 return all(_ComplexNumberQ(i) for i in var) 271 272def PureComplexNumberQ(*var): 273 return all((_ComplexNumberQ(i) and re(i)==0) for i in var) 274 275def RealNumericQ(u): 276 return u.is_real 277 278def PositiveOrZeroQ(u): 279 return u.is_real and u >= 0 280 281def NegativeOrZeroQ(u): 282 return u.is_real and u <= 0 283 284def FractionOrNegativeQ(u): 285 return FractionQ(u) or NegativeQ(u) 286 287def NegQ(var): 288 return Not(PosQ(var)) and NonzeroQ(var) 289 290 291def Equal(a, b): 292 return a == b 293 294def Unequal(a, b): 295 return a != b 296 297def IntPart(u): 298 # IntPart[u] returns the sum of the integer terms of u. 299 if ProductQ(u): 300 if IntegerQ(First(u)): 301 return First(u)*IntPart(Rest(u)) 302 elif IntegerQ(u): 303 return u 304 elif FractionQ(u): 305 return IntegerPart(u) 306 elif SumQ(u): 307 res = 0 308 for i in u.args: 309 res += IntPart(i) 310 return res 311 return 0 312 313def FracPart(u): 314 # FracPart[u] returns the sum of the non-integer terms of u. 315 if ProductQ(u): 316 if IntegerQ(First(u)): 317 return First(u)*FracPart(Rest(u)) 318 319 if IntegerQ(u): 320 return 0 321 elif FractionQ(u): 322 return FractionalPart(u) 323 elif SumQ(u): 324 res = 0 325 for i in u.args: 326 res += FracPart(i) 327 return res 328 else: 329 return u 330 331def RationalQ(*nodes): 332 return all(var.is_Rational for var in nodes) 333 334def ProductQ(expr): 335 return S(expr).is_Mul 336 337def SumQ(expr): 338 return expr.is_Add 339 340def NonsumQ(expr): 341 return not SumQ(expr) 342 343def Subst(a, x, y): 344 if None in [a, x, y]: 345 return None 346 if a.has(Function('Integrate')): 347 # substituting in `Function(Integrate)` won't take care of properties of Integral 348 a = a.replace(Function('Integrate'), Integral) 349 return a.subs(x, y) 350 # return a.xreplace({x: y}) 351 352def First(expr, d=None): 353 """ 354 Gives the first element if it exists, or d otherwise. 355 356 Examples 357 ======== 358 359 >>> from sympy.integrals.rubi.utility_function import First 360 >>> from sympy.abc import a, b, c 361 >>> First(a + b + c) 362 a 363 >>> First(a*b*c) 364 a 365 366 """ 367 if isinstance(expr, list): 368 return expr[0] 369 if isinstance(expr, Symbol): 370 return expr 371 else: 372 if SumQ(expr) or ProductQ(expr): 373 l = Sort(expr.args) 374 return l[0] 375 else: 376 return expr.args[0] 377 378def Rest(expr): 379 """ 380 Gives rest of the elements if it exists 381 382 Examples 383 ======== 384 385 >>> from sympy.integrals.rubi.utility_function import Rest 386 >>> from sympy.abc import a, b, c 387 >>> Rest(a + b + c) 388 b + c 389 >>> Rest(a*b*c) 390 b*c 391 392 """ 393 if isinstance(expr, list): 394 return expr[1:] 395 else: 396 if SumQ(expr) or ProductQ(expr): 397 l = Sort(expr.args) 398 return expr.func(*l[1:]) 399 else: 400 return expr.args[1] 401 402def SqrtNumberQ(expr): 403 # SqrtNumberQ[u] returns True if u^2 is a rational number; else it returns False. 404 if PowerQ(expr): 405 m = expr.base 406 n = expr.exp 407 return (IntegerQ(n) and SqrtNumberQ(m)) or (IntegerQ(n-S(1)/2) and RationalQ(m)) 408 elif expr.is_Mul: 409 return all(SqrtNumberQ(i) for i in expr.args) 410 else: 411 return RationalQ(expr) or expr == I 412 413def SqrtNumberSumQ(u): 414 return SumQ(u) and SqrtNumberQ(First(u)) and SqrtNumberQ(Rest(u)) or ProductQ(u) and SqrtNumberQ(First(u)) and SqrtNumberSumQ(Rest(u)) 415 416def LinearQ(expr, x): 417 """ 418 LinearQ(expr, x) returns True iff u is a polynomial of degree 1. 419 420 Examples 421 ======== 422 423 >>> from sympy.integrals.rubi.utility_function import LinearQ 424 >>> from sympy.abc import x, y, a 425 >>> LinearQ(a, x) 426 False 427 >>> LinearQ(3*x + y**2, x) 428 True 429 >>> LinearQ(3*x + y**2, y) 430 False 431 432 """ 433 if isinstance(expr, list): 434 return all(LinearQ(i, x) for i in expr) 435 elif expr.is_polynomial(x): 436 if degree(Poly(expr, x), gen=x) == 1: 437 return True 438 return False 439 440def Sqrt(a): 441 return sqrt(a) 442 443def ArcCosh(a): 444 return acosh(a) 445 446class Util_Coefficient(Function): 447 def doit(self): 448 if len(self.args) == 2: 449 n = 1 450 else: 451 n = Simplify(self.args[2]) 452 453 if NumericQ(n): 454 expr = expand(self.args[0]) 455 if isinstance(n, (int, Integer)): 456 return expr.coeff(self.args[1], n) 457 else: 458 return expr.coeff(self.args[1]**n) 459 else: 460 return self 461 462def Coefficient(expr, var, n=1): 463 """ 464 Coefficient(expr, var) gives the coefficient of form in the polynomial expr. 465 Coefficient(expr, var, n) gives the coefficient of var**n in expr. 466 467 Examples 468 ======== 469 470 >>> from sympy.integrals.rubi.utility_function import Coefficient 471 >>> from sympy.abc import x, a, b, c 472 >>> Coefficient(7 + 2*x + 4*x**3, x, 1) 473 2 474 >>> Coefficient(a + b*x + c*x**3, x, 0) 475 a 476 >>> Coefficient(a + b*x + c*x**3, x, 4) 477 0 478 >>> Coefficient(b*x + c*x**3, x, 3) 479 c 480 481 """ 482 if NumericQ(n): 483 if expr == 0 or n in (zoo, oo): 484 return 0 485 expr = expand(expr) 486 if isinstance(n, (int, Integer)): 487 return expr.coeff(var, n) 488 else: 489 return expr.coeff(var**n) 490 491 return Util_Coefficient(expr, var, n) 492 493def Denominator(var): 494 var = Simplify(var) 495 if isinstance(var, Pow): 496 if isinstance(var.exp, Integer): 497 if var.exp > 0: 498 return Pow(Denominator(var.base), var.exp) 499 elif var.exp < 0: 500 return Pow(Numerator(var.base), -1*var.exp) 501 elif isinstance(var, Add): 502 var = factor(var) 503 return fraction(var)[1] 504 505def Hypergeometric2F1(a, b, c, z): 506 return hyper([a, b], [c], z) 507 508def Not(var): 509 if isinstance(var, bool): 510 return not var 511 elif var.is_Relational: 512 var = False 513 return not var 514 515 516def FractionalPart(a): 517 return frac(a) 518 519def IntegerPart(a): 520 return floor(a) 521 522def AppellF1(a, b1, b2, c, x, y): 523 return appellf1(a, b1, b2, c, x, y) 524 525def EllipticPi(*args): 526 return elliptic_pi(*args) 527 528def EllipticE(*args): 529 return elliptic_e(*args) 530 531def EllipticF(Phi, m): 532 return elliptic_f(Phi, m) 533 534def ArcTan(a, b = None): 535 if b is None: 536 return atan(a) 537 else: 538 return atan2(a, b) 539 540def ArcCot(a): 541 return acot(a) 542 543def ArcCoth(a): 544 return acoth(a) 545 546def ArcTanh(a): 547 return atanh(a) 548 549def ArcSin(a): 550 return asin(a) 551 552def ArcSinh(a): 553 return asinh(a) 554 555def ArcCos(a): 556 return acos(a) 557 558def ArcCsc(a): 559 return acsc(a) 560 561def ArcSec(a): 562 return asec(a) 563 564def ArcCsch(a): 565 return acsch(a) 566 567def ArcSech(a): 568 return asech(a) 569 570def Sinh(u): 571 return sinh(u) 572 573def Tanh(u): 574 return tanh(u) 575 576def Cosh(u): 577 return cosh(u) 578 579def Sech(u): 580 return sech(u) 581 582def Csch(u): 583 return csch(u) 584 585def Coth(u): 586 return coth(u) 587 588def LessEqual(*args): 589 for i in range(0, len(args) - 1): 590 try: 591 if args[i] > args[i + 1]: 592 return False 593 except (IndexError, NotImplementedError): 594 return False 595 return True 596 597def Less(*args): 598 for i in range(0, len(args) - 1): 599 try: 600 if args[i] >= args[i + 1]: 601 return False 602 except (IndexError, NotImplementedError): 603 return False 604 return True 605 606def Greater(*args): 607 for i in range(0, len(args) - 1): 608 try: 609 if args[i] <= args[i + 1]: 610 return False 611 except (IndexError, NotImplementedError): 612 return False 613 return True 614 615def GreaterEqual(*args): 616 for i in range(0, len(args) - 1): 617 try: 618 if args[i] < args[i + 1]: 619 return False 620 except (IndexError, NotImplementedError): 621 return False 622 return True 623 624def FractionQ(*args): 625 """ 626 FractionQ(m, n,...) returns True if m, n, ... are all explicit fractions, else it returns False. 627 628 Examples 629 ======== 630 631 >>> from sympy import S 632 >>> from sympy.integrals.rubi.utility_function import FractionQ 633 >>> FractionQ(S('3')) 634 False 635 >>> FractionQ(S('3')/S('2')) 636 True 637 638 """ 639 return all(i.is_Rational for i in args) and all(Denominator(i) != S(1) for i in args) 640 641def IntLinearcQ(a, b, c, d, m, n, x): 642 # returns True iff (a+b*x)^m*(c+d*x)^n is integrable wrt x in terms of non-hypergeometric functions. 643 return IntegerQ(m) or IntegerQ(n) or IntegersQ(S(3)*m, S(3)*n) or IntegersQ(S(4)*m, S(4)*n) or IntegersQ(S(2)*m, S(6)*n) or IntegersQ(S(6)*m, S(2)*n) or IntegerQ(m + n) 644 645Defer = UnevaluatedExpr 646 647def Expand(expr): 648 return expr.expand() 649 650def IndependentQ(u, x): 651 """ 652 If u is free from x IndependentQ(u, x) returns True else False. 653 654 Examples 655 ======== 656 657 >>> from sympy.integrals.rubi.utility_function import IndependentQ 658 >>> from sympy.abc import x, a, b 659 >>> IndependentQ(a + b*x, x) 660 False 661 >>> IndependentQ(a + b, x) 662 True 663 664 """ 665 return FreeQ(u, x) 666 667def PowerQ(expr): 668 return expr.is_Pow or ExpQ(expr) 669 670def IntegerPowerQ(u): 671 if isinstance(u, sym_exp): #special case for exp 672 return IntegerQ(u.args[0]) 673 return PowerQ(u) and IntegerQ(u.args[1]) 674 675def PositiveIntegerPowerQ(u): 676 if isinstance(u, sym_exp): 677 return IntegerQ(u.args[0]) and PositiveQ(u.args[0]) 678 return PowerQ(u) and IntegerQ(u.args[1]) and PositiveQ(u.args[1]) 679 680def FractionalPowerQ(u): 681 if isinstance(u, sym_exp): 682 return FractionQ(u.args[0]) 683 return PowerQ(u) and FractionQ(u.args[1]) 684 685def AtomQ(expr): 686 expr = sympify(expr) 687 if isinstance(expr, list): 688 return False 689 if expr in [None, True, False, _E]: # [None, True, False] are atoms in mathematica and _E is also an atom 690 return True 691 # elif isinstance(expr, list): 692 # return all(AtomQ(i) for i in expr) 693 else: 694 return expr.is_Atom 695 696def ExpQ(u): 697 u = replace_pow_exp(u) 698 return Head(u) in (sym_exp, rubi_exp) 699 700def LogQ(u): 701 return u.func in (sym_log, Log) 702 703def Head(u): 704 return u.func 705 706def MemberQ(l, u): 707 if isinstance(l, list): 708 return u in l 709 else: 710 return u in l.args 711 712def TrigQ(u): 713 if AtomQ(u): 714 x = u 715 else: 716 x = Head(u) 717 return MemberQ([sin, cos, tan, cot, sec, csc], x) 718 719def SinQ(u): 720 return Head(u) == sin 721 722def CosQ(u): 723 return Head(u) == cos 724 725def TanQ(u): 726 return Head(u) == tan 727 728def CotQ(u): 729 return Head(u) == cot 730 731def SecQ(u): 732 return Head(u) == sec 733 734def CscQ(u): 735 return Head(u) == csc 736 737def Sin(u): 738 return sin(u) 739 740def Cos(u): 741 return cos(u) 742 743def Tan(u): 744 return tan(u) 745 746def Cot(u): 747 return cot(u) 748 749def Sec(u): 750 return sec(u) 751 752def Csc(u): 753 return csc(u) 754 755def HyperbolicQ(u): 756 if AtomQ(u): 757 x = u 758 else: 759 x = Head(u) 760 return MemberQ([sinh, cosh, tanh, coth, sech, csch], x) 761 762def SinhQ(u): 763 return Head(u) == sinh 764 765def CoshQ(u): 766 return Head(u) == cosh 767 768def TanhQ(u): 769 return Head(u) == tanh 770 771def CothQ(u): 772 return Head(u) == coth 773 774def SechQ(u): 775 return Head(u) == sech 776 777def CschQ(u): 778 return Head(u) == csch 779 780def InverseTrigQ(u): 781 if AtomQ(u): 782 x = u 783 else: 784 x = Head(u) 785 return MemberQ([asin, acos, atan, acot, asec, acsc], x) 786 787def SinCosQ(f): 788 return MemberQ([sin, cos, sec, csc], Head(f)) 789 790def SinhCoshQ(f): 791 return MemberQ([sinh, cosh, sech, csch], Head(f)) 792 793def LeafCount(expr): 794 return len(list(postorder_traversal(expr))) 795 796def Numerator(u): 797 u = Simplify(u) 798 if isinstance(u, Pow): 799 if isinstance(u.exp, Integer): 800 if u.exp > 0: 801 return Pow(Numerator(u.base), u.exp) 802 elif u.exp < 0: 803 return Pow(Denominator(u.base), -1*u.exp) 804 elif isinstance(u, Add): 805 u = factor(u) 806 return fraction(u)[0] 807 808def NumberQ(u): 809 if isinstance(u, (int, float)): 810 return True 811 return u.is_number 812 813def NumericQ(u): 814 return N(u).is_number 815 816def Length(expr): 817 """ 818 Returns number of elements in the expression just as sympy's len. 819 820 Examples 821 ======== 822 823 >>> from sympy.integrals.rubi.utility_function import Length 824 >>> from sympy.abc import x, a, b 825 >>> from sympy import cos, sin 826 >>> Length(a + b) 827 2 828 >>> Length(sin(a)*cos(a)) 829 2 830 831 """ 832 if isinstance(expr, list): 833 return len(expr) 834 return len(expr.args) 835 836def ListQ(u): 837 return isinstance(u, list) 838 839def Im(u): 840 u = S(u) 841 return im(u.doit()) 842 843def Re(u): 844 u = S(u) 845 return re(u.doit()) 846 847def InverseHyperbolicQ(u): 848 if not u.is_Atom: 849 u = Head(u) 850 return u in [acosh, asinh, atanh, acoth, acsch, acsch] 851 852def InverseFunctionQ(u): 853 # returns True if u is a call on an inverse function; else returns False. 854 return LogQ(u) or InverseTrigQ(u) and Length(u) <= 1 or InverseHyperbolicQ(u) or u.func == polylog 855 856def TrigHyperbolicFreeQ(u, x): 857 # If u is free of trig, hyperbolic and calculus functions involving x, TrigHyperbolicFreeQ[u,x] returns true; else it returns False. 858 if AtomQ(u): 859 return True 860 else: 861 if TrigQ(u) | HyperbolicQ(u) | CalculusQ(u): 862 return FreeQ(u, x) 863 else: 864 for i in u.args: 865 if not TrigHyperbolicFreeQ(i, x): 866 return False 867 return True 868 869def InverseFunctionFreeQ(u, x): 870 # If u is free of inverse, calculus and hypergeometric functions involving x, InverseFunctionFreeQ[u,x] returns true; else it returns False. 871 if AtomQ(u): 872 return True 873 else: 874 if InverseFunctionQ(u) or CalculusQ(u) or u.func == hyper or u.func == appellf1: 875 return FreeQ(u, x) 876 else: 877 for i in u.args: 878 if not ElementaryFunctionQ(i): 879 return False 880 return True 881 882def RealQ(u): 883 if ListQ(u): 884 return MapAnd(RealQ, u) 885 elif NumericQ(u): 886 return ZeroQ(Im(N(u))) 887 elif PowerQ(u): 888 u = u.base 889 v = u.exp 890 return RealQ(u) & RealQ(v) & (IntegerQ(v) | PositiveOrZeroQ(u)) 891 elif u.is_Mul: 892 return all(RealQ(i) for i in u.args) 893 elif u.is_Add: 894 return all(RealQ(i) for i in u.args) 895 elif u.is_Function: 896 f = u.func 897 u = u.args[0] 898 if f in [sin, cos, tan, cot, sec, csc, atan, acot, erf]: 899 return RealQ(u) 900 else: 901 if f in [asin, acos]: 902 return LE(-1, u, 1) 903 else: 904 if f == sym_log: 905 return PositiveOrZeroQ(u) 906 else: 907 return False 908 else: 909 return False 910 911def EqQ(u, v): 912 return ZeroQ(u - v) 913 914def FractionalPowerFreeQ(u): 915 if AtomQ(u): 916 return True 917 elif FractionalPowerQ(u): 918 return False 919 920def ComplexFreeQ(u): 921 if AtomQ(u) and Not(ComplexNumberQ(u)): 922 return True 923 else: 924 return False 925 926def PolynomialQ(u, x = None): 927 if x is None : 928 return u.is_polynomial() 929 if isinstance(x, Pow): 930 if isinstance(x.exp, Integer): 931 deg = degree(u, x.base) 932 if u.is_polynomial(x): 933 if deg % x.exp !=0 : 934 return False 935 try: 936 p = Poly(u, x.base) 937 except PolynomialError: 938 return False 939 940 c_list = p.all_coeffs() 941 coeff_list = c_list[:-1:x.exp] 942 coeff_list += [c_list[-1]] 943 for i in coeff_list: 944 if not i == 0: 945 index = c_list.index(i) 946 c_list[index] = 0 947 948 if all(i == 0 for i in c_list): 949 return True 950 else: 951 return False 952 953 else: 954 return False 955 956 elif isinstance(x.exp, (Float, Rational)): #not full - proof 957 if FreeQ(simplify(u), x.base) and Exponent(u, x.base) == 0: 958 if not all(FreeQ(u, i) for i in x.base.free_symbols): 959 return False 960 961 if isinstance(x, Mul): 962 return all(PolynomialQ(u, i) for i in x.args) 963 964 return u.is_polynomial(x) 965 966def FactorSquareFree(u): 967 return sqf(u) 968 969def PowerOfLinearQ(expr, x): 970 u = Wild('u') 971 w = Wild('w') 972 m = Wild('m') 973 n = Wild('n') 974 Match = expr.match(u**m) 975 if PolynomialQ(Match[u], x) and FreeQ(Match[m], x): 976 if IntegerQ(Match[m]): 977 e = FactorSquareFree(Match[u]).match(w**n) 978 if FreeQ(e[n], x) and LinearQ(e[w], x): 979 return True 980 else: 981 return False 982 else: 983 return LinearQ(Match[u], x) 984 else: 985 return False 986 987def Exponent(expr, x): 988 expr = Expand(S(expr)) 989 if S(expr).is_number or (not expr.has(x)): 990 return 0 991 if PolynomialQ(expr, x): 992 if isinstance(x, Rational): 993 return degree(Poly(expr, x), x) 994 return degree(expr, gen = x) 995 else: 996 return 0 997 998def ExponentList(expr, x): 999 expr = Expand(S(expr)) 1000 if S(expr).is_number or (not expr.has(x)): 1001 return [0] 1002 if expr.is_Add: 1003 expr = collect(expr, x) 1004 lst = [] 1005 k = 1 1006 for t in expr.args: 1007 if t.has(x): 1008 if isinstance(x, Rational): 1009 lst += [degree(Poly(t, x), x)] 1010 else: 1011 lst += [degree(t, gen = x)] 1012 else: 1013 if k == 1: 1014 lst += [0] 1015 k += 1 1016 lst.sort() 1017 return lst 1018 else: 1019 if isinstance(x, Rational): 1020 return [degree(Poly(expr, x), x)] 1021 else: 1022 return [degree(expr, gen = x)] 1023 1024def QuadraticQ(u, x): 1025 # QuadraticQ(u, x) returns True iff u is a polynomial of degree 2 and not a monomial of the form a x^2 1026 if ListQ(u): 1027 for expr in u: 1028 if Not(PolyQ(expr, x, 2) and Not(Coefficient(expr, x, 0) == 0 and Coefficient(expr, x, 1) == 0)): 1029 return False 1030 return True 1031 else: 1032 return PolyQ(u, x, 2) and Not(Coefficient(u, x, 0) == 0 and Coefficient(u, x, 1) == 0) 1033 1034def LinearPairQ(u, v, x): 1035 # LinearPairQ(u, v, x) returns True iff u and v are linear not equal x but u/v is a constant wrt x 1036 return LinearQ(u, x) and LinearQ(v, x) and NonzeroQ(u-x) and ZeroQ(Coefficient(u, x, 0)*Coefficient(v, x, 1)-Coefficient(u, x, 1)*Coefficient(v, x, 0)) 1037 1038def BinomialParts(u, x): 1039 if PolynomialQ(u, x): 1040 if Exponent(u, x) > 0: 1041 lst = ExponentList(u, x) 1042 if len(lst)==1: 1043 return [0, Coefficient(u, x, Exponent(u, x)), Exponent(u, x)] 1044 elif len(lst) == 2 and lst[0] == 0: 1045 return [Coefficient(u, x, 0), Coefficient(u, x, Exponent(u, x)), Exponent(u, x)] 1046 else: 1047 return False 1048 else: 1049 return False 1050 elif PowerQ(u): 1051 if u.base == x and FreeQ(u.exp, x): 1052 return [0, 1, u.exp] 1053 else: 1054 return False 1055 elif ProductQ(u): 1056 if FreeQ(First(u), x): 1057 lst2 = BinomialParts(Rest(u), x) 1058 if AtomQ(lst2): 1059 return False 1060 else: 1061 return [First(u)*lst2[0], First(u)*lst2[1], lst2[2]] 1062 elif FreeQ(Rest(u), x): 1063 lst1 = BinomialParts(First(u), x) 1064 if AtomQ(lst1): 1065 return False 1066 else: 1067 return [Rest(u)*lst1[0], Rest(u)*lst1[1], lst1[2]] 1068 lst1 = BinomialParts(First(u), x) 1069 if AtomQ(lst1): 1070 return False 1071 lst2 = BinomialParts(Rest(u), x) 1072 if AtomQ(lst2): 1073 return False 1074 a = lst1[0] 1075 b = lst1[1] 1076 m = lst1[2] 1077 c = lst2[0] 1078 d = lst2[1] 1079 n = lst2[2] 1080 if ZeroQ(a): 1081 if ZeroQ(c): 1082 return [0, b*d, m + n] 1083 elif ZeroQ(m + n): 1084 return [b*d, b*c, m] 1085 else: 1086 return False 1087 if ZeroQ(c): 1088 if ZeroQ(m + n): 1089 return [b*d, a*d, n] 1090 else: 1091 return False 1092 if EqQ(m, n) and ZeroQ(a*d + b*c): 1093 return [a*c, b*d, 2*m] 1094 else: 1095 return False 1096 elif SumQ(u): 1097 if FreeQ(First(u),x): 1098 lst2 = BinomialParts(Rest(u), x) 1099 if AtomQ(lst2): 1100 return False 1101 else: 1102 return [First(u) + lst2[0], lst2[1], lst2[2]] 1103 elif FreeQ(Rest(u), x): 1104 lst1 = BinomialParts(First(u), x) 1105 if AtomQ(lst1): 1106 return False 1107 else: 1108 return[Rest(u) + lst1[0], lst1[1], lst1[2]] 1109 lst1 = BinomialParts(First(u), x) 1110 if AtomQ(lst1): 1111 return False 1112 lst2 = BinomialParts(Rest(u),x) 1113 if AtomQ(lst2): 1114 return False 1115 if EqQ(lst1[2], lst2[2]): 1116 return [lst1[0] + lst2[0], lst1[1] + lst2[1], lst1[2]] 1117 else: 1118 return False 1119 else: 1120 return False 1121 1122def TrinomialParts(u, x): 1123 # If u is equivalent to a trinomial of the form a + b*x^n + c*x^(2*n) where n!=0, b!=0 and c!=0, TrinomialParts[u,x] returns the list {a,b,c,n}; else it returns False. 1124 u = sympify(u) 1125 if PolynomialQ(u, x): 1126 lst = CoefficientList(u, x) 1127 if len(lst)<3 or EvenQ(sympify(len(lst))) or ZeroQ((len(lst)+1)/2): 1128 return False 1129 #Catch( 1130 # Scan(Function(if ZeroQ(lst), Null, Throw(False), Drop(Drop(Drop(lst, [(len(lst)+1)/2]), 1), -1]; 1131 # [First(lst), lst[(len(lst)+1)/2], Last(lst), (len(lst)-1)/2]): 1132 if PowerQ(u): 1133 if EqQ(u.exp, 2): 1134 lst = BinomialParts(u.base, x) 1135 if not lst or ZeroQ(lst[0]): 1136 return False 1137 else: 1138 return [lst[0]**2, 2*lst[0]*lst[1], lst[1]**2, lst[2]] 1139 else: 1140 return False 1141 if ProductQ(u): 1142 if FreeQ(First(u), x): 1143 lst2 = TrinomialParts(Rest(u), x) 1144 if not lst2: 1145 return False 1146 else: 1147 return [First(u)*lst2[0], First(u)*lst2[1], First(u)*lst2[2], lst2[3]] 1148 if FreeQ(Rest(u), x): 1149 lst1 = TrinomialParts(First(u), x) 1150 if not lst1: 1151 return False 1152 else: 1153 return [Rest(u)*lst1[0], Rest(u)*lst1[1], Rest(u)*lst1[2], lst1[3]] 1154 lst1 = BinomialParts(First(u), x) 1155 if not lst1: 1156 return False 1157 lst2 = BinomialParts(Rest(u), x) 1158 if not lst2: 1159 return False 1160 a = lst1[0] 1161 b = lst1[1] 1162 m = lst1[2] 1163 c = lst2[0] 1164 d = lst2[1] 1165 n = lst2[2] 1166 if EqQ(m, n) and NonzeroQ(a*d+b*c): 1167 return [a*c, a*d + b*c, b*d, m] 1168 else: 1169 return False 1170 if SumQ(u): 1171 if FreeQ(First(u), x): 1172 lst2 = TrinomialParts(Rest(u), x) 1173 if not lst2: 1174 return False 1175 else: 1176 return [First(u)+lst2[0], lst2[1], lst2[2], lst2[3]] 1177 if FreeQ(Rest(u), x): 1178 lst1 = TrinomialParts(First(u), x) 1179 if not lst1: 1180 return False 1181 else: 1182 return [Rest(u)+lst1[0], lst1[1], lst1[2], lst1[3]] 1183 lst1 = TrinomialParts(First(u), x) 1184 if not lst1: 1185 lst3 = BinomialParts(First(u), x) 1186 if not lst3: 1187 return False 1188 lst2 = TrinomialParts(Rest(u), x) 1189 if not lst2: 1190 lst4 = BinomialParts(Rest(u), x) 1191 if not lst4: 1192 return False 1193 if EqQ(lst3[2], 2*lst4[2]): 1194 return [lst3[0]+lst4[0], lst4[1], lst3[1], lst4[2]] 1195 if EqQ(lst4[2], 2*lst3[2]): 1196 return [lst3[0]+lst4[0], lst3[1], lst4[1], lst3[2]] 1197 else: 1198 return False 1199 if EqQ(lst3[2], lst2[3]) and NonzeroQ(lst3[1]+lst2[1]): 1200 return [lst3[0]+lst2[0], lst3[1]+lst2[1], lst2[2], lst2[3]] 1201 if EqQ(lst3[2], 2*lst2[3]) and NonzeroQ(lst3[1]+lst2[2]): 1202 return [lst3[0]+lst2[0], lst2[1], lst3[1]+lst2[2], lst2[3]] 1203 else: 1204 return False 1205 lst2 = TrinomialParts(Rest(u), x) 1206 if AtomQ(lst2): 1207 lst4 = BinomialParts(Rest(u), x) 1208 if not lst4: 1209 return False 1210 if EqQ(lst4[2], lst1[3]) and NonzeroQ(lst1[1]+lst4[0]): 1211 return [lst1[0]+lst4[0], lst1[1]+lst4[1], lst1[2], lst1[3]] 1212 if EqQ(lst4[2], 2*lst1[3]) and NonzeroQ(lst1[2]+lst4[1]): 1213 return [lst1[0]+lst4[0], lst1[1], lst1[2]+lst4[1], lst1[3]] 1214 else: 1215 return False 1216 if EqQ(lst1[3], lst2[3]) and NonzeroQ(lst1[1]+lst2[1]) and NonzeroQ(lst1[2]+lst2[2]): 1217 return [lst1[0]+lst2[0], lst1[1]+lst2[1], lst1[2]+lst2[2], lst1[3]] 1218 else: 1219 return False 1220 else: 1221 return False 1222 1223def PolyQ(u, x, n=None): 1224 # returns True iff u is a polynomial of degree n. 1225 if ListQ(u): 1226 return all(PolyQ(i, x) for i in u) 1227 1228 if n is None: 1229 if u == x: 1230 return False 1231 elif isinstance(x, Pow): 1232 n = x.exp 1233 x_base = x.base 1234 if FreeQ(n, x_base): 1235 if PositiveIntegerQ(n): 1236 return PolyQ(u, x_base) and (PolynomialQ(u, x) or PolynomialQ(Together(u), x)) 1237 elif AtomQ(n): 1238 return PolynomialQ(u, x) and FreeQ(CoefficientList(u, x), x_base) 1239 else: 1240 return False 1241 1242 return PolynomialQ(u, x) or PolynomialQ(u, Together(x)) 1243 1244 else: 1245 return PolynomialQ(u, x) and Coefficient(u, x, n) != 0 and Exponent(u, x) == n 1246 1247 1248def EvenQ(u): 1249 # gives True if expr is an even integer, and False otherwise. 1250 return isinstance(u, (Integer, int)) and u%2 == 0 1251 1252def OddQ(u): 1253 # gives True if expr is an odd integer, and False otherwise. 1254 1255 return isinstance(u, (Integer, int)) and u%2 == 1 1256 1257def PerfectSquareQ(u): 1258 # (* If u is a rational number whose squareroot is rational or if u is of the form u1^n1 u2^n2 ... 1259 # and n1, n2, ... are even, PerfectSquareQ[u] returns True; else it returns False. *) 1260 if RationalQ(u): 1261 return Greater(u, 0) and RationalQ(Sqrt(u)) 1262 elif PowerQ(u): 1263 return EvenQ(u.exp) 1264 elif ProductQ(u): 1265 return PerfectSquareQ(First(u)) and PerfectSquareQ(Rest(u)) 1266 elif SumQ(u): 1267 s = Simplify(u) 1268 if NonsumQ(s): 1269 return PerfectSquareQ(s) 1270 return False 1271 else: 1272 return False 1273 1274def NiceSqrtAuxQ(u): 1275 if RationalQ(u): 1276 return u > 0 1277 elif PowerQ(u): 1278 return EvenQ(u.exp) 1279 elif ProductQ(u): 1280 return NiceSqrtAuxQ(First(u)) and NiceSqrtAuxQ(Rest(u)) 1281 elif SumQ(u): 1282 s = Simplify(u) 1283 return NonsumQ(s) and NiceSqrtAuxQ(s) 1284 else: 1285 return False 1286 1287def NiceSqrtQ(u): 1288 return Not(NegativeQ(u)) and NiceSqrtAuxQ(u) 1289 1290def Together(u): 1291 return factor(u) 1292 1293def PosAux(u): 1294 if RationalQ(u): 1295 return u>0 1296 elif NumberQ(u): 1297 if ZeroQ(Re(u)): 1298 return Im(u) > 0 1299 else: 1300 return Re(u) > 0 1301 elif NumericQ(u): 1302 v = N(u) 1303 if ZeroQ(Re(v)): 1304 return Im(v) > 0 1305 else: 1306 return Re(v) > 0 1307 elif PowerQ(u): 1308 if OddQ(u.exp): 1309 return PosAux(u.base) 1310 else: 1311 return True 1312 elif ProductQ(u): 1313 if PosAux(First(u)): 1314 return PosAux(Rest(u)) 1315 else: 1316 return not PosAux(Rest(u)) 1317 elif SumQ(u): 1318 return PosAux(First(u)) 1319 else: 1320 res = u > 0 1321 if res in(True, False): 1322 return res 1323 return True 1324 1325def PosQ(u): 1326 # If u is not 0 and has a positive form, PosQ[u] returns True, else it returns False. 1327 return PosAux(TogetherSimplify(u)) 1328 1329def CoefficientList(u, x): 1330 if PolynomialQ(u, x): 1331 return list(reversed(Poly(u, x).all_coeffs())) 1332 else: 1333 return [] 1334 1335def ReplaceAll(expr, args): 1336 if isinstance(args, list): 1337 n_args = {} 1338 for i in args: 1339 n_args.update(i) 1340 return expr.subs(n_args) 1341 return expr.subs(args) 1342 1343def ExpandLinearProduct(v, u, a, b, x): 1344 # If u is a polynomial in x, ExpandLinearProduct[v,u,a,b,x] expands v*u into a sum of terms of the form c*v*(a+b*x)^n. 1345 if FreeQ([a, b], x) and PolynomialQ(u, x): 1346 lst = CoefficientList(ReplaceAll(u, {x: (x - a)/b}), x) 1347 lst = [SimplifyTerm(i, x) for i in lst] 1348 res = 0 1349 for k in range(1, len(lst)+1): 1350 res = res + Simplify(v*lst[k-1]*(a + b*x)**(k - 1)) 1351 return res 1352 return u*v 1353 1354def GCD(*args): 1355 args = S(args) 1356 if len(args) == 1: 1357 if isinstance(args[0], (int, Integer)): 1358 return args[0] 1359 else: 1360 return S(1) 1361 return gcd(*args) 1362 1363def ContentFactor(expn): 1364 return factor_terms(expn) 1365 1366def NumericFactor(u): 1367 # returns the real numeric factor of u. 1368 if NumberQ(u): 1369 if ZeroQ(Im(u)): 1370 return u 1371 elif ZeroQ(Re(u)): 1372 return Im(u) 1373 else: 1374 return S(1) 1375 elif PowerQ(u): 1376 if RationalQ(u.base) and RationalQ(u.exp): 1377 if u.exp > 0: 1378 return 1/Denominator(u.base) 1379 else: 1380 return 1/(1/Denominator(u.base)) 1381 else: 1382 return S(1) 1383 elif ProductQ(u): 1384 return Mul(*[NumericFactor(i) for i in u.args]) 1385 elif SumQ(u): 1386 if LeafCount(u) < 50: 1387 c = ContentFactor(u) 1388 if SumQ(c): 1389 return S(1) 1390 else: 1391 return NumericFactor(c) 1392 else: 1393 m = NumericFactor(First(u)) 1394 n = NumericFactor(Rest(u)) 1395 if m < 0 and n < 0: 1396 return -GCD(-m, -n) 1397 else: 1398 return GCD(m, n) 1399 return S(1) 1400 1401def NonnumericFactors(u): 1402 if NumberQ(u): 1403 if ZeroQ(Im(u)): 1404 return S(1) 1405 elif ZeroQ(Re(u)): 1406 return I 1407 return u 1408 elif PowerQ(u): 1409 if RationalQ(u.base) and FractionQ(u.exp): 1410 return u/NumericFactor(u) 1411 return u 1412 elif ProductQ(u): 1413 result = 1 1414 for i in u.args: 1415 result *= NonnumericFactors(i) 1416 return result 1417 elif SumQ(u): 1418 if LeafCount(u) < 50: 1419 i = ContentFactor(u) 1420 if SumQ(i): 1421 return u 1422 else: 1423 return NonnumericFactors(i) 1424 n = NumericFactor(u) 1425 result = 0 1426 for i in u.args: 1427 result += i/n 1428 return result 1429 return u 1430 1431def MakeAssocList(u, x, alst=None): 1432 # (* MakeAssocList[u,x,alst] returns an association list of gensymed symbols with the nonatomic 1433 # parameters of a u that are not integer powers, products or sums. *) 1434 if alst is None: 1435 alst = [] 1436 u = replace_pow_exp(u) 1437 x = replace_pow_exp(x) 1438 if AtomQ(u): 1439 return alst 1440 elif IntegerPowerQ(u): 1441 return MakeAssocList(u.base, x, alst) 1442 elif ProductQ(u) or SumQ(u): 1443 return MakeAssocList(Rest(u), x, MakeAssocList(First(u), x, alst)) 1444 elif FreeQ(u, x): 1445 tmp = [] 1446 for i in alst: 1447 if PowerQ(i): 1448 if i.exp == u: 1449 tmp.append(i) 1450 break 1451 elif len(i.args) > 1: # make sure args has length > 1, else causes index error some times 1452 if i.args[1] == u: 1453 tmp.append(i) 1454 break 1455 if tmp == []: 1456 alst.append(u) 1457 return alst 1458 return alst 1459 1460def GensymSubst(u, x, alst=None): 1461 # (* GensymSubst[u,x,alst] returns u with the kernels in alst free of x replaced by gensymed names. *) 1462 if alst is None: 1463 alst =[] 1464 u = replace_pow_exp(u) 1465 x = replace_pow_exp(x) 1466 if AtomQ(u): 1467 return u 1468 elif IntegerPowerQ(u): 1469 return GensymSubst(u.base, x, alst)**u.exp 1470 elif ProductQ(u) or SumQ(u): 1471 return u.func(*[GensymSubst(i, x, alst) for i in u.args]) 1472 elif FreeQ(u, x): 1473 tmp = [] 1474 for i in alst: 1475 if PowerQ(i): 1476 if i.exp == u: 1477 tmp.append(i) 1478 break 1479 1480 elif len(i.args) > 1: # make sure args has length > 1, else causes index error some times 1481 if i.args[1] == u: 1482 tmp.append(i) 1483 break 1484 if tmp == []: 1485 return u 1486 return tmp[0][0] 1487 return u 1488 1489def KernelSubst(u, x, alst): 1490 # (* KernelSubst[u,x,alst] returns u with the gensymed names in alst replaced by kernels free of x. *) 1491 if AtomQ(u): 1492 tmp = [] 1493 for i in alst: 1494 if i.args[0] == u: 1495 tmp.append(i) 1496 break 1497 if tmp == []: 1498 return u 1499 elif len(tmp[0].args) > 1: # make sure args has length > 1, else causes index error some times 1500 return tmp[0].args[1] 1501 1502 elif IntegerPowerQ(u): 1503 tmp = KernelSubst(u.base, x, alst) 1504 if u.exp < 0 and ZeroQ(tmp): 1505 return 'Indeterminate' 1506 return tmp**u.exp 1507 elif ProductQ(u) or SumQ(u): 1508 return u.func(*[KernelSubst(i, x, alst) for i in u.args]) 1509 return u 1510 1511def ExpandExpression(u, x): 1512 if AlgebraicFunctionQ(u, x) and Not(RationalFunctionQ(u, x)): 1513 v = ExpandAlgebraicFunction(u, x) 1514 else: 1515 v = S(0) 1516 if SumQ(v): 1517 return ExpandCleanup(v, x) 1518 v = SmartApart(u, x) 1519 if SumQ(v): 1520 return ExpandCleanup(v, x) 1521 v = SmartApart(RationalFunctionFactors(u, x), x, x) 1522 if SumQ(v): 1523 w = NonrationalFunctionFactors(u, x) 1524 return ExpandCleanup(v.func(*[i*w for i in v.args]), x) 1525 v = Expand(u) 1526 if SumQ(v): 1527 return ExpandCleanup(v, x) 1528 v = Expand(u) 1529 if SumQ(v): 1530 return ExpandCleanup(v, x) 1531 return SimplifyTerm(u, x) 1532 1533def Apart(u, x): 1534 if RationalFunctionQ(u, x): 1535 return apart(u, x) 1536 1537 return u 1538 1539def SmartApart(*args): 1540 if len(args) == 2: 1541 u, x = args 1542 alst = MakeAssocList(u, x) 1543 tmp = KernelSubst(Apart(GensymSubst(u, x, alst), x), x, alst) 1544 if tmp == 'Indeterminate': 1545 return u 1546 return tmp 1547 1548 u, v, x = args 1549 alst = MakeAssocList(u, x) 1550 tmp = KernelSubst(Apart(GensymSubst(u, x, alst), x), x, alst) 1551 if tmp == 'Indeterminate': 1552 return u 1553 return tmp 1554 1555def MatchQ(expr, pattern, *var): 1556 # returns the matched arguments after matching pattern with expression 1557 match = expr.match(pattern) 1558 if match: 1559 return tuple(match[i] for i in var) 1560 else: 1561 return None 1562 1563def PolynomialQuotientRemainder(p, q, x): 1564 return [PolynomialQuotient(p, q, x), PolynomialRemainder(p, q, x)] 1565 1566def FreeFactors(u, x): 1567 # returns the product of the factors of u free of x. 1568 if ProductQ(u): 1569 result = 1 1570 for i in u.args: 1571 if FreeQ(i, x): 1572 result *= i 1573 return result 1574 elif FreeQ(u, x): 1575 return u 1576 else: 1577 return S(1) 1578 1579def NonfreeFactors(u, x): 1580 """ 1581 Returns the product of the factors of u not free of x. 1582 1583 Examples 1584 ======== 1585 1586 >>> from sympy.integrals.rubi.utility_function import NonfreeFactors 1587 >>> from sympy.abc import x, a, b 1588 >>> NonfreeFactors(a, x) 1589 1 1590 >>> NonfreeFactors(x + a, x) 1591 a + x 1592 >>> NonfreeFactors(a*b*x, x) 1593 x 1594 1595 """ 1596 if ProductQ(u): 1597 result = 1 1598 for i in u.args: 1599 if not FreeQ(i, x): 1600 result *= i 1601 return result 1602 elif FreeQ(u, x): 1603 return 1 1604 else: 1605 return u 1606 1607def RemoveContentAux(expr, x): 1608 return RemoveContentAux_replacer.replace(UtilityOperator(expr, x)) 1609 1610def RemoveContent(u, x): 1611 v = NonfreeFactors(u, x) 1612 w = Together(v) 1613 1614 if EqQ(FreeFactors(w, x), 1): 1615 return RemoveContentAux(v, x) 1616 else: 1617 return RemoveContentAux(NonfreeFactors(w, x), x) 1618 1619 1620def FreeTerms(u, x): 1621 """ 1622 Returns the sum of the terms of u free of x. 1623 1624 Examples 1625 ======== 1626 1627 >>> from sympy.integrals.rubi.utility_function import FreeTerms 1628 >>> from sympy.abc import x, a, b 1629 >>> FreeTerms(a, x) 1630 a 1631 >>> FreeTerms(x*a, x) 1632 0 1633 >>> FreeTerms(a*x + b, x) 1634 b 1635 1636 """ 1637 if SumQ(u): 1638 result = 0 1639 for i in u.args: 1640 if FreeQ(i, x): 1641 result += i 1642 return result 1643 elif FreeQ(u, x): 1644 return u 1645 else: 1646 return 0 1647 1648def NonfreeTerms(u, x): 1649 # returns the sum of the terms of u free of x. 1650 if SumQ(u): 1651 result = S(0) 1652 for i in u.args: 1653 if not FreeQ(i, x): 1654 result += i 1655 return result 1656 elif not FreeQ(u, x): 1657 return u 1658 else: 1659 return S(0) 1660 1661def ExpandAlgebraicFunction(expr, x): 1662 if ProductQ(expr): 1663 u_ = Wild('u', exclude=[x]) 1664 n_ = Wild('n', exclude=[x]) 1665 v_ = Wild('v') 1666 pattern = u_*v_ 1667 match = expr.match(pattern) 1668 if match: 1669 keys = [u_, v_] 1670 if len(keys) == len(match): 1671 u, v = tuple([match[i] for i in keys]) 1672 if SumQ(v): 1673 u, v = v, u 1674 if not FreeQ(u, x) and SumQ(u): 1675 result = 0 1676 for i in u.args: 1677 result += i*v 1678 return result 1679 1680 pattern = u_**n_*v_ 1681 match = expr.match(pattern) 1682 if match: 1683 keys = [u_, n_, v_] 1684 if len(keys) == len(match): 1685 u, n, v = tuple([match[i] for i in keys]) 1686 if PositiveIntegerQ(n) and SumQ(u): 1687 w = Expand(u**n) 1688 result = 0 1689 for i in w.args: 1690 result += i*v 1691 return result 1692 1693 return expr 1694 1695def CollectReciprocals(expr, x): 1696 # Basis: e/(a+b x)+f/(c+d x)==(c e+a f+(d e+b f) x)/(a c+(b c+a d) x+b d x^2) 1697 if SumQ(expr): 1698 u_ = Wild('u') 1699 a_ = Wild('a', exclude=[x]) 1700 b_ = Wild('b', exclude=[x]) 1701 c_ = Wild('c', exclude=[x]) 1702 d_ = Wild('d', exclude=[x]) 1703 e_ = Wild('e', exclude=[x]) 1704 f_ = Wild('f', exclude=[x]) 1705 pattern = u_ + e_/(a_ + b_*x) + f_/(c_+d_*x) 1706 match = expr.match(pattern) 1707 if match: 1708 try: # .match() does not work peoperly always 1709 keys = [u_, a_, b_, c_, d_, e_, f_] 1710 u, a, b, c, d, e, f = tuple([match[i] for i in keys]) 1711 if ZeroQ(b*c + a*d) & ZeroQ(d*e + b*f): 1712 return CollectReciprocals(u + (c*e + a*f)/(a*c + b*d*x**2),x) 1713 elif ZeroQ(b*c + a*d) & ZeroQ(c*e + a*f): 1714 return CollectReciprocals(u + (d*e + b*f)*x/(a*c + b*d*x**2),x) 1715 except: 1716 pass 1717 return expr 1718 1719def ExpandCleanup(u, x): 1720 v = CollectReciprocals(u, x) 1721 if SumQ(v): 1722 res = 0 1723 for i in v.args: 1724 res += SimplifyTerm(i, x) 1725 v = res 1726 if SumQ(v): 1727 return UnifySum(v, x) 1728 else: 1729 return v 1730 else: 1731 return v 1732 1733def AlgebraicFunctionQ(u, x, flag=False): 1734 if ListQ(u): 1735 if u == []: 1736 return True 1737 elif AlgebraicFunctionQ(First(u), x, flag): 1738 return AlgebraicFunctionQ(Rest(u), x, flag) 1739 else: 1740 return False 1741 1742 elif AtomQ(u) or FreeQ(u, x): 1743 return True 1744 elif PowerQ(u): 1745 if RationalQ(u.exp) | flag & FreeQ(u.exp, x): 1746 return AlgebraicFunctionQ(u.base, x, flag) 1747 elif ProductQ(u) | SumQ(u): 1748 for i in u.args: 1749 if not AlgebraicFunctionQ(i, x, flag): 1750 return False 1751 return True 1752 1753 return False 1754 1755def Coeff(expr, form, n=1): 1756 if n == 1: 1757 return Coefficient(Together(expr), form, n) 1758 else: 1759 coef1 = Coefficient(expr, form, n) 1760 coef2 = Coefficient(Together(expr), form, n) 1761 if Simplify(coef1 - coef2) == 0: 1762 return coef1 1763 else: 1764 return coef2 1765 1766def LeadTerm(u): 1767 if SumQ(u): 1768 return First(u) 1769 return u 1770 1771def RemainingTerms(u): 1772 if SumQ(u): 1773 return Rest(u) 1774 return u 1775 1776def LeadFactor(u): 1777 # returns the leading factor of u. 1778 if ComplexNumberQ(u) and Re(u) == 0: 1779 if Im(u) == S(1): 1780 return u 1781 else: 1782 return LeadFactor(Im(u)) 1783 elif ProductQ(u): 1784 return LeadFactor(First(u)) 1785 return u 1786 1787def RemainingFactors(u): 1788 # returns the remaining factors of u. 1789 if ComplexNumberQ(u) and Re(u) == 0: 1790 if Im(u) == 1: 1791 return S(1) 1792 else: 1793 return I*RemainingFactors(Im(u)) 1794 elif ProductQ(u): 1795 return RemainingFactors(First(u))*Rest(u) 1796 return S(1) 1797 1798def LeadBase(u): 1799 """ 1800 returns the base of the leading factor of u. 1801 1802 Examples 1803 ======== 1804 1805 >>> from sympy.integrals.rubi.utility_function import LeadBase 1806 >>> from sympy.abc import a, b, c 1807 >>> LeadBase(a**b) 1808 a 1809 >>> LeadBase(a**b*c) 1810 a 1811 """ 1812 v = LeadFactor(u) 1813 if PowerQ(v): 1814 return v.base 1815 return v 1816 1817def LeadDegree(u): 1818 # returns the degree of the leading factor of u. 1819 v = LeadFactor(u) 1820 if PowerQ(v): 1821 return v.exp 1822 return v 1823 1824def Numer(expr): 1825 # returns the numerator of u. 1826 if PowerQ(expr): 1827 if expr.exp < 0: 1828 return 1 1829 if ProductQ(expr): 1830 return Mul(*[Numer(i) for i in expr.args]) 1831 return Numerator(expr) 1832 1833def Denom(u): 1834 # returns the denominator of u 1835 if PowerQ(u): 1836 if u.exp < 0: 1837 return u.args[0]**(-u.args[1]) 1838 elif ProductQ(u): 1839 return Mul(*[Denom(i) for i in u.args]) 1840 return Denominator(u) 1841 1842def hypergeom(n, d, z): 1843 return hyper(n, d, z) 1844 1845def Expon(expr, form): 1846 return Exponent(Together(expr), form) 1847 1848def MergeMonomials(expr, x): 1849 u_ = Wild('u') 1850 p_ = Wild('p', exclude=[x, 1, 0]) 1851 a_ = Wild('a', exclude=[x]) 1852 b_ = Wild('b', exclude=[x, 0]) 1853 c_ = Wild('c', exclude=[x]) 1854 d_ = Wild('d', exclude=[x, 0]) 1855 n_ = Wild('n', exclude=[x]) 1856 m_ = Wild('m', exclude=[x]) 1857 1858 # Basis: If m/n\[Element]\[DoubleStruckCapitalZ], then z^m (c z^n)^p==(c z^n)^(m/n+p)/c^(m/n) 1859 pattern = u_*(a_ + b_*x)**m_*(c_*(a_ + b_*x)**n_)**p_ 1860 match = expr.match(pattern) 1861 if match: 1862 keys = [u_, a_, b_, m_, c_, n_, p_] 1863 if len(keys) == len(match): 1864 u, a, b, m, c, n, p = tuple([match[i] for i in keys]) 1865 if IntegerQ(m/n): 1866 if u*(c*(a + b*x)**n)**(m/n + p)/c**(m/n) is S.NaN: 1867 return expr 1868 else: 1869 return u*(c*(a + b*x)**n)**(m/n + p)/c**(m/n) 1870 1871 1872 # Basis: If m\[Element]\[DoubleStruckCapitalZ] \[And] b c-a d==0, then (a+b z)^m==b^m/d^m (c+d z)^m 1873 pattern = u_*(a_ + b_*x)**m_*(c_ + d_*x)**n_ 1874 match = expr.match(pattern) 1875 if match: 1876 keys = [u_, a_, b_, m_, c_, d_, n_] 1877 if len(keys) == len(match): 1878 u, a, b, m, c, d, n = tuple([match[i] for i in keys]) 1879 if IntegerQ(m) and ZeroQ(b*c - a*d): 1880 if u*b**m/d**m*(c + d*x)**(m + n) is S.NaN: 1881 return expr 1882 else: 1883 return u*b**m/d**m*(c + d*x)**(m + n) 1884 return expr 1885 1886def PolynomialDivide(u, v, x): 1887 1888 1889 quo = PolynomialQuotient(u, v, x) 1890 rem = PolynomialRemainder(u, v, x) 1891 s = 0 1892 for i in ExponentList(quo, x): 1893 s += Simp(Together(Coefficient(quo, x, i)*x**i), x) 1894 quo = s 1895 rem = Together(rem) 1896 free = FreeFactors(rem, x) 1897 rem = NonfreeFactors(rem, x) 1898 monomial = x**Min(ExponentList(rem, x)) 1899 if NegQ(Coefficient(rem, x, 0)): 1900 monomial = -monomial 1901 s = 0 1902 for i in ExponentList(rem, x): 1903 s += Simp(Together(Coefficient(rem, x, i)*x**i/monomial), x) 1904 rem = s 1905 if BinomialQ(v, x): 1906 return quo + free*monomial*rem/ExpandToSum(v, x) 1907 else: 1908 return quo + free*monomial*rem/v 1909 1910 1911 1912def BinomialQ(u, x, n=None): 1913 """ 1914 If u is equivalent to an expression of the form a + b*x**n, BinomialQ(u, x, n) returns True, else it returns False. 1915 1916 Examples 1917 ======== 1918 1919 >>> from sympy.integrals.rubi.utility_function import BinomialQ 1920 >>> from sympy.abc import x 1921 >>> BinomialQ(x**9, x) 1922 True 1923 >>> BinomialQ((1 + x)**3, x) 1924 False 1925 1926 """ 1927 if ListQ(u): 1928 for i in u: 1929 if Not(BinomialQ(i, x, n)): 1930 return False 1931 return True 1932 elif NumberQ(x): 1933 return False 1934 return ListQ(BinomialParts(u, x)) 1935 1936def TrinomialQ(u, x): 1937 """ 1938 If u is equivalent to an expression of the form a + b*x**n + c*x**(2*n) where n, b and c are not 0, 1939 TrinomialQ(u, x) returns True, else it returns False. 1940 1941 Examples 1942 ======== 1943 1944 >>> from sympy.integrals.rubi.utility_function import TrinomialQ 1945 >>> from sympy.abc import x 1946 >>> TrinomialQ((7 + 2*x**6 + 3*x**12), x) 1947 True 1948 >>> TrinomialQ(x**2, x) 1949 False 1950 1951 """ 1952 if ListQ(u): 1953 for i in u.args: 1954 if Not(TrinomialQ(i, x)): 1955 return False 1956 return True 1957 1958 check = False 1959 u = replace_pow_exp(u) 1960 if PowerQ(u): 1961 if u.exp == 2 and BinomialQ(u.base, x): 1962 check = True 1963 1964 return ListQ(TrinomialParts(u,x)) and Not(QuadraticQ(u, x)) and Not(check) 1965 1966def GeneralizedBinomialQ(u, x): 1967 """ 1968 If u is equivalent to an expression of the form a*x**q+b*x**n where n, q and b are not 0, 1969 GeneralizedBinomialQ(u, x) returns True, else it returns False. 1970 1971 Examples 1972 ======== 1973 1974 >>> from sympy.integrals.rubi.utility_function import GeneralizedBinomialQ 1975 >>> from sympy.abc import a, x, q, b, n 1976 >>> GeneralizedBinomialQ(a*x**q, x) 1977 False 1978 1979 """ 1980 if ListQ(u): 1981 return all(GeneralizedBinomialQ(i, x) for i in u) 1982 return ListQ(GeneralizedBinomialParts(u, x)) 1983 1984def GeneralizedTrinomialQ(u, x): 1985 """ 1986 If u is equivalent to an expression of the form a*x**q+b*x**n+c*x**(2*n-q) where n, q, b and c are not 0, 1987 GeneralizedTrinomialQ(u, x) returns True, else it returns False. 1988 1989 Examples 1990 ======== 1991 1992 >>> from sympy.integrals.rubi.utility_function import GeneralizedTrinomialQ 1993 >>> from sympy.abc import x 1994 >>> GeneralizedTrinomialQ(7 + 2*x**6 + 3*x**12, x) 1995 False 1996 1997 """ 1998 if ListQ(u): 1999 return all(GeneralizedTrinomialQ(i, x) for i in u) 2000 return ListQ(GeneralizedTrinomialParts(u, x)) 2001 2002def FactorSquareFreeList(poly): 2003 r = sqf_list(poly) 2004 result = [[1, 1]] 2005 for i in r[1]: 2006 result.append(list(i)) 2007 return result 2008 2009def PerfectPowerTest(u, x): 2010 # If u (x) is equivalent to a polynomial raised to an integer power greater than 1, 2011 # PerfectPowerTest[u,x] returns u (x) as an expanded polynomial raised to the power; 2012 # else it returns False. 2013 if PolynomialQ(u, x): 2014 lst = FactorSquareFreeList(u) 2015 gcd = 0 2016 v = 1 2017 if lst[0] == [1, 1]: 2018 lst = Rest(lst) 2019 for i in lst: 2020 gcd = GCD(gcd, i[1]) 2021 if gcd > 1: 2022 for i in lst: 2023 v = v*i[0]**(i[1]/gcd) 2024 return Expand(v)**gcd 2025 else: 2026 return False 2027 return False 2028 2029def SquareFreeFactorTest(u, x): 2030 # If u (x) can be square free factored, SquareFreeFactorTest[u,x] returns u (x) in 2031 # factored form; else it returns False. 2032 if PolynomialQ(u, x): 2033 v = FactorSquareFree(u) 2034 if PowerQ(v) or ProductQ(v): 2035 return v 2036 return False 2037 return False 2038 2039def RationalFunctionQ(u, x): 2040 # If u is a rational function of x, RationalFunctionQ[u,x] returns True; else it returns False. 2041 if AtomQ(u) or FreeQ(u, x): 2042 return True 2043 elif IntegerPowerQ(u): 2044 return RationalFunctionQ(u.base, x) 2045 elif ProductQ(u) or SumQ(u): 2046 for i in u.args: 2047 if Not(RationalFunctionQ(i, x)): 2048 return False 2049 return True 2050 return False 2051 2052def RationalFunctionFactors(u, x): 2053 # RationalFunctionFactors[u,x] returns the product of the factors of u that are rational functions of x. 2054 if ProductQ(u): 2055 res = 1 2056 for i in u.args: 2057 if RationalFunctionQ(i, x): 2058 res *= i 2059 return res 2060 elif RationalFunctionQ(u, x): 2061 return u 2062 return S(1) 2063 2064def NonrationalFunctionFactors(u, x): 2065 if ProductQ(u): 2066 res = 1 2067 for i in u.args: 2068 if not RationalFunctionQ(i, x): 2069 res *= i 2070 return res 2071 elif RationalFunctionQ(u, x): 2072 return S(1) 2073 return u 2074 2075def Reverse(u): 2076 if isinstance(u, list): 2077 return list(reversed(u)) 2078 else: 2079 l = list(u.args) 2080 return u.func(*list(reversed(l))) 2081 2082def RationalFunctionExponents(u, x): 2083 """ 2084 u is a polynomial or rational function of x. 2085 RationalFunctionExponents(u, x) returns a list of the exponent of the 2086 numerator of u and the exponent of the denominator of u. 2087 2088 Examples 2089 ======== 2090 >>> from sympy.integrals.rubi.utility_function import RationalFunctionExponents 2091 >>> from sympy.abc import x, a 2092 >>> RationalFunctionExponents(x, x) 2093 [1, 0] 2094 >>> RationalFunctionExponents(x**(-1), x) 2095 [0, 1] 2096 >>> RationalFunctionExponents(x**(-1)*a, x) 2097 [0, 1] 2098 2099 """ 2100 if PolynomialQ(u, x): 2101 return [Exponent(u, x), 0] 2102 elif IntegerPowerQ(u): 2103 if PositiveQ(u.exp): 2104 return u.exp*RationalFunctionExponents(u.base, x) 2105 return (-u.exp)*Reverse(RationalFunctionExponents(u.base, x)) 2106 elif ProductQ(u): 2107 lst1 = RationalFunctionExponents(First(u), x) 2108 lst2 = RationalFunctionExponents(Rest(u), x) 2109 return [lst1[0] + lst2[0], lst1[1] + lst2[1]] 2110 elif SumQ(u): 2111 v = Together(u) 2112 if SumQ(v): 2113 lst1 = RationalFunctionExponents(First(u), x) 2114 lst2 = RationalFunctionExponents(Rest(u), x) 2115 return [Max(lst1[0] + lst2[1], lst2[0] + lst1[1]), lst1[1] + lst2[1]] 2116 else: 2117 return RationalFunctionExponents(v, x) 2118 return [0, 0] 2119 2120def RationalFunctionExpand(expr, x): 2121 # expr is a polynomial or rational function of x. 2122 # RationalFunctionExpand[u,x] returns the expansion of the factors of u that are rational functions times the other factors. 2123 def cons_f1(n): 2124 return FractionQ(n) 2125 cons1 = CustomConstraint(cons_f1) 2126 2127 def cons_f2(x, v): 2128 if not isinstance(x, Symbol): 2129 return False 2130 return UnsameQ(v, x) 2131 cons2 = CustomConstraint(cons_f2) 2132 2133 def With1(n, u, x, v): 2134 w = RationalFunctionExpand(u, x) 2135 return If(SumQ(w), Add(*[i*v**n for i in w.args]), v**n*w) 2136 pattern1 = Pattern(UtilityOperator(u_*v_**n_, x_), cons1, cons2) 2137 rule1 = ReplacementRule(pattern1, With1) 2138 def With2(u, x): 2139 v = ExpandIntegrand(u, x) 2140 2141 def _consf_u(a, b, c, d, p, m, n, x): 2142 return And(FreeQ(List(a, b, c, d, p), x), IntegersQ(m, n), Equal(m, Add(n, S(-1)))) 2143 cons_u = CustomConstraint(_consf_u) 2144 pat = Pattern(UtilityOperator(x_**WC('m', S(1))*(x_*WC('d', S(1)) + c_)**p_/(x_**n_*WC('b', S(1)) + a_), x_), cons_u) 2145 result_matchq = is_match(UtilityOperator(u, x), pat) 2146 if UnsameQ(v, u) and not result_matchq: 2147 return v 2148 else: 2149 v = ExpandIntegrand(RationalFunctionFactors(u, x), x) 2150 w = NonrationalFunctionFactors(u, x) 2151 if SumQ(v): 2152 return Add(*[i*w for i in v.args]) 2153 else: 2154 return v*w 2155 pattern2 = Pattern(UtilityOperator(u_, x_)) 2156 rule2 = ReplacementRule(pattern2, With2) 2157 expr = expr.replace(sym_exp, rubi_exp) 2158 res = replace_all(UtilityOperator(expr, x), [rule1, rule2]) 2159 return replace_pow_exp(res) 2160 2161 2162def ExpandIntegrand(expr, x, extra=None): 2163 expr = replace_pow_exp(expr) 2164 if not extra is None: 2165 extra, x = x, extra 2166 w = ExpandIntegrand(extra, x) 2167 r = NonfreeTerms(w, x) 2168 if SumQ(r): 2169 result = [expr*FreeTerms(w, x)] 2170 for i in r.args: 2171 result.append(MergeMonomials(expr*i, x)) 2172 return r.func(*result) 2173 else: 2174 return expr*FreeTerms(w, x) + MergeMonomials(expr*r, x) 2175 2176 else: 2177 u_ = Wild('u', exclude=[0, 1]) 2178 a_ = Wild('a', exclude=[x]) 2179 b_ = Wild('b', exclude=[x, 0]) 2180 F_ = Wild('F', exclude=[0]) 2181 c_ = Wild('c', exclude=[x]) 2182 d_ = Wild('d', exclude=[x, 0]) 2183 n_ = Wild('n', exclude=[0, 1]) 2184 pattern = u_*(a_ + b_*F_)**n_ 2185 match = expr.match(pattern) 2186 if match: 2187 if MemberQ([asin, acos, asinh, acosh], match[F_].func): 2188 keys = [u_, a_, b_, F_, n_] 2189 if len(match) == len(keys): 2190 u, a, b, F, n = tuple([match[i] for i in keys]) 2191 match = F.args[0].match(c_ + d_*x) 2192 if match: 2193 keys = c_, d_ 2194 if len(keys) == len(match): 2195 c, d = tuple([match[i] for i in keys]) 2196 if PolynomialQ(u, x): 2197 F = F.func 2198 return ExpandLinearProduct((a + b*F(c + d*x))**n, u, c, d, x) 2199 2200 expr = expr.replace(sym_exp, rubi_exp) 2201 res = replace_all(UtilityOperator(expr, x), ExpandIntegrand_rules, max_count = 1) 2202 return replace_pow_exp(res) 2203 2204 2205def SimplerQ(u, v): 2206 # If u is simpler than v, SimplerQ(u, v) returns True, else it returns False. SimplerQ(u, u) returns False 2207 if IntegerQ(u): 2208 if IntegerQ(v): 2209 if Abs(u)==Abs(v): 2210 return v<0 2211 else: 2212 return Abs(u)<Abs(v) 2213 else: 2214 return True 2215 elif IntegerQ(v): 2216 return False 2217 elif FractionQ(u): 2218 if FractionQ(v): 2219 if Denominator(u) == Denominator(v): 2220 return SimplerQ(Numerator(u), Numerator(v)) 2221 else: 2222 return Denominator(u)<Denominator(v) 2223 else: 2224 return True 2225 elif FractionQ(v): 2226 return False 2227 elif (Re(u)==0 or Re(u) == 0) and (Re(v)==0 or Re(v) == 0): 2228 return SimplerQ(Im(u), Im(v)) 2229 elif ComplexNumberQ(u): 2230 if ComplexNumberQ(v): 2231 if Re(u) == Re(v): 2232 return SimplerQ(Im(u), Im(v)) 2233 else: 2234 return SimplerQ(Re(u),Re(v)) 2235 else: 2236 return False 2237 elif NumberQ(u): 2238 if NumberQ(v): 2239 return OrderedQ([u,v]) 2240 else: 2241 return True 2242 elif NumberQ(v): 2243 return False 2244 elif AtomQ(u) or (Head(u) == re) or (Head(u) == im): 2245 if AtomQ(v) or (Head(u) == re) or (Head(u) == im): 2246 return OrderedQ([u,v]) 2247 else: 2248 return True 2249 elif AtomQ(v) or (Head(u) == re) or (Head(u) == im): 2250 return False 2251 elif Head(u) == Head(v): 2252 if Length(u) == Length(v): 2253 for i in range(len(u.args)): 2254 if not u.args[i] == v.args[i]: 2255 return SimplerQ(u.args[i], v.args[i]) 2256 return False 2257 return Length(u) < Length(v) 2258 elif LeafCount(u) < LeafCount(v): 2259 return True 2260 elif LeafCount(v) < LeafCount(u): 2261 return False 2262 return Not(OrderedQ([v,u])) 2263 2264def SimplerSqrtQ(u, v): 2265 # If Rt(u, 2) is simpler than Rt(v, 2), SimplerSqrtQ(u, v) returns True, else it returns False. SimplerSqrtQ(u, u) returns False 2266 if NegativeQ(v) and Not(NegativeQ(u)): 2267 return True 2268 if NegativeQ(u) and Not(NegativeQ(v)): 2269 return False 2270 sqrtu = Rt(u, S(2)) 2271 sqrtv = Rt(v, S(2)) 2272 if IntegerQ(sqrtu): 2273 if IntegerQ(sqrtv): 2274 return sqrtu<sqrtv 2275 else: 2276 return True 2277 if IntegerQ(sqrtv): 2278 return False 2279 if RationalQ(sqrtu): 2280 if RationalQ(sqrtv): 2281 return sqrtu<sqrtv 2282 else: 2283 return True 2284 if RationalQ(sqrtv): 2285 return False 2286 if PosQ(u): 2287 if PosQ(v): 2288 return LeafCount(sqrtu)<LeafCount(sqrtv) 2289 else: 2290 return True 2291 if PosQ(v): 2292 return False 2293 if LeafCount(sqrtu)<LeafCount(sqrtv): 2294 return True 2295 if LeafCount(sqrtv)<LeafCount(sqrtu): 2296 return False 2297 else: 2298 return Not(OrderedQ([v, u])) 2299 2300def SumSimplerQ(u, v): 2301 """ 2302 If u + v is simpler than u, SumSimplerQ(u, v) returns True, else it returns False. 2303 If for every term w of v there is a term of u equal to n*w where n<-1/2, u + v will be simpler than u. 2304 2305 Examples 2306 ======== 2307 2308 >>> from sympy.integrals.rubi.utility_function import SumSimplerQ 2309 >>> from sympy.abc import x 2310 >>> from sympy import S 2311 >>> SumSimplerQ(S(4 + x),S(3 + x**3)) 2312 False 2313 2314 """ 2315 if RationalQ(u, v): 2316 if v == S(0): 2317 return False 2318 elif v > S(0): 2319 return u < -S(1) 2320 else: 2321 return u >= -v 2322 else: 2323 return SumSimplerAuxQ(Expand(u), Expand(v)) 2324 2325def BinomialDegree(u, x): 2326 # if u is a binomial. BinomialDegree[u,x] returns the degree of x in u. 2327 bp = BinomialParts(u, x) 2328 if bp == False: 2329 return bp 2330 return bp[2] 2331 2332def TrinomialDegree(u, x): 2333 # If u is equivalent to a trinomial of the form a + b*x^n + c*x^(2*n) where n!=0, b!=0 and c!=0, TrinomialDegree[u,x] returns n 2334 t = TrinomialParts(u, x) 2335 if t: 2336 return t[3] 2337 return t 2338 2339def CancelCommonFactors(u, v): 2340 def _delete_cases(a, b): 2341 # only for CancelCommonFactors 2342 lst = [] 2343 deleted = False 2344 for i in a.args: 2345 if i == b and not deleted: 2346 deleted = True 2347 continue 2348 lst.append(i) 2349 return a.func(*lst) 2350 2351 # CancelCommonFactors[u,v] returns {u',v'} are the noncommon factors of u and v respectively. 2352 if ProductQ(u): 2353 if ProductQ(v): 2354 if MemberQ(v, First(u)): 2355 return CancelCommonFactors(Rest(u), _delete_cases(v, First(u))) 2356 else: 2357 lst = CancelCommonFactors(Rest(u), v) 2358 return [First(u)*lst[0], lst[1]] 2359 else: 2360 if MemberQ(u, v): 2361 return [_delete_cases(u, v), 1] 2362 else: 2363 return[u, v] 2364 elif ProductQ(v): 2365 if MemberQ(v, u): 2366 return [1, _delete_cases(v, u)] 2367 else: 2368 return [u, v] 2369 return[u, v] 2370 2371def SimplerIntegrandQ(u, v, x): 2372 lst = CancelCommonFactors(u, v) 2373 u1 = lst[0] 2374 v1 = lst[1] 2375 if Head(u1) == Head(v1) and Length(u1) == 1 and Length(v1) == 1: 2376 return SimplerIntegrandQ(u1.args[0], v1.args[0], x) 2377 if 4*LeafCount(u1) < 3*LeafCount(v1): 2378 return True 2379 if RationalFunctionQ(u1, x): 2380 if RationalFunctionQ(v1, x): 2381 t1 = 0 2382 t2 = 0 2383 for i in RationalFunctionExponents(u1, x): 2384 t1 += i 2385 for i in RationalFunctionExponents(v1, x): 2386 t2 += i 2387 return t1 < t2 2388 else: 2389 return True 2390 else: 2391 return False 2392 2393def GeneralizedBinomialDegree(u, x): 2394 b = GeneralizedBinomialParts(u, x) 2395 if b: 2396 return b[2] - b[3] 2397 2398def GeneralizedBinomialParts(expr, x): 2399 expr = Expand(expr) 2400 if GeneralizedBinomialMatchQ(expr, x): 2401 a = Wild('a', exclude=[x]) 2402 b = Wild('b', exclude=[x]) 2403 n = Wild('n', exclude=[x]) 2404 q = Wild('q', exclude=[x]) 2405 Match = expr.match(a*x**q + b*x**n) 2406 if Match and PosQ(Match[q] - Match[n]): 2407 return [Match[b], Match[a], Match[q], Match[n]] 2408 else: 2409 return False 2410 2411def GeneralizedTrinomialDegree(u, x): 2412 t = GeneralizedTrinomialParts(u, x) 2413 if t: 2414 return t[3] - t[4] 2415 2416def GeneralizedTrinomialParts(expr, x): 2417 expr = Expand(expr) 2418 if GeneralizedTrinomialMatchQ(expr, x): 2419 a = Wild('a', exclude=[x, 0]) 2420 b = Wild('b', exclude=[x, 0]) 2421 c = Wild('c', exclude=[x]) 2422 n = Wild('n', exclude=[x, 0]) 2423 q = Wild('q', exclude=[x]) 2424 Match = expr.match(a*x**q + b*x**n+c*x**(2*n-q)) 2425 if Match and expr.is_Add: 2426 return [Match[c], Match[b], Match[a], Match[n], 2*Match[n]-Match[q]] 2427 else: 2428 return False 2429 2430def MonomialQ(u, x): 2431 # If u is of the form a*x^n where n!=0 and a!=0, MonomialQ[u,x] returns True; else False 2432 if isinstance(u, list): 2433 return all(MonomialQ(i, x) for i in u) 2434 else: 2435 a = Wild('a', exclude=[x]) 2436 b = Wild('b', exclude=[x]) 2437 re = u.match(a*x**b) 2438 if re: 2439 return True 2440 return False 2441 2442def MonomialSumQ(u, x): 2443 # if u(x) is a sum and each term is free of x or an expression of the form a*x^n, MonomialSumQ(u, x) returns True; else it returns False 2444 if SumQ(u): 2445 for i in u.args: 2446 if Not(FreeQ(i, x) or MonomialQ(i, x)): 2447 return False 2448 return True 2449 2450@doctest_depends_on(modules=('matchpy',)) 2451def MinimumMonomialExponent(u, x): 2452 """ 2453 u is sum whose terms are monomials. MinimumMonomialExponent(u, x) returns the exponent of the term having the smallest exponent 2454 2455 Examples 2456 ======== 2457 2458 >>> from sympy.integrals.rubi.utility_function import MinimumMonomialExponent 2459 >>> from sympy.abc import x 2460 >>> MinimumMonomialExponent(x**2 + 5*x**2 + 3*x**5, x) 2461 2 2462 >>> MinimumMonomialExponent(x**2 + 5*x**2 + 1, x) 2463 0 2464 """ 2465 2466 n =MonomialExponent(First(u), x) 2467 for i in u.args: 2468 if PosQ(n - MonomialExponent(i, x)): 2469 n = MonomialExponent(i, x) 2470 2471 return n 2472 2473def MonomialExponent(u, x): 2474 # u is a monomial. MonomialExponent(u, x) returns the exponent of x in u 2475 a = Wild('a', exclude=[x]) 2476 b = Wild('b', exclude=[x]) 2477 re = u.match(a*x**b) 2478 if re: 2479 return re[b] 2480 2481def LinearMatchQ(u, x): 2482 # LinearMatchQ(u, x) returns True iff u matches patterns of the form a+b*x where a and b are free of x 2483 if isinstance(u, list): 2484 return all(LinearMatchQ(i, x) for i in u) 2485 else: 2486 a = Wild('a', exclude=[x]) 2487 b = Wild('b', exclude=[x]) 2488 re = u.match(a + b*x) 2489 if re: 2490 return True 2491 return False 2492 2493def PowerOfLinearMatchQ(u, x): 2494 if isinstance(u, list): 2495 for i in u: 2496 if not PowerOfLinearMatchQ(i, x): 2497 return False 2498 return True 2499 else: 2500 a = Wild('a', exclude=[x]) 2501 b = Wild('b', exclude=[x, 0]) 2502 m = Wild('m', exclude=[x, 0]) 2503 Match = u.match((a + b*x)**m) 2504 if Match: 2505 return True 2506 else: 2507 return False 2508 2509def QuadraticMatchQ(u, x): 2510 if ListQ(u): 2511 return all(QuadraticMatchQ(i, x) for i in u) 2512 pattern1 = Pattern(UtilityOperator(x_**2*WC('c', 1) + x_*WC('b', 1) + WC('a', 0), x_), CustomConstraint(lambda a, b, c, x: FreeQ([a, b, c], x))) 2513 pattern2 = Pattern(UtilityOperator(x_**2*WC('c', 1) + WC('a', 0), x_), CustomConstraint(lambda a, c, x: FreeQ([a, c], x))) 2514 u1 = UtilityOperator(u, x) 2515 return is_match(u1, pattern1) or is_match(u1, pattern2) 2516 2517def CubicMatchQ(u, x): 2518 if isinstance(u, list): 2519 return all(CubicMatchQ(i, x) for i in u) 2520 else: 2521 pattern1 = Pattern(UtilityOperator(x_**3*WC('d', 1) + x_**2*WC('c', 1) + x_*WC('b', 1) + WC('a', 0), x_), CustomConstraint(lambda a, b, c, d, x: FreeQ([a, b, c, d], x))) 2522 pattern2 = Pattern(UtilityOperator(x_**3*WC('d', 1) + x_*WC('b', 1) + WC('a', 0), x_), CustomConstraint(lambda a, b, d, x: FreeQ([a, b, d], x))) 2523 pattern3 = Pattern(UtilityOperator(x_**3*WC('d', 1) + x_**2*WC('c', 1) + WC('a', 0), x_), CustomConstraint(lambda a, c, d, x: FreeQ([a, c, d], x))) 2524 pattern4 = Pattern(UtilityOperator(x_**3*WC('d', 1) + WC('a', 0), x_), CustomConstraint(lambda a, d, x: FreeQ([a, d], x))) 2525 u1 = UtilityOperator(u, x) 2526 if is_match(u1, pattern1) or is_match(u1, pattern2) or is_match(u1, pattern3) or is_match(u1, pattern4): 2527 return True 2528 else: 2529 return False 2530 2531def BinomialMatchQ(u, x): 2532 if isinstance(u, list): 2533 return all(BinomialMatchQ(i, x) for i in u) 2534 else: 2535 pattern = Pattern(UtilityOperator(x_**WC('n', S(1))*WC('b', S(1)) + WC('a', S(0)), x_) , CustomConstraint(lambda a, b, n, x: FreeQ([a,b,n],x))) 2536 u = UtilityOperator(u, x) 2537 return is_match(u, pattern) 2538 2539def TrinomialMatchQ(u, x): 2540 if isinstance(u, list): 2541 return all(TrinomialMatchQ(i, x) for i in u) 2542 else: 2543 pattern = Pattern(UtilityOperator(x_**WC('j', S(1))*WC('c', S(1)) + x_**WC('n', S(1))*WC('b', S(1)) + WC('a', S(0)), x_) , CustomConstraint(lambda a, b, c, n, x: FreeQ([a, b, c, n], x)), CustomConstraint(lambda j, n: ZeroQ(j-2*n) )) 2544 u = UtilityOperator(u, x) 2545 return is_match(u, pattern) 2546 2547def GeneralizedBinomialMatchQ(u, x): 2548 if isinstance(u, list): 2549 return all(GeneralizedBinomialMatchQ(i, x) for i in u) 2550 else: 2551 a = Wild('a', exclude=[x, 0]) 2552 b = Wild('b', exclude=[x, 0]) 2553 n = Wild('n', exclude=[x, 0]) 2554 q = Wild('q', exclude=[x, 0]) 2555 Match = u.match(a*x**q + b*x**n) 2556 if Match and len(Match) == 4 and Match[q] != 0 and Match[n] != 0: 2557 return True 2558 else: 2559 return False 2560 2561def GeneralizedTrinomialMatchQ(u, x): 2562 if isinstance(u, list): 2563 return all(GeneralizedTrinomialMatchQ(i, x) for i in u) 2564 else: 2565 a = Wild('a', exclude=[x, 0]) 2566 b = Wild('b', exclude=[x, 0]) 2567 n = Wild('n', exclude=[x, 0]) 2568 c = Wild('c', exclude=[x, 0]) 2569 q = Wild('q', exclude=[x, 0]) 2570 Match = u.match(a*x**q + b*x**n + c*x**(2*n - q)) 2571 if Match and len(Match) == 5 and 2*Match[n] - Match[q] != 0 and Match[n] != 0: 2572 return True 2573 else: 2574 return False 2575 2576def QuotientOfLinearsMatchQ(u, x): 2577 if isinstance(u, list): 2578 return all(QuotientOfLinearsMatchQ(i, x) for i in u) 2579 else: 2580 a = Wild('a', exclude=[x]) 2581 b = Wild('b', exclude=[x]) 2582 d = Wild('d', exclude=[x]) 2583 c = Wild('c', exclude=[x]) 2584 e = Wild('e') 2585 Match = u.match(e*(a + b*x)/(c + d*x)) 2586 if Match and len(Match) == 5: 2587 return True 2588 else: 2589 return False 2590 2591def PolynomialTermQ(u, x): 2592 a = Wild('a', exclude=[x]) 2593 n = Wild('n', exclude=[x]) 2594 Match = u.match(a*x**n) 2595 if Match and IntegerQ(Match[n]) and Greater(Match[n], S(0)): 2596 return True 2597 else: 2598 return False 2599 2600def PolynomialTerms(u, x): 2601 s = 0 2602 for i in u.args: 2603 if PolynomialTermQ(i, x): 2604 s = s + i 2605 return s 2606 2607def NonpolynomialTerms(u, x): 2608 s = 0 2609 for i in u.args: 2610 if not PolynomialTermQ(i, x): 2611 s = s + i 2612 return s 2613 2614def PseudoBinomialParts(u, x): 2615 if PolynomialQ(u, x) and Greater(Expon(u, x), S(2)): 2616 n = Expon(u, x) 2617 d = Rt(Coefficient(u, x, n), n) 2618 c = d**(-n + S(1))*Coefficient(u, x, n + S(-1))/n 2619 a = Simplify(u - (c + d*x)**n) 2620 if NonzeroQ(a) and FreeQ(a, x): 2621 return [a, S(1), c, d, n] 2622 else: 2623 return False 2624 else: 2625 return False 2626 2627def NormalizePseudoBinomial(u, x): 2628 lst = PseudoBinomialParts(u, x) 2629 if lst: 2630 return (lst[0] + lst[1]*(lst[2] + lst[3]*x)**lst[4]) 2631 2632def PseudoBinomialPairQ(u, v, x): 2633 lst1 = PseudoBinomialParts(u, x) 2634 if AtomQ(lst1): 2635 return False 2636 else: 2637 lst2 = PseudoBinomialParts(v, x) 2638 if AtomQ(lst2): 2639 return False 2640 else: 2641 return Drop(lst1, 2) == Drop(lst2, 2) 2642 2643def PseudoBinomialQ(u, x): 2644 lst = PseudoBinomialParts(u, x) 2645 if lst: 2646 return True 2647 else: 2648 return False 2649 2650def PolynomialGCD(f, g): 2651 return gcd(f, g) 2652 2653def PolyGCD(u, v, x): 2654 # (* u and v are polynomials in x. *) 2655 # (* PolyGCD[u,v,x] returns the factors of the gcd of u and v dependent on x. *) 2656 return NonfreeFactors(PolynomialGCD(u, v), x) 2657 2658def AlgebraicFunctionFactors(u, x, flag=False): 2659 # (* AlgebraicFunctionFactors[u,x] returns the product of the factors of u that are algebraic functions of x. *) 2660 if ProductQ(u): 2661 result = 1 2662 for i in u.args: 2663 if AlgebraicFunctionQ(i, x, flag): 2664 result *= i 2665 return result 2666 if AlgebraicFunctionQ(u, x, flag): 2667 return u 2668 return 1 2669 2670def NonalgebraicFunctionFactors(u, x): 2671 """ 2672 NonalgebraicFunctionFactors[u,x] returns the product of the factors of u that are not algebraic functions of x. 2673 2674 Examples 2675 ======== 2676 2677 >>> from sympy.integrals.rubi.utility_function import NonalgebraicFunctionFactors 2678 >>> from sympy.abc import x 2679 >>> from sympy import sin 2680 >>> NonalgebraicFunctionFactors(sin(x), x) 2681 sin(x) 2682 >>> NonalgebraicFunctionFactors(x, x) 2683 1 2684 2685 """ 2686 if ProductQ(u): 2687 result = 1 2688 for i in u.args: 2689 if not AlgebraicFunctionQ(i, x): 2690 result *= i 2691 return result 2692 if AlgebraicFunctionQ(u, x): 2693 return 1 2694 return u 2695 2696def QuotientOfLinearsP(u, x): 2697 if LinearQ(u, x): 2698 return True 2699 elif SumQ(u): 2700 if FreeQ(u.args[0], x): 2701 return QuotientOfLinearsP(Rest(u), x) 2702 elif LinearQ(Numerator(u), x) and LinearQ(Denominator(u), x): 2703 return True 2704 elif ProductQ(u): 2705 if FreeQ(First(u), x): 2706 return QuotientOfLinearsP(Rest(u), x) 2707 elif Numerator(u) == 1 and PowerQ(u): 2708 return QuotientOfLinearsP(Denominator(u), x) 2709 return u == x or FreeQ(u, x) 2710 2711def QuotientOfLinearsParts(u, x): 2712 # If u is equivalent to an expression of the form (a+b*x)/(c+d*x), QuotientOfLinearsParts[u,x] 2713 # returns the list {a, b, c, d}. 2714 if LinearQ(u, x): 2715 return [Coefficient(u, x, 0), Coefficient(u, x, 1), 1, 0] 2716 elif PowerQ(u): 2717 if Numerator(u) == 1: 2718 u = Denominator(u) 2719 r = QuotientOfLinearsParts(u, x) 2720 return [r[2], r[3], r[0], r[1]] 2721 elif SumQ(u): 2722 a = First(u) 2723 if FreeQ(a, x): 2724 u = Rest(u) 2725 r = QuotientOfLinearsParts(u, x) 2726 return [r[0] + a*r[2], r[1] + a*r[3], r[2], r[3]] 2727 elif ProductQ(u): 2728 a = First(u) 2729 if FreeQ(a, x): 2730 r = QuotientOfLinearsParts(Rest(u), x) 2731 return [a*r[0], a*r[1], r[2], r[3]] 2732 a = Numerator(u) 2733 d = Denominator(u) 2734 if LinearQ(a, x) and LinearQ(d, x): 2735 return [Coefficient(a, x, 0), Coefficient(a, x, 1), Coefficient(d, x, 0), Coefficient(d, x, 1)] 2736 elif u == x: 2737 return [0, 1, 1, 0] 2738 elif FreeQ(u, x): 2739 return [u, 0, 1, 0] 2740 return [u, 0, 1, 0] 2741 2742def QuotientOfLinearsQ(u, x): 2743 # (*QuotientOfLinearsQ[u,x] returns True iff u is equivalent to an expression of the form (a+b x)/(c+d x) where b!=0 and d!=0.*) 2744 if ListQ(u): 2745 for i in u: 2746 if not QuotientOfLinearsQ(i, x): 2747 return False 2748 return True 2749 q = QuotientOfLinearsParts(u, x) 2750 return QuotientOfLinearsP(u, x) and NonzeroQ(q[1]) and NonzeroQ(q[3]) 2751 2752def Flatten(l): 2753 return flatten(l) 2754 2755def Sort(u, r=False): 2756 return sorted(u, key=lambda x: x.sort_key(), reverse=r) 2757 2758# (*Definition: A number is absurd if it is a rational number, a positive rational number raised to a fractional power, or a product of absurd numbers.*) 2759def AbsurdNumberQ(u): 2760 # (* AbsurdNumberQ[u] returns True if u is an absurd number, else it returns False. *) 2761 if PowerQ(u): 2762 v = u.exp 2763 u = u.base 2764 return RationalQ(u) and u > 0 and FractionQ(v) 2765 elif ProductQ(u): 2766 return all(AbsurdNumberQ(i) for i in u.args) 2767 return RationalQ(u) 2768 2769def AbsurdNumberFactors(u): 2770 # (* AbsurdNumberFactors[u] returns the product of the factors of u that are absurd numbers. *) 2771 if AbsurdNumberQ(u): 2772 return u 2773 elif ProductQ(u): 2774 result = S(1) 2775 for i in u.args: 2776 if AbsurdNumberQ(i): 2777 result *= i 2778 return result 2779 return NumericFactor(u) 2780 2781def NonabsurdNumberFactors(u): 2782 # (* NonabsurdNumberFactors[u] returns the product of the factors of u that are not absurd numbers. *) 2783 if AbsurdNumberQ(u): 2784 return S(1) 2785 elif ProductQ(u): 2786 result = 1 2787 for i in u.args: 2788 result *= NonabsurdNumberFactors(i) 2789 return result 2790 return NonnumericFactors(u) 2791 2792def SumSimplerAuxQ(u, v): 2793 if SumQ(v): 2794 return (RationalQ(First(v)) or SumSimplerAuxQ(u,First(v))) and (RationalQ(Rest(v)) or SumSimplerAuxQ(u,Rest(v))) 2795 elif SumQ(u): 2796 return SumSimplerAuxQ(First(u), v) or SumSimplerAuxQ(Rest(u), v) 2797 else: 2798 return v!=0 and NonnumericFactors(u)==NonnumericFactors(v) and (NumericFactor(u)/NumericFactor(v)<-1/2 or NumericFactor(u)/NumericFactor(v)==-1/2 and NumericFactor(u)<0) 2799 2800def Prepend(l1, l2): 2801 if not isinstance(l2, list): 2802 return [l2] + l1 2803 return l2 + l1 2804 2805def Drop(lst, n): 2806 if isinstance(lst, list): 2807 if isinstance(n, list): 2808 lst = lst[:(n[0]-1)] + lst[n[1]:] 2809 elif n > 0: 2810 lst = lst[n:] 2811 elif n < 0: 2812 lst = lst[:-n] 2813 else: 2814 return lst 2815 return lst 2816 return lst.func(*[i for i in Drop(list(lst.args), n)]) 2817 2818def CombineExponents(lst): 2819 if Length(lst) < 2: 2820 return lst 2821 elif lst[0][0] == lst[1][0]: 2822 return CombineExponents(Prepend(Drop(lst,2),[lst[0][0], lst[0][1] + lst[1][1]])) 2823 return Prepend(CombineExponents(Rest(lst)), First(lst)) 2824 2825def FactorInteger(n, l=None): 2826 if isinstance(n, (int, Integer)): 2827 return sorted(factorint(n, limit=l).items()) 2828 else: 2829 return sorted(factorrat(n, limit=l).items()) 2830 2831def FactorAbsurdNumber(m): 2832 # (* m must be an absurd number. FactorAbsurdNumber[m] returns the prime factorization of m *) 2833 # (* as list of base-degree pairs where the bases are prime numbers and the degrees are rational. *) 2834 if RationalQ(m): 2835 return FactorInteger(m) 2836 elif PowerQ(m): 2837 r = FactorInteger(m.base) 2838 return [r[0], r[1]*m.exp] 2839 2840 # CombineExponents[Sort[Flatten[Map[FactorAbsurdNumber,Apply[List,m]],1], Function[i1[[1]]<i2[[1]]]]] 2841 return list((m.as_base_exp(),)) 2842 2843def SubstForInverseFunction(*args): 2844 """ 2845 SubstForInverseFunction(u, v, w, x) returns u with subexpressions equal to v replaced by x and x replaced by w. 2846 2847 Examples 2848 ======== 2849 2850 >>> from sympy.integrals.rubi.utility_function import SubstForInverseFunction 2851 >>> from sympy.abc import x, a, b 2852 >>> SubstForInverseFunction(a, a, b, x) 2853 a 2854 >>> SubstForInverseFunction(x**a, x**a, b, x) 2855 x 2856 >>> SubstForInverseFunction(a*x**a, a, b, x) 2857 a*b**a 2858 2859 """ 2860 if len(args) == 3: 2861 u, v, x = args[0], args[1], args[2] 2862 return SubstForInverseFunction(u, v, (-Coefficient(v.args[0], x, 0) + InverseFunction(Head(v))(x))/Coefficient(v.args[0], x, 1), x) 2863 elif len(args) == 4: 2864 u, v, w, x = args[0], args[1], args[2], args[3] 2865 if AtomQ(u): 2866 if u == x: 2867 return w 2868 return u 2869 elif Head(u) == Head(v) and ZeroQ(u.args[0] - v.args[0]): 2870 return x 2871 res = [SubstForInverseFunction(i, v, w, x) for i in u.args] 2872 return u.func(*res) 2873 2874def SubstForFractionalPower(u, v, n, w, x): 2875 # (* SubstForFractionalPower[u,v,n,w,x] returns u with subexpressions equal to v^(m/n) replaced 2876 # by x^m and x replaced by w. *) 2877 if AtomQ(u): 2878 if u == x: 2879 return w 2880 return u 2881 elif FractionalPowerQ(u): 2882 if ZeroQ(u.base - v): 2883 return x**(n*u.exp) 2884 res = [SubstForFractionalPower(i, v, n, w, x) for i in u.args] 2885 return u.func(*res) 2886 2887def SubstForFractionalPowerOfQuotientOfLinears(u, x): 2888 # (* If u has a subexpression of the form ((a+b*x)/(c+d*x))^(m/n) where m and n>1 are integers, 2889 # SubstForFractionalPowerOfQuotientOfLinears[u,x] returns the list {v,n,(a+b*x)/(c+d*x),b*c-a*d} where v is u 2890 # with subexpressions of the form ((a+b*x)/(c+d*x))^(m/n) replaced by x^m and x replaced 2891 lst = FractionalPowerOfQuotientOfLinears(u, 1, False, x) 2892 if AtomQ(lst) or AtomQ(lst[1]): 2893 return False 2894 n = lst[0] 2895 tmp = lst[1] 2896 lst = QuotientOfLinearsParts(tmp, x) 2897 a, b, c, d = lst[0], lst[1], lst[2], lst[3] 2898 if ZeroQ(d): 2899 return False 2900 lst = Simplify(x**(n - 1)*SubstForFractionalPower(u, tmp, n, (-a + c*x**n)/(b - d*x**n), x)/(b - d*x**n)**2) 2901 return [NonfreeFactors(lst, x), n, tmp, FreeFactors(lst, x)*(b*c - a*d)] 2902 2903def FractionalPowerOfQuotientOfLinears(u, n, v, x): 2904 # (* If u has a subexpression of the form ((a+b*x)/(c+d*x))^(m/n), 2905 # FractionalPowerOfQuotientOfLinears[u,1,False,x] returns {n,(a+b*x)/(c+d*x)}; else it returns False. *) 2906 if AtomQ(u) or FreeQ(u, x): 2907 return [n, v] 2908 elif CalculusQ(u): 2909 return False 2910 elif FractionalPowerQ(u): 2911 if QuotientOfLinearsQ(u.base, x) and Not(LinearQ(u.base, x)) and (FalseQ(v) or ZeroQ(u.base - v)): 2912 return [LCM(Denominator(u.exp), n), u.base] 2913 lst = [n, v] 2914 for i in u.args: 2915 lst = FractionalPowerOfQuotientOfLinears(i, lst[0], lst[1],x) 2916 if AtomQ(lst): 2917 return False 2918 return lst 2919 2920def SubstForFractionalPowerQ(u, v, x): 2921 # (* If the substitution x=v^(1/n) will not complicate algebraic subexpressions of u, 2922 # SubstForFractionalPowerQ[u,v,x] returns True; else it returns False. *) 2923 if AtomQ(u) or FreeQ(u, x): 2924 return True 2925 elif FractionalPowerQ(u): 2926 return SubstForFractionalPowerAuxQ(u, v, x) 2927 return all(SubstForFractionalPowerQ(i, v, x) for i in u.args) 2928 2929def SubstForFractionalPowerAuxQ(u, v, x): 2930 if AtomQ(u): 2931 return False 2932 elif FractionalPowerQ(u): 2933 if ZeroQ(u.base - v): 2934 return True 2935 return any(SubstForFractionalPowerAuxQ(i, v, x) for i in u.args) 2936 2937def FractionalPowerOfSquareQ(u): 2938 # (* If a subexpression of u is of the form ((v+w)^2)^n where n is a fraction, *) 2939 # (* FractionalPowerOfSquareQ[u] returns (v+w)^2; else it returns False. *) 2940 if AtomQ(u): 2941 return False 2942 elif FractionalPowerQ(u): 2943 a_ = Wild('a', exclude=[0]) 2944 b_ = Wild('b', exclude=[0]) 2945 c_ = Wild('c', exclude=[0]) 2946 match = u.base.match(a_*(b_ + c_)**(S(2))) 2947 if match: 2948 keys = [a_, b_, c_] 2949 if len(keys) == len(match): 2950 a, b, c = tuple(match[i] for i in keys) 2951 if NonsumQ(a): 2952 return (b + c)**S(2) 2953 for i in u.args: 2954 tmp = FractionalPowerOfSquareQ(i) 2955 if Not(FalseQ(tmp)): 2956 return tmp 2957 return False 2958 2959def FractionalPowerSubexpressionQ(u, v, w): 2960 # (* If a subexpression of u is of the form w^n where n is a fraction but not equal to v, *) 2961 # (* FractionalPowerSubexpressionQ[u,v,w] returns True; else it returns False. *) 2962 if AtomQ(u): 2963 return False 2964 elif FractionalPowerQ(u): 2965 if PositiveQ(u.base/w): 2966 return Not(u.base == v) and LeafCount(w) < 3*LeafCount(v) 2967 for i in u.args: 2968 if FractionalPowerSubexpressionQ(i, v, w): 2969 return True 2970 return False 2971 2972def Apply(f, lst): 2973 return f(*lst) 2974 2975def FactorNumericGcd(u): 2976 # (* FactorNumericGcd[u] returns u with the gcd of the numeric coefficients of terms of sums factored out. *) 2977 if PowerQ(u): 2978 if RationalQ(u.exp): 2979 return FactorNumericGcd(u.base)**u.exp 2980 elif ProductQ(u): 2981 res = [FactorNumericGcd(i) for i in u.args] 2982 return Mul(*res) 2983 elif SumQ(u): 2984 g = GCD([NumericFactor(i) for i in u.args]) 2985 r = Add(*[i/g for i in u.args]) 2986 return g*r 2987 return u 2988 2989def MergeableFactorQ(bas, deg, v): 2990 # (* MergeableFactorQ[bas,deg,v] returns True iff bas equals the base of a factor of v or bas is a factor of every term of v. *) 2991 if bas == v: 2992 return RationalQ(deg + S(1)) and (deg + 1>=0 or RationalQ(deg) and deg>0) 2993 elif PowerQ(v): 2994 if bas == v.base: 2995 return RationalQ(deg+v.exp) and (deg+v.exp>=0 or RationalQ(deg) and deg>0) 2996 return SumQ(v.base) and IntegerQ(v.exp) and (Not(IntegerQ(deg) or IntegerQ(deg/v.exp))) and MergeableFactorQ(bas, deg/v.exp, v.base) 2997 elif ProductQ(v): 2998 return MergeableFactorQ(bas, deg, First(v)) or MergeableFactorQ(bas, deg, Rest(v)) 2999 return SumQ(v) and MergeableFactorQ(bas, deg, First(v)) and MergeableFactorQ(bas, deg, Rest(v)) 3000 3001def MergeFactor(bas, deg, v): 3002 # (* If MergeableFactorQ[bas,deg,v], MergeFactor[bas,deg,v] return the product of bas^deg and v, 3003 # but with bas^deg merged into the factor of v whose base equals bas. *) 3004 if bas == v: 3005 return bas**(deg + 1) 3006 elif PowerQ(v): 3007 if bas == v.base: 3008 return bas**(deg + v.exp) 3009 return MergeFactor(bas, deg/v.exp, v.base**v.exp) 3010 elif ProductQ(v): 3011 if MergeableFactorQ(bas, deg, First(v)): 3012 return MergeFactor(bas, deg, First(v))*Rest(v) 3013 return First(v)*MergeFactor(bas, deg, Rest(v)) 3014 return MergeFactor(bas, deg, First(v)) + MergeFactor(bas, deg, Rest(v)) 3015 3016def MergeFactors(u, v): 3017 # (* MergeFactors[u,v] returns the product of u and v, but with the mergeable factors of u merged into v. *) 3018 if ProductQ(u): 3019 return MergeFactors(Rest(u), MergeFactors(First(u), v)) 3020 elif PowerQ(u): 3021 if MergeableFactorQ(u.base, u.exp, v): 3022 return MergeFactor(u.base, u.exp, v) 3023 elif RationalQ(u.exp) and u.exp < -1 and MergeableFactorQ(u.base, -S(1), v): 3024 return MergeFactors(u.base**(u.exp + 1), MergeFactor(u.base, -S(1), v)) 3025 return u*v 3026 elif MergeableFactorQ(u, S(1), v): 3027 return MergeFactor(u, S(1), v) 3028 return u*v 3029 3030def TrigSimplifyQ(u): 3031 # (* TrigSimplifyQ[u] returns True if TrigSimplify[u] actually simplifies u; else False. *) 3032 return ActivateTrig(u) != TrigSimplify(u) 3033 3034def TrigSimplify(u): 3035 # (* TrigSimplify[u] returns a bottom-up trig simplification of u. *) 3036 return ActivateTrig(TrigSimplifyRecur(u)) 3037 3038def TrigSimplifyRecur(u): 3039 if AtomQ(u): 3040 return u 3041 return TrigSimplifyAux(u.func(*[TrigSimplifyRecur(i) for i in u.args])) 3042 3043def Order(expr1, expr2): 3044 if expr1 == expr2: 3045 return 0 3046 elif expr1.sort_key() > expr2.sort_key(): 3047 return -1 3048 return 1 3049 3050def FactorOrder(u, v): 3051 if u == 1: 3052 if v == 1: 3053 return 0 3054 return -1 3055 elif v == 1: 3056 return 1 3057 return Order(u, v) 3058 3059def Smallest(num1, num2=None): 3060 if num2 is None: 3061 lst = num1 3062 num = lst[0] 3063 for i in Rest(lst): 3064 num = Smallest(num, i) 3065 return num 3066 return Min(num1, num2) 3067 3068def OrderedQ(l): 3069 return l == Sort(l) 3070 3071def MinimumDegree(deg1, deg2): 3072 if RationalQ(deg1): 3073 if RationalQ(deg2): 3074 return Min(deg1, deg2) 3075 return deg1 3076 elif RationalQ(deg2): 3077 return deg2 3078 3079 deg = Simplify(deg1- deg2) 3080 3081 if RationalQ(deg): 3082 if deg > 0: 3083 return deg2 3084 return deg1 3085 elif OrderedQ([deg1, deg2]): 3086 return deg1 3087 return deg2 3088 3089def PositiveFactors(u): 3090 # (* PositiveFactors[u] returns the positive factors of u *) 3091 if ZeroQ(u): 3092 return S(1) 3093 elif RationalQ(u): 3094 return Abs(u) 3095 elif PositiveQ(u): 3096 return u 3097 elif ProductQ(u): 3098 res = 1 3099 for i in u.args: 3100 res *= PositiveFactors(i) 3101 return res 3102 return 1 3103 3104def Sign(u): 3105 return sign(u) 3106 3107def NonpositiveFactors(u): 3108 # (* NonpositiveFactors[u] returns the nonpositive factors of u *) 3109 if ZeroQ(u): 3110 return u 3111 elif RationalQ(u): 3112 return Sign(u) 3113 elif PositiveQ(u): 3114 return S(1) 3115 elif ProductQ(u): 3116 res = S(1) 3117 for i in u.args: 3118 res *= NonpositiveFactors(i) 3119 return res 3120 return u 3121 3122def PolynomialInAuxQ(u, v, x): 3123 if u == v: 3124 return True 3125 elif AtomQ(u): 3126 return u != x 3127 elif PowerQ(u): 3128 if PowerQ(v): 3129 if u.base == v.base: 3130 return PositiveIntegerQ(u.exp/v.exp) 3131 return PositiveIntegerQ(u.exp) and PolynomialInAuxQ(u.base, v, x) 3132 elif SumQ(u) or ProductQ(u): 3133 for i in u.args: 3134 if Not(PolynomialInAuxQ(i, v, x)): 3135 return False 3136 return True 3137 return False 3138 3139def PolynomialInQ(u, v, x): 3140 """ 3141 If u is a polynomial in v(x), PolynomialInQ(u, v, x) returns True, else it returns False. 3142 3143 Examples 3144 ======== 3145 3146 >>> from sympy.integrals.rubi.utility_function import PolynomialInQ 3147 >>> from sympy.abc import x 3148 >>> from sympy import log, S 3149 >>> PolynomialInQ(S(1), log(x), x) 3150 True 3151 >>> PolynomialInQ(log(x), log(x), x) 3152 True 3153 >>> PolynomialInQ(1 + log(x)**2, log(x), x) 3154 True 3155 3156 """ 3157 return PolynomialInAuxQ(u, NonfreeFactors(NonfreeTerms(v, x), x), x) 3158 3159def ExponentInAux(u, v, x): 3160 if u == v: 3161 return S(1) 3162 elif AtomQ(u): 3163 return S(0) 3164 elif PowerQ(u): 3165 if PowerQ(v): 3166 if u.base == v.base: 3167 return u.exp/v.exp 3168 return u.exp*ExponentInAux(u.base, v, x) 3169 elif ProductQ(u): 3170 return Add(*[ExponentInAux(i, v, x) for i in u.args]) 3171 return Max(*[ExponentInAux(i, v, x) for i in u.args]) 3172 3173def ExponentIn(u, v, x): 3174 return ExponentInAux(u, NonfreeFactors(NonfreeTerms(v, x), x), x) 3175 3176def PolynomialInSubstAux(u, v, x): 3177 if u == v: 3178 return x 3179 elif AtomQ(u): 3180 return u 3181 elif PowerQ(u): 3182 if PowerQ(v): 3183 if u.base == v.base: 3184 return x**(u.exp/v.exp) 3185 return PolynomialInSubstAux(u.base, v, x)**u.exp 3186 return u.func(*[PolynomialInSubstAux(i, v, x) for i in u.args]) 3187 3188def PolynomialInSubst(u, v, x): 3189 # If u is a polynomial in v[x], PolynomialInSubst[u,v,x] returns the polynomial u in x. 3190 w = NonfreeTerms(v, x) 3191 return ReplaceAll(PolynomialInSubstAux(u, NonfreeFactors(w, x), x), {x: x - FreeTerms(v, x)/FreeFactors(w, x)}) 3192 3193def Distrib(u, v): 3194 # Distrib[u,v] returns the sum of u times each term of v. 3195 if SumQ(v): 3196 return Add(*[u*i for i in v.args]) 3197 return u*v 3198 3199def DistributeDegree(u, m): 3200 # DistributeDegree[u,m] returns the product of the factors of u each raised to the mth degree. 3201 if AtomQ(u): 3202 return u**m 3203 elif PowerQ(u): 3204 return u.base**(u.exp*m) 3205 elif ProductQ(u): 3206 return Mul(*[DistributeDegree(i, m) for i in u.args]) 3207 return u**m 3208 3209def FunctionOfPower(*args): 3210 """ 3211 FunctionOfPower[u,x] returns the gcd of the integer degrees of x in u. 3212 3213 Examples 3214 ======== 3215 3216 >>> from sympy.integrals.rubi.utility_function import FunctionOfPower 3217 >>> from sympy.abc import x 3218 >>> FunctionOfPower(x, x) 3219 1 3220 >>> FunctionOfPower(x**3, x) 3221 3 3222 3223 """ 3224 if len(args) == 2: 3225 return FunctionOfPower(args[0], None, args[1]) 3226 3227 u, n, x = args 3228 3229 if FreeQ(u, x): 3230 return n 3231 elif u == x: 3232 return S(1) 3233 elif PowerQ(u): 3234 if u.base == x and IntegerQ(u.exp): 3235 if n is None: 3236 return u.exp 3237 return GCD(n, u.exp) 3238 tmp = n 3239 for i in u.args: 3240 tmp = FunctionOfPower(i, tmp, x) 3241 return tmp 3242 3243def DivideDegreesOfFactors(u, n): 3244 """ 3245 DivideDegreesOfFactors[u,n] returns the product of the base of the factors of u raised to the degree of the factors divided by n. 3246 3247 Examples 3248 ======== 3249 3250 >>> from sympy import S 3251 >>> from sympy.integrals.rubi.utility_function import DivideDegreesOfFactors 3252 >>> from sympy.abc import a, b 3253 >>> DivideDegreesOfFactors(a**b, S(3)) 3254 a**(b/3) 3255 3256 """ 3257 if ProductQ(u): 3258 return Mul(*[LeadBase(i)**(LeadDegree(i)/n) for i in u.args]) 3259 return LeadBase(u)**(LeadDegree(u)/n) 3260 3261def MonomialFactor(u, x): 3262 # MonomialFactor[u,x] returns the list {n,v} where x^n*v==u and n is free of x. 3263 if AtomQ(u): 3264 if u == x: 3265 return [S(1), S(1)] 3266 return [S(0), u] 3267 elif PowerQ(u): 3268 if IntegerQ(u.exp): 3269 lst = MonomialFactor(u.base, x) 3270 return [lst[0]*u.exp, lst[1]**u.exp] 3271 elif u.base == x and FreeQ(u.exp, x): 3272 return [u.exp, S(1)] 3273 return [S(0), u] 3274 elif ProductQ(u): 3275 lst1 = MonomialFactor(First(u), x) 3276 lst2 = MonomialFactor(Rest(u), x) 3277 return [lst1[0] + lst2[0], lst1[1]*lst2[1]] 3278 elif SumQ(u): 3279 lst = [MonomialFactor(i, x) for i in u.args] 3280 deg = lst[0][0] 3281 for i in Rest(lst): 3282 deg = MinimumDegree(deg, i[0]) 3283 if ZeroQ(deg) or RationalQ(deg) and deg < 0: 3284 return [S(0), u] 3285 return [deg, Add(*[x**(i[0] - deg)*i[1] for i in lst])] 3286 return [S(0), u] 3287 3288def FullSimplify(expr): 3289 return Simplify(expr) 3290 3291def FunctionOfLinearSubst(u, a, b, x): 3292 if FreeQ(u, x): 3293 return u 3294 elif LinearQ(u, x): 3295 tmp = Coefficient(u, x, 1) 3296 if tmp == b: 3297 tmp = S(1) 3298 else: 3299 tmp = tmp/b 3300 return Coefficient(u, x, S(0)) - a*tmp + tmp*x 3301 elif PowerQ(u): 3302 if FreeQ(u.base, x): 3303 return E**(FullSimplify(FunctionOfLinearSubst(Log(u.base)*u.exp, a, b, x))) 3304 lst = MonomialFactor(u, x) 3305 if ProductQ(u) and NonzeroQ(lst[0]): 3306 if RationalQ(LeadFactor(lst[1])) and LeadFactor(lst[1]) < 0: 3307 return -FunctionOfLinearSubst(DivideDegreesOfFactors(-lst[1], lst[0])*x, a, b, x)**lst[0] 3308 return FunctionOfLinearSubst(DivideDegreesOfFactors(lst[1], lst[0])*x, a, b, x)**lst[0] 3309 return u.func(*[FunctionOfLinearSubst(i, a, b, x) for i in u.args]) 3310 3311 3312def FunctionOfLinear(*args): 3313 # (* If u (x) is equivalent to an expression of the form f (a+b*x) and not the case that a==0 and 3314 # b==1, FunctionOfLinear[u,x] returns the list {f (x),a,b}; else it returns False. *) 3315 if len(args) == 2: 3316 u, x = args 3317 lst = FunctionOfLinear(u, False, False, x, False) 3318 if AtomQ(lst) or FalseQ(lst[0]) or (lst[0] == 0 and lst[1] == 1): 3319 return False 3320 return [FunctionOfLinearSubst(u, lst[0], lst[1], x), lst[0], lst[1]] 3321 u, a, b, x, flag = args 3322 if FreeQ(u, x): 3323 return [a, b] 3324 elif CalculusQ(u): 3325 return False 3326 elif LinearQ(u, x): 3327 if FalseQ(a): 3328 return [Coefficient(u, x, 0), Coefficient(u, x, 1)] 3329 lst = CommonFactors([b, Coefficient(u, x, 1)]) 3330 if ZeroQ(Coefficient(u, x, 0)) and Not(flag): 3331 return [0, lst[0]] 3332 elif ZeroQ(b*Coefficient(u, x, 0) - a*Coefficient(u, x, 1)): 3333 return [a/lst[1], lst[0]] 3334 return [0, 1] 3335 elif PowerQ(u): 3336 if FreeQ(u.base, x): 3337 return FunctionOfLinear(Log(u.base)*u.exp, a, b, x, False) 3338 lst = MonomialFactor(u, x) 3339 if ProductQ(u) and NonzeroQ(lst[0]): 3340 if False and IntegerQ(lst[0]) and lst[0] != -1 and FreeQ(lst[1], x): 3341 if RationalQ(LeadFactor(lst[1])) and LeadFactor(lst[1]) < 0: 3342 return FunctionOfLinear(DivideDegreesOfFactors(-lst[1], lst[0])*x, a, b, x, False) 3343 return FunctionOfLinear(DivideDegreesOfFactors(lst[1], lst[0])*x, a, b, x, False) 3344 return False 3345 lst = [a, b] 3346 for i in u.args: 3347 lst = FunctionOfLinear(i, lst[0], lst[1], x, SumQ(u)) 3348 if AtomQ(lst): 3349 return False 3350 return lst 3351 3352def NormalizeIntegrand(u, x): 3353 v = NormalizeLeadTermSigns(NormalizeIntegrandAux(u, x)) 3354 if v == NormalizeLeadTermSigns(u): 3355 return u 3356 else: 3357 return v 3358 3359def NormalizeIntegrandAux(u, x): 3360 if SumQ(u): 3361 l = 0 3362 for i in u.args: 3363 l += NormalizeIntegrandAux(i, x) 3364 return l 3365 if ProductQ(MergeMonomials(u, x)): 3366 l = 1 3367 for i in MergeMonomials(u, x).args: 3368 l *= NormalizeIntegrandFactor(i, x) 3369 return l 3370 else: 3371 return NormalizeIntegrandFactor(MergeMonomials(u, x), x) 3372 3373def NormalizeIntegrandFactor(u, x): 3374 if PowerQ(u): 3375 if FreeQ(u.exp, x): 3376 bas = NormalizeIntegrandFactorBase(u.base, x) 3377 deg = u.exp 3378 if IntegerQ(deg) and SumQ(bas): 3379 if all(MonomialQ(i, x) for i in bas.args): 3380 mi = MinimumMonomialExponent(bas, x) 3381 q = 0 3382 for i in bas.args: 3383 q += Simplify(i/x**mi) 3384 return x**(mi*deg)*q**deg 3385 else: 3386 return bas**deg 3387 else: 3388 return bas**deg 3389 if PowerQ(u): 3390 if FreeQ(u.base, x): 3391 return u.base**NormalizeIntegrandFactorBase(u.exp, x) 3392 bas = NormalizeIntegrandFactorBase(u, x) 3393 if SumQ(bas): 3394 if all(MonomialQ(i, x) for i in bas.args): 3395 mi = MinimumMonomialExponent(bas, x) 3396 z = 0 3397 for j in bas.args: 3398 z += j/x**mi 3399 return x**mi*z 3400 else: 3401 return bas 3402 else: 3403 return bas 3404 3405def NormalizeIntegrandFactorBase(expr, x): 3406 m = Wild('m', exclude=[x]) 3407 u = Wild('u') 3408 match = expr.match(x**m*u) 3409 if match and SumQ(u): 3410 l = 0 3411 for i in u.args: 3412 l += NormalizeIntegrandFactorBase((x**m*i), x) 3413 return l 3414 if BinomialQ(expr, x): 3415 if BinomialMatchQ(expr, x): 3416 return expr 3417 else: 3418 return ExpandToSum(expr, x) 3419 elif TrinomialQ(expr, x): 3420 if TrinomialMatchQ(expr, x): 3421 return expr 3422 else: 3423 return ExpandToSum(expr, x) 3424 elif ProductQ(expr): 3425 l = 1 3426 for i in expr.args: 3427 l *= NormalizeIntegrandFactor(i, x) 3428 return l 3429 elif PolynomialQ(expr, x) and Exponent(expr, x) <= 4: 3430 return ExpandToSum(expr, x) 3431 elif SumQ(expr): 3432 w = Wild('w') 3433 m = Wild('m', exclude=[x]) 3434 v = TogetherSimplify(expr) 3435 if SumQ(v) or v.match(x**m*w) and SumQ(w) or LeafCount(v) > LeafCount(expr) + 2: 3436 return UnifySum(expr, x) 3437 else: 3438 return NormalizeIntegrandFactorBase(v, x) 3439 else: 3440 return expr 3441 3442def NormalizeTogether(u): 3443 return NormalizeLeadTermSigns(Together(u)) 3444 3445def NormalizeLeadTermSigns(u): 3446 if ProductQ(u): 3447 t = 1 3448 for i in u.args: 3449 lst = SignOfFactor(i) 3450 if lst[0] == 1: 3451 t *= lst[1] 3452 else: 3453 t *= AbsorbMinusSign(lst[1]) 3454 return t 3455 else: 3456 lst = SignOfFactor(u) 3457 if lst[0] == 1: 3458 return lst[1] 3459 else: 3460 return AbsorbMinusSign(lst[1]) 3461 3462def AbsorbMinusSign(expr, *x): 3463 m = Wild('m', exclude=[x]) 3464 u = Wild('u') 3465 v = Wild('v') 3466 match = expr.match(u*v**m) 3467 if match: 3468 if len(match) == 3: 3469 if SumQ(match[v]) and OddQ(match[m]): 3470 return match[u]*(-match[v])**match[m] 3471 3472 return -expr 3473 3474def NormalizeSumFactors(u): 3475 if AtomQ(u): 3476 return u 3477 elif ProductQ(u): 3478 k = 1 3479 for i in u.args: 3480 k *= NormalizeSumFactors(i) 3481 return SignOfFactor(k)[0]*SignOfFactor(k)[1] 3482 elif SumQ(u): 3483 k = 0 3484 for i in u.args: 3485 k += NormalizeSumFactors(i) 3486 return k 3487 else: 3488 return u 3489 3490def SignOfFactor(u): 3491 if RationalQ(u) and u < 0 or SumQ(u) and NumericFactor(First(u)) < 0: 3492 return [-1, -u] 3493 elif IntegerPowerQ(u): 3494 if SumQ(u.base) and NumericFactor(First(u.base)) < 0: 3495 return [(-1)**u.exp, (-u.base)**u.exp] 3496 elif ProductQ(u): 3497 k = 1 3498 h = 1 3499 for i in u.args: 3500 k *= SignOfFactor(i)[0] 3501 h *= SignOfFactor(i)[1] 3502 return [k, h] 3503 return [1, u] 3504 3505def NormalizePowerOfLinear(u, x): 3506 v = FactorSquareFree(u) 3507 if PowerQ(v): 3508 if LinearQ(v.base, x) and FreeQ(v.exp, x): 3509 return ExpandToSum(v.base, x)**v.exp 3510 3511 return ExpandToSum(v, x) 3512 3513def SimplifyIntegrand(u, x): 3514 v = NormalizeLeadTermSigns(NormalizeIntegrandAux(Simplify(u), x)) 3515 if 5*LeafCount(v) < 4*LeafCount(u): 3516 return v 3517 if v != NormalizeLeadTermSigns(u): 3518 return v 3519 else: 3520 return u 3521 3522def SimplifyTerm(u, x): 3523 v = Simplify(u) 3524 w = Together(v) 3525 if LeafCount(v) < LeafCount(w): 3526 return NormalizeIntegrand(v, x) 3527 else: 3528 return NormalizeIntegrand(w, x) 3529 3530def TogetherSimplify(u): 3531 v = Together(Simplify(Together(u))) 3532 return FixSimplify(v) 3533 3534def SmartSimplify(u): 3535 v = Simplify(u) 3536 w = factor(v) 3537 if LeafCount(w) < LeafCount(v): 3538 v = w 3539 if Not(FalseQ(w == FractionalPowerOfSquareQ(v))) and FractionalPowerSubexpressionQ(u, w, Expand(w)): 3540 v = SubstForExpn(v, w, Expand(w)) 3541 else: 3542 v = FactorNumericGcd(v) 3543 return FixSimplify(v) 3544 3545def SubstForExpn(u, v, w): 3546 if u == v: 3547 return w 3548 if AtomQ(u): 3549 return u 3550 else: 3551 k = 0 3552 for i in u.args: 3553 k += SubstForExpn(i, v, w) 3554 return k 3555 3556def ExpandToSum(u, *x): 3557 if len(x) == 1: 3558 x = x[0] 3559 expr = 0 3560 if PolyQ(S(u), x): 3561 for t in ExponentList(u, x): 3562 expr += Coeff(u, x, t)*x**t 3563 return expr 3564 if BinomialQ(u, x): 3565 i = BinomialParts(u, x) 3566 expr += i[0] + i[1]*x**i[2] 3567 return expr 3568 if TrinomialQ(u, x): 3569 i = TrinomialParts(u, x) 3570 expr += i[0] + i[1]*x**i[3] + i[2]*x**(2*i[3]) 3571 return expr 3572 if GeneralizedBinomialMatchQ(u, x): 3573 i = GeneralizedBinomialParts(u, x) 3574 expr += i[0]*x**i[3] + i[1]*x**i[2] 3575 return expr 3576 if GeneralizedTrinomialMatchQ(u, x): 3577 i = GeneralizedTrinomialParts(u, x) 3578 expr += i[0]*x**i[4] + i[1]*x**i[3] + i[2]*x**(2*i[3]-i[4]) 3579 return expr 3580 else: 3581 return Expand(u) 3582 else: 3583 v = x[0] 3584 x = x[1] 3585 w = ExpandToSum(v, x) 3586 r = NonfreeTerms(w, x) 3587 if SumQ(r): 3588 k = u*FreeTerms(w, x) 3589 for i in r.args: 3590 k += MergeMonomials(u*i, x) 3591 return k 3592 else: 3593 return u*FreeTerms(w, x) + MergeMonomials(u*r, x) 3594 3595def UnifySum(u, x): 3596 if SumQ(u): 3597 t = 0 3598 lst = [] 3599 for i in u.args: 3600 lst += [i] 3601 for j in UnifyTerms(lst, x): 3602 t += j 3603 return t 3604 else: 3605 return SimplifyTerm(u, x) 3606 3607def UnifyTerms(lst, x): 3608 if lst==[]: 3609 return lst 3610 else: 3611 return UnifyTerm(First(lst), UnifyTerms(Rest(lst), x), x) 3612 3613def UnifyTerm(term, lst, x): 3614 if lst==[]: 3615 return [term] 3616 tmp = Simplify(First(lst)/term) 3617 if FreeQ(tmp, x): 3618 return Prepend(Rest(lst), [(1+tmp)*term]) 3619 else: 3620 return Prepend(UnifyTerm(term, Rest(lst), x), [First(lst)]) 3621 3622def CalculusQ(u): 3623 return False 3624 3625def FunctionOfInverseLinear(*args): 3626 # (* If u is a function of an inverse linear binomial of the form 1/(a+b*x), 3627 # FunctionOfInverseLinear[u,x] returns the list {a,b}; else it returns False. *) 3628 if len(args) == 2: 3629 u, x = args 3630 return FunctionOfInverseLinear(u, None, x) 3631 u, lst, x = args 3632 3633 if FreeQ(u, x): 3634 return lst 3635 elif u == x: 3636 return False 3637 elif QuotientOfLinearsQ(u, x): 3638 tmp = Drop(QuotientOfLinearsParts(u, x), 2) 3639 if tmp[1] == 0: 3640 return False 3641 elif lst is None: 3642 return tmp 3643 elif ZeroQ(lst[0]*tmp[1] - lst[1]*tmp[0]): 3644 return lst 3645 return False 3646 elif CalculusQ(u): 3647 return False 3648 tmp = lst 3649 for i in u.args: 3650 tmp = FunctionOfInverseLinear(i, tmp, x) 3651 if AtomQ(tmp): 3652 return False 3653 return tmp 3654 3655def PureFunctionOfSinhQ(u, v, x): 3656 # (* If u is a pure function of Sinh[v] and/or Csch[v], PureFunctionOfSinhQ[u,v,x] returns True; 3657 # else it returns False. *) 3658 if AtomQ(u): 3659 return u != x 3660 elif CalculusQ(u): 3661 return False 3662 elif HyperbolicQ(u) and ZeroQ(u.args[0] - v): 3663 return SinhQ(u) or CschQ(u) 3664 for i in u.args: 3665 if Not(PureFunctionOfSinhQ(i, v, x)): 3666 return False 3667 return True 3668 3669def PureFunctionOfTanhQ(u, v , x): 3670 # (* If u is a pure function of Tanh[v] and/or Coth[v], PureFunctionOfTanhQ[u,v,x] returns True; 3671 # else it returns False. *) 3672 if AtomQ(u): 3673 return u != x 3674 elif CalculusQ(u): 3675 return False 3676 elif HyperbolicQ(u) and ZeroQ(u.args[0] - v): 3677 return TanhQ(u) or CothQ(u) 3678 for i in u.args: 3679 if Not(PureFunctionOfTanhQ(i, v, x)): 3680 return False 3681 return True 3682 3683def PureFunctionOfCoshQ(u, v, x): 3684 # (* If u is a pure function of Cosh[v] and/or Sech[v], PureFunctionOfCoshQ[u,v,x] returns True; 3685 # else it returns False. *) 3686 if AtomQ(u): 3687 return u != x 3688 elif CalculusQ(u): 3689 return False 3690 elif HyperbolicQ(u) and ZeroQ(u.args[0] - v): 3691 return CoshQ(u) or SechQ(u) 3692 for i in u.args: 3693 if Not(PureFunctionOfCoshQ(i, v, x)): 3694 return False 3695 return True 3696 3697def IntegerQuotientQ(u, v): 3698 # (* If u/v is an integer, IntegerQuotientQ[u,v] returns True; else it returns False. *) 3699 return IntegerQ(Simplify(u/v)) 3700 3701def OddQuotientQ(u, v): 3702 # (* If u/v is odd, OddQuotientQ[u,v] returns True; else it returns False. *) 3703 return OddQ(Simplify(u/v)) 3704 3705def EvenQuotientQ(u, v): 3706 # (* If u/v is even, EvenQuotientQ[u,v] returns True; else it returns False. *) 3707 return EvenQ(Simplify(u/v)) 3708 3709def FindTrigFactor(func1, func2, u, v, flag): 3710 # (* If func[w]^m is a factor of u where m is odd and w is an integer multiple of v, 3711 # FindTrigFactor[func1,func2,u,v,True] returns the list {w,u/func[w]^n}; else it returns False. *) 3712 # (* If func[w]^m is a factor of u where m is odd and w is an integer multiple of v not equal to v, 3713 # FindTrigFactor[func1,func2,u,v,False] returns the list {w,u/func[w]^n}; else it returns False. *) 3714 if u == 1: 3715 return False 3716 elif (Head(LeadBase(u)) == func1 or Head(LeadBase(u)) == func2) and OddQ(LeadDegree(u)) and IntegerQuotientQ(LeadBase(u).args[0], v) and (flag or NonzeroQ(LeadBase(u).args[0] - v)): 3717 return [LeadBase[u].args[0], RemainingFactors(u)] 3718 lst = FindTrigFactor(func1, func2, RemainingFactors(u), v, flag) 3719 if AtomQ(lst): 3720 return False 3721 return [lst[0], LeadFactor(u)*lst[1]] 3722 3723def FunctionOfSinhQ(u, v, x): 3724 # (* If u is a function of Sinh[v], FunctionOfSinhQ[u,v,x] returns True; else it returns False. *) 3725 if AtomQ(u): 3726 return u != x 3727 elif CalculusQ(u): 3728 return False 3729 elif HyperbolicQ(u) and IntegerQuotientQ(u.args[0], v): 3730 if OddQuotientQ(u.args[0], v): 3731 # (* Basis: If m odd, Sinh[m*v]^n is a function of Sinh[v]. *) 3732 return SinhQ(u) or CschQ(u) 3733 # (* Basis: If m even, Cos[m*v]^n is a function of Sinh[v]. *) 3734 return CoshQ(u) or SechQ(u) 3735 elif IntegerPowerQ(u): 3736 if HyperbolicQ(u.base) and IntegerQuotientQ(u.base.args[0], v): 3737 if EvenQ(u.exp): 3738 # (* Basis: If m integer and n even, Hyper[m*v]^n is a function of Sinh[v]. *) 3739 return True 3740 return FunctionOfSinhQ(u.base, v, x) 3741 elif ProductQ(u): 3742 if CoshQ(u.args[0]) and SinhQ(u.args[1]) and ZeroQ(u.args[0].args[0] - v/2) and ZeroQ(u.args[1].args[0] - v/2): 3743 return FunctionOfSinhQ(Drop(u, 2), v, x) 3744 lst = FindTrigFactor(Sinh, Csch, u, v, False) 3745 if ListQ(lst) and EvenQuotientQ(lst[0], v): 3746 # (* Basis: If m even and n odd, Sinh[m*v]^n == Cosh[v]*u where u is a function of Sinh[v]. *) 3747 return FunctionOfSinhQ(Cosh(v)*lst[1], v, x) 3748 lst = FindTrigFactor(Cosh, Sech, u, v, False) 3749 if ListQ(lst) and OddQuotientQ(lst[0], v): 3750 # (* Basis: If m odd and n odd, Cosh[m*v]^n == Cosh[v]*u where u is a function of Sinh[v]. *) 3751 return FunctionOfSinhQ(Cosh(v)*lst[1], v, x) 3752 lst = FindTrigFactor(Tanh, Coth, u, v, True) 3753 if ListQ(lst): 3754 # (* Basis: If m integer and n odd, Tanh[m*v]^n == Cosh[v]*u where u is a function of Sinh[v]. *) 3755 return FunctionOfSinhQ(Cosh(v)*lst[1], v, x) 3756 return all(FunctionOfSinhQ(i, v, x) for i in u.args) 3757 return all(FunctionOfSinhQ(i, v, x) for i in u.args) 3758 3759def FunctionOfCoshQ(u, v, x): 3760 #(* If u is a function of Cosh[v], FunctionOfCoshQ[u,v,x] returns True; else it returns False. *) 3761 if AtomQ(u): 3762 return u != x 3763 elif CalculusQ(u): 3764 return False 3765 elif HyperbolicQ(u) and IntegerQuotientQ(u.args[0], v): 3766 # (* Basis: If m integer, Cosh[m*v]^n is a function of Cosh[v]. *) 3767 return CoshQ(u) or SechQ(u) 3768 elif IntegerPowerQ(u): 3769 if HyperbolicQ(u.base) and IntegerQuotientQ(u.base.args[0], v): 3770 if EvenQ(u.exp): 3771 # (* Basis: If m integer and n even, Hyper[m*v]^n is a function of Cosh[v]. *) 3772 return True 3773 return FunctionOfCoshQ(u.base, v, x) 3774 elif ProductQ(u): 3775 lst = FindTrigFactor(Sinh, Csch, u, v, False) 3776 if ListQ(lst): 3777 # (* Basis: If m integer and n odd, Sinh[m*v]^n == Sinh[v]*u where u is a function of Cosh[v]. *) 3778 return FunctionOfCoshQ(Sinh(v)*lst[1], v, x) 3779 lst = FindTrigFactor(Tanh, Coth, u, v, True) 3780 if ListQ(lst): 3781 # (* Basis: If m integer and n odd, Tanh[m*v]^n == Sinh[v]*u where u is a function of Cosh[v]. *) 3782 return FunctionOfCoshQ(Sinh(v)*lst[1], v, x) 3783 return all(FunctionOfCoshQ(i, v, x) for i in u.args) 3784 return all(FunctionOfCoshQ(i, v, x) for i in u.args) 3785 3786def OddHyperbolicPowerQ(u, v, x): 3787 if SinhQ(u) or CoshQ(u) or SechQ(u) or CschQ(u): 3788 return OddQuotientQ(u.args[0], v) 3789 if PowerQ(u): 3790 return OddQ(u.exp) and OddHyperbolicPowerQ(u.base, v, x) 3791 if ProductQ(u): 3792 if Not(EqQ(FreeFactors(u, x), 1)): 3793 return OddHyperbolicPowerQ(NonfreeFactors(u, x), v, x) 3794 lst = [] 3795 for i in u.args: 3796 if Not(FunctionOfTanhQ(i, v, x)): 3797 lst.append(i) 3798 if lst == []: 3799 return True 3800 return Length(lst)==1 and OddHyperbolicPowerQ(lst[0], v, x) 3801 if SumQ(u): 3802 return all(OddHyperbolicPowerQ(i, v, x) for i in u.args) 3803 return False 3804 3805def FunctionOfTanhQ(u, v, x): 3806 #(* If u is a function of the form f[Tanh[v],Coth[v]] where f is independent of x, 3807 # FunctionOfTanhQ[u,v,x] returns True; else it returns False. *) 3808 if AtomQ(u): 3809 return u != x 3810 elif CalculusQ(u): 3811 return False 3812 elif HyperbolicQ(u) and IntegerQuotientQ(u.args[0], v): 3813 return TanhQ(u) or CothQ(u) or EvenQuotientQ(u.args[0], v) 3814 elif PowerQ(u): 3815 if EvenQ(u.exp) and HyperbolicQ(u.base) and IntegerQuotientQ(u.base.args[0], v): 3816 return True 3817 elif EvenQ(u.args[1]) and SumQ(u.args[0]): 3818 return FunctionOfTanhQ(Expand(u.args[0]**2, v, x)) 3819 if ProductQ(u): 3820 lst = [] 3821 for i in u.args: 3822 if Not(FunctionOfTanhQ(i, v, x)): 3823 lst.append(i) 3824 if lst == []: 3825 return True 3826 return Length(lst)==2 and OddHyperbolicPowerQ(lst[0], v, x) and OddHyperbolicPowerQ(lst[1], v, x) 3827 return all(FunctionOfTanhQ(i, v, x) for i in u.args) 3828 3829def FunctionOfTanhWeight(u, v, x): 3830 """ 3831 u is a function of the form f(tanh(v), coth(v)) where f is independent of x. 3832 FunctionOfTanhWeight(u, v, x) returns a nonnegative number if u is best considered a function of tanh(v), else it returns a negative number. 3833 3834 Examples 3835 ======== 3836 3837 >>> from sympy import sinh, log, tanh 3838 >>> from sympy.abc import x 3839 >>> from sympy.integrals.rubi.utility_function import FunctionOfTanhWeight 3840 >>> FunctionOfTanhWeight(x, log(x), x) 3841 0 3842 >>> FunctionOfTanhWeight(sinh(log(x)), log(x), x) 3843 0 3844 >>> FunctionOfTanhWeight(tanh(log(x)), log(x), x) 3845 1 3846 3847 """ 3848 if AtomQ(u): 3849 return S(0) 3850 elif CalculusQ(u): 3851 return S(0) 3852 elif HyperbolicQ(u) and IntegerQuotientQ(u.args[0], v): 3853 if TanhQ(u) and ZeroQ(u.args[0] - v): 3854 return S(1) 3855 elif CothQ(u) and ZeroQ(u.args[0] - v): 3856 return S(-1) 3857 return S(0) 3858 elif PowerQ(u): 3859 if EvenQ(u.exp) and HyperbolicQ(u.base) and IntegerQuotientQ(u.base.args[0], v): 3860 if TanhQ(u.base) or CoshQ(u.base) or SechQ(u.base): 3861 return S(1) 3862 return S(-1) 3863 if ProductQ(u): 3864 if all(FunctionOfTanhQ(i, v, x) for i in u.args): 3865 return Add(*[FunctionOfTanhWeight(i, v, x) for i in u.args]) 3866 return S(0) 3867 return Add(*[FunctionOfTanhWeight(i, v, x) for i in u.args]) 3868 3869def FunctionOfHyperbolicQ(u, v, x): 3870 # (* If u (x) is equivalent to a function of the form f (Sinh[v],Cosh[v],Tanh[v],Coth[v],Sech[v],Csch[v]) 3871 # where f is independent of x, FunctionOfHyperbolicQ[u,v,x] returns True; else it returns False. *) 3872 if AtomQ(u): 3873 return u != x 3874 elif CalculusQ(u): 3875 return False 3876 elif HyperbolicQ(u) and IntegerQuotientQ(u.args[0], v): 3877 return True 3878 return all(FunctionOfHyperbolicQ(i, v, x) for i in u.args) 3879 3880def SmartNumerator(expr): 3881 if PowerQ(expr): 3882 n = expr.exp 3883 u = expr.base 3884 if RationalQ(n) and n < 0: 3885 return SmartDenominator(u**(-n)) 3886 elif ProductQ(expr): 3887 return Mul(*[SmartNumerator(i) for i in expr.args]) 3888 return Numerator(expr) 3889 3890def SmartDenominator(expr): 3891 if PowerQ(expr): 3892 u = expr.base 3893 n = expr.exp 3894 if RationalQ(n) and n < 0: 3895 return SmartNumerator(u**(-n)) 3896 elif ProductQ(expr): 3897 return Mul(*[SmartDenominator(i) for i in expr.args]) 3898 return Denominator(expr) 3899 3900def ActivateTrig(u): 3901 return u 3902 3903def ExpandTrig(*args): 3904 if len(args) == 2: 3905 u, x = args 3906 return ActivateTrig(ExpandIntegrand(u, x)) 3907 u, v, x = args 3908 w = ExpandTrig(v, x) 3909 z = ActivateTrig(u) 3910 if SumQ(w): 3911 return w.func(*[z*i for i in w.args]) 3912 return z*w 3913 3914def TrigExpand(u): 3915 return expand_trig(u) 3916 3917# SubstForTrig[u_,sin_,cos_,v_,x_] := 3918# If[AtomQ[u], 3919# u, 3920# If[TrigQ[u] && IntegerQuotientQ[u[[1]],v], 3921# If[u[[1]]===v || ZeroQ[u[[1]]-v], 3922# If[SinQ[u], 3923# sin, 3924# If[CosQ[u], 3925# cos, 3926# If[TanQ[u], 3927# sin/cos, 3928# If[CotQ[u], 3929# cos/sin, 3930# If[SecQ[u], 3931# 1/cos, 3932# 1/sin]]]]], 3933# Map[Function[SubstForTrig[#,sin,cos,v,x]], 3934# ReplaceAll[TrigExpand[Head[u][Simplify[u[[1]]/v]*x]],x->v]]], 3935# If[ProductQ[u] && CosQ[u[[1]]] && SinQ[u[[2]]] && ZeroQ[u[[1,1]]-v/2] && ZeroQ[u[[2,1]]-v/2], 3936# sin/2*SubstForTrig[Drop[u,2],sin,cos,v,x], 3937# Map[Function[SubstForTrig[#,sin,cos,v,x]],u]]]] 3938 3939 3940def SubstForTrig(u, sin_ , cos_, v, x): 3941 # (* u (v) is an expression of the form f (Sin[v],Cos[v],Tan[v],Cot[v],Sec[v],Csc[v]). *) 3942 # (* SubstForTrig[u,sin,cos,v,x] returns the expression f (sin,cos,sin/cos,cos/sin,1/cos,1/sin). *) 3943 if AtomQ(u): 3944 return u 3945 elif TrigQ(u) and IntegerQuotientQ(u.args[0], v): 3946 if u.args[0] == v or ZeroQ(u.args[0] - v): 3947 if SinQ(u): 3948 return sin_ 3949 elif CosQ(u): 3950 return cos_ 3951 elif TanQ(u): 3952 return sin_/cos_ 3953 elif CotQ(u): 3954 return cos_/sin_ 3955 elif SecQ(u): 3956 return 1/cos_ 3957 return 1/sin_ 3958 r = ReplaceAll(TrigExpand(Head(u)(Simplify(u.args[0]/v*x))), {x: v}) 3959 return r.func(*[SubstForTrig(i, sin_, cos_, v, x) for i in r.args]) 3960 if ProductQ(u) and CosQ(u.args[0]) and SinQ(u.args[1]) and ZeroQ(u.args[0].args[0] - v/2) and ZeroQ(u.args[1].args[0] - v/2): 3961 return sin(x)/2*SubstForTrig(Drop(u, 2), sin_, cos_, v, x) 3962 return u.func(*[SubstForTrig(i, sin_, cos_, v, x) for i in u.args]) 3963 3964def SubstForHyperbolic(u, sinh_, cosh_, v, x): 3965 # (* u (v) is an expression of the form f (Sinh[v],Cosh[v],Tanh[v],Coth[v],Sech[v],Csch[v]). *) 3966 # (* SubstForHyperbolic[u,sinh,cosh,v,x] returns the expression 3967 # f (sinh,cosh,sinh/cosh,cosh/sinh,1/cosh,1/sinh). *) 3968 if AtomQ(u): 3969 return u 3970 elif HyperbolicQ(u) and IntegerQuotientQ(u.args[0], v): 3971 if u.args[0] == v or ZeroQ(u.args[0] - v): 3972 if SinhQ(u): 3973 return sinh_ 3974 elif CoshQ(u): 3975 return cosh_ 3976 elif TanhQ(u): 3977 return sinh_/cosh_ 3978 elif CothQ(u): 3979 return cosh_/sinh_ 3980 if SechQ(u): 3981 return 1/cosh_ 3982 return 1/sinh_ 3983 r = ReplaceAll(TrigExpand(Head(u)(Simplify(u.args[0]/v)*x)), {x: v}) 3984 return r.func(*[SubstForHyperbolic(i, sinh_, cosh_, v, x) for i in r.args]) 3985 elif ProductQ(u) and CoshQ(u.args[0]) and SinhQ(u.args[1]) and ZeroQ(u.args[0].args[0] - v/2) and ZeroQ(u.args[1].args[0] - v/2): 3986 return sinh(x)/2*SubstForHyperbolic(Drop(u, 2), sinh_, cosh_, v, x) 3987 return u.func(*[SubstForHyperbolic(i, sinh_, cosh_, v, x) for i in u.args]) 3988 3989def InertTrigFreeQ(u): 3990 return FreeQ(u, sin) and FreeQ(u, cos) and FreeQ(u, tan) and FreeQ(u, cot) and FreeQ(u, sec) and FreeQ(u, csc) 3991 3992def LCM(a, b): 3993 return lcm(a, b) 3994 3995def SubstForFractionalPowerOfLinear(u, x): 3996 # (* If u has a subexpression of the form (a+b*x)^(m/n) where m and n>1 are integers, 3997 # SubstForFractionalPowerOfLinear[u,x] returns the list {v,n,a+b*x,1/b} where v is u 3998 # with subexpressions of the form (a+b*x)^(m/n) replaced by x^m and x replaced 3999 # by -a/b+x^n/b, and all times x^(n-1); else it returns False. *) 4000 lst = FractionalPowerOfLinear(u, S(1), False, x) 4001 if AtomQ(lst) or FalseQ(lst[1]): 4002 return False 4003 n = lst[0] 4004 a = Coefficient(lst[1], x, 0) 4005 b = Coefficient(lst[1], x, 1) 4006 tmp = Simplify(x**(n-1)*SubstForFractionalPower(u, lst[1], n, -a/b + x**n/b, x)) 4007 return [NonfreeFactors(tmp, x), n, lst[1], FreeFactors(tmp, x)/b] 4008 4009def FractionalPowerOfLinear(u, n, v, x): 4010 # If u has a subexpression of the form (a + b*x)**(m/n), FractionalPowerOfLinear(u, 1, False, x) returns [n, a + b*x], else it returns False. 4011 if AtomQ(u) or FreeQ(u, x): 4012 return [n, v] 4013 elif CalculusQ(u): 4014 return False 4015 elif FractionalPowerQ(u): 4016 if LinearQ(u.base, x) and (FalseQ(v) or ZeroQ(u.base - v)): 4017 return [LCM(Denominator(u.exp), n), u.base] 4018 lst = [n, v] 4019 for i in u.args: 4020 lst = FractionalPowerOfLinear(i, lst[0], lst[1], x) 4021 if AtomQ(lst): 4022 return False 4023 return lst 4024 4025def InverseFunctionOfLinear(u, x): 4026 # (* If u has a subexpression of the form g[a+b*x] where g is an inverse function, 4027 # InverseFunctionOfLinear[u,x] returns g[a+b*x]; else it returns False. *) 4028 if AtomQ(u) or CalculusQ(u) or FreeQ(u, x): 4029 return False 4030 elif InverseFunctionQ(u) and LinearQ(u.args[0], x): 4031 return u 4032 for i in u.args: 4033 tmp = InverseFunctionOfLinear(i, x) 4034 if Not(AtomQ(tmp)): 4035 return tmp 4036 return False 4037 4038def InertTrigQ(*args): 4039 if len(args) == 1: 4040 f = args[0] 4041 l = [sin,cos,tan,cot,sec,csc] 4042 return any(Head(f) == i for i in l) 4043 elif len(args) == 2: 4044 f, g = args 4045 if f == g: 4046 return InertTrigQ(f) 4047 return InertReciprocalQ(f, g) or InertReciprocalQ(g, f) 4048 else: 4049 f, g, h = args 4050 return InertTrigQ(g, f) and InertTrigQ(g, h) 4051 4052def InertReciprocalQ(f, g): 4053 return (f.func == sin and g.func == csc) or (f.func == cos and g.func == sec) or (f.func == tan and g.func == cot) 4054 4055def DeactivateTrig(u, x): 4056 # (* u is a function of trig functions of a linear function of x. *) 4057 # (* DeactivateTrig[u,x] returns u with the trig functions replaced with inert trig functions. *) 4058 return FixInertTrigFunction(DeactivateTrigAux(u, x), x) 4059 4060def FixInertTrigFunction(u, x): 4061 return u 4062 4063def DeactivateTrigAux(u, x): 4064 if AtomQ(u): 4065 return u 4066 elif TrigQ(u) and LinearQ(u.args[0], x): 4067 v = ExpandToSum(u.args[0], x) 4068 if SinQ(u): 4069 return sin(v) 4070 elif CosQ(u): 4071 return cos(v) 4072 elif TanQ(u): 4073 return tan(u) 4074 elif CotQ(u): 4075 return cot(v) 4076 elif SecQ(u): 4077 return sec(v) 4078 return csc(v) 4079 elif HyperbolicQ(u) and LinearQ(u.args[0], x): 4080 v = ExpandToSum(I*u.args[0], x) 4081 if SinhQ(u): 4082 return -I*sin(v) 4083 elif CoshQ(u): 4084 return cos(v) 4085 elif TanhQ(u): 4086 return -I*tan(v) 4087 elif CothQ(u): 4088 I*cot(v) 4089 elif SechQ(u): 4090 return sec(v) 4091 return I*csc(v) 4092 return u.func(*[DeactivateTrigAux(i, x) for i in u.args]) 4093 4094def PowerOfInertTrigSumQ(u, func, x): 4095 p_ = Wild('p', exclude=[x]) 4096 q_ = Wild('q', exclude=[x]) 4097 a_ = Wild('a', exclude=[x]) 4098 b_ = Wild('b', exclude=[x]) 4099 c_ = Wild('c', exclude=[x]) 4100 d_ = Wild('d', exclude=[x]) 4101 n_ = Wild('n', exclude=[x]) 4102 w_ = Wild('w') 4103 4104 pattern = (a_ + b_*(c_*func(w_))**p_)**n_ 4105 match = u.match(pattern) 4106 if match: 4107 keys = [a_, b_, c_, n_, p_, w_] 4108 if len(keys) == len(match): 4109 return True 4110 4111 pattern = (a_ + b_*(d_*func(w_))**p_ + c_*(d_*func(w_))**q_)**n_ 4112 match = u.match(pattern) 4113 if match: 4114 keys = [a_, b_, c_, d_, n_, p_, q_, w_] 4115 if len(keys) == len(match): 4116 return True 4117 return False 4118 4119def PiecewiseLinearQ(*args): 4120 # (* If the derivative of u wrt x is a constant wrt x, PiecewiseLinearQ[u,x] returns True; 4121 # else it returns False. *) 4122 if len(args) == 3: 4123 u, v, x = args 4124 return PiecewiseLinearQ(u, x) and PiecewiseLinearQ(v, x) 4125 4126 u, x = args 4127 if LinearQ(u, x): 4128 return True 4129 4130 c_ = Wild('c', exclude=[x]) 4131 F_ = Wild('F', exclude=[x]) 4132 v_ = Wild('v') 4133 match = u.match(Log(c_*F_**v_)) 4134 if match: 4135 if len(match) == 3: 4136 if LinearQ(match[v_], x): 4137 return True 4138 try: 4139 F = type(u) 4140 G = type(u.args[0]) 4141 v = u.args[0].args[0] 4142 if LinearQ(v, x): 4143 if MemberQ([[atanh, tanh], [atanh, coth], [acoth, coth], [acoth, tanh], [atan, tan], [atan, cot], [acot, cot], [acot, tan]], [F, G]): 4144 return True 4145 except: 4146 pass 4147 return False 4148 4149def KnownTrigIntegrandQ(lst, u, x): 4150 if u == 1: 4151 return True 4152 a_ = Wild('a', exclude=[x]) 4153 b_ = Wild('b', exclude=[x, 0]) 4154 func_ = WildFunction('func') 4155 m_ = Wild('m', exclude=[x]) 4156 A_ = Wild('A', exclude=[x]) 4157 B_ = Wild('B', exclude=[x, 0]) 4158 C_ = Wild('C', exclude=[x, 0]) 4159 4160 match = u.match((a_ + b_*func_)**m_) 4161 if match: 4162 func = match[func_] 4163 if LinearQ(func.args[0], x) and MemberQ(lst, func.func): 4164 return True 4165 4166 match = u.match((a_ + b_*func_)**m_*(A_ + B_*func_)) 4167 if match: 4168 func = match[func_] 4169 if LinearQ(func.args[0], x) and MemberQ(lst, func.func): 4170 return True 4171 4172 match = u.match(A_ + C_*func_**2) 4173 if match: 4174 func = match[func_] 4175 if LinearQ(func.args[0], x) and MemberQ(lst, func.func): 4176 return True 4177 4178 match = u.match(A_ + B_*func_ + C_*func_**2) 4179 if match: 4180 func = match[func_] 4181 if LinearQ(func.args[0], x) and MemberQ(lst, func.func): 4182 return True 4183 4184 match = u.match((a_ + b_*func_)**m_*(A_ + C_*func_**2)) 4185 if match: 4186 func = match[func_] 4187 if LinearQ(func.args[0], x) and MemberQ(lst, func.func): 4188 return True 4189 4190 match = u.match((a_ + b_*func_)**m_*(A_ + B_*func_ + C_*func_**2)) 4191 if match: 4192 func = match[func_] 4193 if LinearQ(func.args[0], x) and MemberQ(lst, func.func): 4194 return True 4195 4196 return False 4197 4198def KnownSineIntegrandQ(u, x): 4199 return KnownTrigIntegrandQ([sin, cos], u, x) 4200 4201def KnownTangentIntegrandQ(u, x): 4202 return KnownTrigIntegrandQ([tan], u, x) 4203 4204def KnownCotangentIntegrandQ(u, x): 4205 return KnownTrigIntegrandQ([cot], u, x) 4206 4207def KnownSecantIntegrandQ(u, x): 4208 return KnownTrigIntegrandQ([sec, csc], u, x) 4209 4210def TryPureTanSubst(u, x): 4211 a_ = Wild('a', exclude=[x]) 4212 b_ = Wild('b', exclude=[x]) 4213 c_ = Wild('c', exclude=[x]) 4214 G_ = Wild('G') 4215 4216 F = u.func 4217 try: 4218 if MemberQ([atan, acot, atanh, acoth], F): 4219 match = u.args[0].match(c_*(a_ + b_*G_)) 4220 if match: 4221 if len(match) == 4: 4222 G = match[G_] 4223 if MemberQ([tan, cot, tanh, coth], G.func): 4224 if LinearQ(G.args[0], x): 4225 return True 4226 except: 4227 pass 4228 4229 return False 4230 4231def TryTanhSubst(u, x): 4232 if LogQ(u): 4233 return False 4234 elif not FalseQ(FunctionOfLinear(u, x)): 4235 return False 4236 4237 a_ = Wild('a', exclude=[x]) 4238 m_ = Wild('m', exclude=[x]) 4239 p_ = Wild('p', exclude=[x]) 4240 r_, s_, t_, n_, b_, f_, g_ = map(Wild, 'rstnbfg') 4241 4242 match = u.match(r_*(s_ + t_)**n_) 4243 if match: 4244 if len(match) == 4: 4245 r, s, t, n = [match[i] for i in [r_, s_, t_, n_]] 4246 if IntegerQ(n) and PositiveQ(n): 4247 return False 4248 4249 match = u.match(1/(a_ + b_*f_**n_)) 4250 if match: 4251 if len(match) == 4: 4252 a, b, f, n = [match[i] for i in [a_, b_, f_, n_]] 4253 if SinhCoshQ(f) and IntegerQ(n) and n > 2: 4254 return False 4255 4256 match = u.match(f_*g_) 4257 if match: 4258 if len(match) == 2: 4259 f, g = match[f_], match[g_] 4260 if SinhCoshQ(f) and SinhCoshQ(g): 4261 if IntegersQ(f.args[0]/x, g.args[0]/x): 4262 return False 4263 4264 match = u.match(r_*(a_*s_**m_)**p_) 4265 if match: 4266 if len(match) == 5: 4267 r, a, s, m, p = [match[i] for i in [r_, a_, s_, m_, p_]] 4268 if Not(m==2 and (s == Sech(x) or s == Csch(x))): 4269 return False 4270 4271 if u != ExpandIntegrand(u, x): 4272 return False 4273 4274 return True 4275 4276def TryPureTanhSubst(u, x): 4277 F = u.func 4278 a_ = Wild('a', exclude=[x]) 4279 G_ = Wild('G') 4280 4281 if F == sym_log: 4282 return False 4283 4284 match = u.args[0].match(a_*G_) 4285 if match and len(match) == 2: 4286 G = match[G_].func 4287 if MemberQ([atanh, acoth], F) and MemberQ([tanh, coth], G): 4288 return False 4289 4290 if u != ExpandIntegrand(u, x): 4291 return False 4292 4293 return True 4294 4295def AbsurdNumberGCD(*seq): 4296 # (* m, n, ... must be absurd numbers. AbsurdNumberGCD[m,n,...] returns the gcd of m, n, ... *) 4297 lst = list(seq) 4298 if Length(lst) == 1: 4299 return First(lst) 4300 return AbsurdNumberGCDList(FactorAbsurdNumber(First(lst)), FactorAbsurdNumber(AbsurdNumberGCD(*Rest(lst)))) 4301 4302def AbsurdNumberGCDList(lst1, lst2): 4303 # (* lst1 and lst2 must be absurd number prime factorization lists. *) 4304 # (* AbsurdNumberGCDList[lst1,lst2] returns the gcd of the absurd numbers represented by lst1 and lst2. *) 4305 if lst1 == []: 4306 return Mul(*[i[0]**Min(i[1],0) for i in lst2]) 4307 elif lst2 == []: 4308 return Mul(*[i[0]**Min(i[1],0) for i in lst1]) 4309 elif lst1[0][0] == lst2[0][0]: 4310 if lst1[0][1] <= lst2[0][1]: 4311 return lst1[0][0]**lst1[0][1]*AbsurdNumberGCDList(Rest(lst1), Rest(lst2)) 4312 return lst1[0][0]**lst2[0][1]*AbsurdNumberGCDList(Rest(lst1), Rest(lst2)) 4313 elif lst1[0][0] < lst2[0][0]: 4314 if lst1[0][1] < 0: 4315 return lst1[0][0]**lst1[0][1]*AbsurdNumberGCDList(Rest(lst1), lst2) 4316 return AbsurdNumberGCDList(Rest(lst1), lst2) 4317 elif lst2[0][1] < 0: 4318 return lst2[0][0]**lst2[0][1]*AbsurdNumberGCDList(lst1, Rest(lst2)) 4319 return AbsurdNumberGCDList(lst1, Rest(lst2)) 4320 4321def ExpandTrigExpand(u, F, v, m, n, x): 4322 w = Expand(TrigExpand(F.xreplace({x: n*x}))**m).xreplace({x: v}) 4323 if SumQ(w): 4324 t = 0 4325 for i in w.args: 4326 t += u*i 4327 return t 4328 else: 4329 return u*w 4330 4331def ExpandTrigReduce(*args): 4332 if len(args) == 3: 4333 u = args[0] 4334 v = args[1] 4335 x = args[2] 4336 w = ExpandTrigReduce(v, x) 4337 if SumQ(w): 4338 t = 0 4339 for i in w.args: 4340 t += u*i 4341 return t 4342 else: 4343 return u*w 4344 else: 4345 u = args[0] 4346 x = args[1] 4347 return ExpandTrigReduceAux(u, x) 4348 4349def ExpandTrigReduceAux(u, x): 4350 v = TrigReduce(u).expand() 4351 if SumQ(v): 4352 t = 0 4353 for i in v.args: 4354 t += NormalizeTrig(i, x) 4355 return t 4356 return NormalizeTrig(v, x) 4357 4358def NormalizeTrig(v, x): 4359 a = Wild('a', exclude=[x]) 4360 n = Wild('n', exclude=[x, 0]) 4361 F = Wild('F') 4362 expr = a*F**n 4363 M = v.match(expr) 4364 if M and len(M[F].args) == 1 and PolynomialQ(M[F].args[0], x) and Exponent(M[F].args[0], x) > 0: 4365 u = M[F].args[0] 4366 return M[a]*M[F].xreplace({u: ExpandToSum(u, x)})**M[n] 4367 else: 4368 return v 4369#================================= 4370def TrigToExp(expr): 4371 ex = expr.rewrite(sin, sym_exp).rewrite(cos, sym_exp).rewrite(tan, sym_exp).rewrite(sec, sym_exp).rewrite(csc, sym_exp).rewrite(cot, sym_exp) 4372 return ex.replace(sym_exp, rubi_exp) 4373 4374def ExpandTrigToExp(u, *args): 4375 if len(args) == 1: 4376 x = args[0] 4377 return ExpandTrigToExp(1, u, x) 4378 else: 4379 v = args[0] 4380 x = args[1] 4381 w = TrigToExp(v) 4382 k = 0 4383 if SumQ(w): 4384 for i in w.args: 4385 k += SimplifyIntegrand(u*i, x) 4386 w = k 4387 else: 4388 w = SimplifyIntegrand(u*w, x) 4389 return ExpandIntegrand(FreeFactors(w, x), NonfreeFactors(w, x),x) 4390#====================================== 4391def TrigReduce(i): 4392 """ 4393 TrigReduce(expr) rewrites products and powers of trigonometric functions in expr in terms of trigonometric functions with combined arguments. 4394 4395 Examples 4396 ======== 4397 4398 >>> from sympy import sin, cos 4399 >>> from sympy.integrals.rubi.utility_function import TrigReduce 4400 >>> from sympy.abc import x 4401 >>> TrigReduce(cos(x)**2) 4402 cos(2*x)/2 + 1/2 4403 >>> TrigReduce(cos(x)**2*sin(x)) 4404 sin(x)/4 + sin(3*x)/4 4405 >>> TrigReduce(cos(x)**2+sin(x)) 4406 sin(x) + cos(2*x)/2 + 1/2 4407 4408 """ 4409 if SumQ(i): 4410 t = 0 4411 for k in i.args: 4412 t += TrigReduce(k) 4413 return t 4414 if ProductQ(i): 4415 if any(PowerQ(k) for k in i.args): 4416 if (i.rewrite((sin, sinh), sym_exp).rewrite((cos, cosh), sym_exp).expand().rewrite(sym_exp, sin)).has(I, cosh, sinh): 4417 return i.rewrite((sin, sinh), sym_exp).rewrite((cos, cosh), sym_exp).expand().rewrite(sym_exp, sin).simplify() 4418 else: 4419 return i.rewrite((sin, sinh), sym_exp).rewrite((cos, cosh), sym_exp).expand().rewrite(sym_exp, sin) 4420 else: 4421 a = Wild('a') 4422 b = Wild('b') 4423 v = Wild('v') 4424 Match = i.match(v*sin(a)*cos(b)) 4425 if Match: 4426 a = Match[a] 4427 b = Match[b] 4428 v = Match[v] 4429 return i.subs(v*sin(a)*cos(b), v*S(1)/2*(sin(a + b) + sin(a - b))) 4430 Match = i.match(v*sin(a)*sin(b)) 4431 if Match: 4432 a = Match[a] 4433 b = Match[b] 4434 v = Match[v] 4435 return i.subs(v*sin(a)*sin(b), v*S(1)/2*cos(a - b) - cos(a + b)) 4436 Match = i.match(v*cos(a)*cos(b)) 4437 if Match: 4438 a = Match[a] 4439 b = Match[b] 4440 v = Match[v] 4441 return i.subs(v*cos(a)*cos(b), v*S(1)/2*cos(a + b) + cos(a - b)) 4442 Match = i.match(v*sinh(a)*cosh(b)) 4443 if Match: 4444 a = Match[a] 4445 b = Match[b] 4446 v = Match[v] 4447 return i.subs(v*sinh(a)*cosh(b), v*S(1)/2*(sinh(a + b) + sinh(a - b))) 4448 Match = i.match(v*sinh(a)*sinh(b)) 4449 if Match: 4450 a = Match[a] 4451 b = Match[b] 4452 v = Match[v] 4453 return i.subs(v*sinh(a)*sinh(b), v*S(1)/2*cosh(a - b) - cosh(a + b)) 4454 Match = i.match(v*cosh(a)*cosh(b)) 4455 if Match: 4456 a = Match[a] 4457 b = Match[b] 4458 v = Match[v] 4459 return i.subs(v*cosh(a)*cosh(b), v*S(1)/2*cosh(a + b) + cosh(a - b)) 4460 4461 if PowerQ(i): 4462 if i.has(sin, sinh): 4463 if (i.rewrite((sin, sinh), sym_exp).expand().rewrite(sym_exp, sin)).has(I, cosh, sinh): 4464 return i.rewrite((sin, sinh), sym_exp).expand().rewrite(sym_exp, sin).simplify() 4465 else: 4466 return i.rewrite((sin, sinh), sym_exp).expand().rewrite(sym_exp, sin) 4467 if i.has(cos, cosh): 4468 if (i.rewrite((cos, cosh), sym_exp).expand().rewrite(sym_exp, cos)).has(I, cosh, sinh): 4469 return i.rewrite((cos, cosh), sym_exp).expand().rewrite(sym_exp, cos).simplify() 4470 else: 4471 return i.rewrite((cos, cosh), sym_exp).expand().rewrite(sym_exp, cos) 4472 return i 4473 4474def FunctionOfTrig(u, *args): 4475 # If u is a function of trig functions of v where v is a linear function of x, 4476 # FunctionOfTrig[u,x] returns v; else it returns False. 4477 if len(args) == 1: 4478 x = args[0] 4479 v = FunctionOfTrig(u, None, x) 4480 if v: 4481 return v 4482 else: 4483 return False 4484 else: 4485 v, x = args 4486 if AtomQ(u): 4487 if u == x: 4488 return False 4489 else: 4490 return v 4491 if TrigQ(u) and LinearQ(u.args[0], x): 4492 if v is None: 4493 return u.args[0] 4494 else: 4495 a = Coefficient(v, x, 0) 4496 b = Coefficient(v, x, 1) 4497 c = Coefficient(u.args[0], x, 0) 4498 d = Coefficient(u.args[0], x, 1) 4499 if ZeroQ(a*d - b*c) and RationalQ(b/d): 4500 return a/Numerator(b/d) + b*x/Numerator(b/d) 4501 else: 4502 return False 4503 if HyperbolicQ(u) and LinearQ(u.args[0], x): 4504 if v is None: 4505 return I*u.args[0] 4506 a = Coefficient(v, x, 0) 4507 b = Coefficient(v, x, 1) 4508 c = I*Coefficient(u.args[0], x, 0) 4509 d = I*Coefficient(u.args[0], x, 1) 4510 if ZeroQ(a*d - b*c) and RationalQ(b/d): 4511 return a/Numerator(b/d) + b*x/Numerator(b/d) 4512 else: 4513 return False 4514 if CalculusQ(u): 4515 return False 4516 else: 4517 w = v 4518 for i in u.args: 4519 w = FunctionOfTrig(i, w, x) 4520 if FalseQ(w): 4521 return False 4522 return w 4523 4524def AlgebraicTrigFunctionQ(u, x): 4525 # If u is algebraic function of trig functions, AlgebraicTrigFunctionQ(u,x) returns True; else it returns False. 4526 if AtomQ(u): 4527 return True 4528 elif TrigQ(u) and LinearQ(u.args[0], x): 4529 return True 4530 elif HyperbolicQ(u) and LinearQ(u.args[0], x): 4531 return True 4532 elif PowerQ(u): 4533 if FreeQ(u.exp, x): 4534 return AlgebraicTrigFunctionQ(u.base, x) 4535 elif ProductQ(u) or SumQ(u): 4536 for i in u.args: 4537 if not AlgebraicTrigFunctionQ(i, x): 4538 return False 4539 return True 4540 4541 return False 4542 4543def FunctionOfHyperbolic(u, *x): 4544 # If u is a function of hyperbolic trig functions of v where v is linear in x, 4545 # FunctionOfHyperbolic(u,x) returns v; else it returns False. 4546 if len(x) == 1: 4547 x = x[0] 4548 v = FunctionOfHyperbolic(u, None, x) 4549 if v is None: 4550 return False 4551 else: 4552 return v 4553 else: 4554 v = x[0] 4555 x = x[1] 4556 if AtomQ(u): 4557 if u == x: 4558 return False 4559 return v 4560 if HyperbolicQ(u) and LinearQ(u.args[0], x): 4561 if v is None: 4562 return u.args[0] 4563 a = Coefficient(v, x, 0) 4564 b = Coefficient(v, x, 1) 4565 c = Coefficient(u.args[0], x, 0) 4566 d = Coefficient(u.args[0], x, 1) 4567 if ZeroQ(a*d - b*c) and RationalQ(b/d): 4568 return a/Numerator(b/d) + b*x/Numerator(b/d) 4569 else: 4570 return False 4571 if CalculusQ(u): 4572 return False 4573 w = v 4574 for i in u.args: 4575 if w == FunctionOfHyperbolic(i, w, x): 4576 return False 4577 return w 4578 4579def FunctionOfQ(v, u, x, PureFlag=False): 4580 # v is a function of x. If u is a function of v, FunctionOfQ(v, u, x) returns True; else it returns False. *) 4581 if FreeQ(u, x): 4582 return False 4583 elif AtomQ(v): 4584 return True 4585 elif ProductQ(v) and Not(EqQ(FreeFactors(v, x), 1)): 4586 return FunctionOfQ(NonfreeFactors(v, x), u, x, PureFlag) 4587 elif PureFlag: 4588 if SinQ(v) or CscQ(v): 4589 return PureFunctionOfSinQ(u, v.args[0], x) 4590 elif CosQ(v) or SecQ(v): 4591 return PureFunctionOfCosQ(u, v.args[0], x) 4592 elif TanQ(v): 4593 return PureFunctionOfTanQ(u, v.args[0], x) 4594 elif CotQ(v): 4595 return PureFunctionOfCotQ(u, v.args[0], x) 4596 elif SinhQ(v) or CschQ(v): 4597 return PureFunctionOfSinhQ(u, v.args[0], x) 4598 elif CoshQ(v) or SechQ(v): 4599 return PureFunctionOfCoshQ(u, v.args[0], x) 4600 elif TanhQ(v): 4601 return PureFunctionOfTanhQ(u, v.args[0], x) 4602 elif CothQ(v): 4603 return PureFunctionOfCothQ(u, v.args[0], x) 4604 else: 4605 return FunctionOfExpnQ(u, v, x) != False 4606 elif SinQ(v) or CscQ(v): 4607 return FunctionOfSinQ(u, v.args[0], x) 4608 elif CosQ(v) or SecQ(v): 4609 return FunctionOfCosQ(u, v.args[0], x) 4610 elif TanQ(v) or CotQ(v): 4611 FunctionOfTanQ(u, v.args[0], x) 4612 elif SinhQ(v) or CschQ(v): 4613 return FunctionOfSinhQ(u, v.args[0], x) 4614 elif CoshQ(v) or SechQ(v): 4615 return FunctionOfCoshQ(u, v.args[0], x) 4616 elif TanhQ(v) or CothQ(v): 4617 return FunctionOfTanhQ(u, v.args[0], x) 4618 return FunctionOfExpnQ(u, v, x) != False 4619 4620 4621 4622def FunctionOfExpnQ(u, v, x): 4623 if u == v: 4624 return 1 4625 if AtomQ(u): 4626 if u == x: 4627 return False 4628 else: 4629 return 0 4630 if CalculusQ(u): 4631 return False 4632 if PowerQ(u): 4633 if FreeQ(u.exp, x): 4634 if ZeroQ(u.base - v): 4635 if IntegerQ(u.exp): 4636 return u.exp 4637 else: 4638 return 1 4639 if PowerQ(v): 4640 if FreeQ(v.exp, x) and ZeroQ(u.base-v.base): 4641 if RationalQ(v.exp): 4642 if RationalQ(u.exp) and IntegerQ(u.exp/v.exp) and (v.exp>0 or u.exp<0): 4643 return u.exp/v.exp 4644 else: 4645 return False 4646 if IntegerQ(Simplify(u.exp/v.exp)): 4647 return Simplify(u.exp/v.exp) 4648 else: 4649 return False 4650 return FunctionOfExpnQ(u.base, v, x) 4651 if ProductQ(u) and Not(EqQ(FreeFactors(u, x), 1)): 4652 return FunctionOfExpnQ(NonfreeFactors(u, x), v, x) 4653 if ProductQ(u) and ProductQ(v): 4654 deg1 = FunctionOfExpnQ(First(u), First(v), x) 4655 if deg1==False: 4656 return False 4657 deg2 = FunctionOfExpnQ(Rest(u), Rest(v), x); 4658 if deg1==deg2 and FreeQ(Simplify(u/v^deg1), x): 4659 return deg1 4660 else: 4661 return False 4662 lst = [] 4663 for i in u.args: 4664 if FunctionOfExpnQ(i, v, x) is False: 4665 return False 4666 lst.append(FunctionOfExpnQ(i, v, x)) 4667 return Apply(GCD, lst) 4668 4669def PureFunctionOfSinQ(u, v, x): 4670 # If u is a pure function of Sin(v) and/or Csc(v), PureFunctionOfSinQ(u, v, x) returns True; else it returns False. 4671 if AtomQ(u): 4672 return u!=x 4673 if CalculusQ(u): 4674 return False 4675 if TrigQ(u) and ZeroQ(u.args[0]-v): 4676 return SinQ(u) or CscQ(u) 4677 for i in u.args: 4678 if Not(PureFunctionOfSinQ(i, v, x)): 4679 return False 4680 return True 4681 4682def PureFunctionOfCosQ(u, v, x): 4683 # If u is a pure function of Cos(v) and/or Sec(v), PureFunctionOfCosQ(u, v, x) returns True; else it returns False. 4684 if AtomQ(u): 4685 return u!=x 4686 if CalculusQ(u): 4687 return False 4688 if TrigQ(u) and ZeroQ(u.args[0]-v): 4689 return CosQ(u) or SecQ(u) 4690 for i in u.args: 4691 if Not(PureFunctionOfCosQ(i, v, x)): 4692 return False 4693 return True 4694 4695def PureFunctionOfTanQ(u, v, x): 4696 # If u is a pure function of Tan(v) and/or Cot(v), PureFunctionOfTanQ(u, v, x) returns True; else it returns False. 4697 if AtomQ(u): 4698 return u!=x 4699 if CalculusQ(u): 4700 return False 4701 if TrigQ(u) and ZeroQ(u.args[0]-v): 4702 return TanQ(u) or CotQ(u) 4703 for i in u.args: 4704 if Not(PureFunctionOfTanQ(i, v, x)): 4705 return False 4706 return True 4707 4708def PureFunctionOfCotQ(u, v, x): 4709 # If u is a pure function of Cot(v), PureFunctionOfCotQ(u, v, x) returns True; else it returns False. 4710 if AtomQ(u): 4711 return u!=x 4712 if CalculusQ(u): 4713 return False 4714 if TrigQ(u) and ZeroQ(u.args[0]-v): 4715 return CotQ(u) 4716 for i in u.args: 4717 if Not(PureFunctionOfCotQ(i, v, x)): 4718 return False 4719 return True 4720 4721def FunctionOfCosQ(u, v, x): 4722 # If u is a function of Cos[v], FunctionOfCosQ[u,v,x] returns True; else it returns False. 4723 if AtomQ(u): 4724 return u != x 4725 elif CalculusQ(u): 4726 return False 4727 elif TrigQ(u) and IntegerQuotientQ(u.args[0], v): 4728 # Basis: If m integer, Cos[m*v]^n is a function of Cos[v]. *) 4729 return CosQ(u) or SecQ(u) 4730 elif IntegerPowerQ(u): 4731 if TrigQ(u.base) and IntegerQuotientQ(u.base.args[0], v): 4732 if EvenQ(u.exp): 4733 # Basis: If m integer and n even, Trig[m*v]^n is a function of Cos[v]. *) 4734 return True 4735 return FunctionOfCosQ(u.base, v, x) 4736 elif ProductQ(u): 4737 lst = FindTrigFactor(sin, csc, u, v, False) 4738 if ListQ(lst): 4739 # (* Basis: If m integer and n odd, Sin[m*v]^n == Sin[v]*u where u is a function of Cos[v]. *) 4740 return FunctionOfCosQ(Sin(v)*lst[1], v, x) 4741 lst = FindTrigFactor(tan, cot, u, v, True) 4742 if ListQ(lst): 4743 # (* Basis: If m integer and n odd, Tan[m*v]^n == Sin[v]*u where u is a function of Cos[v]. *) 4744 return FunctionOfCosQ(Sin(v)*lst[1], v, x) 4745 return all(FunctionOfCosQ(i, v, x) for i in u.args) 4746 return all(FunctionOfCosQ(i, v, x) for i in u.args) 4747 4748def FunctionOfSinQ(u, v, x): 4749 # If u is a function of Sin[v], FunctionOfSinQ[u,v,x] returns True; else it returns False. 4750 if AtomQ(u): 4751 return u != x 4752 elif CalculusQ(u): 4753 return False 4754 elif TrigQ(u) and IntegerQuotientQ(u.args[0], v): 4755 if OddQuotientQ(u.args[0], v): 4756 # Basis: If m odd, Sin[m*v]^n is a function of Sin[v]. 4757 return SinQ(u) or CscQ(u) 4758 # Basis: If m even, Cos[m*v]^n is a function of Sin[v]. 4759 return CosQ(u) or SecQ(u) 4760 elif IntegerPowerQ(u): 4761 if TrigQ(u.base) and IntegerQuotientQ(u.base.args[0], v): 4762 if EvenQ(u.exp): 4763 # Basis: If m integer and n even, Hyper[m*v]^n is a function of Sin[v]. 4764 return True 4765 return FunctionOfSinQ(u.base, v, x) 4766 elif ProductQ(u): 4767 if CosQ(u.args[0]) and SinQ(u.args[1]) and ZeroQ(u.args[0].args[0] - v/2) and ZeroQ(u.args[1].args[0] - v/2): 4768 return FunctionOfSinQ(Drop(u, 2), v, x) 4769 lst = FindTrigFactor(sin, csch, u, v, False) 4770 if ListQ(lst) and EvenQuotientQ(lst[0], v): 4771 # Basis: If m even and n odd, Sin[m*v]^n == Cos[v]*u where u is a function of Sin[v]. 4772 return FunctionOfSinQ(Cos(v)*lst[1], v, x) 4773 lst = FindTrigFactor(cos, sec, u, v, False) 4774 if ListQ(lst) and OddQuotientQ(lst[0], v): 4775 # Basis: If m odd and n odd, Cos[m*v]^n == Cos[v]*u where u is a function of Sin[v]. 4776 return FunctionOfSinQ(Cos(v)*lst[1], v, x) 4777 lst = FindTrigFactor(tan, cot, u, v, True) 4778 if ListQ(lst): 4779 # Basis: If m integer and n odd, Tan[m*v]^n == Cos[v]*u where u is a function of Sin[v]. 4780 return FunctionOfSinQ(Cos(v)*lst[1], v, x) 4781 return all(FunctionOfSinQ(i, v, x) for i in u.args) 4782 return all(FunctionOfSinQ(i, v, x) for i in u.args) 4783 4784def OddTrigPowerQ(u, v, x): 4785 if SinQ(u) or CosQ(u) or SecQ(u) or CscQ(u): 4786 return OddQuotientQ(u.args[0], v) 4787 if PowerQ(u): 4788 return OddQ(u.exp) and OddTrigPowerQ(u.base, v, x) 4789 if ProductQ(u): 4790 if not FreeFactors(u, x) == 1: 4791 return OddTrigPowerQ(NonfreeFactors(u, x), v, x) 4792 lst = [] 4793 for i in u.args: 4794 if Not(FunctionOfTanQ(i, v, x)): 4795 lst.append(i) 4796 if lst == []: 4797 return True 4798 return Length(lst)==1 and OddTrigPowerQ(lst[0], v, x) 4799 if SumQ(u): 4800 return all(OddTrigPowerQ(i, v, x) for i in u.args) 4801 return False 4802 4803def FunctionOfTanQ(u, v, x): 4804 # If u is a function of the form f[Tan[v],Cot[v]] where f is independent of x, 4805 # FunctionOfTanQ[u,v,x] returns True; else it returns False. 4806 if AtomQ(u): 4807 return u != x 4808 elif CalculusQ(u): 4809 return False 4810 elif TrigQ(u) and IntegerQuotientQ(u.args[0], v): 4811 return TanQ(u) or CotQ(u) or EvenQuotientQ(u.args[0], v) 4812 elif PowerQ(u): 4813 if EvenQ(u.exp) and TrigQ(u.base) and IntegerQuotientQ(u.base.args[0], v): 4814 return True 4815 elif EvenQ(u.exp) and SumQ(u.base): 4816 return FunctionOfTanQ(Expand(u.base**2, v, x)) 4817 if ProductQ(u): 4818 lst = [] 4819 for i in u.args: 4820 if Not(FunctionOfTanQ(i, v, x)): 4821 lst.append(i) 4822 if lst == []: 4823 return True 4824 return Length(lst)==2 and OddTrigPowerQ(lst[0], v, x) and OddTrigPowerQ(lst[1], v, x) 4825 return all(FunctionOfTanQ(i, v, x) for i in u.args) 4826 4827def FunctionOfTanWeight(u, v, x): 4828 # (* u is a function of the form f[Tan[v],Cot[v]] where f is independent of x. 4829 # FunctionOfTanWeight[u,v,x] returns a nonnegative number if u is best considered a function 4830 # of Tan[v]; else it returns a negative number. *) 4831 if AtomQ(u): 4832 return S(0) 4833 elif CalculusQ(u): 4834 return S(0) 4835 elif TrigQ(u) and IntegerQuotientQ(u.args[0], v): 4836 if TanQ(u) and ZeroQ(u.args[0] - v): 4837 return S(1) 4838 elif CotQ(u) and ZeroQ(u.args[0] - v): 4839 return S(-1) 4840 return S(0) 4841 elif PowerQ(u): 4842 if EvenQ(u.exp) and TrigQ(u.base) and IntegerQuotientQ(u.base.args[0], v): 4843 if TanQ(u.base) or CosQ(u.base) or SecQ(u.base): 4844 return S(1) 4845 return S(-1) 4846 if ProductQ(u): 4847 if all(FunctionOfTanQ(i, v, x) for i in u.args): 4848 return Add(*[FunctionOfTanWeight(i, v, x) for i in u.args]) 4849 return S(0) 4850 return Add(*[FunctionOfTanWeight(i, v, x) for i in u.args]) 4851 4852def FunctionOfTrigQ(u, v, x): 4853 # If u (x) is equivalent to a function of the form f (Sin[v],Cos[v],Tan[v],Cot[v],Sec[v],Csc[v]) where f is independent of x, FunctionOfTrigQ[u,v,x] returns True; else it returns False. 4854 if AtomQ(u): 4855 return u != x 4856 elif CalculusQ(u): 4857 return False 4858 elif TrigQ(u) and IntegerQuotientQ(u.args[0], v): 4859 return True 4860 return all(FunctionOfTrigQ(i, v, x) for i in u.args) 4861 4862def FunctionOfDensePolynomialsQ(u, x): 4863 # If all occurrences of x in u (x) are in dense polynomials, FunctionOfDensePolynomialsQ[u,x] returns True; else it returns False. 4864 if FreeQ(u, x): 4865 return True 4866 if PolynomialQ(u, x): 4867 return Length(ExponentList(u, x)) > 1 4868 return all(FunctionOfDensePolynomialsQ(i, x) for i in u.args) 4869 4870def FunctionOfLog(u, *args): 4871 # If u (x) is equivalent to an expression of the form f (Log[a*x^n]), FunctionOfLog[u,x] returns 4872 # the list {f (x),a*x^n,n}; else it returns False. 4873 if len(args) == 1: 4874 x = args[0] 4875 lst = FunctionOfLog(u, False, False, x) 4876 if AtomQ(lst) or FalseQ(lst[1]) or not isinstance(x, Symbol): 4877 return False 4878 else: 4879 return lst 4880 else: 4881 v = args[0] 4882 n = args[1] 4883 x = args[2] 4884 if AtomQ(u): 4885 if u==x: 4886 return False 4887 else: 4888 return [u, v, n] 4889 if CalculusQ(u): 4890 return False 4891 lst = BinomialParts(u.args[0], x) 4892 if LogQ(u) and ListQ(lst) and ZeroQ(lst[0]): 4893 if FalseQ(v) or u.args[0] == v: 4894 return [x, u.args[0], lst[2]] 4895 else: 4896 return False 4897 lst = [0, v, n] 4898 l = [] 4899 for i in u.args: 4900 lst = FunctionOfLog(i, lst[1], lst[2], x) 4901 if AtomQ(lst): 4902 return False 4903 else: 4904 l.append(lst[0]) 4905 4906 return [u.func(*l), lst[1], lst[2]] 4907 4908def PowerVariableExpn(u, m, x): 4909 # If m is an integer, u is an expression of the form f((c*x)**n) and g=GCD(m,n)>1, 4910 # PowerVariableExpn(u,m,x) returns the list {x**(m/g)*f((c*x)**(n/g)),g,c}; else it returns False. 4911 if IntegerQ(m): 4912 lst = PowerVariableDegree(u, m, 1, x) 4913 if not lst: 4914 return False 4915 else: 4916 return [x**(m/lst[0])*PowerVariableSubst(u, lst[0], x), lst[0], lst[1]] 4917 else: 4918 return False 4919 4920def PowerVariableDegree(u, m, c, x): 4921 if FreeQ(u, x): 4922 return [m, c] 4923 if AtomQ(u) or CalculusQ(u): 4924 return False 4925 if PowerQ(u): 4926 if FreeQ(u.base/x, x): 4927 if ZeroQ(m) or m == u.exp and c == u.base/x: 4928 return [u.exp, u.base/x] 4929 if IntegerQ(u.exp) and IntegerQ(m) and GCD(m, u.exp)>1 and c==u.base/x: 4930 return [GCD(m, u.exp), c] 4931 else: 4932 return False 4933 lst = [m, c] 4934 for i in u.args: 4935 if PowerVariableDegree(i, lst[0], lst[1], x) == False: 4936 return False 4937 lst1 = PowerVariableDegree(i, lst[0], lst[1], x) 4938 if not lst1: 4939 return False 4940 else: 4941 return lst1 4942 4943def PowerVariableSubst(u, m, x): 4944 if FreeQ(u, x) or AtomQ(u) or CalculusQ(u): 4945 return u 4946 if PowerQ(u): 4947 if FreeQ(u.base/x, x): 4948 return x**(u.exp/m) 4949 if ProductQ(u): 4950 l = 1 4951 for i in u.args: 4952 l *= (PowerVariableSubst(i, m, x)) 4953 return l 4954 if SumQ(u): 4955 l = 0 4956 for i in u.args: 4957 l += (PowerVariableSubst(i, m, x)) 4958 return l 4959 return u 4960 4961def EulerIntegrandQ(expr, x): 4962 a = Wild('a', exclude=[x]) 4963 b = Wild('b', exclude=[x]) 4964 n = Wild('n', exclude=[x, 0]) 4965 m = Wild('m', exclude=[x, 0]) 4966 p = Wild('p', exclude=[x, 0]) 4967 u = Wild('u') 4968 v = Wild('v') 4969 # Pattern 1 4970 M = expr.match((a*x + b*u**n)**p) 4971 if M: 4972 if len(M) == 5 and FreeQ([M[a], M[b]], x) and IntegerQ(M[n] + 1/2) and QuadraticQ(M[u], x) and Not(RationalQ(M[p])) or NegativeIntegerQ(M[p]) and Not(BinomialQ(M[u], x)): 4973 return True 4974 # Pattern 2 4975 M = expr.match(v**m*(a*x + b*u**n)**p) 4976 if M: 4977 if len(M) == 6 and FreeQ([M[a], M[b]], x) and ZeroQ(M[u] - M[v]) and IntegersQ(2*M[m], M[n] + 1/2) and QuadraticQ(M[u], x) and Not(RationalQ(M[p])) or NegativeIntegerQ(M[p]) and Not(BinomialQ(M[u], x)): 4978 return True 4979 # Pattern 3 4980 M = expr.match(u**n*v**p) 4981 if M: 4982 if len(M) == 3 and NegativeIntegerQ(M[p]) and IntegerQ(M[n] + 1/2) and QuadraticQ(M[u], x) and QuadraticQ(M[v], x) and Not(BinomialQ(M[v], x)): 4983 return True 4984 else: 4985 return False 4986 4987def FunctionOfSquareRootOfQuadratic(u, *args): 4988 if len(args) == 1: 4989 x = args[0] 4990 pattern = Pattern(UtilityOperator(x_**WC('m', 1)*(a_ + x**WC('n', 1)*WC('b', 1))**p_, x), CustomConstraint(lambda a, b, m, n, p, x: FreeQ([a, b, m, n, p], x))) 4991 M = is_match(UtilityOperator(u, args[0]), pattern) 4992 if M: 4993 return False 4994 tmp = FunctionOfSquareRootOfQuadratic(u, False, x) 4995 if AtomQ(tmp) or FalseQ(tmp[0]): 4996 return False 4997 tmp = tmp[0] 4998 a = Coefficient(tmp, x, 0) 4999 b = Coefficient(tmp, x, 1) 5000 c = Coefficient(tmp, x, 2) 5001 if ZeroQ(a) and ZeroQ(b) or ZeroQ(b**2-4*a*c): 5002 return False 5003 if PosQ(c): 5004 sqrt = Rt(c, S(2)); 5005 q = a*sqrt + b*x + sqrt*x**2 5006 r = b + 2*sqrt*x 5007 return [Simplify(SquareRootOfQuadraticSubst(u, q/r, (-a+x**2)/r, x)*q/r**2), Simplify(sqrt*x + Sqrt(tmp)), 2] 5008 if PosQ(a): 5009 sqrt = Rt(a, S(2)) 5010 q = c*sqrt - b*x + sqrt*x**2 5011 r = c - x**2 5012 return [Simplify(SquareRootOfQuadraticSubst(u, q/r, (-b+2*sqrt*x)/r, x)*q/r**2), Simplify((-sqrt+Sqrt(tmp))/x), 1] 5013 sqrt = Rt(b**2 - 4*a*c, S(2)) 5014 r = c - x**2 5015 return[Simplify(-sqrt*SquareRootOfQuadraticSubst(u, -sqrt*x/r, -(b*c+c*sqrt+(-b+sqrt)*x**2)/(2*c*r), x)*x/r**2), FullSimplify(2*c*Sqrt(tmp)/(b-sqrt+2*c*x)), 3] 5016 else: 5017 v = args[0] 5018 x = args[1] 5019 if AtomQ(u) or FreeQ(u, x): 5020 return [v] 5021 if PowerQ(u): 5022 if FreeQ(u.exp, x): 5023 if FractionQ(u.exp) and Denominator(u.exp) == 2 and PolynomialQ(u.base, x) and Exponent(u.base, x) == 2: 5024 if FalseQ(v) or u.base == v: 5025 return [u.base] 5026 else: 5027 return False 5028 return FunctionOfSquareRootOfQuadratic(u.base, v, x) 5029 if ProductQ(u) or SumQ(u): 5030 lst = [v] 5031 lst1 = [] 5032 for i in u.args: 5033 if FunctionOfSquareRootOfQuadratic(i, lst[0], x) == False: 5034 return False 5035 lst1 = FunctionOfSquareRootOfQuadratic(i, lst[0], x) 5036 return lst1 5037 else: 5038 return False 5039 5040def SquareRootOfQuadraticSubst(u, vv, xx, x): 5041 # SquareRootOfQuadraticSubst(u, vv, xx, x) returns u with fractional powers replaced by vv raised to the power and x replaced by xx. 5042 if AtomQ(u) or FreeQ(u, x): 5043 if u==x: 5044 return xx 5045 return u 5046 if PowerQ(u): 5047 if FreeQ(u.exp, x): 5048 if FractionQ(u.exp) and Denominator(u.exp)==2 and PolynomialQ(u.base, x) and Exponent(u.base, x)==2: 5049 return vv**Numerator(u.exp) 5050 return SquareRootOfQuadraticSubst(u.base, vv, xx, x)**u.exp 5051 elif SumQ(u): 5052 t = 0 5053 for i in u.args: 5054 t += SquareRootOfQuadraticSubst(i, vv, xx, x) 5055 return t 5056 elif ProductQ(u): 5057 t = 1 5058 for i in u.args: 5059 t *= SquareRootOfQuadraticSubst(i, vv, xx, x) 5060 return t 5061 5062def Divides(y, u, x): 5063 # If u divided by y is free of x, Divides[y,u,x] returns the quotient; else it returns False. 5064 v = Simplify(u/y) 5065 if FreeQ(v, x): 5066 return v 5067 else: 5068 return False 5069 5070def DerivativeDivides(y, u, x): 5071 """ 5072 If y not equal to x, y is easy to differentiate wrt x, and u divided by the derivative of y 5073 is free of x, DerivativeDivides[y,u,x] returns the quotient; else it returns False. 5074 """ 5075 from matchpy import is_match 5076 pattern0 = Pattern(Mul(a , b_), CustomConstraint(lambda a, b : FreeQ(a, b))) 5077 def f1(y, u, x): 5078 if PolynomialQ(y, x): 5079 return PolynomialQ(u, x) and Exponent(u, x) == Exponent(y, x) - 1 5080 else: 5081 return EasyDQ(y, x) 5082 5083 if is_match(y, pattern0): 5084 return False 5085 5086 elif f1(y, u, x): 5087 v = D(y ,x) 5088 if EqQ(v, 0): 5089 return False 5090 else: 5091 v = Simplify(u/v) 5092 if FreeQ(v, x): 5093 return v 5094 else: 5095 return False 5096 else: 5097 return False 5098 5099 5100def EasyDQ(expr, x): 5101 # If u is easy to differentiate wrt x, EasyDQ(u, x) returns True; else it returns False *) 5102 u = Wild('u',exclude=[1]) 5103 m = Wild('m',exclude=[x, 0]) 5104 M = expr.match(u*x**m) 5105 if M: 5106 return EasyDQ(M[u], x) 5107 if AtomQ(expr) or FreeQ(expr, x) or Length(expr)==0: 5108 return True 5109 elif CalculusQ(expr): 5110 return False 5111 elif Length(expr)==1: 5112 return EasyDQ(expr.args[0], x) 5113 elif BinomialQ(expr, x) or ProductOfLinearPowersQ(expr, x): 5114 return True 5115 elif RationalFunctionQ(expr, x) and RationalFunctionExponents(expr, x)==[1, 1]: 5116 return True 5117 elif ProductQ(expr): 5118 if FreeQ(First(expr), x): 5119 return EasyDQ(Rest(expr), x) 5120 elif FreeQ(Rest(expr), x): 5121 return EasyDQ(First(expr), x) 5122 else: 5123 return False 5124 elif SumQ(expr): 5125 return EasyDQ(First(expr), x) and EasyDQ(Rest(expr), x) 5126 elif Length(expr)==2: 5127 if FreeQ(expr.args[0], x): 5128 EasyDQ(expr.args[1], x) 5129 elif FreeQ(expr.args[1], x): 5130 return EasyDQ(expr.args[0], x) 5131 else: 5132 return False 5133 return False 5134 5135def ProductOfLinearPowersQ(u, x): 5136 # ProductOfLinearPowersQ(u, x) returns True iff u is a product of factors of the form v^n where v is linear in x 5137 v = Wild('v') 5138 n = Wild('n', exclude=[x]) 5139 M = u.match(v**n) 5140 return FreeQ(u, x) or M and LinearQ(M[v], x) or ProductQ(u) and ProductOfLinearPowersQ(First(u), x) and ProductOfLinearPowersQ(Rest(u), x) 5141 5142def Rt(u, n): 5143 return RtAux(TogetherSimplify(u), n) 5144 5145def NthRoot(u, n): 5146 return nsimplify(u**(S(1)/n)) 5147 5148def AtomBaseQ(u): 5149 # If u is an atom or an atom raised to an odd degree, AtomBaseQ(u) returns True; else it returns False 5150 return AtomQ(u) or PowerQ(u) and OddQ(u.args[1]) and AtomBaseQ(u.args[0]) 5151 5152def SumBaseQ(u): 5153 # If u is a sum or a sum raised to an odd degree, SumBaseQ(u) returns True; else it returns False 5154 return SumQ(u) or PowerQ(u) and OddQ(u.args[1]) and SumBaseQ(u.args[0]) 5155 5156def NegSumBaseQ(u): 5157 # If u is a sum or a sum raised to an odd degree whose lead term has a negative form, NegSumBaseQ(u) returns True; else it returns False 5158 return SumQ(u) and NegQ(First(u)) or PowerQ(u) and OddQ(u.args[1]) and NegSumBaseQ(u.args[0]) 5159 5160def AllNegTermQ(u): 5161 # If all terms of u have a negative form, AllNegTermQ(u) returns True; else it returns False 5162 if PowerQ(u): 5163 if OddQ(u.exp): 5164 return AllNegTermQ(u.base) 5165 if SumQ(u): 5166 return NegQ(First(u)) and AllNegTermQ(Rest(u)) 5167 return NegQ(u) 5168 5169def SomeNegTermQ(u): 5170 # If some term of u has a negative form, SomeNegTermQ(u) returns True; else it returns False 5171 if PowerQ(u): 5172 if OddQ(u.exp): 5173 return SomeNegTermQ(u.base) 5174 if SumQ(u): 5175 return NegQ(First(u)) or SomeNegTermQ(Rest(u)) 5176 return NegQ(u) 5177 5178def TrigSquareQ(u): 5179 # If u is an expression of the form Sin(z)^2 or Cos(z)^2, TrigSquareQ(u) returns True, else it returns False 5180 return PowerQ(u) and EqQ(u.args[1], 2) and MemberQ([sin, cos], Head(u.args[0])) 5181 5182def RtAux(u, n): 5183 if PowerQ(u): 5184 return u.base**(u.exp/n) 5185 if ComplexNumberQ(u): 5186 a = Re(u) 5187 b = Im(u) 5188 if Not(IntegerQ(a) and IntegerQ(b)) and IntegerQ(a/(a**2 + b**2)) and IntegerQ(b/(a**2 + b**2)): 5189 # Basis: a+b*I==1/(a/(a^2+b^2)-b/(a^2+b^2)*I) 5190 return S(1)/RtAux(a/(a**2 + b**2) - b/(a**2 + b**2)*I, n) 5191 else: 5192 return NthRoot(u, n) 5193 if ProductQ(u): 5194 lst = SplitProduct(PositiveQ, u) 5195 if ListQ(lst): 5196 return RtAux(lst[0], n)*RtAux(lst[1], n) 5197 lst = SplitProduct(NegativeQ, u) 5198 if ListQ(lst): 5199 if EqQ(lst[0], -1): 5200 v = lst[1] 5201 if PowerQ(v): 5202 if NegativeQ(v.exp): 5203 return 1/RtAux(-v.base**(-v.exp), n) 5204 if ProductQ(v): 5205 if ListQ(SplitProduct(SumBaseQ, v)): 5206 lst = SplitProduct(AllNegTermQ, v) 5207 if ListQ(lst): 5208 return RtAux(-lst[0], n)*RtAux(lst[1], n) 5209 lst = SplitProduct(NegSumBaseQ, v) 5210 if ListQ(lst): 5211 return RtAux(-lst[0], n)*RtAux(lst[1], n) 5212 lst = SplitProduct(SomeNegTermQ, v) 5213 if ListQ(lst): 5214 return RtAux(-lst[0], n)*RtAux(lst[1], n) 5215 lst = SplitProduct(SumBaseQ, v) 5216 return RtAux(-lst[0], n)*RtAux(lst[1], n) 5217 lst = SplitProduct(AtomBaseQ, v) 5218 if ListQ(lst): 5219 return RtAux(-lst[0], n)*RtAux(lst[1], n) 5220 else: 5221 return RtAux(-First(v), n)*RtAux(Rest(v), n) 5222 if OddQ(n): 5223 return -RtAux(v, n) 5224 else: 5225 return NthRoot(u, n) 5226 else: 5227 return RtAux(-lst[0], n)*RtAux(-lst[1], n) 5228 lst = SplitProduct(AllNegTermQ, u) 5229 if ListQ(lst) and ListQ(SplitProduct(SumBaseQ, lst[1])): 5230 return RtAux(-lst[0], n)*RtAux(-lst[1], n) 5231 lst = SplitProduct(NegSumBaseQ, u) 5232 if ListQ(lst) and ListQ(SplitProduct(NegSumBaseQ, lst[1])): 5233 return RtAux(-lst[0], n)*RtAux(-lst[1], n) 5234 return u.func(*[RtAux(i, n) for i in u.args]) 5235 v = TrigSquare(u) 5236 if Not(AtomQ(v)): 5237 return RtAux(v, n) 5238 if OddQ(n) and NegativeQ(u): 5239 return -RtAux(-u, n) 5240 if OddQ(n) and NegQ(u) and PosQ(-u): 5241 return -RtAux(-u, n) 5242 else: 5243 return NthRoot(u, n) 5244 5245def TrigSquare(u): 5246 # If u is an expression of the form a-a*Sin(z)^2 or a-a*Cos(z)^2, TrigSquare(u) returns Cos(z)^2 or Sin(z)^2 respectively, 5247 # else it returns False. 5248 if SumQ(u): 5249 for i in u.args: 5250 v = SplitProduct(TrigSquareQ, i) 5251 if v == False or SplitSum(v, u) == False: 5252 return False 5253 lst = SplitSum(SplitProduct(TrigSquareQ, i)) 5254 if lst and ZeroQ(lst[1][2] + lst[1]): 5255 if Head(lst[0][0].args[0]) == sin: 5256 return lst[1]*cos(lst[1][1][1][1])**2 5257 return lst[1]*sin(lst[1][1][1][1])**2 5258 else: 5259 return False 5260 else: 5261 return False 5262 5263def IntSum(u, x): 5264 # If u is free of x or of the form c*(a+b*x)^m, IntSum[u,x] returns the antiderivative of u wrt x; 5265 # else it returns d*Int[v,x] where d*v=u and d is free of x. 5266 return Add(*[Integral(i, x) for i in u.args]) 5267 5268def IntTerm(expr, x): 5269 # If u is of the form c*(a+b*x)**m, IntTerm(u,x) returns the antiderivative of u wrt x; 5270 # else it returns d*Int(v,x) where d*v=u and d is free of x. 5271 c = Wild('c', exclude=[x]) 5272 m = Wild('m', exclude=[x, 0]) 5273 v = Wild('v') 5274 M = expr.match(c/v) 5275 if M and len(M) == 2 and FreeQ(M[c], x) and LinearQ(M[v], x): 5276 return Simp(M[c]*Log(RemoveContent(M[v], x))/Coefficient(M[v], x, 1), x) 5277 M = expr.match(c*v**m) 5278 if M and len(M) == 3 and NonzeroQ(M[m] + 1) and LinearQ(M[v], x): 5279 return Simp(M[c]*M[v]**(M[m] + 1)/(Coefficient(M[v], x, 1)*(M[m] + 1)), x) 5280 if SumQ(expr): 5281 t = 0 5282 for i in expr.args: 5283 t += IntTerm(i, x) 5284 return t 5285 else: 5286 u = expr 5287 return Dist(FreeFactors(u,x), Integral(NonfreeFactors(u, x), x), x) 5288 5289def Map2(f, lst1, lst2): 5290 result = [] 5291 for i in range(0, len(lst1)): 5292 result.append(f(lst1[i], lst2[i])) 5293 return result 5294 5295def ConstantFactor(u, x): 5296 # (* ConstantFactor[u,x] returns a 2-element list of the factors of u[x] free of x and the 5297 # factors not free of u[x]. Common constant factors of the terms of sums are also collected. *) 5298 if FreeQ(u, x): 5299 return [u, S(1)] 5300 elif AtomQ(u): 5301 return [S(1), u] 5302 elif PowerQ(u): 5303 if FreeQ(u.exp, x): 5304 lst = ConstantFactor(u.base, x) 5305 if IntegerQ(u.exp): 5306 return [lst[0]**u.exp, lst[1]**u.exp] 5307 tmp = PositiveFactors(lst[0]) 5308 if tmp == 1: 5309 return [S(1), u] 5310 return [tmp**u.exp, (NonpositiveFactors(lst[0])*lst[1])**u.exp] 5311 elif ProductQ(u): 5312 lst = [ConstantFactor(i, x) for i in u.args] 5313 return [Mul(*[First(i) for i in lst]), Mul(*[i[1] for i in lst])] 5314 elif SumQ(u): 5315 lst1 = [ConstantFactor(i, x) for i in u.args] 5316 if SameQ(*[i[1] for i in lst1]): 5317 return [Add(*[i[0] for i in lst]), lst1[0][1]] 5318 lst2 = CommonFactors([First(i) for i in lst1]) 5319 return [First(lst2), Add(*Map2(Mul, Rest(lst2), [i[1] for i in lst1]))] 5320 return [S(1), u] 5321 5322def SameQ(*args): 5323 for i in range(0, len(args) - 1): 5324 if args[i] != args[i+1]: 5325 return False 5326 return True 5327 5328def ReplacePart(lst, a, b): 5329 lst[b] = a 5330 return lst 5331 5332def CommonFactors(lst): 5333 # (* If lst is a list of n terms, CommonFactors[lst] returns a n+1-element list whose first 5334 # element is the product of the factors common to all terms of lst, and whose remaining 5335 # elements are quotients of each term divided by the common factor. *) 5336 lst1 = [NonabsurdNumberFactors(i) for i in lst] 5337 lst2 = [AbsurdNumberFactors(i) for i in lst] 5338 num = AbsurdNumberGCD(*lst2) 5339 common = num 5340 lst2 = [i/num for i in lst2] 5341 while (True): 5342 lst3 = [LeadFactor(i) for i in lst1] 5343 5344 if SameQ(*lst3): 5345 common = common*lst3[0] 5346 lst1 = [RemainingFactors(i) for i in lst1] 5347 elif (all((LogQ(i) and IntegerQ(First(i)) and First(i) > 0) for i in lst3) and 5348 all(RationalQ(i) for i in [FullSimplify(j/First(lst3)) for j in lst3])): 5349 lst4 = [FullSimplify(j/First(lst3)) for j in lst3] 5350 num = GCD(*lst4) 5351 common = common*Log((First(lst3)[0])**num) 5352 lst2 = [lst2[i]*lst4[i]/num for i in range(0, len(lst2))] 5353 lst1 = [RemainingFactors(i) for i in lst1] 5354 lst4 = [LeadDegree(i) for i in lst1] 5355 if SameQ(*[LeadBase(i) for i in lst1]) and RationalQ(*lst4): 5356 num = Smallest(lst4) 5357 base = LeadBase(lst1[0]) 5358 if num != 0: 5359 common = common*base**num 5360 lst2 = [lst2[i]*base**(lst4[i] - num) for i in range(0, len(lst2))] 5361 lst1 = [RemainingFactors(i) for i in lst1] 5362 elif (Length(lst1) == 2 and ZeroQ(LeadBase(lst1[0]) + LeadBase(lst1[1])) and 5363 NonzeroQ(lst1[0] - 1) and IntegerQ(lst4[0]) and FractionQ(lst4[1])): 5364 num = Min(lst4) 5365 base = LeadBase(lst1[1]) 5366 if num != 0: 5367 common = common*base**num 5368 lst2 = [lst2[0]*(-1)**lst4[0], lst2[1]] 5369 lst2 = [lst2[i]*base**(lst4[i] - num) for i in range(0, len(lst2))] 5370 lst1 = [RemainingFactors(i) for i in lst1] 5371 elif (Length(lst1) == 2 and ZeroQ(lst1[0] + LeadBase(lst1[1])) and 5372 NonzeroQ(lst1[1] - 1) and IntegerQ(lst1[1]) and FractionQ(lst4[0])): 5373 num = Min(lst4) 5374 base = LeadBase(lst1[0]) 5375 if num != 0: 5376 common = common*base**num 5377 lst2 = [lst2[0], lst2[1]*(-1)**lst4[1]] 5378 lst2 = [lst2[i]*base**(lst4[i] - num) for i in range(0, len(lst2))] 5379 lst1 = [RemainingFactors(i) for i in lst1] 5380 else: 5381 num = MostMainFactorPosition(lst3) 5382 lst2 = ReplacePart(lst2, lst3[num]*lst2[num], num) 5383 lst1 = ReplacePart(lst1, RemainingFactors(lst1[num]), num) 5384 if all(i==1 for i in lst1): 5385 return Prepend(lst2, common) 5386 5387def MostMainFactorPosition(lst): 5388 factor = S(1) 5389 num = 0 5390 for i in range(0, Length(lst)): 5391 if FactorOrder(lst[i], factor) > 0: 5392 factor = lst[i] 5393 num = i 5394 return num 5395 5396SbaseS, SexponS = None, None 5397SexponFlagS = False 5398def FunctionOfExponentialQ(u, x): 5399 # (* FunctionOfExponentialQ[u,x] returns True iff u is a function of F^v where F is a constant and v is linear in x, *) 5400 # (* and such an exponential explicitly occurs in u (i.e. not just implicitly in hyperbolic functions). *) 5401 global SbaseS, SexponS, SexponFlagS 5402 SbaseS, SexponS = None, None 5403 SexponFlagS = False 5404 res = FunctionOfExponentialTest(u, x) 5405 return res and SexponFlagS 5406 5407def FunctionOfExponential(u, x): 5408 global SbaseS, SexponS, SexponFlagS 5409 # (* u is a function of F^v where v is linear in x. FunctionOfExponential[u,x] returns F^v. *) 5410 SbaseS, SexponS = None, None 5411 SexponFlagS = False 5412 FunctionOfExponentialTest(u, x) 5413 return SbaseS**SexponS 5414 5415def FunctionOfExponentialFunction(u, x): 5416 global SbaseS, SexponS, SexponFlagS 5417 # (* u is a function of F^v where v is linear in x. FunctionOfExponentialFunction[u,x] returns u with F^v replaced by x. *) 5418 SbaseS, SexponS = None, None 5419 SexponFlagS = False 5420 FunctionOfExponentialTest(u, x) 5421 return SimplifyIntegrand(FunctionOfExponentialFunctionAux(u, x), x) 5422 5423def FunctionOfExponentialFunctionAux(u, x): 5424 # (* u is a function of F^v where v is linear in x, and the fluid variables $base$=F and $expon$=v. *) 5425 # (* FunctionOfExponentialFunctionAux[u,x] returns u with F^v replaced by x. *) 5426 global SbaseS, SexponS, SexponFlagS 5427 if AtomQ(u): 5428 return u 5429 elif PowerQ(u): 5430 if FreeQ(u.base, x) and LinearQ(u.exp, x): 5431 if ZeroQ(Coefficient(SexponS, x, 0)): 5432 return u.base**Coefficient(u.exp, x, 0)*x**FullSimplify(Log(u.base)*Coefficient(u.exp, x, 1)/(Log(SbaseS)*Coefficient(SexponS, x, 1))) 5433 return x**FullSimplify(Log(u.base)*Coefficient(u.exp, x, 1)/(Log(SbaseS)*Coefficient(SexponS, x, 1))) 5434 elif HyperbolicQ(u) and LinearQ(u.args[0], x): 5435 tmp = x**FullSimplify(Coefficient(u.args[0], x, 1)/(Log(SbaseS)*Coefficient(SexponS, x, 1))) 5436 if SinhQ(u): 5437 return tmp/2 - 1/(2*tmp) 5438 elif CoshQ(u): 5439 return tmp/2 + 1/(2*tmp) 5440 elif TanhQ(u): 5441 return (tmp - 1/tmp)/(tmp + 1/tmp) 5442 elif CothQ(u): 5443 return (tmp + 1/tmp)/(tmp - 1/tmp) 5444 elif SechQ(u): 5445 return 2/(tmp + 1/tmp) 5446 return 2/(tmp - 1/tmp) 5447 if PowerQ(u): 5448 if FreeQ(u.base, x) and SumQ(u.exp): 5449 return FunctionOfExponentialFunctionAux(u.base**First(u.exp), x)*FunctionOfExponentialFunctionAux(u.base**Rest(u.exp), x) 5450 return u.func(*[FunctionOfExponentialFunctionAux(i, x) for i in u.args]) 5451 5452def FunctionOfExponentialTest(u, x): 5453 # (* FunctionOfExponentialTest[u,x] returns True iff u is a function of F^v where F is a constant and v is linear in x. *) 5454 # (* Before it is called, the fluid variables $base$ and $expon$ should be set to Null and $exponFlag$ to False. *) 5455 # (* If u is a function of F^v, $base$ and $expon$ are set to F and v, respectively. *) 5456 # (* If an explicit exponential occurs in u, $exponFlag$ is set to True. *) 5457 global SbaseS, SexponS, SexponFlagS 5458 if FreeQ(u, x): 5459 return True 5460 elif u == x or CalculusQ(u): 5461 return False 5462 elif PowerQ(u): 5463 if FreeQ(u.base, x) and LinearQ(u.exp, x): 5464 SexponFlagS = True 5465 return FunctionOfExponentialTestAux(u.base, u.exp, x) 5466 elif HyperbolicQ(u) and LinearQ(u.args[0], x): 5467 return FunctionOfExponentialTestAux(E, u.args[0], x) 5468 if PowerQ(u): 5469 if FreeQ(u.base, x) and SumQ(u.exp): 5470 return FunctionOfExponentialTest(u.base**First(u.exp), x) and FunctionOfExponentialTest(u.base**Rest(u.exp), x) 5471 return all(FunctionOfExponentialTest(i, x) for i in u.args) 5472 5473def FunctionOfExponentialTestAux(base, expon, x): 5474 global SbaseS, SexponS, SexponFlagS 5475 if SbaseS is None: 5476 SbaseS = base 5477 SexponS = expon 5478 return True 5479 tmp = FullSimplify(Log(base)*Coefficient(expon, x, 1)/(Log(SbaseS)*Coefficient(SexponS, x, 1))) 5480 if Not(RationalQ(tmp)): 5481 return False 5482 elif ZeroQ(Coefficient(SexponS, x, 0)) or NonzeroQ(tmp - FullSimplify(Log(base)*Coefficient(expon, x, 0)/(Log(SbaseS)*Coefficient(SexponS, x, 0)))): 5483 if PositiveIntegerQ(base, SbaseS) and base < SbaseS: 5484 SbaseS = base 5485 SexponS = expon 5486 tmp = 1/tmp 5487 SexponS = Coefficient(SexponS, x, 1)*x/Denominator(tmp) 5488 if tmp < 0 and NegQ(Coefficient(SexponS, x, 1)): 5489 SexponS = -SexponS 5490 return True 5491 SexponS = SexponS/Denominator(tmp) 5492 if tmp < 0 and NegQ(Coefficient(SexponS, x, 1)): 5493 SexponS = -SexponS 5494 return True 5495 5496def stdev(lst): 5497 """Calculates the standard deviation for a list of numbers.""" 5498 num_items = len(lst) 5499 mean = sum(lst) / num_items 5500 differences = [x - mean for x in lst] 5501 sq_differences = [d ** 2 for d in differences] 5502 ssd = sum(sq_differences) 5503 variance = ssd / num_items 5504 sd = sqrt(variance) 5505 5506 return sd 5507 5508def rubi_test(expr, x, optimal_output, expand=False, _hyper_check=False, _diff=False, _numerical=False): 5509 #Returns True if (expr - optimal_output) is equal to 0 or a constant 5510 #expr: integrated expression 5511 #x: integration variable 5512 #expand=True equates `expr` with `optimal_output` in expanded form 5513 #_hyper_check=True evaluates numerically 5514 #_diff=True differentiates the expressions before equating 5515 #_numerical=True equates the expressions at random `x`. Normally used for large expressions. 5516 from sympy import nsimplify 5517 if not expr.has(csc, sec, cot, csch, sech, coth): 5518 optimal_output = process_trig(optimal_output) 5519 if expr == optimal_output: 5520 return True 5521 if simplify(expr) == simplify(optimal_output): 5522 return True 5523 5524 if nsimplify(expr) == nsimplify(optimal_output): 5525 return True 5526 5527 if expr.has(sym_exp): 5528 expr = powsimp(powdenest(expr), force=True) 5529 if simplify(expr) == simplify(powsimp(optimal_output, force=True)): 5530 return True 5531 res = expr - optimal_output 5532 if _numerical: 5533 args = res.free_symbols 5534 rand_val = [] 5535 try: 5536 for i in range(0, 5): # check at 5 random points 5537 rand_x = randint(1, 40) 5538 substitutions = {s: rand_x for s in args} 5539 rand_val.append(float(abs(res.subs(substitutions).n()))) 5540 5541 if stdev(rand_val) < Pow(10, -3): 5542 return True 5543 except: 5544 pass 5545 # return False 5546 5547 dres = res.diff(x) 5548 if _numerical: 5549 args = dres.free_symbols 5550 rand_val = [] 5551 try: 5552 for i in range(0, 5): # check at 5 random points 5553 rand_x = randint(1, 40) 5554 substitutions = {s: rand_x for s in args} 5555 rand_val.append(float(abs(dres.subs(substitutions).n()))) 5556 if stdev(rand_val) < Pow(10, -3): 5557 return True 5558 # return False 5559 except: 5560 pass 5561 # return False 5562 5563 5564 5565 r = Simplify(nsimplify(res)) 5566 if r == 0 or (not r.has(x)): 5567 return True 5568 5569 if _diff: 5570 if dres == 0: 5571 return True 5572 elif Simplify(dres) == 0: 5573 return True 5574 5575 if expand: # expands the expression and equates 5576 e = res.expand() 5577 if Simplify(e) == 0 or (not e.has(x)): 5578 return True 5579 5580 5581 return False 5582 5583 5584def If(cond, t, f): 5585 # returns t if condition is true else f 5586 if cond: 5587 return t 5588 return f 5589 5590def IntQuadraticQ(a, b, c, d, e, m, p, x): 5591 # (* IntQuadraticQ[a,b,c,d,e,m,p,x] returns True iff (d+e*x)^m*(a+b*x+c*x^2)^p is integrable wrt x in terms of non-Appell functions. *) 5592 return IntegerQ(p) or PositiveIntegerQ(m) or IntegersQ(2*m, 2*p) or IntegersQ(m, 4*p) or IntegersQ(m, p + S(1)/3) and (ZeroQ(c**2*d**2 - b*c*d*e + b**2*e**2 - 3*a*c*e**2) or ZeroQ(c**2*d**2 - b*c*d*e - 2*b**2*e**2 + 9*a*c*e**2)) 5593 5594def IntBinomialQ(*args): 5595 #(* IntBinomialQ(a,b,c,n,m,p,x) returns True iff (c*x)^m*(a+b*x^n)^p is integrable wrt x in terms of non-hypergeometric functions. *) 5596 if len(args) == 8: 5597 a, b, c, d, n, p, q, x = args 5598 return IntegersQ(p,q) or PositiveIntegerQ(p) or PositiveIntegerQ(q) or (ZeroQ(n-2) or ZeroQ(n-4)) and (IntegersQ(p,4*q) or IntegersQ(4*p,q)) or ZeroQ(n-2) and (IntegersQ(2*p,2*q) or IntegersQ(3*p,q) and ZeroQ(b*c+3*a*d) or IntegersQ(p,3*q) and ZeroQ(3*b*c+a*d)) 5599 elif len(args) == 7: 5600 a, b, c, n, m, p, x = args 5601 return IntegerQ(2*p) or IntegerQ((m+1)/n + p) or (ZeroQ(n - 2) or ZeroQ(n - 4)) and IntegersQ(2*m, 4*p) or ZeroQ(n - 2) and IntegerQ(6*p) and (IntegerQ(m) or IntegerQ(m - p)) 5602 elif len(args) == 10: 5603 a, b, c, d, e, m, n, p, q, x = args 5604 return IntegersQ(p,q) or PositiveIntegerQ(p) or PositiveIntegerQ(q) or ZeroQ(n-2) and IntegerQ(m) and IntegersQ(2*p,2*q) or ZeroQ(n-4) and (IntegersQ(m,p,2*q) or IntegersQ(m,2*p,q)) 5605 5606def RectifyTangent(*args): 5607 # (* RectifyTangent(u,a,b,r,x) returns an expression whose derivative equals the derivative of r*ArcTan(a+b*Tan(u)) wrt x. *) 5608 if len(args) == 5: 5609 u, a, b, r, x = args 5610 t1 = Together(a) 5611 t2 = Together(b) 5612 if (PureComplexNumberQ(t1) or (ProductQ(t1) and any(PureComplexNumberQ(i) for i in t1.args))) and (PureComplexNumberQ(t2) or ProductQ(t2) and any(PureComplexNumberQ(i) for i in t2.args)): 5613 c = a/I 5614 d = b/I 5615 if NegativeQ(d): 5616 return RectifyTangent(u, -a, -b, -r, x) 5617 e = SmartDenominator(Together(c + d*x)) 5618 c = c*e 5619 d = d*e 5620 if EvenQ(Denominator(NumericFactor(Together(u)))): 5621 return I*r*Log(RemoveContent(Simplify((c+e)**2+d**2)+Simplify((c+e)**2-d**2)*Cos(2*u)+Simplify(2*(c+e)*d)*Sin(2*u),x))/4 - I*r*Log(RemoveContent(Simplify((c-e)**2+d**2)+Simplify((c-e)**2-d**2)*Cos(2*u)+Simplify(2*(c-e)*d)*Sin(2*u),x))/4 5622 return I*r*Log(RemoveContent(Simplify((c+e)**2)+Simplify(2*(c+e)*d)*Cos(u)*Sin(u)-Simplify((c+e)**2-d**2)*Sin(u)**2,x))/4 - I*r*Log(RemoveContent(Simplify((c-e)**2)+Simplify(2*(c-e)*d)*Cos(u)*Sin(u)-Simplify((c-e)**2-d**2)*Sin(u)**2,x))/4 5623 elif NegativeQ(b): 5624 return RectifyTangent(u, -a, -b, -r, x) 5625 elif EvenQ(Denominator(NumericFactor(Together(u)))): 5626 return r*SimplifyAntiderivative(u,x) + r*ArcTan(Simplify((2*a*b*Cos(2*u)-(1+a**2-b**2)*Sin(2*u))/(a**2+(1+b)**2+(1+a**2-b**2)*Cos(2*u)+2*a*b*Sin(2*u)))) 5627 return r*SimplifyAntiderivative(u,x) - r*ArcTan(ActivateTrig(Simplify((a*b-2*a*b*cos(u)**2+(1+a**2-b**2)*cos(u)*sin(u))/(b*(1+b)+(1+a**2-b**2)*cos(u)**2+2*a*b*cos(u)*sin(u))))) 5628 5629 u, a, b, x = args 5630 t = Together(a) 5631 if PureComplexNumberQ(t) or (ProductQ(t) and any(PureComplexNumberQ(i) for i in t.args)): 5632 c = a/I 5633 if NegativeQ(c): 5634 return RectifyTangent(u, -a, -b, x) 5635 if ZeroQ(c - 1): 5636 if EvenQ(Denominator(NumericFactor(Together(u)))): 5637 return I*b*ArcTanh(Sin(2*u))/2 5638 return I*b*ArcTanh(2*cos(u)*sin(u))/2 5639 e = SmartDenominator(c) 5640 c = c*e 5641 return I*b*Log(RemoveContent(e*Cos(u)+c*Sin(u),x))/2 - I*b*Log(RemoveContent(e*Cos(u)-c*Sin(u),x))/2 5642 elif NegativeQ(a): 5643 return RectifyTangent(u, -a, -b, x) 5644 elif ZeroQ(a - 1): 5645 return b*SimplifyAntiderivative(u, x) 5646 elif EvenQ(Denominator(NumericFactor(Together(u)))): 5647 c = Simplify((1 + a)/(1 - a)) 5648 numr = SmartNumerator(c) 5649 denr = SmartDenominator(c) 5650 return b*SimplifyAntiderivative(u,x) - b*ArcTan(NormalizeLeadTermSigns(denr*Sin(2*u)/(numr+denr*Cos(2*u)))), 5651 elif PositiveQ(a - 1): 5652 c = Simplify(1/(a - 1)) 5653 numr = SmartNumerator(c) 5654 denr = SmartDenominator(c) 5655 return b*SimplifyAntiderivative(u,x) + b*ArcTan(NormalizeLeadTermSigns(denr*Cos(u)*Sin(u)/(numr+denr*Sin(u)**2))), 5656 c = Simplify(a/(1 - a)) 5657 numr = SmartNumerator(c) 5658 denr = SmartDenominator(c) 5659 return b*SimplifyAntiderivative(u,x) - b*ArcTan(NormalizeLeadTermSigns(denr*Cos(u)*Sin(u)/(numr+denr*Cos(u)**2))) 5660 5661def RectifyCotangent(*args): 5662 #(* RectifyCotangent[u,a,b,r,x] returns an expression whose derivative equals the derivative of r*ArcTan[a+b*Cot[u]] wrt x. *) 5663 if len(args) == 5: 5664 u, a, b, r, x = args 5665 t1 = Together(a) 5666 t2 = Together(b) 5667 if (PureComplexNumberQ(t1) or (ProductQ(t1) and any(PureComplexNumberQ(i) for i in t1.args))) and (PureComplexNumberQ(t2) or ProductQ(t2) and any(PureComplexNumberQ(i) for i in t2.args)): 5668 c = a/I 5669 d = b/I 5670 if NegativeQ(d): 5671 return RectifyTangent(u,-a,-b,-r,x) 5672 e = SmartDenominator(Together(c + d*x)) 5673 c = c*e 5674 d = d*e 5675 if EvenQ(Denominator(NumericFactor(Together(u)))): 5676 return I*r*Log(RemoveContent(Simplify((c+e)**2+d**2)-Simplify((c+e)**2-d**2)*Cos(2*u)+Simplify(2*(c+e)*d)*Sin(2*u),x))/4 - I*r*Log(RemoveContent(Simplify((c-e)**2+d**2)-Simplify((c-e)**2-d**2)*Cos(2*u)+Simplify(2*(c-e)*d)*Sin(2*u),x))/4 5677 return I*r*Log(RemoveContent(Simplify((c+e)**2)-Simplify((c+e)**2-d**2)*Cos(u)**2+Simplify(2*(c+e)*d)*Cos(u)*Sin(u),x))/4 - I*r*Log(RemoveContent(Simplify((c-e)**2)-Simplify((c-e)**2-d**2)*Cos(u)**2+Simplify(2*(c-e)*d)*Cos(u)*Sin(u),x))/4 5678 elif NegativeQ(b): 5679 return RectifyCotangent(u,-a,-b,-r,x) 5680 elif EvenQ(Denominator(NumericFactor(Together(u)))): 5681 return -r*SimplifyAntiderivative(u,x) - r*ArcTan(Simplify((2*a*b*Cos(2*u)+(1+a**2-b**2)*Sin(2*u))/(a**2+(1+b)**2-(1+a**2-b**2)*Cos(2*u)+2*a*b*Sin(2*u)))) 5682 return -r*SimplifyAntiderivative(u,x) - r*ArcTan(ActivateTrig(Simplify((a*b-2*a*b*sin(u)**2+(1+a**2-b**2)*cos(u)*sin(u))/(b*(1+b)+(1+a**2-b**2)*sin(u)**2+2*a*b*cos(u)*sin(u))))) 5683 5684 u, a, b, x = args 5685 t = Together(a) 5686 if PureComplexNumberQ(t) or (ProductQ(t) and any(PureComplexNumberQ(i) for i in t.args)): 5687 c = a/I 5688 if NegativeQ(c): 5689 return RectifyCotangent(u,-a,-b,x) 5690 elif ZeroQ(c - 1): 5691 if EvenQ(Denominator(NumericFactor(Together(u)))): 5692 return -I*b*ArcTanh(Sin(2*u))/2 5693 return -I*b*ArcTanh(2*Cos(u)*Sin(u))/2 5694 e = SmartDenominator(c) 5695 c = c*e 5696 return -I*b*Log(RemoveContent(c*Cos(u)+e*Sin(u),x))/2 + I*b*Log(RemoveContent(c*Cos(u)-e*Sin(u),x))/2 5697 elif NegativeQ(a): 5698 return RectifyCotangent(u,-a,-b,x) 5699 elif ZeroQ(a-1): 5700 return b*SimplifyAntiderivative(u,x) 5701 elif EvenQ(Denominator(NumericFactor(Together(u)))): 5702 c = Simplify(a - 1) 5703 numr = SmartNumerator(c) 5704 denr = SmartDenominator(c) 5705 return b*SimplifyAntiderivative(u,x) - b*ArcTan(NormalizeLeadTermSigns(denr*Cos(u)*Sin(u)/(numr+denr*Cos(u)**2))) 5706 c = Simplify(a/(1-a)) 5707 numr = SmartNumerator(c) 5708 denr = SmartDenominator(c) 5709 return b*SimplifyAntiderivative(u,x) + b*ArcTan(NormalizeLeadTermSigns(denr*Cos(u)*Sin(u)/(numr+denr*Sin(u)**2))) 5710 5711def Inequality(*args): 5712 f = args[1::2] 5713 e = args[0::2] 5714 r = [] 5715 for i in range(0, len(f)): 5716 r.append(f[i](e[i], e[i + 1])) 5717 return all(r) 5718 5719def Condition(r, c): 5720 # returns r if c is True 5721 if c: 5722 return r 5723 else: 5724 raise NotImplementedError('In Condition()') 5725 5726def Simp(u, x): 5727 u = replace_pow_exp(u) 5728 return NormalizeSumFactors(SimpHelp(u, x)) 5729 5730def SimpHelp(u, x): 5731 if AtomQ(u): 5732 return u 5733 elif FreeQ(u, x): 5734 v = SmartSimplify(u) 5735 if LeafCount(v) <= LeafCount(u): 5736 return v 5737 return u 5738 elif ProductQ(u): 5739 #m = MatchQ[Rest[u],a_.+n_*Pi+b_.*v_ /; FreeQ[{a,b},x] && Not[FreeQ[v,x]] && EqQ[n^2,1/4]] 5740 #if EqQ(First(u), S(1)/2) and m: 5741 # if 5742 #If[EqQ[First[u],1/2] && MatchQ[Rest[u],a_.+n_*Pi+b_.*v_ /; FreeQ[{a,b},x] && Not[FreeQ[v,x]] && EqQ[n^2,1/4]], 5743 # If[MatchQ[Rest[u],n_*Pi+b_.*v_ /; FreeQ[b,x] && Not[FreeQ[v,x]] && EqQ[n^2,1/4]], 5744 # Map[Function[1/2*#],Rest[u]], 5745 # If[MatchQ[Rest[u],m_*a_.+n_*Pi+p_*b_.*v_ /; FreeQ[{a,b},x] && Not[FreeQ[v,x]] && IntegersQ[m/2,p/2]], 5746 # Map[Function[1/2*#],Rest[u]], 5747 # u]], 5748 5749 v = FreeFactors(u, x) 5750 w = NonfreeFactors(u, x) 5751 v = NumericFactor(v)*SmartSimplify(NonnumericFactors(v)*x**2)/x**2 5752 if ProductQ(w): 5753 w = Mul(*[SimpHelp(i,x) for i in w.args]) 5754 else: 5755 w = SimpHelp(w, x) 5756 w = FactorNumericGcd(w) 5757 v = MergeFactors(v, w) 5758 if ProductQ(v): 5759 return Mul(*[SimpFixFactor(i, x) for i in v.args]) 5760 return v 5761 elif SumQ(u): 5762 Pi = pi 5763 a_ = Wild('a', exclude=[x]) 5764 b_ = Wild('b', exclude=[x, 0]) 5765 n_ = Wild('n', exclude=[x, 0, 0]) 5766 pattern = a_ + n_*Pi + b_*x 5767 match = u.match(pattern) 5768 m = False 5769 if match: 5770 if EqQ(match[n_]**3, S(1)/16): 5771 m = True 5772 if m: 5773 return u 5774 elif PolynomialQ(u, x) and Exponent(u, x) <= 0: 5775 return SimpHelp(Coefficient(u, x, 0), x) 5776 elif PolynomialQ(u, x) and Exponent(u, x) == 1 and Coefficient(u, x, 0) == 0: 5777 return SimpHelp(Coefficient(u, x, 1), x)*x 5778 5779 v = 0 5780 w = 0 5781 for i in u.args: 5782 if FreeQ(i, x): 5783 v = i + v 5784 else: 5785 w = i + w 5786 v = SmartSimplify(v) 5787 if SumQ(w): 5788 w = Add(*[SimpHelp(i, x) for i in w.args]) 5789 else: 5790 w = SimpHelp(w, x) 5791 return v + w 5792 return u.func(*[SimpHelp(i, x) for i in u.args]) 5793 5794def SplitProduct(func, u): 5795 #(* If func[v] is True for a factor v of u, SplitProduct[func,u] returns {v, u/v} where v is the first such factor; else it returns False. *) 5796 if ProductQ(u): 5797 if func(First(u)): 5798 return [First(u), Rest(u)] 5799 lst = SplitProduct(func, Rest(u)) 5800 if AtomQ(lst): 5801 return False 5802 return [lst[0], First(u)*lst[1]] 5803 if func(u): 5804 return [u, 1] 5805 return False 5806 5807def SplitSum(func, u): 5808 # (* If func[v] is nonatomic for a term v of u, SplitSum[func,u] returns {func[v], u-v} where v is the first such term; else it returns False. *) 5809 if SumQ(u): 5810 if Not(AtomQ(func(First(u)))): 5811 return [func(First(u)), Rest(u)] 5812 lst = SplitSum(func, Rest(u)) 5813 if AtomQ(lst): 5814 return False 5815 return [lst[0], First(u) + lst[1]] 5816 elif Not(AtomQ(func(u))): 5817 return [func(u), 0] 5818 return False 5819 5820def SubstFor(*args): 5821 if len(args) == 4: 5822 w, v, u, x = args 5823 # u is a function of v. SubstFor(w,v,u,x) returns w times u with v replaced by x. 5824 return SimplifyIntegrand(w*SubstFor(v, u, x), x) 5825 v, u, x = args 5826 # u is a function of v. SubstFor(v, u, x) returns u with v replaced by x. 5827 if AtomQ(v): 5828 return Subst(u, v, x) 5829 elif Not(EqQ(FreeFactors(v, x), 1)): 5830 return SubstFor(NonfreeFactors(v, x), u, x/FreeFactors(v, x)) 5831 elif SinQ(v): 5832 return SubstForTrig(u, x, Sqrt(1 - x**2), v.args[0], x) 5833 elif CosQ(v): 5834 return SubstForTrig(u, Sqrt(1 - x**2), x, v.args[0], x) 5835 elif TanQ(v): 5836 return SubstForTrig(u, x/Sqrt(1 + x**2), 1/Sqrt(1 + x**2), v.args[0], x) 5837 elif CotQ(v): 5838 return SubstForTrig(u, 1/Sqrt(1 + x**2), x/Sqrt(1 + x**2), v.args[0], x) 5839 elif SecQ(v): 5840 return SubstForTrig(u, 1/Sqrt(1 - x**2), 1/x, v.args[0], x) 5841 elif CscQ(v): 5842 return SubstForTrig(u, 1/x, 1/Sqrt(1 - x**2), v.args[0], x) 5843 elif SinhQ(v): 5844 return SubstForHyperbolic(u, x, Sqrt(1 + x**2), v.args[0], x) 5845 elif CoshQ(v): 5846 return SubstForHyperbolic(u, Sqrt( - 1 + x**2), x, v.args[0], x) 5847 elif TanhQ(v): 5848 return SubstForHyperbolic(u, x/Sqrt(1 - x**2), 1/Sqrt(1 - x**2), v.args[0], x) 5849 elif CothQ(v): 5850 return SubstForHyperbolic(u, 1/Sqrt( - 1 + x**2), x/Sqrt( - 1 + x**2), v.args[0], x) 5851 elif SechQ(v): 5852 return SubstForHyperbolic(u, 1/Sqrt( - 1 + x**2), 1/x, v.args[0], x) 5853 elif CschQ(v): 5854 return SubstForHyperbolic(u, 1/x, 1/Sqrt(1 + x**2), v.args[0], x) 5855 else: 5856 return SubstForAux(u, v, x) 5857 5858def SubstForAux(u, v, x): 5859 # u is a function of v. SubstForAux(u, v, x) returns u with v replaced by x. 5860 if u==v: 5861 return x 5862 elif AtomQ(u): 5863 if PowerQ(v): 5864 if FreeQ(v.exp, x) and ZeroQ(u - v.base): 5865 return x**Simplify(1/v.exp) 5866 return u 5867 elif PowerQ(u): 5868 if FreeQ(u.exp, x): 5869 if ZeroQ(u.base - v): 5870 return x**u.exp 5871 if PowerQ(v): 5872 if FreeQ(v.exp, x) and ZeroQ(u.base - v.base): 5873 return x**Simplify(u.exp/v.exp) 5874 return SubstForAux(u.base, v, x)**u.exp 5875 elif ProductQ(u) and Not(EqQ(FreeFactors(u, x), 1)): 5876 return FreeFactors(u, x)*SubstForAux(NonfreeFactors(u, x), v, x) 5877 elif ProductQ(u) and ProductQ(v): 5878 return SubstForAux(First(u), First(v), x) 5879 5880 return u.func(*[SubstForAux(i, v, x) for i in u.args]) 5881 5882def FresnelS(x): 5883 return fresnels(x) 5884 5885def FresnelC(x): 5886 return fresnelc(x) 5887 5888def Erf(x): 5889 return erf(x) 5890 5891def Erfc(x): 5892 return erfc(x) 5893 5894def Erfi(x): 5895 return erfi(x) 5896 5897class Gamma(Function): 5898 @classmethod 5899 def eval(cls,*args): 5900 a = args[0] 5901 if len(args) == 1: 5902 return gamma(a) 5903 else: 5904 b = args[1] 5905 if (NumericQ(a) and NumericQ(b)) or a == 1: 5906 return uppergamma(a, b) 5907 5908def FunctionOfTrigOfLinearQ(u, x): 5909 # If u is an algebraic function of trig functions of a linear function of x, 5910 # FunctionOfTrigOfLinearQ[u,x] returns True; else it returns False. 5911 if FunctionOfTrig(u, None, x) and AlgebraicTrigFunctionQ(u, x) and FunctionOfLinear(FunctionOfTrig(u, None, x), x): 5912 return True 5913 else: 5914 return False 5915 5916def ElementaryFunctionQ(u): 5917 # ElementaryExpressionQ[u] returns True if u is a sum, product, or power and all the operands 5918 # are elementary expressions; or if u is a call on a trig, hyperbolic, or inverse function 5919 # and all the arguments are elementary expressions; else it returns False. 5920 if AtomQ(u): 5921 return True 5922 elif SumQ(u) or ProductQ(u) or PowerQ(u) or TrigQ(u) or HyperbolicQ(u) or InverseFunctionQ(u): 5923 for i in u.args: 5924 if not ElementaryFunctionQ(i): 5925 return False 5926 return True 5927 return False 5928 5929def Complex(a, b): 5930 return a + I*b 5931 5932def UnsameQ(a, b): 5933 return a != b 5934 5935@doctest_depends_on(modules=('matchpy',)) 5936def _SimpFixFactor(): 5937 replacer = ManyToOneReplacer() 5938 5939 pattern1 = Pattern(UtilityOperator(Pow(Add(Mul(Complex(S(0), c_), WC('a', S(1))), Mul(Complex(S(0), d_), WC('b', S(1)))), WC('p', S(1))), x_), CustomConstraint(lambda p: IntegerQ(p))) 5940 rule1 = ReplacementRule(pattern1, lambda b, c, x, a, p, d : Mul(Pow(I, p), SimpFixFactor(Pow(Add(Mul(a, c), Mul(b, d)), p), x))) 5941 replacer.add(rule1) 5942 5943 pattern2 = Pattern(UtilityOperator(Pow(Add(Mul(Complex(S(0), d_), WC('a', S(1))), Mul(Complex(S(0), e_), WC('b', S(1))), Mul(Complex(S(0), f_), WC('c', S(1)))), WC('p', S(1))), x_), CustomConstraint(lambda p: IntegerQ(p))) 5944 rule2 = ReplacementRule(pattern2, lambda b, c, x, f, a, p, e, d : Mul(Pow(I, p), SimpFixFactor(Pow(Add(Mul(a, d), Mul(b, e), Mul(c, f)), p), x))) 5945 replacer.add(rule2) 5946 5947 pattern3 = Pattern(UtilityOperator(Pow(Add(Mul(WC('a', S(1)), Pow(c_, r_)), Mul(WC('b', S(1)), Pow(x_, WC('n', S(1))))), WC('p', S(1))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda n, p: IntegersQ(n, p)), CustomConstraint(lambda c: AtomQ(c)), CustomConstraint(lambda r: RationalQ(r)), CustomConstraint(lambda r: Less(r, S(0)))) 5948 rule3 = ReplacementRule(pattern3, lambda b, c, r, n, x, a, p : Mul(Pow(c, Mul(r, p)), SimpFixFactor(Pow(Add(a, Mul(Mul(b, Pow(Pow(c, r), S(-1))), Pow(x, n))), p), x))) 5949 replacer.add(rule3) 5950 5951 pattern4 = Pattern(UtilityOperator(Pow(Add(WC('a', S(0)), Mul(WC('b', S(1)), Pow(c_, r_), Pow(x_, WC('n', S(1))))), WC('p', S(1))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda n, p: IntegersQ(n, p)), CustomConstraint(lambda c: AtomQ(c)), CustomConstraint(lambda r: RationalQ(r)), CustomConstraint(lambda r: Less(r, S(0)))) 5952 rule4 = ReplacementRule(pattern4, lambda b, c, r, n, x, a, p : Mul(Pow(c, Mul(r, p)), SimpFixFactor(Pow(Add(Mul(a, Pow(Pow(c, r), S(-1))), Mul(b, Pow(x, n))), p), x))) 5953 replacer.add(rule4) 5954 5955 pattern5 = Pattern(UtilityOperator(Pow(Add(Mul(WC('a', S(1)), Pow(c_, WC('s', S(1)))), Mul(WC('b', S(1)), Pow(c_, WC('r', S(1))), Pow(x_, WC('n', S(1))))), WC('p', S(1))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda n, p: IntegersQ(n, p)), CustomConstraint(lambda r, s: RationalQ(s, r)), CustomConstraint(lambda r, s: Inequality(S(0), Less, s, LessEqual, r)), CustomConstraint(lambda p, c, s: UnsameQ(Pow(c, Mul(s, p)), S(-1)))) 5956 rule5 = ReplacementRule(pattern5, lambda b, c, r, n, x, a, p, s : Mul(Pow(c, Mul(s, p)), SimpFixFactor(Pow(Add(a, Mul(b, Pow(c, Add(r, Mul(S(-1), s))), Pow(x, n))), p), x))) 5957 replacer.add(rule5) 5958 5959 pattern6 = Pattern(UtilityOperator(Pow(Add(Mul(WC('a', S(1)), Pow(c_, WC('s', S(1)))), Mul(WC('b', S(1)), Pow(c_, WC('r', S(1))), Pow(x_, WC('n', S(1))))), WC('p', S(1))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda n, p: IntegersQ(n, p)), CustomConstraint(lambda r, s: RationalQ(s, r)), CustomConstraint(lambda s, r: Less(S(0), r, s)), CustomConstraint(lambda p, c, r: UnsameQ(Pow(c, Mul(r, p)), S(-1)))) 5960 rule6 = ReplacementRule(pattern6, lambda b, c, r, n, x, a, p, s : Mul(Pow(c, Mul(r, p)), SimpFixFactor(Pow(Add(Mul(a, Pow(c, Add(s, Mul(S(-1), r)))), Mul(b, Pow(x, n))), p), x))) 5961 replacer.add(rule6) 5962 5963 return replacer 5964 5965@doctest_depends_on(modules=('matchpy',)) 5966def SimpFixFactor(expr, x): 5967 r = SimpFixFactor_replacer.replace(UtilityOperator(expr, x)) 5968 if isinstance(r, UtilityOperator): 5969 return expr 5970 return r 5971 5972@doctest_depends_on(modules=('matchpy',)) 5973def _FixSimplify(): 5974 Plus = Add 5975 def cons_f1(n): 5976 return OddQ(n) 5977 cons1 = CustomConstraint(cons_f1) 5978 5979 def cons_f2(m): 5980 return RationalQ(m) 5981 cons2 = CustomConstraint(cons_f2) 5982 5983 def cons_f3(n): 5984 return FractionQ(n) 5985 cons3 = CustomConstraint(cons_f3) 5986 5987 def cons_f4(u): 5988 return SqrtNumberSumQ(u) 5989 cons4 = CustomConstraint(cons_f4) 5990 5991 def cons_f5(v): 5992 return SqrtNumberSumQ(v) 5993 cons5 = CustomConstraint(cons_f5) 5994 5995 def cons_f6(u): 5996 return PositiveQ(u) 5997 cons6 = CustomConstraint(cons_f6) 5998 5999 def cons_f7(v): 6000 return PositiveQ(v) 6001 cons7 = CustomConstraint(cons_f7) 6002 6003 def cons_f8(v): 6004 return SqrtNumberSumQ(S(1)/v) 6005 cons8 = CustomConstraint(cons_f8) 6006 6007 def cons_f9(m): 6008 return IntegerQ(m) 6009 cons9 = CustomConstraint(cons_f9) 6010 6011 def cons_f10(u): 6012 return NegativeQ(u) 6013 cons10 = CustomConstraint(cons_f10) 6014 6015 def cons_f11(n, m, a, b): 6016 return RationalQ(a, b, m, n) 6017 cons11 = CustomConstraint(cons_f11) 6018 6019 def cons_f12(a): 6020 return Greater(a, S(0)) 6021 cons12 = CustomConstraint(cons_f12) 6022 6023 def cons_f13(b): 6024 return Greater(b, S(0)) 6025 cons13 = CustomConstraint(cons_f13) 6026 6027 def cons_f14(p): 6028 return PositiveIntegerQ(p) 6029 cons14 = CustomConstraint(cons_f14) 6030 6031 def cons_f15(p): 6032 return IntegerQ(p) 6033 cons15 = CustomConstraint(cons_f15) 6034 6035 def cons_f16(p, n): 6036 return Greater(-n + p, S(0)) 6037 cons16 = CustomConstraint(cons_f16) 6038 6039 def cons_f17(a, b): 6040 return SameQ(a + b, S(0)) 6041 cons17 = CustomConstraint(cons_f17) 6042 6043 def cons_f18(n): 6044 return Not(IntegerQ(n)) 6045 cons18 = CustomConstraint(cons_f18) 6046 6047 def cons_f19(c, a, b, d): 6048 return ZeroQ(-a*d + b*c) 6049 cons19 = CustomConstraint(cons_f19) 6050 6051 def cons_f20(a): 6052 return Not(RationalQ(a)) 6053 cons20 = CustomConstraint(cons_f20) 6054 6055 def cons_f21(t): 6056 return IntegerQ(t) 6057 cons21 = CustomConstraint(cons_f21) 6058 6059 def cons_f22(n, m): 6060 return RationalQ(m, n) 6061 cons22 = CustomConstraint(cons_f22) 6062 6063 def cons_f23(n, m): 6064 return Inequality(S(0), Less, m, LessEqual, n) 6065 cons23 = CustomConstraint(cons_f23) 6066 6067 def cons_f24(p, n, m): 6068 return RationalQ(m, n, p) 6069 cons24 = CustomConstraint(cons_f24) 6070 6071 def cons_f25(p, n, m): 6072 return Inequality(S(0), Less, m, LessEqual, n, LessEqual, p) 6073 cons25 = CustomConstraint(cons_f25) 6074 6075 def cons_f26(p, n, m, q): 6076 return Inequality(S(0), Less, m, LessEqual, n, LessEqual, p, LessEqual, q) 6077 cons26 = CustomConstraint(cons_f26) 6078 6079 def cons_f27(w): 6080 return Not(RationalQ(w)) 6081 cons27 = CustomConstraint(cons_f27) 6082 6083 def cons_f28(n): 6084 return Less(n, S(0)) 6085 cons28 = CustomConstraint(cons_f28) 6086 6087 def cons_f29(n, w, v): 6088 return ZeroQ(v + w**(-n)) 6089 cons29 = CustomConstraint(cons_f29) 6090 6091 def cons_f30(n): 6092 return IntegerQ(n) 6093 cons30 = CustomConstraint(cons_f30) 6094 6095 def cons_f31(w, v): 6096 return ZeroQ(v + w) 6097 cons31 = CustomConstraint(cons_f31) 6098 6099 def cons_f32(p, n): 6100 return IntegerQ(n/p) 6101 cons32 = CustomConstraint(cons_f32) 6102 6103 def cons_f33(w, v): 6104 return ZeroQ(v - w) 6105 cons33 = CustomConstraint(cons_f33) 6106 6107 def cons_f34(p, n): 6108 return IntegersQ(n, n/p) 6109 cons34 = CustomConstraint(cons_f34) 6110 6111 def cons_f35(a): 6112 return AtomQ(a) 6113 cons35 = CustomConstraint(cons_f35) 6114 6115 def cons_f36(b): 6116 return AtomQ(b) 6117 cons36 = CustomConstraint(cons_f36) 6118 6119 pattern1 = Pattern(UtilityOperator((w_ + Complex(S(0), b_)*WC('v', S(1)))**WC('n', S(1))*Complex(S(0), a_)*WC('u', S(1))), cons1) 6120 def replacement1(n, u, w, v, a, b): 6121 return (S(-1))**(n/S(2) + S(1)/2)*a*u*FixSimplify((b*v - w*Complex(S(0), S(1)))**n) 6122 rule1 = ReplacementRule(pattern1, replacement1) 6123 def With2(m, n, u, w, v): 6124 z = u**(m/GCD(m, n))*v**(n/GCD(m, n)) 6125 if Or(AbsurdNumberQ(z), SqrtNumberSumQ(z)): 6126 return True 6127 return False 6128 pattern2 = Pattern(UtilityOperator(u_**WC('m', S(1))*v_**n_*WC('w', S(1))), cons2, cons3, cons4, cons5, cons6, cons7, CustomConstraint(With2)) 6129 def replacement2(m, n, u, w, v): 6130 z = u**(m/GCD(m, n))*v**(n/GCD(m, n)) 6131 return FixSimplify(w*z**GCD(m, n)) 6132 rule2 = ReplacementRule(pattern2, replacement2) 6133 def With3(m, n, u, w, v): 6134 z = u**(m/GCD(m, -n))*v**(n/GCD(m, -n)) 6135 if Or(AbsurdNumberQ(z), SqrtNumberSumQ(z)): 6136 return True 6137 return False 6138 pattern3 = Pattern(UtilityOperator(u_**WC('m', S(1))*v_**n_*WC('w', S(1))), cons2, cons3, cons4, cons8, cons6, cons7, CustomConstraint(With3)) 6139 def replacement3(m, n, u, w, v): 6140 z = u**(m/GCD(m, -n))*v**(n/GCD(m, -n)) 6141 return FixSimplify(w*z**GCD(m, -n)) 6142 rule3 = ReplacementRule(pattern3, replacement3) 6143 def With4(m, n, u, w, v): 6144 z = v**(n/GCD(m, n))*(-u)**(m/GCD(m, n)) 6145 if Or(AbsurdNumberQ(z), SqrtNumberSumQ(z)): 6146 return True 6147 return False 6148 pattern4 = Pattern(UtilityOperator(u_**WC('m', S(1))*v_**n_*WC('w', S(1))), cons9, cons3, cons4, cons5, cons10, cons7, CustomConstraint(With4)) 6149 def replacement4(m, n, u, w, v): 6150 z = v**(n/GCD(m, n))*(-u)**(m/GCD(m, n)) 6151 return FixSimplify(-w*z**GCD(m, n)) 6152 rule4 = ReplacementRule(pattern4, replacement4) 6153 def With5(m, n, u, w, v): 6154 z = v**(n/GCD(m, -n))*(-u)**(m/GCD(m, -n)) 6155 if Or(AbsurdNumberQ(z), SqrtNumberSumQ(z)): 6156 return True 6157 return False 6158 pattern5 = Pattern(UtilityOperator(u_**WC('m', S(1))*v_**n_*WC('w', S(1))), cons9, cons3, cons4, cons8, cons10, cons7, CustomConstraint(With5)) 6159 def replacement5(m, n, u, w, v): 6160 z = v**(n/GCD(m, -n))*(-u)**(m/GCD(m, -n)) 6161 return FixSimplify(-w*z**GCD(m, -n)) 6162 rule5 = ReplacementRule(pattern5, replacement5) 6163 def With6(p, m, n, u, w, v, a, b): 6164 c = a**(m/p)*b**n 6165 if RationalQ(c): 6166 return True 6167 return False 6168 pattern6 = Pattern(UtilityOperator(a_**m_*(b_**n_*WC('v', S(1)) + u_)**WC('p', S(1))*WC('w', S(1))), cons11, cons12, cons13, cons14, CustomConstraint(With6)) 6169 def replacement6(p, m, n, u, w, v, a, b): 6170 c = a**(m/p)*b**n 6171 return FixSimplify(w*(a**(m/p)*u + c*v)**p) 6172 rule6 = ReplacementRule(pattern6, replacement6) 6173 pattern7 = Pattern(UtilityOperator(a_**WC('m', S(1))*(a_**n_*WC('u', S(1)) + b_**WC('p', S(1))*WC('v', S(1)))*WC('w', S(1))), cons2, cons3, cons15, cons16, cons17) 6174 def replacement7(p, m, n, u, w, v, a, b): 6175 return FixSimplify(a**(m + n)*w*((S(-1))**p*a**(-n + p)*v + u)) 6176 rule7 = ReplacementRule(pattern7, replacement7) 6177 def With8(m, d, n, w, c, a, b): 6178 q = b/d 6179 if FreeQ(q, Plus): 6180 return True 6181 return False 6182 pattern8 = Pattern(UtilityOperator((a_ + b_)**WC('m', S(1))*(c_ + d_)**n_*WC('w', S(1))), cons9, cons18, cons19, CustomConstraint(With8)) 6183 def replacement8(m, d, n, w, c, a, b): 6184 q = b/d 6185 return FixSimplify(q**m*w*(c + d)**(m + n)) 6186 rule8 = ReplacementRule(pattern8, replacement8) 6187 pattern9 = Pattern(UtilityOperator((a_**WC('m', S(1))*WC('u', S(1)) + a_**WC('n', S(1))*WC('v', S(1)))**WC('t', S(1))*WC('w', S(1))), cons20, cons21, cons22, cons23) 6188 def replacement9(m, n, u, w, v, a, t): 6189 return FixSimplify(a**(m*t)*w*(a**(-m + n)*v + u)**t) 6190 rule9 = ReplacementRule(pattern9, replacement9) 6191 pattern10 = Pattern(UtilityOperator((a_**WC('m', S(1))*WC('u', S(1)) + a_**WC('n', S(1))*WC('v', S(1)) + a_**WC('p', S(1))*WC('z', S(1)))**WC('t', S(1))*WC('w', S(1))), cons20, cons21, cons24, cons25) 6192 def replacement10(p, m, n, u, w, v, a, z, t): 6193 return FixSimplify(a**(m*t)*w*(a**(-m + n)*v + a**(-m + p)*z + u)**t) 6194 rule10 = ReplacementRule(pattern10, replacement10) 6195 pattern11 = Pattern(UtilityOperator((a_**WC('m', S(1))*WC('u', S(1)) + a_**WC('n', S(1))*WC('v', S(1)) + a_**WC('p', S(1))*WC('z', S(1)) + a_**WC('q', S(1))*WC('y', S(1)))**WC('t', S(1))*WC('w', S(1))), cons20, cons21, cons24, cons26) 6196 def replacement11(p, m, n, u, q, w, v, a, z, y, t): 6197 return FixSimplify(a**(m*t)*w*(a**(-m + n)*v + a**(-m + p)*z + a**(-m + q)*y + u)**t) 6198 rule11 = ReplacementRule(pattern11, replacement11) 6199 pattern12 = Pattern(UtilityOperator((sqrt(v_)*WC('b', S(1)) + sqrt(v_)*WC('c', S(1)) + sqrt(v_)*WC('d', S(1)) + sqrt(v_)*WC('a', S(1)) + WC('u', S(0)))*WC('w', S(1)))) 6200 def replacement12(d, u, w, v, c, a, b): 6201 return FixSimplify(w*(u + sqrt(v)*FixSimplify(a + b + c + d))) 6202 rule12 = ReplacementRule(pattern12, replacement12) 6203 pattern13 = Pattern(UtilityOperator((sqrt(v_)*WC('b', S(1)) + sqrt(v_)*WC('c', S(1)) + sqrt(v_)*WC('a', S(1)) + WC('u', S(0)))*WC('w', S(1)))) 6204 def replacement13(u, w, v, c, a, b): 6205 return FixSimplify(w*(u + sqrt(v)*FixSimplify(a + b + c))) 6206 rule13 = ReplacementRule(pattern13, replacement13) 6207 pattern14 = Pattern(UtilityOperator((sqrt(v_)*WC('b', S(1)) + sqrt(v_)*WC('a', S(1)) + WC('u', S(0)))*WC('w', S(1)))) 6208 def replacement14(u, w, v, a, b): 6209 return FixSimplify(w*(u + sqrt(v)*FixSimplify(a + b))) 6210 rule14 = ReplacementRule(pattern14, replacement14) 6211 pattern15 = Pattern(UtilityOperator(v_**m_*w_**n_*WC('u', S(1))), cons2, cons27, cons3, cons28, cons29) 6212 def replacement15(m, n, u, w, v): 6213 return -FixSimplify(u*v**(m + S(-1))) 6214 rule15 = ReplacementRule(pattern15, replacement15) 6215 pattern16 = Pattern(UtilityOperator(v_**m_*w_**WC('n', S(1))*WC('u', S(1))), cons2, cons27, cons30, cons31) 6216 def replacement16(m, n, u, w, v): 6217 return (S(-1))**n*FixSimplify(u*v**(m + n)) 6218 rule16 = ReplacementRule(pattern16, replacement16) 6219 pattern17 = Pattern(UtilityOperator(w_**WC('n', S(1))*(-v_**WC('p', S(1)))**m_*WC('u', S(1))), cons2, cons27, cons32, cons33) 6220 def replacement17(p, m, n, u, w, v): 6221 return (S(-1))**(n/p)*FixSimplify(u*(-v**p)**(m + n/p)) 6222 rule17 = ReplacementRule(pattern17, replacement17) 6223 pattern18 = Pattern(UtilityOperator(w_**WC('n', S(1))*(-v_**WC('p', S(1)))**m_*WC('u', S(1))), cons2, cons27, cons34, cons31) 6224 def replacement18(p, m, n, u, w, v): 6225 return (S(-1))**(n + n/p)*FixSimplify(u*(-v**p)**(m + n/p)) 6226 rule18 = ReplacementRule(pattern18, replacement18) 6227 pattern19 = Pattern(UtilityOperator((a_ - b_)**WC('m', S(1))*(a_ + b_)**WC('m', S(1))*WC('u', S(1))), cons9, cons35, cons36) 6228 def replacement19(m, u, a, b): 6229 return u*(a**S(2) - b**S(2))**m 6230 rule19 = ReplacementRule(pattern19, replacement19) 6231 pattern20 = Pattern(UtilityOperator((S(729)*c - e*(-S(20)*e + S(540)))**WC('m', S(1))*WC('u', S(1))), cons2) 6232 def replacement20(m, u): 6233 return u*(a*e**S(2) - b*d*e + c*d**S(2))**m 6234 rule20 = ReplacementRule(pattern20, replacement20) 6235 pattern21 = Pattern(UtilityOperator((S(729)*c + e*(S(20)*e + S(-540)))**WC('m', S(1))*WC('u', S(1))), cons2) 6236 def replacement21(m, u): 6237 return u*(a*e**S(2) - b*d*e + c*d**S(2))**m 6238 rule21 = ReplacementRule(pattern21, replacement21) 6239 pattern22 = Pattern(UtilityOperator(u_)) 6240 def replacement22(u): 6241 return u 6242 rule22 = ReplacementRule(pattern22, replacement22) 6243 return [rule1, rule2, rule3, rule4, rule5, rule6, rule7, rule8, rule9, rule10, rule11, rule12, rule13, rule14, rule15, rule16, rule17, rule18, rule19, rule20, rule21, rule22, ] 6244 6245@doctest_depends_on(modules=('matchpy',)) 6246def FixSimplify(expr): 6247 if isinstance(expr, (list, tuple, TupleArg)): 6248 return [replace_all(UtilityOperator(i), FixSimplify_rules) for i in expr] 6249 return replace_all(UtilityOperator(expr), FixSimplify_rules) 6250 6251@doctest_depends_on(modules=('matchpy',)) 6252def _SimplifyAntiderivativeSum(): 6253 replacer = ManyToOneReplacer() 6254 6255 pattern1 = Pattern(UtilityOperator(Add(Mul(Log(Add(a_, Mul(WC('b', S(1)), Pow(Tan(u_), WC('n', S(1)))))), WC('A', S(1))), Mul(Log(Cos(u_)), WC('B', S(1))), WC('v', S(0))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda A, x: FreeQ(A, x)), CustomConstraint(lambda B, x: FreeQ(B, x)), CustomConstraint(lambda n: IntegerQ(n)), CustomConstraint(lambda B, A, n: ZeroQ(Add(Mul(n, A), Mul(S(1), B))))) 6256 rule1 = ReplacementRule(pattern1, lambda n, x, v, b, B, A, u, a : Add(SimplifyAntiderivativeSum(v, x), Mul(A, Log(RemoveContent(Add(Mul(a, Pow(Cos(u), n)), Mul(b, Pow(Sin(u), n))), x))))) 6257 replacer.add(rule1) 6258 6259 pattern2 = Pattern(UtilityOperator(Add(Mul(Log(Add(Mul(Pow(Cot(u_), WC('n', S(1))), WC('b', S(1))), a_)), WC('A', S(1))), Mul(Log(Sin(u_)), WC('B', S(1))), WC('v', S(0))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda A, x: FreeQ(A, x)), CustomConstraint(lambda B, x: FreeQ(B, x)), CustomConstraint(lambda n: IntegerQ(n)), CustomConstraint(lambda B, A, n: ZeroQ(Add(Mul(n, A), Mul(S(1), B))))) 6260 rule2 = ReplacementRule(pattern2, lambda n, x, v, b, B, A, a, u : Add(SimplifyAntiderivativeSum(v, x), Mul(A, Log(RemoveContent(Add(Mul(a, Pow(Sin(u), n)), Mul(b, Pow(Cos(u), n))), x))))) 6261 replacer.add(rule2) 6262 6263 pattern3 = Pattern(UtilityOperator(Add(Mul(Log(Add(a_, Mul(WC('b', S(1)), Pow(Tan(u_), WC('n', S(1)))))), WC('A', S(1))), Mul(Log(Add(c_, Mul(WC('d', S(1)), Pow(Tan(u_), WC('n', S(1)))))), WC('B', S(1))), WC('v', S(0))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda d, x: FreeQ(d, x)), CustomConstraint(lambda A, x: FreeQ(A, x)), CustomConstraint(lambda B, x: FreeQ(B, x)), CustomConstraint(lambda n: IntegerQ(n)), CustomConstraint(lambda B, A: ZeroQ(Add(A, B)))) 6264 rule3 = ReplacementRule(pattern3, lambda n, x, v, b, A, B, u, c, d, a : Add(SimplifyAntiderivativeSum(v, x), Mul(A, Log(RemoveContent(Add(Mul(a, Pow(Cos(u), n)), Mul(b, Pow(Sin(u), n))), x))), Mul(B, Log(RemoveContent(Add(Mul(c, Pow(Cos(u), n)), Mul(d, Pow(Sin(u), n))), x))))) 6265 replacer.add(rule3) 6266 6267 pattern4 = Pattern(UtilityOperator(Add(Mul(Log(Add(Mul(Pow(Cot(u_), WC('n', S(1))), WC('b', S(1))), a_)), WC('A', S(1))), Mul(Log(Add(Mul(Pow(Cot(u_), WC('n', S(1))), WC('d', S(1))), c_)), WC('B', S(1))), WC('v', S(0))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda d, x: FreeQ(d, x)), CustomConstraint(lambda A, x: FreeQ(A, x)), CustomConstraint(lambda B, x: FreeQ(B, x)), CustomConstraint(lambda n: IntegerQ(n)), CustomConstraint(lambda B, A: ZeroQ(Add(A, B)))) 6268 rule4 = ReplacementRule(pattern4, lambda n, x, v, b, A, B, c, a, d, u : Add(SimplifyAntiderivativeSum(v, x), Mul(A, Log(RemoveContent(Add(Mul(b, Pow(Cos(u), n)), Mul(a, Pow(Sin(u), n))), x))), Mul(B, Log(RemoveContent(Add(Mul(d, Pow(Cos(u), n)), Mul(c, Pow(Sin(u), n))), x))))) 6269 replacer.add(rule4) 6270 6271 pattern5 = Pattern(UtilityOperator(Add(Mul(Log(Add(a_, Mul(WC('b', S(1)), Pow(Tan(u_), WC('n', S(1)))))), WC('A', S(1))), Mul(Log(Add(c_, Mul(WC('d', S(1)), Pow(Tan(u_), WC('n', S(1)))))), WC('B', S(1))), Mul(Log(Add(e_, Mul(WC('f', S(1)), Pow(Tan(u_), WC('n', S(1)))))), WC('C', S(1))), WC('v', S(0))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda d, x: FreeQ(d, x)), CustomConstraint(lambda e, x: FreeQ(e, x)), CustomConstraint(lambda f, x: FreeQ(f, x)), CustomConstraint(lambda A, x: FreeQ(A, x)), CustomConstraint(lambda B, x: FreeQ(B, x)), CustomConstraint(lambda C, x: FreeQ(C, x)), CustomConstraint(lambda n: IntegerQ(n)), CustomConstraint(lambda B, A, C: ZeroQ(Add(A, B, C)))) 6272 rule5 = ReplacementRule(pattern5, lambda n, e, x, v, b, A, B, u, c, f, d, a, C : Add(SimplifyAntiderivativeSum(v, x), Mul(A, Log(RemoveContent(Add(Mul(a, Pow(Cos(u), n)), Mul(b, Pow(Sin(u), n))), x))), Mul(B, Log(RemoveContent(Add(Mul(c, Pow(Cos(u), n)), Mul(d, Pow(Sin(u), n))), x))), Mul(C, Log(RemoveContent(Add(Mul(e, Pow(Cos(u), n)), Mul(f, Pow(Sin(u), n))), x))))) 6273 replacer.add(rule5) 6274 6275 pattern6 = Pattern(UtilityOperator(Add(Mul(Log(Add(Mul(Pow(Cot(u_), WC('n', S(1))), WC('b', S(1))), a_)), WC('A', S(1))), Mul(Log(Add(Mul(Pow(Cot(u_), WC('n', S(1))), WC('d', S(1))), c_)), WC('B', S(1))), Mul(Log(Add(Mul(Pow(Cot(u_), WC('n', S(1))), WC('f', S(1))), e_)), WC('C', S(1))), WC('v', S(0))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda d, x: FreeQ(d, x)), CustomConstraint(lambda e, x: FreeQ(e, x)), CustomConstraint(lambda f, x: FreeQ(f, x)), CustomConstraint(lambda A, x: FreeQ(A, x)), CustomConstraint(lambda B, x: FreeQ(B, x)), CustomConstraint(lambda C, x: FreeQ(C, x)), CustomConstraint(lambda n: IntegerQ(n)), CustomConstraint(lambda B, A, C: ZeroQ(Add(A, B, C)))) 6276 rule6 = ReplacementRule(pattern6, lambda n, e, x, v, b, A, B, c, a, f, d, u, C : Add(SimplifyAntiderivativeSum(v, x), Mul(A, Log(RemoveContent(Add(Mul(b, Pow(Cos(u), n)), Mul(a, Pow(Sin(u), n))), x))), Mul(B, Log(RemoveContent(Add(Mul(d, Pow(Cos(u), n)), Mul(c, Pow(Sin(u), n))), x))), Mul(C, Log(RemoveContent(Add(Mul(f, Pow(Cos(u), n)), Mul(e, Pow(Sin(u), n))), x))))) 6277 replacer.add(rule6) 6278 6279 return replacer 6280 6281@doctest_depends_on(modules=('matchpy',)) 6282def SimplifyAntiderivativeSum(expr, x): 6283 r = SimplifyAntiderivativeSum_replacer.replace(UtilityOperator(expr, x)) 6284 if isinstance(r, UtilityOperator): 6285 return expr 6286 return r 6287 6288@doctest_depends_on(modules=('matchpy',)) 6289def _SimplifyAntiderivative(): 6290 replacer = ManyToOneReplacer() 6291 6292 pattern2 = Pattern(UtilityOperator(Log(Mul(c_, u_)), x_), CustomConstraint(lambda c, x: FreeQ(c, x))) 6293 rule2 = ReplacementRule(pattern2, lambda x, c, u : SimplifyAntiderivative(Log(u), x)) 6294 replacer.add(rule2) 6295 6296 pattern3 = Pattern(UtilityOperator(Log(Pow(u_, n_)), x_), CustomConstraint(lambda n, x: FreeQ(n, x))) 6297 rule3 = ReplacementRule(pattern3, lambda x, n, u : Mul(n, SimplifyAntiderivative(Log(u), x))) 6298 replacer.add(rule3) 6299 6300 pattern7 = Pattern(UtilityOperator(Log(Pow(f_, u_)), x_), CustomConstraint(lambda f, x: FreeQ(f, x))) 6301 rule7 = ReplacementRule(pattern7, lambda x, f, u : Mul(Log(f), SimplifyAntiderivative(u, x))) 6302 replacer.add(rule7) 6303 6304 pattern8 = Pattern(UtilityOperator(Log(Add(a_, Mul(WC('b', S(1)), Tan(u_)))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda b, a: ZeroQ(Add(Pow(a, S(2)), Pow(b, S(2)))))) 6305 rule8 = ReplacementRule(pattern8, lambda x, b, u, a : Add(Mul(Mul(b, Pow(a, S(1))), SimplifyAntiderivative(u, x)), Mul(S(1), SimplifyAntiderivative(Log(Cos(u)), x)))) 6306 replacer.add(rule8) 6307 6308 pattern9 = Pattern(UtilityOperator(Log(Add(Mul(Cot(u_), WC('b', S(1))), a_)), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda b, a: ZeroQ(Add(Pow(a, S(2)), Pow(b, S(2)))))) 6309 rule9 = ReplacementRule(pattern9, lambda x, b, u, a : Add(Mul(Mul(Mul(S(1), b), Pow(a, S(1))), SimplifyAntiderivative(u, x)), Mul(S(1), SimplifyAntiderivative(Log(Sin(u)), x)))) 6310 replacer.add(rule9) 6311 6312 pattern10 = Pattern(UtilityOperator(ArcTan(Mul(WC('a', S(1)), Tan(u_))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda a: PositiveQ(Pow(a, S(2)))), CustomConstraint(lambda u: ComplexFreeQ(u))) 6313 rule10 = ReplacementRule(pattern10, lambda x, u, a : RectifyTangent(u, a, S(1), x)) 6314 replacer.add(rule10) 6315 6316 pattern11 = Pattern(UtilityOperator(ArcCot(Mul(WC('a', S(1)), Tan(u_))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda a: PositiveQ(Pow(a, S(2)))), CustomConstraint(lambda u: ComplexFreeQ(u))) 6317 rule11 = ReplacementRule(pattern11, lambda x, u, a : RectifyTangent(u, a, S(1), x)) 6318 replacer.add(rule11) 6319 6320 pattern12 = Pattern(UtilityOperator(ArcCot(Mul(WC('a', S(1)), Tanh(u_))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda u: ComplexFreeQ(u))) 6321 rule12 = ReplacementRule(pattern12, lambda x, u, a : Mul(S(1), SimplifyAntiderivative(ArcTan(Mul(a, Tanh(u))), x))) 6322 replacer.add(rule12) 6323 6324 pattern13 = Pattern(UtilityOperator(ArcTanh(Mul(WC('a', S(1)), Tan(u_))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda a: PositiveQ(Pow(a, S(2)))), CustomConstraint(lambda u: ComplexFreeQ(u))) 6325 rule13 = ReplacementRule(pattern13, lambda x, u, a : RectifyTangent(u, Mul(I, a), Mul(S(1), I), x)) 6326 replacer.add(rule13) 6327 6328 pattern14 = Pattern(UtilityOperator(ArcCoth(Mul(WC('a', S(1)), Tan(u_))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda a: PositiveQ(Pow(a, S(2)))), CustomConstraint(lambda u: ComplexFreeQ(u))) 6329 rule14 = ReplacementRule(pattern14, lambda x, u, a : RectifyTangent(u, Mul(I, a), Mul(S(1), I), x)) 6330 replacer.add(rule14) 6331 6332 pattern15 = Pattern(UtilityOperator(ArcTanh(Tanh(u_)), x_)) 6333 rule15 = ReplacementRule(pattern15, lambda x, u : SimplifyAntiderivative(u, x)) 6334 replacer.add(rule15) 6335 6336 pattern16 = Pattern(UtilityOperator(ArcCoth(Tanh(u_)), x_)) 6337 rule16 = ReplacementRule(pattern16, lambda x, u : SimplifyAntiderivative(u, x)) 6338 replacer.add(rule16) 6339 6340 pattern17 = Pattern(UtilityOperator(ArcCot(Mul(Cot(u_), WC('a', S(1)))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda a: PositiveQ(Pow(a, S(2)))), CustomConstraint(lambda u: ComplexFreeQ(u))) 6341 rule17 = ReplacementRule(pattern17, lambda x, u, a : RectifyCotangent(u, a, S(1), x)) 6342 replacer.add(rule17) 6343 6344 pattern18 = Pattern(UtilityOperator(ArcTan(Mul(Cot(u_), WC('a', S(1)))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda a: PositiveQ(Pow(a, S(2)))), CustomConstraint(lambda u: ComplexFreeQ(u))) 6345 rule18 = ReplacementRule(pattern18, lambda x, u, a : RectifyCotangent(u, a, S(1), x)) 6346 replacer.add(rule18) 6347 6348 pattern19 = Pattern(UtilityOperator(ArcTan(Mul(Coth(u_), WC('a', S(1)))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda u: ComplexFreeQ(u))) 6349 rule19 = ReplacementRule(pattern19, lambda x, u, a : Mul(S(1), SimplifyAntiderivative(ArcTan(Mul(Tanh(u), Pow(a, S(1)))), x))) 6350 replacer.add(rule19) 6351 6352 pattern20 = Pattern(UtilityOperator(ArcCoth(Mul(Cot(u_), WC('a', S(1)))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda a: PositiveQ(Pow(a, S(2)))), CustomConstraint(lambda u: ComplexFreeQ(u))) 6353 rule20 = ReplacementRule(pattern20, lambda x, u, a : RectifyCotangent(u, Mul(I, a), I, x)) 6354 replacer.add(rule20) 6355 6356 pattern21 = Pattern(UtilityOperator(ArcTanh(Mul(Cot(u_), WC('a', S(1)))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda a: PositiveQ(Pow(a, S(2)))), CustomConstraint(lambda u: ComplexFreeQ(u))) 6357 rule21 = ReplacementRule(pattern21, lambda x, u, a : RectifyCotangent(u, Mul(I, a), I, x)) 6358 replacer.add(rule21) 6359 6360 pattern22 = Pattern(UtilityOperator(ArcCoth(Coth(u_)), x_)) 6361 rule22 = ReplacementRule(pattern22, lambda x, u : SimplifyAntiderivative(u, x)) 6362 replacer.add(rule22) 6363 6364 pattern23 = Pattern(UtilityOperator(ArcTanh(Mul(Coth(u_), WC('a', S(1)))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda u: ComplexFreeQ(u))) 6365 rule23 = ReplacementRule(pattern23, lambda x, u, a : SimplifyAntiderivative(ArcTanh(Mul(Tanh(u), Pow(a, S(1)))), x)) 6366 replacer.add(rule23) 6367 6368 pattern24 = Pattern(UtilityOperator(ArcTanh(Coth(u_)), x_)) 6369 rule24 = ReplacementRule(pattern24, lambda x, u : SimplifyAntiderivative(u, x)) 6370 replacer.add(rule24) 6371 6372 pattern25 = Pattern(UtilityOperator(ArcTan(Mul(WC('c', S(1)), Add(a_, Mul(WC('b', S(1)), Tan(u_))))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda c, a: PositiveQ(Mul(Pow(a, S(2)), Pow(c, S(2))))), CustomConstraint(lambda c, b: PositiveQ(Mul(Pow(b, S(2)), Pow(c, S(2))))), CustomConstraint(lambda u: ComplexFreeQ(u))) 6373 rule25 = ReplacementRule(pattern25, lambda x, a, b, u, c : RectifyTangent(u, Mul(a, c), Mul(b, c), S(1), x)) 6374 replacer.add(rule25) 6375 6376 pattern26 = Pattern(UtilityOperator(ArcTanh(Mul(WC('c', S(1)), Add(a_, Mul(WC('b', S(1)), Tan(u_))))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda c, a: PositiveQ(Mul(Pow(a, S(2)), Pow(c, S(2))))), CustomConstraint(lambda c, b: PositiveQ(Mul(Pow(b, S(2)), Pow(c, S(2))))), CustomConstraint(lambda u: ComplexFreeQ(u))) 6377 rule26 = ReplacementRule(pattern26, lambda x, a, b, u, c : RectifyTangent(u, Mul(I, a, c), Mul(I, b, c), Mul(S(1), I), x)) 6378 replacer.add(rule26) 6379 6380 pattern27 = Pattern(UtilityOperator(ArcTan(Mul(WC('c', S(1)), Add(Mul(Cot(u_), WC('b', S(1))), a_))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda c, a: PositiveQ(Mul(Pow(a, S(2)), Pow(c, S(2))))), CustomConstraint(lambda c, b: PositiveQ(Mul(Pow(b, S(2)), Pow(c, S(2))))), CustomConstraint(lambda u: ComplexFreeQ(u))) 6381 rule27 = ReplacementRule(pattern27, lambda x, a, b, u, c : RectifyCotangent(u, Mul(a, c), Mul(b, c), S(1), x)) 6382 replacer.add(rule27) 6383 6384 pattern28 = Pattern(UtilityOperator(ArcTanh(Mul(WC('c', S(1)), Add(Mul(Cot(u_), WC('b', S(1))), a_))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda c, a: PositiveQ(Mul(Pow(a, S(2)), Pow(c, S(2))))), CustomConstraint(lambda c, b: PositiveQ(Mul(Pow(b, S(2)), Pow(c, S(2))))), CustomConstraint(lambda u: ComplexFreeQ(u))) 6385 rule28 = ReplacementRule(pattern28, lambda x, a, b, u, c : RectifyCotangent(u, Mul(I, a, c), Mul(I, b, c), Mul(S(1), I), x)) 6386 replacer.add(rule28) 6387 6388 pattern29 = Pattern(UtilityOperator(ArcTan(Add(WC('a', S(0)), Mul(WC('b', S(1)), Tan(u_)), Mul(WC('c', S(1)), Pow(Tan(u_), S(2))))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda u: ComplexFreeQ(u))) 6389 rule29 = ReplacementRule(pattern29, lambda x, a, b, u, c : If(EvenQ(Denominator(NumericFactor(Together(u)))), ArcTan(NormalizeTogether(Mul(Add(a, c, S(1), Mul(Add(a, Mul(S(1), c), S(1)), Cos(Mul(S(2), u))), Mul(b, Sin(Mul(S(2), u)))), Pow(Add(a, c, S(1), Mul(Add(a, Mul(S(1), c), S(1)), Cos(Mul(S(2), u))), Mul(b, Sin(Mul(S(2), u)))), S(1))))), ArcTan(NormalizeTogether(Mul(Add(c, Mul(Add(a, Mul(S(1), c), S(1)), Pow(Cos(u), S(2))), Mul(b, Cos(u), Sin(u))), Pow(Add(c, Mul(Add(a, Mul(S(1), c), S(1)), Pow(Cos(u), S(2))), Mul(b, Cos(u), Sin(u))), S(1))))))) 6390 replacer.add(rule29) 6391 6392 pattern30 = Pattern(UtilityOperator(ArcTan(Add(WC('a', S(0)), Mul(WC('b', S(1)), Add(WC('d', S(0)), Mul(WC('e', S(1)), Tan(u_)))), Mul(WC('c', S(1)), Pow(Add(WC('f', S(0)), Mul(WC('g', S(1)), Tan(u_))), S(2))))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda b, x: FreeQ(b, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda u: ComplexFreeQ(u))) 6393 rule30 = ReplacementRule(pattern30, lambda x, d, a, e, f, b, u, c, g : SimplifyAntiderivative(ArcTan(Add(a, Mul(b, d), Mul(c, Pow(f, S(2))), Mul(Add(Mul(b, e), Mul(S(2), c, f, g)), Tan(u)), Mul(c, Pow(g, S(2)), Pow(Tan(u), S(2))))), x)) 6394 replacer.add(rule30) 6395 6396 pattern31 = Pattern(UtilityOperator(ArcTan(Add(WC('a', S(0)), Mul(WC('c', S(1)), Pow(Tan(u_), S(2))))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda u: ComplexFreeQ(u))) 6397 rule31 = ReplacementRule(pattern31, lambda x, c, u, a : If(EvenQ(Denominator(NumericFactor(Together(u)))), ArcTan(NormalizeTogether(Mul(Add(a, c, S(1), Mul(Add(a, Mul(S(1), c), S(1)), Cos(Mul(S(2), u)))), Pow(Add(a, c, S(1), Mul(Add(a, Mul(S(1), c), S(1)), Cos(Mul(S(2), u)))), S(1))))), ArcTan(NormalizeTogether(Mul(Add(c, Mul(Add(a, Mul(S(1), c), S(1)), Pow(Cos(u), S(2)))), Pow(Add(c, Mul(Add(a, Mul(S(1), c), S(1)), Pow(Cos(u), S(2)))), S(1))))))) 6398 replacer.add(rule31) 6399 6400 pattern32 = Pattern(UtilityOperator(ArcTan(Add(WC('a', S(0)), Mul(WC('c', S(1)), Pow(Add(WC('f', S(0)), Mul(WC('g', S(1)), Tan(u_))), S(2))))), x_), CustomConstraint(lambda a, x: FreeQ(a, x)), CustomConstraint(lambda c, x: FreeQ(c, x)), CustomConstraint(lambda u: ComplexFreeQ(u))) 6401 rule32 = ReplacementRule(pattern32, lambda x, a, f, u, c, g : SimplifyAntiderivative(ArcTan(Add(a, Mul(c, Pow(f, S(2))), Mul(Mul(S(2), c, f, g), Tan(u)), Mul(c, Pow(g, S(2)), Pow(Tan(u), S(2))))), x)) 6402 replacer.add(rule32) 6403 6404 return replacer 6405 6406@doctest_depends_on(modules=('matchpy',)) 6407def SimplifyAntiderivative(expr, x): 6408 r = SimplifyAntiderivative_replacer.replace(UtilityOperator(expr, x)) 6409 if isinstance(r, UtilityOperator): 6410 if ProductQ(expr): 6411 u, c = S(1), S(1) 6412 for i in expr.args: 6413 if FreeQ(i, x): 6414 c *= i 6415 else: 6416 u *= i 6417 if FreeQ(c, x) and c != S(1): 6418 v = SimplifyAntiderivative(u, x) 6419 if SumQ(v) and NonsumQ(u): 6420 return Add(*[c*i for i in v.args]) 6421 return c*v 6422 elif LogQ(expr): 6423 F = expr.args[0] 6424 if MemberQ([cot, sec, csc, coth, sech, csch], Head(F)): 6425 return -SimplifyAntiderivative(Log(1/F), x) 6426 if MemberQ([Log, atan, acot], Head(expr)): 6427 F = Head(expr) 6428 G = expr.args[0] 6429 if MemberQ([cot, sec, csc, coth, sech, csch], Head(G)): 6430 return -SimplifyAntiderivative(F(1/G), x) 6431 if MemberQ([atanh, acoth], Head(expr)): 6432 F = Head(expr) 6433 G = expr.args[0] 6434 if MemberQ([cot, sec, csc, coth, sech, csch], Head(G)): 6435 return SimplifyAntiderivative(F(1/G), x) 6436 u = expr 6437 if FreeQ(u, x): 6438 return S(0) 6439 elif LogQ(u): 6440 return Log(RemoveContent(u.args[0], x)) 6441 elif SumQ(u): 6442 return SimplifyAntiderivativeSum(Add(*[SimplifyAntiderivative(i, x) for i in u.args]), x) 6443 return u 6444 else: 6445 return r 6446 6447@doctest_depends_on(modules=('matchpy',)) 6448def _TrigSimplifyAux(): 6449 replacer = ManyToOneReplacer() 6450 6451 pattern1 = Pattern(UtilityOperator(Mul(WC('u', S(1)), Pow(Add(Mul(WC('a', S(1)), Pow(v_, WC('m', S(1)))), Mul(WC('b', S(1)), Pow(v_, WC('n', S(1))))), p_))), CustomConstraint(lambda v: InertTrigQ(v)), CustomConstraint(lambda p: IntegerQ(p)), CustomConstraint(lambda n, m: RationalQ(m, n)), CustomConstraint(lambda n, m: Less(m, n))) 6452 rule1 = ReplacementRule(pattern1, lambda n, a, p, m, u, v, b : Mul(u, Pow(v, Mul(m, p)), Pow(TrigSimplifyAux(Add(a, Mul(b, Pow(v, Add(n, Mul(S(-1), m)))))), p))) 6453 replacer.add(rule1) 6454 6455 pattern2 = Pattern(UtilityOperator(Add(Mul(Pow(cos(u_), S('2')), WC('a', S(1))), WC('v', S(0)), Mul(WC('b', S(1)), Pow(sin(u_), S('2'))))), CustomConstraint(lambda b, a: SameQ(a, b))) 6456 rule2 = ReplacementRule(pattern2, lambda u, v, b, a : Add(a, v)) 6457 replacer.add(rule2) 6458 6459 pattern3 = Pattern(UtilityOperator(Add(WC('v', S(0)), Mul(WC('a', S(1)), Pow(sec(u_), S('2'))), Mul(WC('b', S(1)), Pow(tan(u_), S('2'))))), CustomConstraint(lambda b, a: SameQ(a, Mul(S(-1), b)))) 6460 rule3 = ReplacementRule(pattern3, lambda u, v, b, a : Add(a, v)) 6461 replacer.add(rule3) 6462 6463 pattern4 = Pattern(UtilityOperator(Add(Mul(Pow(csc(u_), S('2')), WC('a', S(1))), Mul(Pow(cot(u_), S('2')), WC('b', S(1))), WC('v', S(0)))), CustomConstraint(lambda b, a: SameQ(a, Mul(S(-1), b)))) 6464 rule4 = ReplacementRule(pattern4, lambda u, v, b, a : Add(a, v)) 6465 replacer.add(rule4) 6466 6467 pattern5 = Pattern(UtilityOperator(Pow(Add(Mul(Pow(cos(u_), S('2')), WC('a', S(1))), WC('v', S(0)), Mul(WC('b', S(1)), Pow(sin(u_), S('2')))), n_))) 6468 rule5 = ReplacementRule(pattern5, lambda n, a, u, v, b : Pow(Add(Mul(Add(b, Mul(S(-1), a)), Pow(Sin(u), S('2'))), a, v), n)) 6469 replacer.add(rule5) 6470 6471 pattern6 = Pattern(UtilityOperator(Add(WC('w', S(0)), u_, Mul(WC('v', S(1)), Pow(sin(z_), S('2'))))), CustomConstraint(lambda u, v: SameQ(u, Mul(S(-1), v)))) 6472 rule6 = ReplacementRule(pattern6, lambda u, w, z, v : Add(Mul(u, Pow(Cos(z), S('2'))), w)) 6473 replacer.add(rule6) 6474 6475 pattern7 = Pattern(UtilityOperator(Add(Mul(Pow(cos(z_), S('2')), WC('v', S(1))), WC('w', S(0)), u_)), CustomConstraint(lambda u, v: SameQ(u, Mul(S(-1), v)))) 6476 rule7 = ReplacementRule(pattern7, lambda z, w, v, u : Add(Mul(u, Pow(Sin(z), S('2'))), w)) 6477 replacer.add(rule7) 6478 6479 pattern8 = Pattern(UtilityOperator(Add(WC('w', S(0)), u_, Mul(WC('v', S(1)), Pow(tan(z_), S('2'))))), CustomConstraint(lambda u, v: SameQ(u, v))) 6480 rule8 = ReplacementRule(pattern8, lambda u, w, z, v : Add(Mul(u, Pow(Sec(z), S('2'))), w)) 6481 replacer.add(rule8) 6482 6483 pattern9 = Pattern(UtilityOperator(Add(Mul(Pow(cot(z_), S('2')), WC('v', S(1))), WC('w', S(0)), u_)), CustomConstraint(lambda u, v: SameQ(u, v))) 6484 rule9 = ReplacementRule(pattern9, lambda z, w, v, u : Add(Mul(u, Pow(Csc(z), S('2'))), w)) 6485 replacer.add(rule9) 6486 6487 pattern10 = Pattern(UtilityOperator(Add(WC('w', S(0)), u_, Mul(WC('v', S(1)), Pow(sec(z_), S('2'))))), CustomConstraint(lambda u, v: SameQ(u, Mul(S(-1), v)))) 6488 rule10 = ReplacementRule(pattern10, lambda u, w, z, v : Add(Mul(v, Pow(Tan(z), S('2'))), w)) 6489 replacer.add(rule10) 6490 6491 pattern11 = Pattern(UtilityOperator(Add(Mul(Pow(csc(z_), S('2')), WC('v', S(1))), WC('w', S(0)), u_)), CustomConstraint(lambda u, v: SameQ(u, Mul(S(-1), v)))) 6492 rule11 = ReplacementRule(pattern11, lambda z, w, v, u : Add(Mul(v, Pow(Cot(z), S('2'))), w)) 6493 replacer.add(rule11) 6494 6495 pattern12 = Pattern(UtilityOperator(Mul(WC('u', S(1)), Pow(Add(Mul(cos(v_), WC('b', S(1))), a_), S(-1)), Pow(sin(v_), S('2')))), CustomConstraint(lambda b, a: ZeroQ(Add(Pow(a, S('2')), Mul(S(-1), Pow(b, S('2'))))))) 6496 rule12 = ReplacementRule(pattern12, lambda u, v, b, a : Mul(u, Add(Mul(S(1), Pow(a, S(-1))), Mul(S(-1), Mul(Cos(v), Pow(b, S(-1))))))) 6497 replacer.add(rule12) 6498 6499 pattern13 = Pattern(UtilityOperator(Mul(Pow(cos(v_), S('2')), WC('u', S(1)), Pow(Add(a_, Mul(WC('b', S(1)), sin(v_))), S(-1)))), CustomConstraint(lambda b, a: ZeroQ(Add(Pow(a, S('2')), Mul(S(-1), Pow(b, S('2'))))))) 6500 rule13 = ReplacementRule(pattern13, lambda u, v, b, a : Mul(u, Add(Mul(S(1), Pow(a, S(-1))), Mul(S(-1), Mul(Sin(v), Pow(b, S(-1))))))) 6501 replacer.add(rule13) 6502 6503 pattern14 = Pattern(UtilityOperator(Mul(WC('u', S(1)), Pow(tan(v_), WC('n', S(1))), Pow(Add(a_, Mul(WC('b', S(1)), Pow(tan(v_), WC('n', S(1))))), S(-1)))), CustomConstraint(lambda n: PositiveIntegerQ(n)), CustomConstraint(lambda a: NonsumQ(a))) 6504 rule14 = ReplacementRule(pattern14, lambda n, a, u, v, b : Mul(u, Pow(Add(b, Mul(a, Pow(Cot(v), n))), S(-1)))) 6505 replacer.add(rule14) 6506 6507 pattern15 = Pattern(UtilityOperator(Mul(Pow(cot(v_), WC('n', S(1))), WC('u', S(1)), Pow(Add(Mul(Pow(cot(v_), WC('n', S(1))), WC('b', S(1))), a_), S(-1)))), CustomConstraint(lambda n: PositiveIntegerQ(n)), CustomConstraint(lambda a: NonsumQ(a))) 6508 rule15 = ReplacementRule(pattern15, lambda n, a, u, v, b : Mul(u, Pow(Add(b, Mul(a, Pow(Tan(v), n))), S(-1)))) 6509 replacer.add(rule15) 6510 6511 pattern16 = Pattern(UtilityOperator(Mul(WC('u', S(1)), Pow(sec(v_), WC('n', S(1))), Pow(Add(a_, Mul(WC('b', S(1)), Pow(sec(v_), WC('n', S(1))))), S(-1)))), CustomConstraint(lambda n: PositiveIntegerQ(n)), CustomConstraint(lambda a: NonsumQ(a))) 6512 rule16 = ReplacementRule(pattern16, lambda n, a, u, v, b : Mul(u, Pow(Add(b, Mul(a, Pow(Cos(v), n))), S(-1)))) 6513 replacer.add(rule16) 6514 6515 pattern17 = Pattern(UtilityOperator(Mul(Pow(csc(v_), WC('n', S(1))), WC('u', S(1)), Pow(Add(Mul(Pow(csc(v_), WC('n', S(1))), WC('b', S(1))), a_), S(-1)))), CustomConstraint(lambda n: PositiveIntegerQ(n)), CustomConstraint(lambda a: NonsumQ(a))) 6516 rule17 = ReplacementRule(pattern17, lambda n, a, u, v, b : Mul(u, Pow(Add(b, Mul(a, Pow(Sin(v), n))), S(-1)))) 6517 replacer.add(rule17) 6518 6519 pattern18 = Pattern(UtilityOperator(Mul(WC('u', S(1)), Pow(Add(a_, Mul(WC('b', S(1)), Pow(sec(v_), WC('n', S(1))))), S(-1)), Pow(tan(v_), WC('n', S(1))))), CustomConstraint(lambda n: PositiveIntegerQ(n)), CustomConstraint(lambda a: NonsumQ(a))) 6520 rule18 = ReplacementRule(pattern18, lambda n, a, u, v, b : Mul(u, Mul(Pow(Sin(v), n), Pow(Add(b, Mul(a, Pow(Cos(v), n))), S(-1))))) 6521 replacer.add(rule18) 6522 6523 pattern19 = Pattern(UtilityOperator(Mul(Pow(cot(v_), WC('n', S(1))), WC('u', S(1)), Pow(Add(Mul(Pow(csc(v_), WC('n', S(1))), WC('b', S(1))), a_), S(-1)))), CustomConstraint(lambda n: PositiveIntegerQ(n)), CustomConstraint(lambda a: NonsumQ(a))) 6524 rule19 = ReplacementRule(pattern19, lambda n, a, u, v, b : Mul(u, Mul(Pow(Cos(v), n), Pow(Add(b, Mul(a, Pow(Sin(v), n))), S(-1))))) 6525 replacer.add(rule19) 6526 6527 pattern20 = Pattern(UtilityOperator(Mul(WC('u', S(1)), Pow(Add(Mul(WC('a', S(1)), Pow(sec(v_), WC('n', S(1)))), Mul(WC('b', S(1)), Pow(tan(v_), WC('n', S(1))))), WC('p', S(1))))), CustomConstraint(lambda n, p: IntegersQ(n, p))) 6528 rule20 = ReplacementRule(pattern20, lambda n, a, p, u, v, b : Mul(u, Pow(Sec(v), Mul(n, p)), Pow(Add(a, Mul(b, Pow(Sin(v), n))), p))) 6529 replacer.add(rule20) 6530 6531 pattern21 = Pattern(UtilityOperator(Mul(Pow(Add(Mul(Pow(csc(v_), WC('n', S(1))), WC('a', S(1))), Mul(Pow(cot(v_), WC('n', S(1))), WC('b', S(1)))), WC('p', S(1))), WC('u', S(1)))), CustomConstraint(lambda n, p: IntegersQ(n, p))) 6532 rule21 = ReplacementRule(pattern21, lambda n, a, p, u, v, b : Mul(u, Pow(Csc(v), Mul(n, p)), Pow(Add(a, Mul(b, Pow(Cos(v), n))), p))) 6533 replacer.add(rule21) 6534 6535 pattern22 = Pattern(UtilityOperator(Mul(WC('u', S(1)), Pow(Add(Mul(WC('b', S(1)), Pow(sin(v_), WC('n', S(1)))), Mul(WC('a', S(1)), Pow(tan(v_), WC('n', S(1))))), WC('p', S(1))))), CustomConstraint(lambda n, p: IntegersQ(n, p))) 6536 rule22 = ReplacementRule(pattern22, lambda n, a, p, u, v, b : Mul(u, Pow(Tan(v), Mul(n, p)), Pow(Add(a, Mul(b, Pow(Cos(v), n))), p))) 6537 replacer.add(rule22) 6538 6539 pattern23 = Pattern(UtilityOperator(Mul(Pow(Add(Mul(Pow(cot(v_), WC('n', S(1))), WC('a', S(1))), Mul(Pow(cos(v_), WC('n', S(1))), WC('b', S(1)))), WC('p', S(1))), WC('u', S(1)))), CustomConstraint(lambda n, p: IntegersQ(n, p))) 6540 rule23 = ReplacementRule(pattern23, lambda n, a, p, u, v, b : Mul(u, Pow(Cot(v), Mul(n, p)), Pow(Add(a, Mul(b, Pow(Sin(v), n))), p))) 6541 replacer.add(rule23) 6542 6543 pattern24 = Pattern(UtilityOperator(Mul(Pow(cos(v_), WC('m', S(1))), WC('u', S(1)), Pow(Add(WC('a', S(0)), Mul(WC('c', S(1)), Pow(sec(v_), WC('n', S(1)))), Mul(WC('b', S(1)), Pow(tan(v_), WC('n', S(1))))), WC('p', S(1))))), CustomConstraint(lambda n, p, m: IntegersQ(m, n, p))) 6544 rule24 = ReplacementRule(pattern24, lambda n, a, c, p, m, u, v, b : Mul(u, Pow(Cos(v), Add(m, Mul(S(-1), Mul(n, p)))), Pow(Add(c, Mul(b, Pow(Sin(v), n)), Mul(a, Pow(Cos(v), n))), p))) 6545 replacer.add(rule24) 6546 6547 pattern25 = Pattern(UtilityOperator(Mul(WC('u', S(1)), Pow(sec(v_), WC('m', S(1))), Pow(Add(WC('a', S(0)), Mul(WC('c', S(1)), Pow(sec(v_), WC('n', S(1)))), Mul(WC('b', S(1)), Pow(tan(v_), WC('n', S(1))))), WC('p', S(1))))), CustomConstraint(lambda n, p, m: IntegersQ(m, n, p))) 6548 rule25 = ReplacementRule(pattern25, lambda n, a, c, p, m, u, v, b : Mul(u, Pow(Sec(v), Add(m, Mul(n, p))), Pow(Add(c, Mul(b, Pow(Sin(v), n)), Mul(a, Pow(Cos(v), n))), p))) 6549 replacer.add(rule25) 6550 6551 pattern26 = Pattern(UtilityOperator(Mul(Pow(Add(WC('a', S(0)), Mul(Pow(cot(v_), WC('n', S(1))), WC('b', S(1))), Mul(Pow(csc(v_), WC('n', S(1))), WC('c', S(1)))), WC('p', S(1))), WC('u', S(1)), Pow(sin(v_), WC('m', S(1))))), CustomConstraint(lambda n, p, m: IntegersQ(m, n, p))) 6552 rule26 = ReplacementRule(pattern26, lambda n, a, c, p, m, u, v, b : Mul(u, Pow(Sin(v), Add(m, Mul(S(-1), Mul(n, p)))), Pow(Add(c, Mul(b, Pow(Cos(v), n)), Mul(a, Pow(Sin(v), n))), p))) 6553 replacer.add(rule26) 6554 6555 pattern27 = Pattern(UtilityOperator(Mul(Pow(csc(v_), WC('m', S(1))), Pow(Add(WC('a', S(0)), Mul(Pow(cot(v_), WC('n', S(1))), WC('b', S(1))), Mul(Pow(csc(v_), WC('n', S(1))), WC('c', S(1)))), WC('p', S(1))), WC('u', S(1)))), CustomConstraint(lambda n, p, m: IntegersQ(m, n, p))) 6556 rule27 = ReplacementRule(pattern27, lambda n, a, c, p, m, u, v, b : Mul(u, Pow(Csc(v), Add(m, Mul(n, p))), Pow(Add(c, Mul(b, Pow(Cos(v), n)), Mul(a, Pow(Sin(v), n))), p))) 6557 replacer.add(rule27) 6558 6559 pattern28 = Pattern(UtilityOperator(Mul(WC('u', S(1)), Pow(Add(Mul(Pow(csc(v_), WC('m', S(1))), WC('a', S(1))), Mul(WC('b', S(1)), Pow(sin(v_), WC('n', S(1))))), WC('p', S(1))))), CustomConstraint(lambda n, m: IntegersQ(m, n))) 6560 rule28 = ReplacementRule(pattern28, lambda n, a, p, m, u, v, b : If(And(ZeroQ(Add(m, n, S(-2))), ZeroQ(Add(a, b))), Mul(u, Pow(Mul(a, Mul(Pow(Cos(v), S('2')), Pow(Pow(Sin(v), m), S(-1)))), p)), Mul(u, Pow(Mul(Add(a, Mul(b, Pow(Sin(v), Add(m, n)))), Pow(Pow(Sin(v), m), S(-1))), p)))) 6561 replacer.add(rule28) 6562 6563 pattern29 = Pattern(UtilityOperator(Mul(WC('u', S(1)), Pow(Add(Mul(Pow(cos(v_), WC('n', S(1))), WC('b', S(1))), Mul(WC('a', S(1)), Pow(sec(v_), WC('m', S(1))))), WC('p', S(1))))), CustomConstraint(lambda n, m: IntegersQ(m, n))) 6564 rule29 = ReplacementRule(pattern29, lambda n, a, p, m, u, v, b : If(And(ZeroQ(Add(m, n, S(-2))), ZeroQ(Add(a, b))), Mul(u, Pow(Mul(a, Mul(Pow(Sin(v), S('2')), Pow(Pow(Cos(v), m), S(-1)))), p)), Mul(u, Pow(Mul(Add(a, Mul(b, Pow(Cos(v), Add(m, n)))), Pow(Pow(Cos(v), m), S(-1))), p)))) 6565 replacer.add(rule29) 6566 6567 pattern30 = Pattern(UtilityOperator(u_)) 6568 rule30 = ReplacementRule(pattern30, lambda u : u) 6569 replacer.add(rule30) 6570 6571 return replacer 6572 6573@doctest_depends_on(modules=('matchpy',)) 6574def TrigSimplifyAux(expr): 6575 return TrigSimplifyAux_replacer.replace(UtilityOperator(expr)) 6576 6577def Cancel(expr): 6578 return cancel(expr) 6579 6580class Util_Part(Function): 6581 def doit(self): 6582 i = Simplify(self.args[0]) 6583 if len(self.args) > 2 : 6584 lst = list(self.args[1:]) 6585 else: 6586 lst = self.args[1] 6587 if isinstance(i, (int, Integer)): 6588 if isinstance(lst, list): 6589 return lst[i - 1] 6590 elif AtomQ(lst): 6591 return lst 6592 return lst.args[i - 1] 6593 else: 6594 return self 6595 6596def Part(lst, i): #see i = -1 6597 if isinstance(lst, list): 6598 return Util_Part(i, *lst).doit() 6599 return Util_Part(i, lst).doit() 6600 6601def PolyLog(n, p, z=None): 6602 return polylog(n, p) 6603 6604def D(f, x): 6605 try: 6606 return f.diff(x) 6607 except ValueError: 6608 return Function('D')(f, x) 6609 6610def IntegralFreeQ(u): 6611 return FreeQ(u, Integral) 6612 6613def Dist(u, v, x): 6614 #Dist(u,v) returns the sum of u times each term of v, provided v is free of Int 6615 u = replace_pow_exp(u) # to replace back to sympy's exp 6616 v = replace_pow_exp(v) 6617 w = Simp(u*x**2, x)/x**2 6618 if u == 1: 6619 return v 6620 elif u == 0: 6621 return 0 6622 elif NumericFactor(u) < 0 and NumericFactor(-u) > 0: 6623 return -Dist(-u, v, x) 6624 elif SumQ(v): 6625 return Add(*[Dist(u, i, x) for i in v.args]) 6626 elif IntegralFreeQ(v): 6627 return Simp(u*v, x) 6628 elif w != u and FreeQ(w, x) and w == Simp(w, x) and w == Simp(w*x**2, x)/x**2: 6629 return Dist(w, v, x) 6630 else: 6631 return Simp(u*v, x) 6632 6633def PureFunctionOfCothQ(u, v, x): 6634 # If u is a pure function of Coth[v], PureFunctionOfCothQ[u,v,x] returns True; 6635 if AtomQ(u): 6636 return u != x 6637 elif CalculusQ(u): 6638 return False 6639 elif HyperbolicQ(u) and ZeroQ(u.args[0] - v): 6640 return CothQ(u) 6641 return all(PureFunctionOfCothQ(i, v, x) for i in u.args) 6642 6643def LogIntegral(z): 6644 return li(z) 6645 6646def ExpIntegralEi(z): 6647 return Ei(z) 6648 6649def ExpIntegralE(a, b): 6650 return expint(a, b).evalf() 6651 6652def SinIntegral(z): 6653 return Si(z) 6654 6655def CosIntegral(z): 6656 return Ci(z) 6657 6658def SinhIntegral(z): 6659 return Shi(z) 6660 6661def CoshIntegral(z): 6662 return Chi(z) 6663 6664class PolyGamma(Function): 6665 @classmethod 6666 def eval(cls, *args): 6667 if len(args) == 2: 6668 return polygamma(args[0], args[1]) 6669 return digamma(args[0]) 6670 6671def LogGamma(z): 6672 return loggamma(z) 6673 6674class ProductLog(Function): 6675 @classmethod 6676 def eval(cls, *args): 6677 if len(args) == 2: 6678 return LambertW(args[1], args[0]).evalf() 6679 return LambertW(args[0]).evalf() 6680 6681def Factorial(a): 6682 return factorial(a) 6683 6684def Zeta(*args): 6685 return zeta(*args) 6686 6687def HypergeometricPFQ(a, b, c): 6688 return hyper(a, b, c) 6689 6690def Sum_doit(exp, args): 6691 """ 6692 This function perform summation using sympy's `Sum`. 6693 6694 Examples 6695 ======== 6696 6697 >>> from sympy.integrals.rubi.utility_function import Sum_doit 6698 >>> from sympy.abc import x 6699 >>> Sum_doit(2*x + 2, [x, 0, 1.7]) 6700 6 6701 6702 """ 6703 exp = replace_pow_exp(exp) 6704 if not isinstance(args[2], (int, Integer)): 6705 new_args = [args[0], args[1], Floor(args[2])] 6706 return Sum(exp, new_args).doit() 6707 6708 return Sum(exp, args).doit() 6709 6710def PolynomialQuotient(p, q, x): 6711 try: 6712 p = poly(p, x) 6713 q = poly(q, x) 6714 6715 except: 6716 p = poly(p) 6717 q = poly(q) 6718 try: 6719 return quo(p, q).as_expr() 6720 except (PolynomialDivisionFailed, UnificationFailed): 6721 return p/q 6722 6723def PolynomialRemainder(p, q, x): 6724 try: 6725 p = poly(p, x) 6726 q = poly(q, x) 6727 6728 except: 6729 p = poly(p) 6730 q = poly(q) 6731 try: 6732 return rem(p, q).as_expr() 6733 except (PolynomialDivisionFailed, UnificationFailed): 6734 return S(0) 6735 6736def Floor(x, a = None): 6737 if a is None: 6738 return floor(x) 6739 return a*floor(x/a) 6740 6741def Factor(var): 6742 return factor(var) 6743 6744def Rule(a, b): 6745 return {a: b} 6746 6747def Distribute(expr, *args): 6748 if len(args) == 1: 6749 if isinstance(expr, args[0]): 6750 return expr 6751 else: 6752 return expr.expand() 6753 if len(args) == 2: 6754 if isinstance(expr, args[1]): 6755 return expr.expand() 6756 else: 6757 return expr 6758 return expr.expand() 6759 6760def CoprimeQ(*args): 6761 args = S(args) 6762 g = gcd(*args) 6763 if g == 1: 6764 return True 6765 return False 6766 6767def Discriminant(a, b): 6768 try: 6769 return discriminant(a, b) 6770 except PolynomialError: 6771 return Function('Discriminant')(a, b) 6772 6773def Negative(x): 6774 return x < S(0) 6775 6776def Quotient(m, n): 6777 return Floor(m/n) 6778 6779def process_trig(expr): 6780 """ 6781 This function processes trigonometric expressions such that all `cot` is 6782 rewritten in terms of `tan`, `sec` in terms of `cos`, `csc` in terms of `sin` and 6783 similarly for `coth`, `sech` and `csch`. 6784 6785 Examples 6786 ======== 6787 6788 >>> from sympy.integrals.rubi.utility_function import process_trig 6789 >>> from sympy.abc import x 6790 >>> from sympy import coth, cot, csc 6791 >>> process_trig(x*cot(x)) 6792 x/tan(x) 6793 >>> process_trig(coth(x)*csc(x)) 6794 1/(sin(x)*tanh(x)) 6795 6796 """ 6797 expr = expr.replace(lambda x: isinstance(x, cot), lambda x: 1/tan(x.args[0])) 6798 expr = expr.replace(lambda x: isinstance(x, sec), lambda x: 1/cos(x.args[0])) 6799 expr = expr.replace(lambda x: isinstance(x, csc), lambda x: 1/sin(x.args[0])) 6800 expr = expr.replace(lambda x: isinstance(x, coth), lambda x: 1/tanh(x.args[0])) 6801 expr = expr.replace(lambda x: isinstance(x, sech), lambda x: 1/cosh(x.args[0])) 6802 expr = expr.replace(lambda x: isinstance(x, csch), lambda x: 1/sinh(x.args[0])) 6803 return expr 6804 6805def _ExpandIntegrand(): 6806 Plus = Add 6807 Times = Mul 6808 def cons_f1(m): 6809 return PositiveIntegerQ(m) 6810 6811 cons1 = CustomConstraint(cons_f1) 6812 def cons_f2(d, c, b, a): 6813 return ZeroQ(-a*d + b*c) 6814 6815 cons2 = CustomConstraint(cons_f2) 6816 def cons_f3(a, x): 6817 return FreeQ(a, x) 6818 6819 cons3 = CustomConstraint(cons_f3) 6820 def cons_f4(b, x): 6821 return FreeQ(b, x) 6822 6823 cons4 = CustomConstraint(cons_f4) 6824 def cons_f5(c, x): 6825 return FreeQ(c, x) 6826 6827 cons5 = CustomConstraint(cons_f5) 6828 def cons_f6(d, x): 6829 return FreeQ(d, x) 6830 6831 cons6 = CustomConstraint(cons_f6) 6832 def cons_f7(e, x): 6833 return FreeQ(e, x) 6834 6835 cons7 = CustomConstraint(cons_f7) 6836 def cons_f8(f, x): 6837 return FreeQ(f, x) 6838 6839 cons8 = CustomConstraint(cons_f8) 6840 def cons_f9(g, x): 6841 return FreeQ(g, x) 6842 6843 cons9 = CustomConstraint(cons_f9) 6844 def cons_f10(h, x): 6845 return FreeQ(h, x) 6846 6847 cons10 = CustomConstraint(cons_f10) 6848 def cons_f11(e, b, c, f, n, p, F, x, d, m): 6849 if not isinstance(x, Symbol): 6850 return False 6851 return FreeQ(List(F, b, c, d, e, f, m, n, p), x) 6852 6853 cons11 = CustomConstraint(cons_f11) 6854 def cons_f12(F, x): 6855 return FreeQ(F, x) 6856 6857 cons12 = CustomConstraint(cons_f12) 6858 def cons_f13(m, x): 6859 return FreeQ(m, x) 6860 6861 cons13 = CustomConstraint(cons_f13) 6862 def cons_f14(n, x): 6863 return FreeQ(n, x) 6864 6865 cons14 = CustomConstraint(cons_f14) 6866 def cons_f15(p, x): 6867 return FreeQ(p, x) 6868 6869 cons15 = CustomConstraint(cons_f15) 6870 def cons_f16(e, b, c, f, n, a, p, F, x, d, m): 6871 if not isinstance(x, Symbol): 6872 return False 6873 return FreeQ(List(F, a, b, c, d, e, f, m, n, p), x) 6874 6875 cons16 = CustomConstraint(cons_f16) 6876 def cons_f17(n, m): 6877 return IntegersQ(m, n) 6878 6879 cons17 = CustomConstraint(cons_f17) 6880 def cons_f18(n): 6881 return Less(n, S(0)) 6882 6883 cons18 = CustomConstraint(cons_f18) 6884 def cons_f19(x, u): 6885 if not isinstance(x, Symbol): 6886 return False 6887 return PolynomialQ(u, x) 6888 6889 cons19 = CustomConstraint(cons_f19) 6890 def cons_f20(G, F, u): 6891 return SameQ(F(u)*G(u), S(1)) 6892 6893 cons20 = CustomConstraint(cons_f20) 6894 def cons_f21(q, x): 6895 return FreeQ(q, x) 6896 6897 cons21 = CustomConstraint(cons_f21) 6898 def cons_f22(F): 6899 return MemberQ(List(ArcSin, ArcCos, ArcSinh, ArcCosh), F) 6900 6901 cons22 = CustomConstraint(cons_f22) 6902 def cons_f23(j, n): 6903 return ZeroQ(j - S(2)*n) 6904 6905 cons23 = CustomConstraint(cons_f23) 6906 def cons_f24(A, x): 6907 return FreeQ(A, x) 6908 6909 cons24 = CustomConstraint(cons_f24) 6910 def cons_f25(B, x): 6911 return FreeQ(B, x) 6912 6913 cons25 = CustomConstraint(cons_f25) 6914 def cons_f26(m, u, x): 6915 if not isinstance(x, Symbol): 6916 return False 6917 def _cons_f_u(d, w, c, p, x): 6918 return And(FreeQ(List(c, d), x), IntegerQ(p), Greater(p, m)) 6919 cons_u = CustomConstraint(_cons_f_u) 6920 pat = Pattern(UtilityOperator((c_ + x_*WC('d', S(1)))**p_*WC('w', S(1)), x_), cons_u) 6921 result_matchq = is_match(UtilityOperator(u, x), pat) 6922 return Not(And(PositiveIntegerQ(m), result_matchq)) 6923 6924 cons26 = CustomConstraint(cons_f26) 6925 def cons_f27(b, v, n, a, x, u, m): 6926 if not isinstance(x, Symbol): 6927 return False 6928 return And(FreeQ(List(a, b, m), x), NegativeIntegerQ(n), Not(IntegerQ(m)), PolynomialQ(u, x), PolynomialQ(v, x),\ 6929 RationalQ(m), Less(m, -1), GreaterEqual(Exponent(u, x), (-n - IntegerPart(m))*Exponent(v, x))) 6930 cons27 = CustomConstraint(cons_f27) 6931 def cons_f28(v, n, x, u, m): 6932 if not isinstance(x, Symbol): 6933 return False 6934 return And(FreeQ(List(a, b, m), x), NegativeIntegerQ(n), Not(IntegerQ(m)), PolynomialQ(u, x),\ 6935 PolynomialQ(v, x), GreaterEqual(Exponent(u, x), -n*Exponent(v, x))) 6936 cons28 = CustomConstraint(cons_f28) 6937 def cons_f29(n): 6938 return PositiveIntegerQ(n/S(4)) 6939 6940 cons29 = CustomConstraint(cons_f29) 6941 def cons_f30(n): 6942 return IntegerQ(n) 6943 6944 cons30 = CustomConstraint(cons_f30) 6945 def cons_f31(n): 6946 return Greater(n, S(1)) 6947 6948 cons31 = CustomConstraint(cons_f31) 6949 def cons_f32(n, m): 6950 return Less(S(0), m, n) 6951 6952 cons32 = CustomConstraint(cons_f32) 6953 def cons_f33(n, m): 6954 return OddQ(n/GCD(m, n)) 6955 6956 cons33 = CustomConstraint(cons_f33) 6957 def cons_f34(a, b): 6958 return PosQ(a/b) 6959 6960 cons34 = CustomConstraint(cons_f34) 6961 def cons_f35(n, m, p): 6962 return IntegersQ(m, n, p) 6963 6964 cons35 = CustomConstraint(cons_f35) 6965 def cons_f36(n, m, p): 6966 return Less(S(0), m, p, n) 6967 6968 cons36 = CustomConstraint(cons_f36) 6969 def cons_f37(q, n, m, p): 6970 return IntegersQ(m, n, p, q) 6971 6972 cons37 = CustomConstraint(cons_f37) 6973 def cons_f38(n, q, m, p): 6974 return Less(S(0), m, p, q, n) 6975 6976 cons38 = CustomConstraint(cons_f38) 6977 def cons_f39(n): 6978 return IntegerQ(n/S(2)) 6979 6980 cons39 = CustomConstraint(cons_f39) 6981 def cons_f40(p): 6982 return NegativeIntegerQ(p) 6983 6984 cons40 = CustomConstraint(cons_f40) 6985 def cons_f41(n, m): 6986 return IntegersQ(m, n/S(2)) 6987 6988 cons41 = CustomConstraint(cons_f41) 6989 def cons_f42(n, m): 6990 return Unequal(m, n/S(2)) 6991 6992 cons42 = CustomConstraint(cons_f42) 6993 def cons_f43(c, b, a): 6994 return NonzeroQ(-S(4)*a*c + b**S(2)) 6995 6996 cons43 = CustomConstraint(cons_f43) 6997 def cons_f44(j, n, m): 6998 return IntegersQ(m, n, j) 6999 7000 cons44 = CustomConstraint(cons_f44) 7001 def cons_f45(n, m): 7002 return Less(S(0), m, S(2)*n) 7003 7004 cons45 = CustomConstraint(cons_f45) 7005 def cons_f46(n, m, p): 7006 return Not(And(Equal(m, n), Equal(p, S(-1)))) 7007 7008 cons46 = CustomConstraint(cons_f46) 7009 def cons_f47(v, x): 7010 if not isinstance(x, Symbol): 7011 return False 7012 return PolynomialQ(v, x) 7013 7014 cons47 = CustomConstraint(cons_f47) 7015 def cons_f48(v, x): 7016 if not isinstance(x, Symbol): 7017 return False 7018 return BinomialQ(v, x) 7019 7020 cons48 = CustomConstraint(cons_f48) 7021 def cons_f49(v, x, u): 7022 if not isinstance(x, Symbol): 7023 return False 7024 return Inequality(Exponent(u, x), Equal, Exponent(v, x) + S(-1), GreaterEqual, S(2)) 7025 7026 cons49 = CustomConstraint(cons_f49) 7027 def cons_f50(v, x, u): 7028 if not isinstance(x, Symbol): 7029 return False 7030 return GreaterEqual(Exponent(u, x), Exponent(v, x)) 7031 7032 cons50 = CustomConstraint(cons_f50) 7033 def cons_f51(p): 7034 return Not(IntegerQ(p)) 7035 7036 cons51 = CustomConstraint(cons_f51) 7037 7038 def With2(e, b, c, f, n, a, g, h, x, d, m): 7039 tmp = a*h - b*g 7040 k = Symbol('k') 7041 return f**(e*(c + d*x)**n)*SimplifyTerm(h**(-m)*tmp**m, x)/(g + h*x) + Sum_doit(f**(e*(c + d*x)**n)*(a + b*x)**(-k + m)*SimplifyTerm(b*h**(-k)*tmp**(k - 1), x), List(k, 1, m)) 7042 pattern2 = Pattern(UtilityOperator(f_**((x_*WC('d', S(1)) + WC('c', S(0)))**WC('n', S(1))*WC('e', S(1)))*(x_*WC('b', S(1)) + WC('a', S(0)))**WC('m', S(1))/(x_*WC('h', S(1)) + WC('g', S(0))), x_), cons3, cons4, cons5, cons6, cons7, cons8, cons9, cons10, cons1, cons2) 7043 rule2 = ReplacementRule(pattern2, With2) 7044 pattern3 = Pattern(UtilityOperator(F_**((x_*WC('d', S(1)) + WC('c', S(0)))**WC('n', S(1))*WC('b', S(1)))*x_**WC('m', S(1))*(e_ + x_*WC('f', S(1)))**WC('p', S(1)), x_), cons12, cons4, cons5, cons6, cons7, cons8, cons13, cons14, cons15, cons11) 7045 def replacement3(e, b, c, f, n, p, F, x, d, m): 7046 return If(And(PositiveIntegerQ(m, p), LessEqual(m, p), Or(EqQ(n, S(1)), ZeroQ(-c*f + d*e))), ExpandLinearProduct(F**(b*(c + d*x)**n)*(e + f*x)**p, x**m, e, f, x), If(PositiveIntegerQ(p), Distribute(F**(b*(c + d*x)**n)*x**m*(e + f*x)**p, Plus, Times), ExpandIntegrand(F**(b*(c + d*x)**n), x**m*(e + f*x)**p, x))) 7047 rule3 = ReplacementRule(pattern3, replacement3) 7048 pattern4 = Pattern(UtilityOperator(F_**((x_*WC('d', S(1)) + WC('c', S(0)))**WC('n', S(1))*WC('b', S(1)) + WC('a', S(0)))*x_**WC('m', S(1))*(e_ + x_*WC('f', S(1)))**WC('p', S(1)), x_), cons12, cons3, cons4, cons5, cons6, cons7, cons8, cons13, cons14, cons15, cons16) 7049 def replacement4(e, b, c, f, n, a, p, F, x, d, m): 7050 return If(And(PositiveIntegerQ(m, p), LessEqual(m, p), Or(EqQ(n, S(1)), ZeroQ(-c*f + d*e))), ExpandLinearProduct(F**(a + b*(c + d*x)**n)*(e + f*x)**p, x**m, e, f, x), If(PositiveIntegerQ(p), Distribute(F**(a + b*(c + d*x)**n)*x**m*(e + f*x)**p, Plus, Times), ExpandIntegrand(F**(a + b*(c + d*x)**n), x**m*(e + f*x)**p, x))) 7051 rule4 = ReplacementRule(pattern4, replacement4) 7052 def With5(b, v, c, n, a, F, u, x, d, m): 7053 if not isinstance(x, Symbol) or not (FreeQ([F, a, b, c, d], x) and IntegersQ(m, n) and n < 0): 7054 return False 7055 w = ExpandIntegrand((a + b*x)**m*(c + d*x)**n, x) 7056 w = ReplaceAll(w, Rule(x, F**v)) 7057 if SumQ(w): 7058 return True 7059 return False 7060 pattern5 = Pattern(UtilityOperator((F_**v_*WC('b', S(1)) + a_)**WC('m', S(1))*(F_**v_*WC('d', S(1)) + c_)**n_*WC('u', S(1)), x_), cons12, cons3, cons4, cons5, cons6, cons17, cons18, CustomConstraint(With5)) 7061 def replacement5(b, v, c, n, a, F, u, x, d, m): 7062 w = ReplaceAll(ExpandIntegrand((a + b*x)**m*(c + d*x)**n, x), Rule(x, F**v)) 7063 return w.func(*[u*i for i in w.args]) 7064 rule5 = ReplacementRule(pattern5, replacement5) 7065 def With6(e, b, c, f, n, a, x, u, d, m): 7066 if not isinstance(x, Symbol) or not (FreeQ([a, b, c, d, e, f, m, n], x) and PolynomialQ(u,x)): 7067 return False 7068 v = ExpandIntegrand(u*(a + b*x)**m, x) 7069 if SumQ(v): 7070 return True 7071 return False 7072 pattern6 = Pattern(UtilityOperator(f_**((x_*WC('d', S(1)) + WC('c', S(0)))**WC('n', S(1))*WC('e', S(1)))*u_*(x_*WC('b', S(1)) + WC('a', S(0)))**WC('m', S(1)), x_), cons3, cons4, cons5, cons6, cons7, cons8, cons13, cons14, cons19, CustomConstraint(With6)) 7073 def replacement6(e, b, c, f, n, a, x, u, d, m): 7074 v = ExpandIntegrand(u*(a + b*x)**m, x) 7075 return Distribute(f**(e*(c + d*x)**n)*v, Plus, Times) 7076 rule6 = ReplacementRule(pattern6, replacement6) 7077 pattern7 = Pattern(UtilityOperator(u_*(x_*WC('b', S(1)) + WC('a', S(0)))**WC('m', S(1))*Log((x_**WC('n', S(1))*WC('e', S(1)) + WC('d', S(0)))**WC('p', S(1))*WC('c', S(1))), x_), cons3, cons4, cons5, cons6, cons7, cons13, cons14, cons15, cons19) 7078 def replacement7(e, b, c, n, a, p, x, u, d, m): 7079 return ExpandIntegrand(Log(c*(d + e*x**n)**p), u*(a + b*x)**m, x) 7080 rule7 = ReplacementRule(pattern7, replacement7) 7081 pattern8 = Pattern(UtilityOperator(f_**((x_*WC('d', S(1)) + WC('c', S(0)))**WC('n', S(1))*WC('e', S(1)))*u_, x_), cons5, cons6, cons7, cons8, cons14, cons19) 7082 def replacement8(e, c, f, n, x, u, d): 7083 return If(EqQ(n, S(1)), ExpandIntegrand(f**(e*(c + d*x)**n), u, x), ExpandLinearProduct(f**(e*(c + d*x)**n), u, c, d, x)) 7084 rule8 = ReplacementRule(pattern8, replacement8) 7085 # pattern9 = Pattern(UtilityOperator(F_**u_*(G_*u_*WC('b', S(1)) + a_)**WC('n', S(1)), x_), cons3, cons4, cons17, cons20) 7086 # def replacement9(b, G, n, a, F, u, x, m): 7087 # return ReplaceAll(ExpandIntegrand(x**(-m)*(a + b*x)**n, x), Rule(x, G(u))) 7088 # rule9 = ReplacementRule(pattern9, replacement9) 7089 pattern10 = Pattern(UtilityOperator(u_*(WC('a', S(0)) + WC('b', S(1))*Log(((x_*WC('f', S(1)) + WC('e', S(0)))**WC('p', S(1))*WC('d', S(1)))**WC('q', S(1))*WC('c', S(1))))**n_, x_), cons3, cons4, cons5, cons6, cons7, cons8, cons14, cons15, cons21, cons19) 7090 def replacement10(e, b, c, f, n, a, p, x, u, d, q): 7091 return ExpandLinearProduct((a + b*Log(c*(d*(e + f*x)**p)**q))**n, u, e, f, x) 7092 rule10 = ReplacementRule(pattern10, replacement10) 7093 # pattern11 = Pattern(UtilityOperator(u_*(F_*(x_*WC('d', S(1)) + WC('c', S(0)))*WC('b', S(1)) + WC('a', S(0)))**n_, x_), cons3, cons4, cons5, cons6, cons14, cons19, cons22) 7094 # def replacement11(b, c, n, a, F, u, x, d): 7095 # return ExpandLinearProduct((a + b*F(c + d*x))**n, u, c, d, x) 7096 # rule11 = ReplacementRule(pattern11, replacement11) 7097 pattern12 = Pattern(UtilityOperator(WC('u', S(1))/(x_**n_*WC('a', S(1)) + sqrt(c_ + x_**j_*WC('d', S(1)))*WC('b', S(1))), x_), cons3, cons4, cons5, cons6, cons14, cons23) 7098 def replacement12(b, c, n, a, x, u, d, j): 7099 return ExpandIntegrand(u*(a*x**n - b*sqrt(c + d*x**(S(2)*n)))/(-b**S(2)*c + x**(S(2)*n)*(a**S(2) - b**S(2)*d)), x) 7100 rule12 = ReplacementRule(pattern12, replacement12) 7101 pattern13 = Pattern(UtilityOperator((a_ + x_*WC('b', S(1)))**m_/(c_ + x_*WC('d', S(1))), x_), cons3, cons4, cons5, cons6, cons1) 7102 def replacement13(b, c, a, x, d, m): 7103 if RationalQ(a, b, c, d): 7104 return ExpandExpression((a + b*x)**m/(c + d*x), x) 7105 else: 7106 tmp = a*d - b*c 7107 k = Symbol("k") 7108 return Sum_doit((a + b*x)**(-k + m)*SimplifyTerm(b*d**(-k)*tmp**(k + S(-1)), x), List(k, S(1), m)) + SimplifyTerm(d**(-m)*tmp**m, x)/(c + d*x) 7109 7110 rule13 = ReplacementRule(pattern13, replacement13) 7111 pattern14 = Pattern(UtilityOperator((A_ + x_*WC('B', S(1)))*(a_ + x_*WC('b', S(1)))**WC('m', S(1))/(c_ + x_*WC('d', S(1))), x_), cons3, cons4, cons5, cons6, cons24, cons25, cons1) 7112 def replacement14(b, B, A, c, a, x, d, m): 7113 if RationalQ(a, b, c, d, A, B): 7114 return ExpandExpression((A + B*x)*(a + b*x)**m/(c + d*x), x) 7115 else: 7116 tmp1 = (A*d - B*c)/d 7117 tmp2 = ExpandIntegrand((a + b*x)**m/(c + d*x), x) 7118 tmp2 = If(SumQ(tmp2), tmp2.func(*[SimplifyTerm(tmp1*i, x) for i in tmp2.args]), SimplifyTerm(tmp1*tmp2, x)) 7119 return SimplifyTerm(B/d, x)*(a + b*x)**m + tmp2 7120 rule14 = ReplacementRule(pattern14, replacement14) 7121 7122 def With15(b, a, x, u, m): 7123 tmp1 = ExpandLinearProduct((a + b*x)**m, u, a, b, x) 7124 if not IntegerQ(m): 7125 return tmp1 7126 else: 7127 tmp2 = ExpandExpression(u*(a + b*x)**m, x) 7128 if SumQ(tmp2) and LessEqual(LeafCount(tmp2), LeafCount(tmp1) + S(2)): 7129 return tmp2 7130 else: 7131 return tmp1 7132 pattern15 = Pattern(UtilityOperator(u_*(a_ + x_*WC('b', S(1)))**m_, x_), cons3, cons4, cons13, cons19, cons26) 7133 rule15 = ReplacementRule(pattern15, With15) 7134 pattern16 = Pattern(UtilityOperator(u_*v_**n_*(a_ + x_*WC('b', S(1)))**m_, x_), cons27) 7135 def replacement16(b, v, n, a, x, u, m): 7136 s = PolynomialQuotientRemainder(u, v**(-n)*(a+b*x)**(-IntegerPart(m)), x) 7137 return ExpandIntegrand((a + b*x)**FractionalPart(m)*s[0], x) + ExpandIntegrand(v**n*(a + b*x)**m*s[1], x) 7138 rule16 = ReplacementRule(pattern16, replacement16) 7139 7140 pattern17 = Pattern(UtilityOperator(u_*v_**n_*(a_ + x_*WC('b', S(1)))**m_, x_), cons28) 7141 def replacement17(b, v, n, a, x, u, m): 7142 s = PolynomialQuotientRemainder(u, v**(-n),x) 7143 return ExpandIntegrand((a + b*x)**(m)*s[0], x) + ExpandIntegrand(v**n*(a + b*x)**m*s[1], x) 7144 rule17 = ReplacementRule(pattern17, replacement17) 7145 7146 def With18(b, n, a, x, u): 7147 r = Numerator(Rt(-a/b, S(2))) 7148 s = Denominator(Rt(-a/b, S(2))) 7149 return r/(S(2)*a*(r + s*u**(n/S(2)))) + r/(S(2)*a*(r - s*u**(n/S(2)))) 7150 pattern18 = Pattern(UtilityOperator(S(1)/(a_ + u_**n_*WC('b', S(1))), x_), cons3, cons4, cons29) 7151 rule18 = ReplacementRule(pattern18, With18) 7152 def With19(b, n, a, x, u): 7153 k = Symbol("k") 7154 r = Numerator(Rt(-a/b, n)) 7155 s = Denominator(Rt(-a/b, n)) 7156 return Sum_doit(r/(a*n*(-(-1)**(2*k/n)*s*u + r)), List(k, 1, n)) 7157 pattern19 = Pattern(UtilityOperator(S(1)/(a_ + u_**n_*WC('b', S(1))), x_), cons3, cons4, cons30, cons31) 7158 rule19 = ReplacementRule(pattern19, With19) 7159 def With20(b, n, a, x, u, m): 7160 k = Symbol("k") 7161 g = GCD(m, n) 7162 r = Numerator(Rt(a/b, n/GCD(m, n))) 7163 s = Denominator(Rt(a/b, n/GCD(m, n))) 7164 return If(CoprimeQ(g + m, n), Sum_doit((-1)**(-2*k*m/n)*r*(-r/s)**(m/g)/(a*n*((-1)**(2*g*k/n)*s*u**g + r)), List(k, 1, n/g)), Sum_doit((-1)**(2*k*(g + m)/n)*r*(-r/s)**(m/g)/(a*n*((-1)**(2*g*k/n)*r + s*u**g)), List(k, 1, n/g))) 7165 pattern20 = Pattern(UtilityOperator(u_**WC('m', S(1))/(a_ + u_**n_*WC('b', S(1))), x_), cons3, cons4, cons17, cons32, cons33, cons34) 7166 rule20 = ReplacementRule(pattern20, With20) 7167 def With21(b, n, a, x, u, m): 7168 k = Symbol("k") 7169 g = GCD(m, n) 7170 r = Numerator(Rt(-a/b, n/GCD(m, n))) 7171 s = Denominator(Rt(-a/b, n/GCD(m, n))) 7172 return If(Equal(n/g, S(2)), s/(S(2)*b*(r + s*u**g)) - s/(S(2)*b*(r - s*u**g)), If(CoprimeQ(g + m, n), Sum_doit((S(-1))**(-S(2)*k*m/n)*r*(r/s)**(m/g)/(a*n*(-(S(-1))**(S(2)*g*k/n)*s*u**g + r)), List(k, S(1), n/g)), Sum_doit((S(-1))**(S(2)*k*(g + m)/n)*r*(r/s)**(m/g)/(a*n*((S(-1))**(S(2)*g*k/n)*r - s*u**g)), List(k, S(1), n/g)))) 7173 pattern21 = Pattern(UtilityOperator(u_**WC('m', S(1))/(a_ + u_**n_*WC('b', S(1))), x_), cons3, cons4, cons17, cons32) 7174 rule21 = ReplacementRule(pattern21, With21) 7175 def With22(b, c, n, a, x, u, d, m): 7176 k = Symbol("k") 7177 r = Numerator(Rt(-a/b, n)) 7178 s = Denominator(Rt(-a/b, n)) 7179 return Sum_doit((c*r + (-1)**(-2*k*m/n)*d*r*(r/s)**m)/(a*n*(-(-1)**(2*k/n)*s*u + r)), List(k, 1, n)) 7180 pattern22 = Pattern(UtilityOperator((c_ + u_**WC('m', S(1))*WC('d', S(1)))/(a_ + u_**n_*WC('b', S(1))), x_), cons3, cons4, cons5, cons6, cons17, cons32) 7181 rule22 = ReplacementRule(pattern22, With22) 7182 def With23(e, b, c, n, a, p, x, u, d, m): 7183 k = Symbol("k") 7184 r = Numerator(Rt(-a/b, n)) 7185 s = Denominator(Rt(-a/b, n)) 7186 return Sum_doit((c*r + (-1)**(-2*k*p/n)*e*r*(r/s)**p + (-1)**(-2*k*m/n)*d*r*(r/s)**m)/(a*n*(-(-1)**(2*k/n)*s*u + r)), List(k, 1, n)) 7187 pattern23 = Pattern(UtilityOperator((u_**p_*WC('e', S(1)) + u_**WC('m', S(1))*WC('d', S(1)) + WC('c', S(0)))/(a_ + u_**n_*WC('b', S(1))), x_), cons3, cons4, cons5, cons6, cons7, cons35, cons36) 7188 rule23 = ReplacementRule(pattern23, With23) 7189 def With24(e, b, c, f, n, a, p, x, u, d, q, m): 7190 k = Symbol("k") 7191 r = Numerator(Rt(-a/b, n)) 7192 s = Denominator(Rt(-a/b, n)) 7193 return Sum_doit((c*r + (-1)**(-2*k*q/n)*f*r*(r/s)**q + (-1)**(-2*k*p/n)*e*r*(r/s)**p + (-1)**(-2*k*m/n)*d*r*(r/s)**m)/(a*n*(-(-1)**(2*k/n)*s*u + r)), List(k, 1, n)) 7194 pattern24 = Pattern(UtilityOperator((u_**p_*WC('e', S(1)) + u_**q_*WC('f', S(1)) + u_**WC('m', S(1))*WC('d', S(1)) + WC('c', S(0)))/(a_ + u_**n_*WC('b', S(1))), x_), cons3, cons4, cons5, cons6, cons7, cons8, cons37, cons38) 7195 rule24 = ReplacementRule(pattern24, With24) 7196 def With25(c, n, a, p, x, u): 7197 q = Symbol('q') 7198 return ReplaceAll(ExpandIntegrand(c**(-p), (c*x - q)**p*(c*x + q)**p, x), List(Rule(q, Rt(-a*c, S(2))), Rule(x, u**(n/S(2))))) 7199 pattern25 = Pattern(UtilityOperator((a_ + u_**WC('n', S(1))*WC('c', S(1)))**p_, x_), cons3, cons5, cons39, cons40) 7200 rule25 = ReplacementRule(pattern25, With25) 7201 def With26(c, n, a, p, x, u, m): 7202 q = Symbol('q') 7203 return ReplaceAll(ExpandIntegrand(c**(-p), x**m*(c*x**(n/S(2)) - q)**p*(c*x**(n/S(2)) + q)**p, x), List(Rule(q, Rt(-a*c, S(2))), Rule(x, u))) 7204 pattern26 = Pattern(UtilityOperator(u_**WC('m', S(1))*(u_**WC('n', S(1))*WC('c', S(1)) + WC('a', S(0)))**p_, x_), cons3, cons5, cons41, cons40, cons32, cons42) 7205 rule26 = ReplacementRule(pattern26, With26) 7206 def With27(b, c, n, a, p, x, u, j): 7207 q = Symbol('q') 7208 return ReplaceAll(ExpandIntegrand(S(4)**(-p)*c**(-p), (b + S(2)*c*x - q)**p*(b + S(2)*c*x + q)**p, x), List(Rule(q, Rt(-S(4)*a*c + b**S(2), S(2))), Rule(x, u**n))) 7209 pattern27 = Pattern(UtilityOperator((u_**WC('j', S(1))*WC('c', S(1)) + u_**WC('n', S(1))*WC('b', S(1)) + WC('a', S(0)))**p_, x_), cons3, cons4, cons5, cons30, cons23, cons40, cons43) 7210 rule27 = ReplacementRule(pattern27, With27) 7211 def With28(b, c, n, a, p, x, u, j, m): 7212 q = Symbol('q') 7213 return ReplaceAll(ExpandIntegrand(S(4)**(-p)*c**(-p), x**m*(b + S(2)*c*x**n - q)**p*(b + S(2)*c*x**n + q)**p, x), List(Rule(q, Rt(-S(4)*a*c + b**S(2), S(2))), Rule(x, u))) 7214 pattern28 = Pattern(UtilityOperator(u_**WC('m', S(1))*(u_**WC('j', S(1))*WC('c', S(1)) + u_**WC('n', S(1))*WC('b', S(1)) + WC('a', S(0)))**p_, x_), cons3, cons4, cons5, cons44, cons23, cons40, cons45, cons46, cons43) 7215 rule28 = ReplacementRule(pattern28, With28) 7216 def With29(b, c, n, a, x, u, d, j): 7217 q = Rt(-a/b, S(2)) 7218 return -(c - d*q)/(S(2)*b*q*(q + u**n)) - (c + d*q)/(S(2)*b*q*(q - u**n)) 7219 pattern29 = Pattern(UtilityOperator((u_**WC('n', S(1))*WC('d', S(1)) + WC('c', S(0)))/(a_ + u_**WC('j', S(1))*WC('b', S(1))), x_), cons3, cons4, cons5, cons6, cons14, cons23) 7220 rule29 = ReplacementRule(pattern29, With29) 7221 def With30(e, b, c, f, n, a, g, x, u, d, j): 7222 q = Rt(-S(4)*a*c + b**S(2), S(2)) 7223 r = TogetherSimplify((-b*e*g + S(2)*c*(d + e*f))/q) 7224 return (e*g - r)/(b + 2*c*u**n + q) + (e*g + r)/(b + 2*c*u**n - q) 7225 pattern30 = Pattern(UtilityOperator(((u_**WC('n', S(1))*WC('g', S(1)) + WC('f', S(0)))*WC('e', S(1)) + WC('d', S(0)))/(u_**WC('j', S(1))*WC('c', S(1)) + u_**WC('n', S(1))*WC('b', S(1)) + WC('a', S(0))), x_), cons3, cons4, cons5, cons6, cons7, cons8, cons9, cons14, cons23, cons43) 7226 rule30 = ReplacementRule(pattern30, With30) 7227 def With31(v, x, u): 7228 lst = CoefficientList(u, x) 7229 i = Symbol('i') 7230 return x**Exponent(u, x)*lst[-1]/v + Sum_doit(x**(i - 1)*Part(lst, i), List(i, 1, Exponent(u, x)))/v 7231 pattern31 = Pattern(UtilityOperator(u_/v_, x_), cons19, cons47, cons48, cons49) 7232 rule31 = ReplacementRule(pattern31, With31) 7233 pattern32 = Pattern(UtilityOperator(u_/v_, x_), cons19, cons47, cons50) 7234 def replacement32(v, x, u): 7235 return PolynomialDivide(u, v, x) 7236 rule32 = ReplacementRule(pattern32, replacement32) 7237 pattern33 = Pattern(UtilityOperator(u_*(x_*WC('a', S(1)))**p_, x_), cons51, cons19) 7238 def replacement33(x, a, u, p): 7239 return ExpandToSum((a*x)**p, u, x) 7240 rule33 = ReplacementRule(pattern33, replacement33) 7241 pattern34 = Pattern(UtilityOperator(v_**p_*WC('u', S(1)), x_), cons51) 7242 def replacement34(v, x, u, p): 7243 return ExpandIntegrand(NormalizeIntegrand(v**p, x), u, x) 7244 rule34 = ReplacementRule(pattern34, replacement34) 7245 pattern35 = Pattern(UtilityOperator(u_, x_)) 7246 def replacement35(x, u): 7247 return ExpandExpression(u, x) 7248 rule35 = ReplacementRule(pattern35, replacement35) 7249 return [ rule2,rule3, rule4, rule5, rule6, rule7, rule8, rule10, rule12, rule13, rule14, rule15, rule16, rule17, rule18, rule19, rule20, rule21, rule22, rule23, rule24, rule25, rule26, rule27, rule28, rule29, rule30, rule31, rule32, rule33, rule34, rule35] 7250 7251def _RemoveContentAux(): 7252 def cons_f1(b, a): 7253 return IntegersQ(a, b) 7254 7255 cons1 = CustomConstraint(cons_f1) 7256 7257 def cons_f2(b, a): 7258 return Equal(a + b, S(0)) 7259 7260 cons2 = CustomConstraint(cons_f2) 7261 7262 def cons_f3(m): 7263 return RationalQ(m) 7264 7265 cons3 = CustomConstraint(cons_f3) 7266 7267 def cons_f4(m, n): 7268 return RationalQ(m, n) 7269 7270 cons4 = CustomConstraint(cons_f4) 7271 7272 def cons_f5(m, n): 7273 return GreaterEqual(-m + n, S(0)) 7274 7275 cons5 = CustomConstraint(cons_f5) 7276 7277 def cons_f6(a, x): 7278 return FreeQ(a, x) 7279 7280 cons6 = CustomConstraint(cons_f6) 7281 7282 def cons_f7(m, n, p): 7283 return RationalQ(m, n, p) 7284 7285 cons7 = CustomConstraint(cons_f7) 7286 7287 def cons_f8(m, p): 7288 return GreaterEqual(-m + p, S(0)) 7289 7290 cons8 = CustomConstraint(cons_f8) 7291 7292 pattern1 = Pattern(UtilityOperator(a_**m_*WC('u', S(1)) + b_*WC('v', S(1)), x_), cons1, cons2, cons3) 7293 def replacement1(v, x, a, u, m, b): 7294 return If(Greater(m, S(1)), RemoveContentAux(a**(m + S(-1))*u - v, x), RemoveContentAux(-a**(-m + S(1))*v + u, x)) 7295 rule1 = ReplacementRule(pattern1, replacement1) 7296 pattern2 = Pattern(UtilityOperator(a_**WC('m', S(1))*WC('u', S(1)) + a_**WC('n', S(1))*WC('v', S(1)), x_), cons6, cons4, cons5) 7297 def replacement2(n, v, x, u, m, a): 7298 return RemoveContentAux(a**(-m + n)*v + u, x) 7299 rule2 = ReplacementRule(pattern2, replacement2) 7300 pattern3 = Pattern(UtilityOperator(a_**WC('m', S(1))*WC('u', S(1)) + a_**WC('n', S(1))*WC('v', S(1)) + a_**WC('p', S(1))*WC('w', S(1)), x_), cons6, cons7, cons5, cons8) 7301 def replacement3(n, v, x, p, u, w, m, a): 7302 return RemoveContentAux(a**(-m + n)*v + a**(-m + p)*w + u, x) 7303 rule3 = ReplacementRule(pattern3, replacement3) 7304 pattern4 = Pattern(UtilityOperator(u_, x_)) 7305 def replacement4(u, x): 7306 return If(And(SumQ(u), NegQ(First(u))), -u, u) 7307 rule4 = ReplacementRule(pattern4, replacement4) 7308 return [rule1, rule2, rule3, rule4, ] 7309 7310IntHide = Int 7311Log = rubi_log 7312Null = None 7313if matchpy: 7314 RemoveContentAux_replacer = ManyToOneReplacer(* _RemoveContentAux()) 7315 ExpandIntegrand_rules = _ExpandIntegrand() 7316 TrigSimplifyAux_replacer = _TrigSimplifyAux() 7317 SimplifyAntiderivative_replacer = _SimplifyAntiderivative() 7318 SimplifyAntiderivativeSum_replacer = _SimplifyAntiderivativeSum() 7319 FixSimplify_rules = _FixSimplify() 7320 SimpFixFactor_replacer = _SimpFixFactor() 7321