code: def search_arima(
      x,
      d=0,
      D=0,
      max_p=5,
      max_q=5,
      max_P=2,
      max_Q=2,
      max_order=5,
      stationary=False,
      ic="aic",
      trace=False,
      approximation=False,
      xreg=None,
      offset=None,
      allow_drift=True,
      allow_mean=True,
      period=1,
      **kwargs,
  ):
      m = period
      allow_drift = allow_drift and (d + D) == 1
      allow_mean = allow_mean and (d + D) == 0
      max_K = int(allow_drift or allow_mean)
  
      best_ic = np.inf
      best_fit = None
      for i in range(max_p + 1):
          for j in range(max_q + 1):
              for I in range(max_P + 1):
                  for J in range(max_Q + 1):
                      if i + j + I + J > max_order:
                          continue
                      for K in range(max_K + 1):
                          fit = myarima(
                              x,
                              order=(i, d, j),
                              seasonal={
                                  "order": (I, D, J),
                                  "period": m,
                              },
                              constant=K == 1,
                              trace=trace,
                              ic=ic,
                              approximation=approximation,
                              offset=offset,
                              xreg=xreg,
                              **kwargs,
                          )
                          if fit["ic"] < best_ic:
                              best_ic = fit["ic"]
                              best_fit = fit
                              constant = K == 1
      if best_fit is None:
          raise RuntimeError("No ARIMA model able to be estimated")
      if approximation:
          if trace:
              print(
                  "Now re-fitting the best model(s) without approximations...\n"
              )
          new_best_fit = myarima(
              x,
              order=tuple(best_fit["arma"][i] for i in [0, 5, 1]),
              seasonal={
                  "order": tuple(
                      best_fit["arma"][i] for i in [2, 6, 3]
                  ),
                  "period": m,
              },
              constant=constant,
              ic=ic,
              trace=False,
              approximation=False,
              xreg=xreg,
              **kwargs,
          )
          if math.isfinite(new_best_fit["ic"]):
              best_fit = new_best_fit
          else:
              best_fit = search_arima(
                  x,
                  d=d,
                  D=D,
                  max_p=max_p,
                  max_q=max_q,
                  max_P=max_P,
                  max_Q=max_Q,
                  max_order=max_order,
                  stationary=stationary,
                  ic=ic,
                  trace=trace,
                  approximation=False,
                  xreg=xreg,
                  offset=offset,
                  allow_drift=allow_drift,
                  allow_mean=allow_mean,
                  **kwargs,
              )
      return best_fit
  
imports: import math
  import warnings
  from collections import namedtuple
  from functools import partial
  from typing import Optional, Dict, Union, Tuple
  import numpy
  import pandas
  import statsmodels.api
  from numba import njit
  from scipy.optimize import minimize
  from scipy.stats import norm
  from .mstl import mstl
  from .utils import CACHE, NOGIL
label_desc: Use image node_id 25 for calling a global function with example usage: search_arima(x, d, D, max_p, max_q, max_P, max_Q, max_order, stationary, ic, trace, approximation, xreg, offset, allow_drift, allow_mean, period) and returns: best_fit