//  [python]
def reset_gp(self):
        if self.kwargs.get('random_init_gp', False):
            self.noise_variance = np.random.uniform(0.1, 1.0)
            self.kernel_lengthscale = np.random.uniform(0.5, 1.0)
            self.kernel_variance = 1.0

        # reset gp
        if "kernel" in self.f_opts and "Matern52" in self.f_opts["kernel"]:
            self.kernel = GPy.kern.Matern52(input_dim=self.D,
                                variance=self.kernel_variance,
                                lengthscale=self.kernel_lengthscale,
                                ARD=True)
        elif "kernel" in self.f_opts and "Matern" in self.f_opts["kernel"]:
            self.kernel = GPy.kern.Matern32(input_dim=self.D,
                                variance=self.kernel_variance,
                                lengthscale=self.kernel_lengthscale,
                                ARD=True)
        elif "kernel" in self.f_opts and "ExpSS" in self.f_opts["kernel"]:
            self.kernel = GPy.kern.StdPeriodic(input_dim=self.D,
                                    variance=self.kernel_variance,
                                    lengthscale=np.ones((self.D))*self.kernel_lengthscale,
                                    period=0.5,
                                    ARD2=True)
        elif "kernel" in self.f_opts and "Mixture" in self.f_opts["kernel"]:
            cat_dims = np.array(self.f_opts["cat_dims"])
            cont_dims = np.array(self.f_opts["cont_dims"])
            cat_dims += len(cat_dims) + len(cont_dims) if np.all(cat_dims < 0) else 0
            self.kernel = MixtureKernel(
                categorical_dims=cat_dims,
                continuous_dims=cont_dims,
            )
            self.kernel.continuous_kern.lengthscale = self.f_opts["continuous_kern_lengthscale"]
            self.kernel.categorical_kern.lengthscale = self.f_opts["categorical_kern_lengthscale"]
            self.kernel.lengthscale = self.f_opts["outputscale"]
            self.kernel.lamda = self.f_opts["lamda"]
        elif "kernel" in self.f_opts and self.f_opts["kernel"] == 'Categorical':
            cat_dims = np.array(self.f_opts["cat_dims"])
            self.kernel = ScaleKernel(TransformedCategorical(
                ard_num_dims=len(cat_dims)
            ))
            self.kernel.base_kernel.lengthscale = self.f_opts["lengthscale"]
        else:
            self.kernel = GPy.kern.RBF(input_dim=self.D,
                                variance=self.kernel_variance,
                                lengthscale=self.kernel_lengthscale,
                                ARD=True)

        if self.use_prior_mean_function:
            self.mf = GPy.core.Mapping(self.D, 1)
            self.mf.f = lambda X: np.mean(self.Y, axis=0)[0] if self.Y is not None else 0.0
            self.mf.update_gradients = lambda a, b: 0
            self.mf.gradients_X = lambda a, b: 0
        else:
            self.mf = None

        normalizer = False

        # this is only dummy data as GPy is not able to have empty training set
        # for prediction, the GP is not used for empty training set
        if self.n_init_samples > 0:
            X = self.initial_design.reshape(self.n_init_samples,self.D)
            Y = []
            for inid in self.initial_design:
                Y.append(self.f(inid.reshape(1,-1)))
            Y = np.array(Y).reshape(self.n_init_samples,1)
            self.X = X
            self.Y = Y
        else:
            self.X = self.Y = None
            X = np.zeros((1, self.D))
            Y = np.zeros((1, 1))
        self.gp_is_empty = True

        if isinstance(self.kernel, MixtureKernel):
            self.gp = SingleTaskGP(train_X=torch.from_numpy(X),
                                   train_Y=torch.from_numpy(Y).view(-1, 1),
                                   covar_module=self.kernel)
            self.gp.covar_module.continuous_kern.lengthscale = self.f_opts["continuous_kern_lengthscale"]
            self.gp.covar_module.categorical_kern.lengthscale = self.f_opts["categorical_kern_lengthscale"]
            self.gp.covar_module.lengthscale = self.f_opts["outputscale"]
            self.gp.covar_module.lamda = self.f_opts["lamda"]
            self.gp.mean_module.constant = self.f_opts["mean_constant"]
            self.gp.likelihood.noise = self.f_opts["likelihood_noise"]
        elif isinstance(self.kernel.base_kernel, TransformedCategorical):
            self.gp = SingleTaskGP(train_X=torch.from_numpy(X).to(float),
                                   train_Y=torch.from_numpy(Y),
                                   covar_module=self.kernel)
            self.gp.covar_module.base_kernel.lengthscale = self.f_opts['lengthscale']
            self.gp.likelihood.noise = self.f_opts['likelihood_noise']
            self.gp.mean_module.constant = self.f_opts['mean_constant']
        else:
            self.gp = GPy.models.gp_regression.GPRegression(X, Y,
                                                            noise_var=self.noise_variance,
                                                            kernel=self.kernel,
                                                            mean_function=self.mf,
                                                            normalizer=normalizer)
            self.gp.Gaussian_noise.variance = self.noise_variance
            self.gp.kern.lengthscale = self.kernel_lengthscale
            self.gp.kern.variance = self.kernel_variance