code: def dual_annealing(
      func,
      bounds,
      args=(),
      maxiter=1000,
      minimizer_kwargs=None,
      initial_temp=5230.0,
      restart_temp_ratio=2.0e-5,
      visit=2.62,
      accept=-5.0,
      maxfun=1e7,
      seed=None,
      no_local_search=False,
      callback=None,
      x0=None,
  ):
      """
      Find the global minimum of a function using Dual Annealing.
  
      Parameters
      ----------
      func : callable
          The objective function to be minimized. Must be in the form
          ``f(x, *args)``, where ``x`` is the argument in the form of a 1-D array
          and ``args`` is a  tuple of any additional fixed parameters needed to
          completely specify the function.
      bounds : sequence or `Bounds`
          Bounds for variables. There are two ways to specify the bounds:
  
          1. Instance of `Bounds` class.
          2. Sequence of ``(min, max)`` pairs for each element in `x`.
  
      args : tuple, optional
          Any additional fixed parameters needed to completely specify the
          objective function.
      maxiter : int, optional
          The maximum number of global search iterations. Default value is 1000.
      minimizer_kwargs : dict, optional
          Extra keyword arguments to be passed to the local minimizer
          (`minimize`). Some important options could be:
          ``method`` for the minimizer method to use and ``args`` for
          objective function additional arguments.
      initial_temp : float, optional
          The initial temperature, use higher values to facilitates a wider
          search of the energy landscape, allowing dual_annealing to escape
          local minima that it is trapped in. Default value is 5230. Range is
          (0.01, 5.e4].
      restart_temp_ratio : float, optional
          During the annealing process, temperature is decreasing, when it
          reaches ``initial_temp * restart_temp_ratio``, the reannealing process
          is triggered. Default value of the ratio is 2e-5. Range is (0, 1).
      visit : float, optional
          Parameter for visiting distribution. Default value is 2.62. Higher
          values give the visiting distribution a heavier tail, this makes
          the algorithm jump to a more distant region. The value range is (1, 3].
      accept : float, optional
          Parameter for acceptance distribution. It is used to control the
          probability of acceptance. The lower the acceptance parameter, the
          smaller the probability of acceptance. Default value is -5.0 with
          a range (-1e4, -5].
      maxfun : int, optional
          Soft limit for the number of objective function calls. If the
          algorithm is in the middle of a local search, this number will be
          exceeded, the algorithm will stop just after the local search is
          done. Default value is 1e7.
      seed : {None, int, `numpy.random.Generator`, `numpy.random.RandomState`}, optional
          If `seed` is None (or `np.random`), the `numpy.random.RandomState`
          singleton is used.
          If `seed` is an int, a new ``RandomState`` instance is used,
          seeded with `seed`.
          If `seed` is already a ``Generator`` or ``RandomState`` instance then
          that instance is used.
          Specify `seed` for repeatable minimizations. The random numbers
          generated with this seed only affect the visiting distribution function
          and new coordinates generation.
      no_local_search : bool, optional
          If `no_local_search` is set to True, a traditional Generalized
          Simulated Annealing will be performed with no local search
          strategy applied.
      callback : callable, optional
          A callback function with signature ``callback(x, f, context)``,
          which will be called for all minima found.
          ``x`` and ``f`` are the coordinates and function value of the
          latest minimum found, and ``context`` has value in [0, 1, 2], with the
          following meaning:
  
              - 0: minimum detected in the annealing process.
              - 1: detection occurred in the local search process.
              - 2: detection done in the dual annealing process.
  
          If the callback implementation returns True, the algorithm will stop.
      x0 : ndarray, shape(n,), optional
          Coordinates of a single N-D starting point.
  
      Returns
      -------
      res : OptimizeResult
          The optimization result represented as a `OptimizeResult` object.
          Important attributes are: ``x`` the solution array, ``fun`` the value
          of the function at the solution, and ``message`` which describes the
          cause of the termination.
          See `OptimizeResult` for a description of other attributes.
  
      Notes
      -----
      This function implements the Dual Annealing optimization. This stochastic
      approach derived from [3]_ combines the generalization of CSA (Classical
      Simulated Annealing) and FSA (Fast Simulated Annealing) [1]_ [2]_ coupled
      to a strategy for applying a local search on accepted locations [4]_.
      An alternative implementation of this same algorithm is described in [5]_
      and benchmarks are presented in [6]_. This approach introduces an advanced
      method to refine the solution found by the generalized annealing
      process. This algorithm uses a distorted Cauchy-Lorentz visiting
      distribution, with its shape controlled by the parameter :math:`q_{v}`
  
      .. math::
  
          g_{q_{v}}(\\Delta x(t)) \\propto \\frac{ \\
          \\left[T_{q_{v}}(t) \\right]^{-\\frac{D}{3-q_{v}}}}{ \\
          \\left[{1+(q_{v}-1)\\frac{(\\Delta x(t))^{2}} { \\
          \\left[T_{q_{v}}(t)\\right]^{\\frac{2}{3-q_{v}}}}}\\right]^{ \\
          \\frac{1}{q_{v}-1}+\\frac{D-1}{2}}}
  
      Where :math:`t` is the artificial time. This visiting distribution is used
      to generate a trial jump distance :math:`\\Delta x(t)` of variable
      :math:`x(t)` under artificial temperature :math:`T_{q_{v}}(t)`.
  
      From the starting point, after calling the visiting distribution
      function, the acceptance probability is computed as follows:
  
      .. math::
  
          p_{q_{a}} = \\min{\\{1,\\left[1-(1-q_{a}) \\beta \\Delta E \\right]^{ \\
          \\frac{1}{1-q_{a}}}\\}}
  
      Where :math:`q_{a}` is a acceptance parameter. For :math:`q_{a}<1`, zero
      acceptance probability is assigned to the cases where
  
      .. math::
  
          [1-(1-q_{a}) \\beta \\Delta E] < 0
  
      The artificial temperature :math:`T_{q_{v}}(t)` is decreased according to
  
      .. math::
  
          T_{q_{v}}(t) = T_{q_{v}}(1) \\frac{2^{q_{v}-1}-1}{\\left( \\
          1 + t\\right)^{q_{v}-1}-1}
  
      Where :math:`q_{v}` is the visiting parameter.
  
      .. versionadded:: 1.2.0
  
      References
      ----------
      .. [1] Tsallis C. Possible generalization of Boltzmann-Gibbs
          statistics. Journal of Statistical Physics, 52, 479-487 (1998).
      .. [2] Tsallis C, Stariolo DA. Generalized Simulated Annealing.
          Physica A, 233, 395-406 (1996).
      .. [3] Xiang Y, Sun DY, Fan W, Gong XG. Generalized Simulated
          Annealing Algorithm and Its Application to the Thomson Model.
          Physics Letters A, 233, 216-220 (1997).
      .. [4] Xiang Y, Gong XG. Efficiency of Generalized Simulated
          Annealing. Physical Review E, 62, 4473 (2000).
      .. [5] Xiang Y, Gubian S, Suomela B, Hoeng J. Generalized
          Simulated Annealing for Efficient Global Optimization: the GenSA
          Package for R. The R Journal, Volume 5/1 (2013).
      .. [6] Mullen, K. Continuous Global Optimization in R. Journal of
          Statistical Software, 60(6), 1 - 45, (2014).
          :doi:`10.18637/jss.v060.i06`
  
      Examples
      --------
      The following example is a 10-D problem, with many local minima.
      The function involved is called Rastrigin
      (https://en.wikipedia.org/wiki/Rastrigin_function)
  
      >>> import numpy as np
      >>> from scipy.optimize import dual_annealing
      >>> func = lambda x: np.sum(x*x - 10*np.cos(2*np.pi*x)) + 10*np.size(x)
      >>> lw = [-5.12] * 10
      >>> up = [5.12] * 10
      >>> ret = dual_annealing(func, bounds=list(zip(lw, up)))
      >>> ret.x
      array([-4.26437714e-09, -3.91699361e-09, -1.86149218e-09, -3.97165720e-09,
             -6.29151648e-09, -6.53145322e-09, -3.93616815e-09, -6.55623025e-09,
             -6.05775280e-09, -5.00668935e-09]) # random
      >>> ret.fun
      0.000000
  
      """
  
      if isinstance(bounds, Bounds):
          bounds = new_bounds_to_old(
              bounds.lb, bounds.ub, len(bounds.lb)
          )
  
      if x0 is not None and not len(x0) == len(bounds):
          raise ValueError("Bounds size does not match x0")
  
      lu = list(zip(*bounds))
      lower = np.array(lu[0])
      upper = np.array(lu[1])
      # Check that restart temperature ratio is correct
      if restart_temp_ratio <= 0.0 or restart_temp_ratio >= 1.0:
          raise ValueError(
              "Restart temperature ratio has to be in range (0, 1)"
          )
      # Checking bounds are valid
      if (
          np.any(np.isinf(lower))
          or np.any(np.isinf(upper))
          or np.any(np.isnan(lower))
          or np.any(np.isnan(upper))
      ):
          raise ValueError(
              "Some bounds values are inf values or nan values"
          )
      # Checking that bounds are consistent
      if not np.all(lower < upper):
          raise ValueError("Bounds are not consistent min < max")
      # Checking that bounds are the same length
      if not len(lower) == len(upper):
          raise ValueError("Bounds do not have the same dimensions")
  
      # Wrapper for the objective function
      func_wrapper = ObjectiveFunWrapper(func, maxfun, *args)
  
      # minimizer_kwargs has to be a dict, not None
      minimizer_kwargs = minimizer_kwargs or {}
  
      minimizer_wrapper = LocalSearchWrapper(
          bounds, func_wrapper, *args, **minimizer_kwargs
      )
  
      # Initialization of random Generator for reproducible runs if seed provided
      rand_state = check_random_state(seed)
      # Initialization of the energy state
      energy_state = EnergyState(lower, upper, callback)
      energy_state.reset(func_wrapper, rand_state, x0)
      # Minimum value of annealing temperature reached to perform
      # re-annealing
      temperature_restart = initial_temp * restart_temp_ratio
      # VisitingDistribution instance
      visit_dist = VisitingDistribution(lower, upper, visit, rand_state)
      # Strategy chain instance
      strategy_chain = StrategyChain(
          accept,
          visit_dist,
          func_wrapper,
          minimizer_wrapper,
          rand_state,
          energy_state,
      )
      need_to_stop = False
      iteration = 0
      message = []
      # OptimizeResult object to be returned
      optimize_res = OptimizeResult()
      optimize_res.success = True
      optimize_res.status = 0
  
      t1 = np.exp((visit - 1) * np.log(2.0)) - 1.0
      # Run the search loop
      while not need_to_stop:
          for i in range(maxiter):
              # Compute temperature for this step
              s = float(i) + 2.0
              t2 = np.exp((visit - 1) * np.log(s)) - 1.0
              temperature = initial_temp * t1 / t2
              if iteration >= maxiter:
                  message.append("Maximum number of iteration reached")
                  need_to_stop = True
                  break
              # Need a re-annealing process?
              if temperature < temperature_restart:
                  energy_state.reset(func_wrapper, rand_state)
                  break
              # starting strategy chain
              val = strategy_chain.run(i, temperature)
              if val is not None:
                  message.append(val)
                  need_to_stop = True
                  optimize_res.success = False
                  break
              # Possible local search at the end of the strategy chain
              if not no_local_search:
                  val = strategy_chain.local_search()
                  if val is not None:
                      message.append(val)
                      need_to_stop = True
                      optimize_res.success = False
                      break
              iteration += 1
  
      # Setting the OptimizeResult values
      optimize_res.x = energy_state.xbest
      optimize_res.fun = energy_state.ebest
      optimize_res.nit = iteration
      optimize_res.nfev = func_wrapper.nfev
      optimize_res.njev = func_wrapper.ngev
      optimize_res.nhev = func_wrapper.nhev
      optimize_res.message = message
      return optimize_res
  
imports: import numpy
  from scipy.optimize import OptimizeResult
  from scipy.optimize import minimize, Bounds
  from scipy.special import gammaln
  from scipy._lib._util import check_random_state
  from scipy.optimize._constraints import new_bounds_to_old
label_desc: Use image node_id 1 for calling a global function with example usage: dual_annealing(func, bounds, args, maxiter, minimizer_kwargs, initial_temp, restart_temp_ratio, visit, accept, maxfun, seed, no_local_search, callback, x0) and returns: optimize_res