class_docstr: Represents unevaluated integral.
docstr: Perform the integration using any hints given.
  
  Examples
  ========
  
  >>> from sympy import Piecewise, S
  >>> from sympy.abc import x, t
  >>> p = x**2 + Piecewise((0, x/t < 0), (1, True))
  >>> p.integrate((t, S(4)/5, 1), (x, -1, 1))
  1/3
  
  See Also
  ========
  
  sympy.integrals.trigonometry.trigintegrate
  sympy.integrals.heurisch.heurisch
  sympy.integrals.rationaltools.ratint
  as_sum : Approximate the integral using a sum
docstr_tok: ["Perform","the","integration","using","any","hints","given",".","Examples","========",">",">",">","from","sympy","import","Piecewise",",","S",">",">",">","from","sympy.abc","import","x",",","t",">",">",">","p","=","x","*","*","2","+","Piecewise","(","(","0",",","x\/t","<","0",")",",","(","1",",","True",")",")",">",">",">","p.integrate","(","(","t",",","S","(","4",")","\/5",",","1",")",",","(","x",",","-1",",","1",")",")","1\/3","See","Also","========","sympy.integrals.trigonometry.trigintegrate","sympy.integrals.heurisch.heurisch","sympy.integrals.rationaltools.ratint","as_sum",":","Approximate","the","integral","using","a","sum"]
code: def doit(self, **hints):
      """
      Perform the integration using any hints given.
  
      Examples
      ========
  
      >>> from sympy import Piecewise, S
      >>> from sympy.abc import x, t
      >>> p = x**2 + Piecewise((0, x/t < 0), (1, True))
      >>> p.integrate((t, S(4)/5, 1), (x, -1, 1))
      1/3
  
      See Also
      ========
  
      sympy.integrals.trigonometry.trigintegrate
      sympy.integrals.heurisch.heurisch
      sympy.integrals.rationaltools.ratint
      as_sum : Approximate the integral using a sum
      """
      if not hints.get("integrals", True):
          return self
  
      deep = hints.get("deep", True)
      meijerg = hints.get("meijerg", None)
      conds = hints.get("conds", "piecewise")
      risch = hints.get("risch", None)
      heurisch = hints.get("heurisch", None)
      manual = hints.get("manual", None)
      if (
          len(list(filter(None, (manual, meijerg, risch, heurisch))))
          > 1
      ):
          raise ValueError(
              "At most one of manual, meijerg, risch, heurisch can be True"
          )
      elif manual:
          meijerg = risch = heurisch = False
      elif meijerg:
          manual = risch = heurisch = False
      elif risch:
          manual = meijerg = heurisch = False
      elif heurisch:
          manual = meijerg = risch = False
      eval_kwargs = {
          "meijerg": meijerg,
          "risch": risch,
          "manual": manual,
          "heurisch": heurisch,
          "conds": conds,
      }
  
      if conds not in ("separate", "piecewise", "none"):
          raise ValueError(
              'conds must be one of "separate", "piecewise", '
              '"none", got: %s' % conds
          )
  
      if risch and any(len(xab) > 1 for xab in self.limits):
          raise ValueError(
              "risch=True is only allowed for indefinite integrals."
          )
  
      # check for the trivial zero
      if self.is_zero:
          return S.Zero
  
      # hacks to handle integrals of
      # nested summations
      from sympy.concrete.summations import Sum
  
      if isinstance(self.function, Sum):
          if any(v in self.function.limits[0] for v in self.variables):
              raise ValueError(
                  "Limit of the sum cannot be an integration variable."
              )
          if any(l.is_infinite for l in self.function.limits[0][1:]):
              return self
          _i = self
          _sum = self.function
          return _sum.func(
              _i.func(_sum.function, *_i.limits).doit(), *_sum.limits
          ).doit()
  
      # now compute and check the function
      function = self.function
  
      # hack to use a consistent Heaviside(x, 1/2)
      function = function.replace(
          lambda x: isinstance(x, Heaviside) and x.args[1] * 2 != 1,
          lambda x: Heaviside(x.args[0]),
      )
  
      if deep:
          function = function.doit(**hints)
      if function.is_zero:
          return S.Zero
  
      # hacks to handle special cases
      if isinstance(function, MatrixBase):
          return function.applyfunc(
              lambda f: self.func(f, *self.limits).doit(**hints)
          )
  
      if isinstance(function, FormalPowerSeries):
          if len(self.limits) > 1:
              raise NotImplementedError
          xab = self.limits[0]
          if len(xab) > 1:
              return function.integrate(xab, **eval_kwargs)
          else:
              return function.integrate(xab[0], **eval_kwargs)
  
      # There is no trivial answer and special handling
      # is done so continue
  
      # first make sure any definite limits have integration
      # variables with matching assumptions
      reps = {}
      for xab in self.limits:
          if len(xab) != 3:
              # it makes sense to just make
              # all x real but in practice with the
              # current state of integration...this
              # doesn't work out well
              # x = xab[0]
              # if x not in reps and not x.is_real:
              #     reps[x] = Dummy(real=True)
              continue
          x, a, b = xab
          l = (a, b)
          if all(i.is_nonnegative for i in l) and not x.is_nonnegative:
              d = Dummy(positive=True)
          elif (
              all(i.is_nonpositive for i in l) and not x.is_nonpositive
          ):
              d = Dummy(negative=True)
          elif all(i.is_real for i in l) and not x.is_real:
              d = Dummy(real=True)
          else:
              d = None
          if d:
              reps[x] = d
      if reps:
          undo = {v: k for k, v in reps.items()}
          did = self.xreplace(reps).doit(**hints)
          if isinstance(did, tuple):  # when separate=True
              did = tuple([i.xreplace(undo) for i in did])
          else:
              did = did.xreplace(undo)
          return did
  
      # continue with existing assumptions
      undone_limits = []
      # ulj = free symbols of any undone limits' upper and lower limits
      ulj = set()
      for xab in self.limits:
          # compute uli, the free symbols in the
          # Upper and Lower limits of limit I
          if len(xab) == 1:
              uli = set(xab[:1])
          elif len(xab) == 2:
              uli = xab[1].free_symbols
          elif len(xab) == 3:
              uli = xab[1].free_symbols.union(xab[2].free_symbols)
          # this integral can be done as long as there is no blocking
          # limit that has been undone. An undone limit is blocking if
          # it contains an integration variable that is in this limit's
          # upper or lower free symbols or vice versa
          if xab[0] in ulj or any(v[0] in uli for v in undone_limits):
              undone_limits.append(xab)
              ulj.update(uli)
              function = self.func(*([function] + [xab]))
              factored_function = function.factor()
              if not isinstance(factored_function, Integral):
                  function = factored_function
              continue
  
          if function.has(Abs, sign) and (
              (len(xab) < 3 and all(x.is_extended_real for x in xab))
              or (
                  len(xab) == 3
                  and all(
                      x.is_extended_real and not x.is_infinite
                      for x in xab[1:]
                  )
              )
          ):
              # some improper integrals are better off with Abs
              xr = Dummy("xr", real=True)
              function = (
                  function.xreplace({xab[0]: xr})
                  .rewrite(Piecewise)
                  .xreplace({xr: xab[0]})
              )
          elif function.has(Min, Max):
              function = function.rewrite(Piecewise)
          if function.has(Piecewise) and not isinstance(
              function, Piecewise
          ):
              function = piecewise_fold(function)
          if isinstance(function, Piecewise):
              if len(xab) == 1:
                  antideriv = function._eval_integral(
                      xab[0], **eval_kwargs
                  )
              else:
                  antideriv = self._eval_integral(
                      function, xab[0], **eval_kwargs
                  )
          else:
              # There are a number of tradeoffs in using the
              # Meijer G method. It can sometimes be a lot faster
              # than other methods, and sometimes slower. And
              # there are certain types of integrals for which it
              # is more likely to work than others. These
              # heuristics are incorporated in deciding what
              # integration methods to try, in what order. See the
              # integrate() docstring for details.
              def try_meijerg(function, xab):
                  ret = None
                  if len(xab) == 3 and meijerg is not False:
                      x, a, b = xab
                      try:
                          res = meijerint_definite(function, x, a, b)
                      except NotImplementedError:
                          _debug(
                              "NotImplementedError "
                              "from meijerint_definite"
                          )
                          res = None
                      if res is not None:
                          f, cond = res
                          if conds == "piecewise":
                              u = self.func(function, (x, a, b))
                              # if Piecewise modifies cond too
                              # much it may not be recognized by
                              # _condsimp pattern matching so just
                              # turn off all evaluation
                              return Piecewise(
                                  (f, cond), (u, True), evaluate=False
                              )
                          elif conds == "separate":
                              if len(self.limits) != 1:
                                  raise ValueError(
                                      filldedent(
                                          """
                                          conds=separate not supported in
                                          multiple integrals"""
                                      )
                                  )
                              ret = f, cond
                          else:
                              ret = f
                  return ret
  
              meijerg1 = meijerg
              if (
                  meijerg is not False
                  and len(xab) == 3
                  and xab[1].is_extended_real
                  and xab[2].is_extended_real
                  and not function.is_Poly
                  and (xab[1].has(oo, -oo) or xab[2].has(oo, -oo))
              ):
                  ret = try_meijerg(function, xab)
                  if ret is not None:
                      function = ret
                      continue
                  meijerg1 = False
              # If the special meijerg code did not succeed in
              # finding a definite integral, then the code using
              # meijerint_indefinite will not either (it might
              # find an antiderivative, but the answer is likely
              # to be nonsensical). Thus if we are requested to
              # only use Meijer G-function methods, we give up at
              # this stage. Otherwise we just disable G-function
              # methods.
              if meijerg1 is False and meijerg is True:
                  antideriv = None
              else:
                  antideriv = self._eval_integral(
                      function, xab[0], **eval_kwargs
                  )
                  if antideriv is None and meijerg is True:
                      ret = try_meijerg(function, xab)
                      if ret is not None:
                          function = ret
                          continue
  
          final = hints.get("final", True)
          # dotit may be iterated but floor terms making atan and acot
          # continuous should only be added in the final round
          if (
              final
              and not isinstance(antideriv, Integral)
              and antideriv is not None
          ):
              for atan_term in antideriv.atoms(atan):
                  atan_arg = atan_term.args[0]
                  # Checking `atan_arg` to be linear combination of `tan` or `cot`
                  for tan_part in atan_arg.atoms(tan):
                      x1 = Dummy("x1")
                      tan_exp1 = atan_arg.subs(tan_part, x1)
                      # The coefficient of `tan` should be constant
                      coeff = tan_exp1.diff(x1)
                      if x1 not in coeff.free_symbols:
                          a = tan_part.args[0]
                          antideriv = antideriv.subs(
                              atan_term,
                              Add(
                                  atan_term,
                                  sign(coeff)
                                  * pi
                                  * floor((a - pi / 2) / pi),
                              ),
                          )
                  for cot_part in atan_arg.atoms(cot):
                      x1 = Dummy("x1")
                      cot_exp1 = atan_arg.subs(cot_part, x1)
                      # The coefficient of `cot` should be constant
                      coeff = cot_exp1.diff(x1)
                      if x1 not in coeff.free_symbols:
                          a = cot_part.args[0]
                          antideriv = antideriv.subs(
                              atan_term,
                              Add(
                                  atan_term,
                                  sign(coeff) * pi * floor((a) / pi),
                              ),
                          )
  
          if antideriv is None:
              undone_limits.append(xab)
              function = self.func(*([function] + [xab])).factor()
              factored_function = function.factor()
              if not isinstance(factored_function, Integral):
                  function = factored_function
              continue
          else:
              if len(xab) == 1:
                  function = antideriv
              else:
                  if len(xab) == 3:
                      x, a, b = xab
                  elif len(xab) == 2:
                      x, b = xab
                      a = None
                  else:
                      raise NotImplementedError
  
                  if deep:
                      if isinstance(a, Basic):
                          a = a.doit(**hints)
                      if isinstance(b, Basic):
                          b = b.doit(**hints)
  
                  if antideriv.is_Poly:
                      gens = list(antideriv.gens)
                      gens.remove(x)
  
                      antideriv = antideriv.as_expr()
  
                      function = antideriv._eval_interval(x, a, b)
                      function = Poly(function, *gens)
                  else:
  
                      def is_indef_int(g, x):
                          return isinstance(g, Integral) and any(
                              i == (x,) for i in g.limits
                          )
  
                      def eval_factored(f, x, a, b):
                          # _eval_interval for integrals with
                          # (constant) factors
                          # a single indefinite integral is assumed
                          args = []
                          for g in Mul.make_args(f):
                              if is_indef_int(g, x):
                                  args.append(g._eval_interval(x, a, b))
                              else:
                                  args.append(g)
                          return Mul(*args)
  
                      integrals, others, piecewises = [], [], []
                      for f in Add.make_args(antideriv):
                          if any(
                              is_indef_int(g, x)
                              for g in Mul.make_args(f)
                          ):
                              integrals.append(f)
                          elif any(
                              isinstance(g, Piecewise)
                              for g in Mul.make_args(f)
                          ):
                              piecewises.append(piecewise_fold(f))
                          else:
                              others.append(f)
                      uneval = Add(
                          *[
                              eval_factored(f, x, a, b)
                              for f in integrals
                          ]
                      )
                      try:
                          evalued = Add(*others)._eval_interval(x, a, b)
                          evalued_pw = piecewise_fold(
                              Add(*piecewises)
                          )._eval_interval(x, a, b)
                          function = uneval + evalued + evalued_pw
                      except NotImplementedError:
                          # This can happen if _eval_interval depends in a
                          # complicated way on limits that cannot be computed
                          undone_limits.append(xab)
                          function = self.func(*([function] + [xab]))
                          factored_function = function.factor()
                          if not isinstance(
                              factored_function, Integral
                          ):
                              function = factored_function
      return function
  
imports: from typing import Tuple
  from sympy.concrete.expr_with_limits import AddWithLimits
  from sympy.core.add import Add
  from sympy.core.basic import Basic
  from sympy.core.containers import Tuple
  from sympy.core.expr import Expr
  from sympy.core.exprtools import factor_terms
  from sympy.core.function import diff
  from sympy.core.logic import fuzzy_bool
  from sympy.core.mul import Mul
  from sympy.core.numbers import oo, pi
  from sympy.core.relational import Ne
  from sympy.core.singleton import S
  from sympy.core.symbol import Dummy, Symbol, Wild
  from sympy.core.sympify import sympify
  from sympy.functions import Piecewise, sqrt, piecewise_fold, tan, cot, atan
  from sympy.functions.elementary.exponential import log
  from sympy.functions.elementary.integers import floor
  from sympy.functions.elementary.complexes import Abs, sign
  from sympy.functions.elementary.miscellaneous import Min, Max
  from sympy.functions.special.singularity_functions import Heaviside
  from .rationaltools import ratint
  from sympy.matrices import MatrixBase
  from sympy.polys import Poly, PolynomialError
  from sympy.series.formal import FormalPowerSeries
  from sympy.series.limits import limit
  from sympy.series.order import Order
  from sympy.tensor.functions import shape
  from sympy.utilities.exceptions import sympy_deprecation_warning
  from sympy.utilities.iterables import is_sequence
  from sympy.utilities.misc import filldedent
  from .deltafunctions import deltaintegrate
  from .meijerint import meijerint_definite, meijerint_indefinite, _debug
  from .trigonometry import trigintegrate
label_desc: Use image node_id 6 for calling the Integral obj's underlying member method code with example usage: obj.doit() and returns: function, self, S, _sum, S, function, did, self, function, function, ret, unknown, Mul, Piecewise