Computes the expected change in mean and variance at the representer 
        points (cf. Section 2.4 in the paper). 
        
        
        :param x: candidate for which to compute the expected change in the GP
        :type x: np.array(1, input_dim)
        
        :return: innovation of mean (without samples) and variance at the representer points
        :rtype: (np.array(num_repr_points, 1), np.array(num_repr_points, num_repr_points))

def _innovations(self, x):
        """
        Computes the expected change in mean and variance at the representer 
        points (cf. Section 2.4 in the paper). 
        
        
        :param x: candidate for which to compute the expected change in the GP
        :type x: np.array(1, input_dim)
        
        :return: innovation of mean (without samples) and variance at the representer points
        :rtype: (np.array(num_repr_points, 1), np.array(num_repr_points, num_repr_points))
                    
        """
        
        
        '''
        The notation differs from the paper. The representer points
        play the role of x*, the test input x is X. The Omega term is applied
        in the calling function _compute_acq. Another difference is that we
        ignore the noise as in the original Matlab implementation:
        https://github.com/ProbabilisticNumerics/entropy-search/blob/master/matlab/GP_innovation_local.m
        '''
        
        # Get the standard deviation at x without noise
        _, stdev_x = self.model.predict(x, with_noise=False)

        # Compute the variance between the test point x and the representer points
        sigma_x_rep = self.model.get_covariance_between_points(self.repr_points, x)
        dm_rep = sigma_x_rep / stdev_x

        # Compute the deterministic innovation for the variance
        dv_rep = -dm_rep.dot(dm_rep.T)
        return dm_rep, dv_rep