class_docstr: A container for all the information relating to a differential extension.
  
  Explanation
  ===========
  
  The attributes of this object are (see also the docstring of __init__):
  
  - f: The original (Expr) integrand.
  - x: The variable of integration.
  - T: List of variables in the extension.
  - D: List of derivations in the extension; corresponds to the elements of T.
  - fa: Poly of the numerator of the integrand.
  - fd: Poly of the denominator of the integrand.
  - Tfuncs: Lambda() representations of each element of T (except for x).
    For back-substitution after integration.
  - backsubs: A (possibly empty) list of further substitutions to be made on
    the final integral to make it look more like the integrand.
  - exts:
  - extargs:
  - cases: List of string representations of the cases of T.
  - t: The top level extension variable, as defined by the current level
    (see level below).
  - d: The top level extension derivation, as defined by the current
    derivation (see level below).
  - case: The string representation of the case of self.d.
  (Note that self.T and self.D will always contain the complete extension,
  regardless of the level.  Therefore, you should ALWAYS use DE.t and DE.d
  instead of DE.T[-1] and DE.D[-1].  If you want to have a list of the
  derivations or variables only up to the current level, use
  DE.D[:len(DE.D) + DE.level + 1] and DE.T[:len(DE.T) + DE.level + 1].  Note
  that, in particular, the derivation() function does this.)
  
  The following are also attributes, but will probably not be useful other
  than in internal use:
  - newf: Expr form of fa/fd.
  - level: The number (between -1 and -len(self.T)) such that
    self.T[self.level] == self.t and self.D[self.level] == self.d.
    Use the methods self.increment_level() and self.decrement_level() to change
    the current level.
class_docstr_tok: ["A","container","for","all","the","information","relating","to","a","differential","extension",".","Explanation","===========","The","attributes","of","this","object","are","(","see","also","the","docstring","of","__init__",")",":","-","f",":","The","original","(","Expr",")","integrand",".","-","x",":","The","variable","of","integration",".","-","T",":","List","of","variables","in","the","extension",".","-","D",":","List","of","derivations","in","the","extension",";","corresponds","to","the","elements","of","T.","-","fa",":","Poly","of","the","numerator","of","the","integrand",".","-","fd",":","Poly","of","the","denominator","of","the","integrand",".","-","Tfuncs",":","Lambda","(",")","representations","of","each","element","of","T","(","except","for","x",")",".","For","back-substitution","after","integration",".","-","backsubs",":","A","(","possibly","empty",")","list","of","further","substitutions","to","be","made","on","the","final","integral","to","make","it","look","more","like","the","integrand",".","-","exts",":","-","extargs",":","-","cases",":","List","of","string","representations","of","the","cases","of","T.","-","t",":","The","top","level","extension","variable",",","as","defined","by","the","current","level","(","see","level","below",")",".","-","d",":","The","top","level","extension","derivation",",","as","defined","by","the","current","derivation","(","see","level","below",")",".","-","case",":","The","string","representation","of","the","case","of","self.d",".","(","Note","that","self.T","and","self.D","will","always","contain","the","complete","extension",",","regardless","of","the","level",".","Therefore",",","you","should","ALWAYS","use","DE.t","and","DE.d","instead","of","DE.T","[","-1","]","and","DE.D","[","-1","]",".","If","you","want","to","have","a","list","of","the","derivations","or","variables","only","up","to","the","current","level",",","use","DE.D","[",":","len","(","DE.D",")","+","DE.level","+","1","]","and","DE.T","[",":","len","(","DE.T",")","+","DE.level","+","1","]",".","Note","that",",","in","particular",",","the","derivation","(",")","function","does","this",".",")","The","following","are","also","attributes",",","but","will","probably","not","be","useful","other","than","in","internal","use",":","-","newf",":","Expr","form","of","fa\/fd",".","-","level",":","The","number","(","between","-1","and","-len","(","self.T",")",")","such","that","self.T","[","self.level","]","==","self.t","and","self.D","[","self.level","]","==","self.d",".","Use","the","methods","self.increment_level","(",")","and","self.decrement_level","(",")","to","change","the","current","level","."]
docstr: Tries to build a transcendental extension tower from ``f`` with respect to ``x``.
  
  Explanation
  ===========
  
  If it is successful, creates a DifferentialExtension object with, among
  others, the attributes fa, fd, D, T, Tfuncs, and backsubs such that
  fa and fd are Polys in T[-1] with rational coefficients in T[:-1],
  fa/fd == f, and D[i] is a Poly in T[i] with rational coefficients in
  T[:i] representing the derivative of T[i] for each i from 1 to len(T).
  Tfuncs is a list of Lambda objects for back replacing the functions
  after integrating.  Lambda() is only used (instead of lambda) to make
  them easier to test and debug. Note that Tfuncs corresponds to the
  elements of T, except for T[0] == x, but they should be back-substituted
  in reverse order.  backsubs is a (possibly empty) back-substitution list
  that should be applied on the completed integral to make it look more
  like the original integrand.
  
  If it is unsuccessful, it raises NotImplementedError.
  
  You can also create an object by manually setting the attributes as a
  dictionary to the extension keyword argument.  You must include at least
  D.  Warning, any attribute that is not given will be set to None. The
  attributes T, t, d, cases, case, x, and level are set automatically and
  do not need to be given.  The functions in the Risch Algorithm will NOT
  check to see if an attribute is None before using it.  This also does not
  check to see if the extension is valid (non-algebraic) or even if it is
  self-consistent.  Therefore, this should only be used for
  testing/debugging purposes.
docstr_tok: ["Tries","to","build","a","transcendental","extension","tower","from","``","f","``","with","respect","to","``","x","``",".","Explanation","===========","If","it","is","successful",",","creates","a","DifferentialExtension","object","with",",","among","others",",","the","attributes","fa",",","fd",",","D",",","T",",","Tfuncs",",","and","backsubs","such","that","fa","and","fd","are","Polys","in","T","[","-1","]","with","rational","coefficients","in","T","[",":","-1","]",",","fa\/fd","==","f",",","and","D","[","i","]","is","a","Poly","in","T","[","i","]","with","rational","coefficients","in","T","[",":","i","]","representing","the","derivative","of","T","[","i","]","for","each","i","from","1","to","len","(","T",")",".","Tfuncs","is","a","list","of","Lambda","objects","for","back","replacing","the","functions","after","integrating",".","Lambda","(",")","is","only","used","(","instead","of","lambda",")","to","make","them","easier","to","test","and","debug",".","Note","that","Tfuncs","corresponds","to","the","elements","of","T",",","except","for","T","[","0","]","==","x",",","but","they","should","be","back-substituted","in","reverse","order",".","backsubs","is","a","(","possibly","empty",")","back-substitution","list","that","should","be","applied","on","the","completed","integral","to","make","it","look","more","like","the","original","integrand",".","If","it","is","unsuccessful",",","it","raises","NotImplementedError",".","You","can","also","create","an","object","by","manually","setting","the","attributes","as","a","dictionary","to","the","extension","keyword","argument",".","You","must","include","at","least","D.","Warning",",","any","attribute","that","is","not","given","will","be","set","to","None",".","The","attributes","T",",","t",",","d",",","cases",",","case",",","x",",","and","level","are","set","automatically","and","do","not","need","to","be","given",".","The","functions","in","the","Risch","Algorithm","will","NOT","check","to","see","if","an","attribute","is","None","before","using","it",".","This","also","does","not","check","to","see","if","the","extension","is","valid","(","non-algebraic",")","or","even","if","it","is","self-consistent",".","Therefore",",","this","should","only","be","used","for","testing\/debugging","purposes","."]
code: def __init__(
      self,
      f=None,
      x=None,
      handle_first="log",
      dummy=False,
      extension=None,
      rewrite_complex=None,
  ):
      """
      Tries to build a transcendental extension tower from ``f`` with respect to ``x``.
  
      Explanation
      ===========
  
      If it is successful, creates a DifferentialExtension object with, among
      others, the attributes fa, fd, D, T, Tfuncs, and backsubs such that
      fa and fd are Polys in T[-1] with rational coefficients in T[:-1],
      fa/fd == f, and D[i] is a Poly in T[i] with rational coefficients in
      T[:i] representing the derivative of T[i] for each i from 1 to len(T).
      Tfuncs is a list of Lambda objects for back replacing the functions
      after integrating.  Lambda() is only used (instead of lambda) to make
      them easier to test and debug. Note that Tfuncs corresponds to the
      elements of T, except for T[0] == x, but they should be back-substituted
      in reverse order.  backsubs is a (possibly empty) back-substitution list
      that should be applied on the completed integral to make it look more
      like the original integrand.
  
      If it is unsuccessful, it raises NotImplementedError.
  
      You can also create an object by manually setting the attributes as a
      dictionary to the extension keyword argument.  You must include at least
      D.  Warning, any attribute that is not given will be set to None. The
      attributes T, t, d, cases, case, x, and level are set automatically and
      do not need to be given.  The functions in the Risch Algorithm will NOT
      check to see if an attribute is None before using it.  This also does not
      check to see if the extension is valid (non-algebraic) or even if it is
      self-consistent.  Therefore, this should only be used for
      testing/debugging purposes.
      """
      # XXX: If you need to debug this function, set the break point here
  
      if extension:
          if "D" not in extension:
              raise ValueError(
                  "At least the key D must be included with "
                  "the extension flag to DifferentialExtension."
              )
          for attr in extension:
              setattr(self, attr, extension[attr])
  
          self._auto_attrs()
  
          return
      elif f is None or x is None:
          raise ValueError(
              "Either both f and x or a manual extension must "
              "be given."
          )
  
      if handle_first not in ("log", "exp"):
          raise ValueError(
              "handle_first must be 'log' or 'exp', not %s."
              % str(handle_first)
          )
  
      # f will be the original function, self.f might change if we reset
      # (e.g., we pull out a constant from an exponential)
      self.f = f
      self.x = x
      # setting the default value 'dummy'
      self.dummy = dummy
      self.reset()
      exp_new_extension, log_new_extension = True, True
  
      # case of 'automatic' choosing
      if rewrite_complex is None:
          rewrite_complex = I in self.f.atoms()
  
      if rewrite_complex:
          rewritables = {
              (sin, cos, cot, tan, sinh, cosh, coth, tanh): exp,
              (asin, acos, acot, atan): log,
          }
          # rewrite the trigonometric components
          for candidates, rule in rewritables.items():
              self.newf = self.newf.rewrite(candidates, rule)
          self.newf = cancel(self.newf)
      else:
          if any(
              i.has(x)
              for i in self.f.atoms(sin, cos, tan, atan, asin, acos)
          ):
              raise NotImplementedError(
                  "Trigonometric extensions are not " "supported (yet!)"
              )
  
      exps = set()
      pows = set()
      numpows = set()
      sympows = set()
      logs = set()
      symlogs = set()
  
      while True:
          if self.newf.is_rational_function(*self.T):
              break
  
          if not exp_new_extension and not log_new_extension:
              # We couldn't find a new extension on the last pass, so I guess
              # we can't do it.
              raise NotImplementedError(
                  "Couldn't find an elementary "
                  "transcendental extension for %s.  Try using a "
                  % str(f)
                  + "manual extension with the extension flag."
              )
  
          (
              exps,
              pows,
              numpows,
              sympows,
              log_new_extension,
          ) = self._rewrite_exps_pows(
              exps, pows, numpows, sympows, log_new_extension
          )
  
          logs, symlogs = self._rewrite_logs(logs, symlogs)
  
          if handle_first == "exp" or not log_new_extension:
              exp_new_extension = self._exp_part(exps)
              if exp_new_extension is None:
                  # reset and restart
                  self.f = self.newf
                  self.reset()
                  exp_new_extension = True
                  continue
  
          if handle_first == "log" or not exp_new_extension:
              log_new_extension = self._log_part(logs)
  
      self.fa, self.fd = frac_in(self.newf, self.t)
      self._auto_attrs()
  
      return
  
imports: from types import GeneratorType
  from functools import reduce
  from sympy.core.function import Lambda
  from sympy.core.mul import Mul
  from sympy.core.intfunc import ilcm
  from sympy.core.numbers import I, oo
  from sympy.core.power import Pow
  from sympy.core.relational import Ne
  from sympy.core.singleton import S
  from sympy.core.sorting import ordered, default_sort_key
  from sympy.core.symbol import Dummy, Symbol
  from sympy.functions.elementary.exponential import log, exp
  from sympy.functions.elementary.hyperbolic import cosh, coth, sinh, tanh
  from sympy.functions.elementary.piecewise import Piecewise
  from sympy.functions.elementary.trigonometric import atan, sin, cos, tan, acot, cot, asin, acos
  from .integrals import integrate, Integral
  from .heurisch import _symbols
  from sympy.polys.polyerrors import DomainError, PolynomialError
  from sympy.polys.polytools import real_roots, cancel, Poly, gcd, reduced
  from sympy.polys.rootoftools import RootSum
  from sympy.utilities.iterables import numbered_symbols
label_desc: Use image node_id 1 to create a new DifferentialExtension object  with example: obj = DifferentialExtension(f, x, handle_first, dummy, extension, rewrite_complex)