# Buggy code
def _arg_max_reduced_likelihood_function(self):
    """
    This function estimates the autocorrelation parameters theta as the
    maximizer of the reduced likelihood function.
    (Minimization of the opposite reduced likelihood function is used for
    convenience)

    Parameters
    ----------
    self : All parameters are stored in the Gaussian Process model object.

    Returns
    -------
    optimal_theta : array_like
        The best set of autocorrelation parameters (the sought maximizer of
        the reduced likelihood function).

    optimal_reduced_likelihood_function_value : double
        The optimal reduced likelihood function value.

    optimal_par : dict
        The BLUP parameters associated to thetaOpt.
    """

    # Initialize output
    best_optimal_theta = []
    best_optimal_rlf_value = []
    best_optimal_par = []

    if self.verbose:
        print("The chosen optimizer is: " + str(self.optimizer))
        if self.random_start > 1:
            print(str(self.random_start) + " random starts are required.")

    percent_completed = 0.0

    # Force optimizer to fmin_cobyla if the model is meant to be isotropic
    if self.optimizer == "Welch" and self.theta0.size == 1:
        self.optimizer = "fmin_cobyla"

    if self.optimizer == "fmin_cobyla":

        def minus_reduced_likelihood_function(log10t):
            return -self.reduced_likelihood_function(theta=10.0**log10t)[0]

        constraints = []
        for i in range(self.theta0.size):
            constraints.append(lambda log10t: log10t[i] - np.log10(self.thetaL[0, i]))
            constraints.append(lambda log10t: np.log10(self.thetaU[0, i]) - log10t[i])

        for k in range(self.random_start):
            if k == 0:
                # Use specified starting point as first guess
                theta0 = self.theta0
            else:
                # Generate a random starting point log10-uniformly
                # distributed between bounds
                log10theta0 = np.log10(self.thetaL) + rand(self.theta0.size).reshape(
                    self.theta0.shape
                ) * np.log10(self.thetaU / self.thetaL)
                theta0 = 10.0**log10theta0

            # Run Cobyla
            try:
                log10_optimal_theta = optimize.fmin_cobyla(
                    minus_reduced_likelihood_function,
                    np.log10(theta0),
                    constraints,
                    iprint=0,
                )
            except ValueError as ve:
                print("Optimization failed. Try increasing the ``nugget``")
                raise ve

            optimal_theta = 10.0**log10_optimal_theta
            optimal_minus_rlf_value, optimal_par = self.reduced_likelihood_function(
                theta=optimal_theta
            )
            optimal_rlf_value = -optimal_minus_rlf_value

            # Compare the new optimizer to the best previous one
            if k > 0:
                if optimal_rlf_value > best_optimal_rlf_value:
                    best_optimal_rlf_value = optimal_rlf_value
                    best_optimal_par = optimal_par
                    best_optimal_theta = optimal_theta
            else:
                best_optimal_rlf_value = optimal_rlf_value
                best_optimal_par = optimal_par
                best_optimal_theta = optimal_theta
            if self.verbose and self.random_start > 1:
                if (20 * k) / self.random_start > percent_completed:
                    percent_completed = (20 * k) / self.random_start
                    print("%s completed" % (5 * percent_completed))

        optimal_rlf_value = best_optimal_rlf_value
        optimal_par = best_optimal_par
        optimal_theta = best_optimal_theta

    elif self.optimizer == "Welch":
        # Backup of the given atrributes
        theta0, thetaL, thetaU = self.theta0, self.thetaL, self.thetaU
        corr = self.corr
        verbose = self.verbose

        # This will iterate over fmin_cobyla optimizer
        self.optimizer = "fmin_cobyla"
        self.verbose = False

        # Initialize under isotropy assumption
        if verbose:
            print("Initialize under isotropy assumption...")
        self.theta0 = array2d(self.theta0.min())
        self.thetaL = array2d(self.thetaL.min())
        self.thetaU = array2d(self.thetaU.max())
        theta_iso, optimal_rlf_value_iso, par_iso = (
            self._arg_max_reduced_likelihood_function()
        )
        optimal_theta = theta_iso + np.zeros(theta0.shape)

        # Iterate over all dimensions of theta allowing for anisotropy
        if verbose:
            print("Now improving allowing for anisotropy...")
        for i in self.random_state.permutation(theta0.size):
            if verbose:
                print("Proceeding along dimension %d..." % (i + 1))
            self.theta0 = array2d(theta_iso)
            self.thetaL = array2d(thetaL[0, i])
            self.thetaU = array2d(thetaU[0, i])

            def corr_cut(t, d):
                return corr(
                    array2d(
                        np.hstack(
                            [optimal_theta[0][0:i], t[0], optimal_theta[0][(i + 1) : :]]
                        )
                    ),
                    d,
                )

            self.corr = corr_cut
            optimal_theta[0, i], optimal_rlf_value, optimal_par = (
                self._arg_max_reduced_likelihood_function()
            )

        # Restore the given atrributes
        self.theta0, self.thetaL, self.thetaU = theta0, thetaL, thetaU
        self.corr = corr
        self.optimizer = "Welch"
        self.verbose = verbose

    else:
        raise NotImplementedError(
            "This optimizer ('%s') is not "
            "implemented yet. Please contribute!" % self.optimizer
        )

    return optimal_theta, optimal_rlf_value, optimal_par


# Traceback (IndexError)
======================================================================
ERROR: sklearn.tests.test_common.test_regressors_train('RANSACRegressor', <class 'sklearn.linear_model.ransac.RANSACRegr
essor'>, array([[-0.44836249, -0.47282444, -1.20608008, ..., -0.75500806,
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\nose\case.py", line 197, in runTest
self.test(*self.arg)
File "C:\Python27\lib\site-packages\sklearn\tests\test_common.py", line 850, in check_regressors_train
assert_raises(ValueError, regressor.fit, X, y[:-1])
File "C:\Python27\lib\unittest\case.py", line 473, in assertRaises
callableObj(*args, **kwargs)
File "C:\Python27\lib\site-packages\sklearn\linear_model\ransac.py", line 261, in fit
y_subset = y[subset_idxs]
IndexError: index 199 is out of bounds for axis 0 with size 199

# Fixed code
def _arg_max_reduced_likelihood_function(self):
    """
    This function estimates the autocorrelation parameters theta as the
    maximizer of the reduced likelihood function.
    (Minimization of the opposite reduced likelihood function is used for
    convenience)

    Parameters
    ----------
    self : All parameters are stored in the Gaussian Process model object.

    Returns
    -------
    optimal_theta : array_like
        The best set of autocorrelation parameters (the sought maximizer of
        the reduced likelihood function).

    optimal_reduced_likelihood_function_value : double
        The optimal reduced likelihood function value.

    optimal_par : dict
        The BLUP parameters associated to thetaOpt.
    """

    # Initialize output
    best_optimal_theta = []
    best_optimal_rlf_value = []
    best_optimal_par = []

    if self.verbose:
        print("The chosen optimizer is: " + str(self.optimizer))
        if self.random_start > 1:
            print(str(self.random_start) + " random starts are required.")

    percent_completed = 0.0

    # Force optimizer to fmin_cobyla if the model is meant to be isotropic
    if self.optimizer == "Welch" and self.theta0.size == 1:
        self.optimizer = "fmin_cobyla"

    if self.optimizer == "fmin_cobyla":

        def minus_reduced_likelihood_function(log10t):
            return -self.reduced_likelihood_function(theta=10.0**log10t)[0]

        constraints = []
        for i in range(self.theta0.size):
            constraints.append(
                lambda log10t, i=i: log10t[i] - np.log10(self.thetaL[0, i])
            )
            constraints.append(
                lambda log10t, i=i: np.log10(self.thetaU[0, i]) - log10t[i]
            )

        for k in range(self.random_start):
            if k == 0:
                # Use specified starting point as first guess
                theta0 = self.theta0
            else:
                # Generate a random starting point log10-uniformly
                # distributed between bounds
                log10theta0 = np.log10(self.thetaL) + rand(self.theta0.size).reshape(
                    self.theta0.shape
                ) * np.log10(self.thetaU / self.thetaL)
                theta0 = 10.0**log10theta0

            # Run Cobyla
            try:
                log10_optimal_theta = optimize.fmin_cobyla(
                    minus_reduced_likelihood_function,
                    np.log10(theta0),
                    constraints,
                    iprint=0,
                )
            except ValueError as ve:
                print("Optimization failed. Try increasing the ``nugget``")
                raise ve

            optimal_theta = 10.0**log10_optimal_theta
            optimal_minus_rlf_value, optimal_par = self.reduced_likelihood_function(
                theta=optimal_theta
            )
            optimal_rlf_value = -optimal_minus_rlf_value

            # Compare the new optimizer to the best previous one
            if k > 0:
                if optimal_rlf_value > best_optimal_rlf_value:
                    best_optimal_rlf_value = optimal_rlf_value
                    best_optimal_par = optimal_par
                    best_optimal_theta = optimal_theta
            else:
                best_optimal_rlf_value = optimal_rlf_value
                best_optimal_par = optimal_par
                best_optimal_theta = optimal_theta
            if self.verbose and self.random_start > 1:
                if (20 * k) / self.random_start > percent_completed:
                    percent_completed = (20 * k) / self.random_start
                    print("%s completed" % (5 * percent_completed))

        optimal_rlf_value = best_optimal_rlf_value
        optimal_par = best_optimal_par
        optimal_theta = best_optimal_theta

    elif self.optimizer == "Welch":
        # Backup of the given atrributes
        theta0, thetaL, thetaU = self.theta0, self.thetaL, self.thetaU
        corr = self.corr
        verbose = self.verbose

        # This will iterate over fmin_cobyla optimizer
        self.optimizer = "fmin_cobyla"
        self.verbose = False

        # Initialize under isotropy assumption
        if verbose:
            print("Initialize under isotropy assumption...")
        self.theta0 = array2d(self.theta0.min())
        self.thetaL = array2d(self.thetaL.min())
        self.thetaU = array2d(self.thetaU.max())
        theta_iso, optimal_rlf_value_iso, par_iso = (
            self._arg_max_reduced_likelihood_function()
        )
        optimal_theta = theta_iso + np.zeros(theta0.shape)

        # Iterate over all dimensions of theta allowing for anisotropy
        if verbose:
            print("Now improving allowing for anisotropy...")
        for i in self.random_state.permutation(theta0.size):
            if verbose:
                print("Proceeding along dimension %d..." % (i + 1))
            self.theta0 = array2d(theta_iso)
            self.thetaL = array2d(thetaL[0, i])
            self.thetaU = array2d(thetaU[0, i])

            def corr_cut(t, d):
                return corr(
                    array2d(
                        np.hstack(
                            [optimal_theta[0][0:i], t[0], optimal_theta[0][(i + 1) : :]]
                        )
                    ),
                    d,
                )

            self.corr = corr_cut
            optimal_theta[0, i], optimal_rlf_value, optimal_par = (
                self._arg_max_reduced_likelihood_function()
            )

        # Restore the given atrributes
        self.theta0, self.thetaL, self.thetaU = theta0, thetaL, thetaU
        self.corr = corr
        self.optimizer = "Welch"
        self.verbose = verbose

    else:
        raise NotImplementedError(
            "This optimizer ('%s') is not "
            "implemented yet. Please contribute!" % self.optimizer
        )

    return optimal_theta, optimal_rlf_value, optimal_par