# Buggy code
def fit(
    self,
    start_params=None,
    method="newton",
    maxiter=100,
    full_output=True,
    disp=True,
    fargs=(),
    callback=None,
    retall=False,
    skip_hessian=False,
    **kwargs,
):
    """
    Fit method for likelihood based models

    Parameters
    ----------
    start_params : array-like, optional
        Initial guess of the solution for the loglikelihood maximization.
        The default is an array of zeros.
    method : str, optional
        The `method` determines which solver from `scipy.optimize`
        is used, and it can be chosen from among the following strings:

        - 'newton' for Newton-Raphson, 'nm' for Nelder-Mead
        - 'bfgs' for Broyden-Fletcher-Goldfarb-Shanno (BFGS)
        - 'lbfgs' for limited-memory BFGS with optional box constraints
        - 'powell' for modified Powell's method
        - 'cg' for conjugate gradient
        - 'ncg' for Newton-conjugate gradient
        - 'basinhopping' for global basin-hopping solver

        The explicit arguments in `fit` are passed to the solver,
        with the exception of the basin-hopping solver. Each
        solver has several optional arguments that are not the same across
        solvers. See the notes section below (or scipy.optimize) for the
        available arguments and for the list of explicit arguments that the
        basin-hopping solver supports.
    maxiter : int, optional
        The maximum number of iterations to perform.
    full_output : bool, optional
        Set to True to have all available output in the Results object's
        mle_retvals attribute. The output is dependent on the solver.
        See LikelihoodModelResults notes section for more information.
    disp : bool, optional
        Set to True to print convergence messages.
    fargs : tuple, optional
        Extra arguments passed to the likelihood function, i.e.,
        loglike(x,*args)
    callback : callable callback(xk), optional
        Called after each iteration, as callback(xk), where xk is the
        current parameter vector.
    retall : bool, optional
        Set to True to return list of solutions at each iteration.
        Available in Results object's mle_retvals attribute.
    skip_hessian : bool, optional
        If False (default), then the negative inverse hessian is calculated
        after the optimization. If True, then the hessian will not be
        calculated. However, it will be available in methods that use the
        hessian in the optimization (currently only with `"newton"`).
    kwargs : keywords
        All kwargs are passed to the chosen solver with one exception. The
        following keyword controls what happens after the fit::

            warn_convergence : bool, optional
                If True, checks the model for the converged flag. If the
                converged flag is False, a ConvergenceWarning is issued.

    Notes
    -----
    The 'basinhopping' solver ignores `maxiter`, `retall`, `full_output`
    explicit arguments.

    Optional arguments for solvers (see returned Results.mle_settings)::

        'newton'
            tol : float
                Relative error in params acceptable for convergence.
        'nm' -- Nelder Mead
            xtol : float
                Relative error in params acceptable for convergence
            ftol : float
                Relative error in loglike(params) acceptable for
                convergence
            maxfun : int
                Maximum number of function evaluations to make.
        'bfgs'
            gtol : float
                Stop when norm of gradient is less than gtol.
            norm : float
                Order of norm (np.Inf is max, -np.Inf is min)
            epsilon
                If fprime is approximated, use this value for the step
                size. Only relevant if LikelihoodModel.score is None.
        'lbfgs'
            m : int
                This many terms are used for the Hessian approximation.
            factr : float
                A stop condition that is a variant of relative error.
            pgtol : float
                A stop condition that uses the projected gradient.
            epsilon
                If fprime is approximated, use this value for the step
                size. Only relevant if LikelihoodModel.score is None.
            maxfun : int
                Maximum number of function evaluations to make.
            bounds : sequence
                (min, max) pairs for each element in x,
                defining the bounds on that parameter.
                Use None for one of min or max when there is no bound
                in that direction.
        'cg'
            gtol : float
                Stop when norm of gradient is less than gtol.
            norm : float
                Order of norm (np.Inf is max, -np.Inf is min)
            epsilon : float
                If fprime is approximated, use this value for the step
                size. Can be scalar or vector.  Only relevant if
                Likelihoodmodel.score is None.
        'ncg'
            fhess_p : callable f'(x,*args)
                Function which computes the Hessian of f times an arbitrary
                vector, p.  Should only be supplied if
                LikelihoodModel.hessian is None.
            avextol : float
                Stop when the average relative error in the minimizer
                falls below this amount.
            epsilon : float or ndarray
                If fhess is approximated, use this value for the step size.
                Only relevant if Likelihoodmodel.hessian is None.
        'powell'
            xtol : float
                Line-search error tolerance
            ftol : float
                Relative error in loglike(params) for acceptable for
                convergence.
            maxfun : int
                Maximum number of function evaluations to make.
            start_direc : ndarray
                Initial direction set.
        'basinhopping'
            niter : integer
                The number of basin hopping iterations.
            niter_success : integer
                Stop the run if the global minimum candidate remains the
                same for this number of iterations.
            T : float
                The "temperature" parameter for the accept or reject
                criterion. Higher "temperatures" mean that larger jumps
                in function value will be accepted. For best results
                `T` should be comparable to the separation (in function
                value) between local minima.
            stepsize : float
                Initial step size for use in the random displacement.
            interval : integer
                The interval for how often to update the `stepsize`.
            minimizer : dict
                Extra keyword arguments to be passed to the minimizer
                `scipy.optimize.minimize()`, for example 'method' - the
                minimization method (e.g. 'L-BFGS-B'), or 'tol' - the
                tolerance for termination. Other arguments are mapped from
                explicit argument of `fit`:
                  - `args` <- `fargs`
                  - `jac` <- `score`
                  - `hess` <- `hess`
    """
    Hinv = None  # JP error if full_output=0, Hinv not defined

    if start_params is None:
        if hasattr(self, "start_params"):
            start_params = self.start_params
        elif self.exog is not None:
            # fails for shape (K,)?
            start_params = [0] * self.exog.shape[1]
        else:
            raise ValueError("If exog is None, then start_params should be specified")

    # TODO: separate args from nonarg taking score and hessian, ie.,
    # user-supplied and numerically evaluated estimate frprime doesn't take
    # args in most (any?) of the optimize function

    nobs = self.endog.shape[0]
    f = lambda params, *args: -self.loglike(params, *args) / nobs
    score = lambda params, *args: -self.score(params, *args) / nobs
    try:
        hess = lambda params, *args: -self.hessian(params, *args) / nobs
    except:
        hess = None

    if method == "newton":
        score = lambda params, *args: self.score(params, *args) / nobs
        hess = lambda params, *args: self.hessian(params, *args) / nobs
        # TODO: why are score and hess positive?

    warn_convergence = kwargs.pop("warn_convergence", True)
    optimizer = Optimizer()
    xopt, retvals, optim_settings = optimizer._fit(
        f,
        score,
        start_params,
        fargs,
        kwargs,
        hessian=hess,
        method=method,
        disp=disp,
        maxiter=maxiter,
        callback=callback,
        retall=retall,
        full_output=full_output,
    )

    # NOTE: this is for fit_regularized and should be generalized
    cov_params_func = kwargs.setdefault("cov_params_func", None)
    if cov_params_func:
        Hinv = cov_params_func(self, xopt, retvals)
    elif method == "newton" and full_output:
        Hinv = np.linalg.inv(-retvals["Hessian"]) / nobs
    elif not skip_hessian:
        try:
            Hinv = np.linalg.inv(-1 * self.hessian(xopt))
        except:
            # might want custom warning ResultsWarning? NumericalWarning?
            from warnings import warn

            warndoc = "Inverting hessian failed, no bse or cov_params available"
            warn(warndoc, RuntimeWarning)
            Hinv = None

    if "cov_type" in kwargs:
        cov_kwds = kwargs.get("cov_kwds", {})
        kwds = {"cov_type": kwargs["cov_type"], "cov_kwds": cov_kwds}
    else:
        kwds = {}
    if "use_t" in kwargs:
        kwds["use_t"] = kwargs["use_t"]
    # prints for debugging
    # print('kwargs inLikelihoodModel.fit', kwargs)
    # print('kwds inLikelihoodModel.fit', kwds)
    # TODO: add Hessian approximation and change the above if needed
    mlefit = LikelihoodModelResults(self, xopt, Hinv, scale=1.0, **kwds)

    # TODO: hardcode scale?
    if isinstance(retvals, dict):
        mlefit.mle_retvals = retvals
        if warn_convergence and not retvals["converged"]:
            from warnings import warn
            from statsmodels.tools.sm_exceptions import ConvergenceWarning

            warn(
                "Maximum Likelihood optimization failed to converge. Check mle_retvals",
                ConvergenceWarning,
            )

    mlefit.mle_settings = optim_settings
    return mlefit


# Traceback (ValueError)
Traceback (most recent call last):
File "C:\git\statsmodels\statsmodels\base\model.py", line 447, in fit
H = -1 * self.hessian(xopt)
File "C:\git\statsmodels\statsmodels\tsa\arima_model.py", line 593, in hessian
return approx_hess_cs(params, self.loglike, args=(False,))
File "C:\git\statsmodels\statsmodels\tools\numdiff.py", line 243, in approx_hess_cs
**kwargs)).imag/2./hess[i, j]
File "C:\git\statsmodels\statsmodels\tsa\arima_model.py", line 776, in loglike
return self.loglike_kalman(params, set_sigma2)
File "C:\git\statsmodels\statsmodels\tsa\arima_model.py", line 786, in loglike_kalman
return KalmanFilter.loglike(params, self, set_sigma2)
File "C:\git\statsmodels\statsmodels\tsa\kalmanf\kalmanfilter.py", line 666, in loglike
R_mat, T_mat)
File "statsmodels\tsa\kalmanf\kalman_loglike.pyx", line 359, in statsmodels.tsa.kalmanf.kalman_loglike.kalman_loglike_complex (statsmodels/tsa/kalmanf/kalman_loglike.c:6432)
v, F, loglikelihood = kalman_filter_complex(y,k,p,q,r,nobs,Z_mat,R_mat,T_mat)
File "statsmodels\tsa\kalmanf\kalman_loglike.pyx", line 229, in statsmodels.tsa.kalmanf.kalman_loglike.kalman_filter_complex (statsmodels/tsa/kalmanf/kalman_loglike.c:4956)
dot(R_mat,R_mat.T).ravel('F')).reshape(r,r, order='F'))
File "statsmodels\tsa\kalmanf\stringsource", line 644, in View.MemoryView.memoryview_cwrapper (statsmodels/tsa/kalmanf/kalman_loglike.c:14545)
File "statsmodels\tsa\kalmanf\stringsource", line 345, in View.MemoryView.memoryview.__cinit__ (statsmodels/tsa/kalmanf/kalman_loglike.c:10820)
ValueError: ndarray is not Fortran contiguous

# Fixed code
def fit(
    self,
    start_params=None,
    method="newton",
    maxiter=100,
    full_output=True,
    disp=True,
    fargs=(),
    callback=None,
    retall=False,
    skip_hessian=False,
    **kwargs,
):
    """
    Fit method for likelihood based models

    Parameters
    ----------
    start_params : array-like, optional
        Initial guess of the solution for the loglikelihood maximization.
        The default is an array of zeros.
    method : str, optional
        The `method` determines which solver from `scipy.optimize`
        is used, and it can be chosen from among the following strings:

        - 'newton' for Newton-Raphson, 'nm' for Nelder-Mead
        - 'bfgs' for Broyden-Fletcher-Goldfarb-Shanno (BFGS)
        - 'lbfgs' for limited-memory BFGS with optional box constraints
        - 'powell' for modified Powell's method
        - 'cg' for conjugate gradient
        - 'ncg' for Newton-conjugate gradient
        - 'basinhopping' for global basin-hopping solver

        The explicit arguments in `fit` are passed to the solver,
        with the exception of the basin-hopping solver. Each
        solver has several optional arguments that are not the same across
        solvers. See the notes section below (or scipy.optimize) for the
        available arguments and for the list of explicit arguments that the
        basin-hopping solver supports.
    maxiter : int, optional
        The maximum number of iterations to perform.
    full_output : bool, optional
        Set to True to have all available output in the Results object's
        mle_retvals attribute. The output is dependent on the solver.
        See LikelihoodModelResults notes section for more information.
    disp : bool, optional
        Set to True to print convergence messages.
    fargs : tuple, optional
        Extra arguments passed to the likelihood function, i.e.,
        loglike(x,*args)
    callback : callable callback(xk), optional
        Called after each iteration, as callback(xk), where xk is the
        current parameter vector.
    retall : bool, optional
        Set to True to return list of solutions at each iteration.
        Available in Results object's mle_retvals attribute.
    skip_hessian : bool, optional
        If False (default), then the negative inverse hessian is calculated
        after the optimization. If True, then the hessian will not be
        calculated. However, it will be available in methods that use the
        hessian in the optimization (currently only with `"newton"`).
    kwargs : keywords
        All kwargs are passed to the chosen solver with one exception. The
        following keyword controls what happens after the fit::

            warn_convergence : bool, optional
                If True, checks the model for the converged flag. If the
                converged flag is False, a ConvergenceWarning is issued.

    Notes
    -----
    The 'basinhopping' solver ignores `maxiter`, `retall`, `full_output`
    explicit arguments.

    Optional arguments for solvers (see returned Results.mle_settings)::

        'newton'
            tol : float
                Relative error in params acceptable for convergence.
        'nm' -- Nelder Mead
            xtol : float
                Relative error in params acceptable for convergence
            ftol : float
                Relative error in loglike(params) acceptable for
                convergence
            maxfun : int
                Maximum number of function evaluations to make.
        'bfgs'
            gtol : float
                Stop when norm of gradient is less than gtol.
            norm : float
                Order of norm (np.Inf is max, -np.Inf is min)
            epsilon
                If fprime is approximated, use this value for the step
                size. Only relevant if LikelihoodModel.score is None.
        'lbfgs'
            m : int
                This many terms are used for the Hessian approximation.
            factr : float
                A stop condition that is a variant of relative error.
            pgtol : float
                A stop condition that uses the projected gradient.
            epsilon
                If fprime is approximated, use this value for the step
                size. Only relevant if LikelihoodModel.score is None.
            maxfun : int
                Maximum number of function evaluations to make.
            bounds : sequence
                (min, max) pairs for each element in x,
                defining the bounds on that parameter.
                Use None for one of min or max when there is no bound
                in that direction.
        'cg'
            gtol : float
                Stop when norm of gradient is less than gtol.
            norm : float
                Order of norm (np.Inf is max, -np.Inf is min)
            epsilon : float
                If fprime is approximated, use this value for the step
                size. Can be scalar or vector.  Only relevant if
                Likelihoodmodel.score is None.
        'ncg'
            fhess_p : callable f'(x,*args)
                Function which computes the Hessian of f times an arbitrary
                vector, p.  Should only be supplied if
                LikelihoodModel.hessian is None.
            avextol : float
                Stop when the average relative error in the minimizer
                falls below this amount.
            epsilon : float or ndarray
                If fhess is approximated, use this value for the step size.
                Only relevant if Likelihoodmodel.hessian is None.
        'powell'
            xtol : float
                Line-search error tolerance
            ftol : float
                Relative error in loglike(params) for acceptable for
                convergence.
            maxfun : int
                Maximum number of function evaluations to make.
            start_direc : ndarray
                Initial direction set.
        'basinhopping'
            niter : integer
                The number of basin hopping iterations.
            niter_success : integer
                Stop the run if the global minimum candidate remains the
                same for this number of iterations.
            T : float
                The "temperature" parameter for the accept or reject
                criterion. Higher "temperatures" mean that larger jumps
                in function value will be accepted. For best results
                `T` should be comparable to the separation (in function
                value) between local minima.
            stepsize : float
                Initial step size for use in the random displacement.
            interval : integer
                The interval for how often to update the `stepsize`.
            minimizer : dict
                Extra keyword arguments to be passed to the minimizer
                `scipy.optimize.minimize()`, for example 'method' - the
                minimization method (e.g. 'L-BFGS-B'), or 'tol' - the
                tolerance for termination. Other arguments are mapped from
                explicit argument of `fit`:
                  - `args` <- `fargs`
                  - `jac` <- `score`
                  - `hess` <- `hess`
    """
    Hinv = None  # JP error if full_output=0, Hinv not defined

    if start_params is None:
        if hasattr(self, "start_params"):
            start_params = self.start_params
        elif self.exog is not None:
            # fails for shape (K,)?
            start_params = [0] * self.exog.shape[1]
        else:
            raise ValueError("If exog is None, then start_params should be specified")

    # TODO: separate args from nonarg taking score and hessian, ie.,
    # user-supplied and numerically evaluated estimate frprime doesn't take
    # args in most (any?) of the optimize function

    nobs = self.endog.shape[0]
    f = lambda params, *args: -self.loglike(params, *args) / nobs
    score = lambda params, *args: -self.score(params, *args) / nobs
    try:
        hess = lambda params, *args: -self.hessian(params, *args) / nobs
    except:
        hess = None

    if method == "newton":
        score = lambda params, *args: self.score(params, *args) / nobs
        hess = lambda params, *args: self.hessian(params, *args) / nobs
        # TODO: why are score and hess positive?

    warn_convergence = kwargs.pop("warn_convergence", True)
    optimizer = Optimizer()
    xopt, retvals, optim_settings = optimizer._fit(
        f,
        score,
        start_params,
        fargs,
        kwargs,
        hessian=hess,
        method=method,
        disp=disp,
        maxiter=maxiter,
        callback=callback,
        retall=retall,
        full_output=full_output,
    )

    # NOTE: this is for fit_regularized and should be generalized
    cov_params_func = kwargs.setdefault("cov_params_func", None)
    if cov_params_func:
        Hinv = cov_params_func(self, xopt, retvals)
    elif method == "newton" and full_output:
        Hinv = np.linalg.inv(-retvals["Hessian"]) / nobs
    elif not skip_hessian:
        H = -1 * self.hessian(xopt)
        invertible = False
        if np.all(np.isfinite(H)):
            eigvals, eigvecs = np.linalg.eigh(H)
            if np.min(eigvals) > 0:
                invertible = True

        if invertible:
            Hinv = eigvecs.dot(np.diag(1.0 / eigvals)).dot(eigvecs.T)
            Hinv = np.asfortranarray((Hinv + Hinv.T) / 2.0)
        else:
            from warnings import warn

            warn(
                "Inverting hessian failed, no bse or cov_params available",
                HessianInversionWarning,
            )
            Hinv = None

    if "cov_type" in kwargs:
        cov_kwds = kwargs.get("cov_kwds", {})
        kwds = {"cov_type": kwargs["cov_type"], "cov_kwds": cov_kwds}
    else:
        kwds = {}
    if "use_t" in kwargs:
        kwds["use_t"] = kwargs["use_t"]
    # prints for debugging
    # print('kwargs inLikelihoodModel.fit', kwargs)
    # print('kwds inLikelihoodModel.fit', kwds)
    # TODO: add Hessian approximation and change the above if needed
    mlefit = LikelihoodModelResults(self, xopt, Hinv, scale=1.0, **kwds)

    # TODO: hardcode scale?
    if isinstance(retvals, dict):
        mlefit.mle_retvals = retvals
        if warn_convergence and not retvals["converged"]:
            from warnings import warn
            from statsmodels.tools.sm_exceptions import ConvergenceWarning

            warn(
                "Maximum Likelihood optimization failed to converge. Check mle_retvals",
                ConvergenceWarning,
            )

    mlefit.mle_settings = optim_settings
    return mlefit