<commit_before>import numpy as np
import emcee
from robo.util.loss_functions import logLoss

from robo.acquisition.LogEI import LogEI
from robo.acquisition.Entropy import Entropy
from robo import BayesianOptimizationError

sq2 = np.sqrt(2)
l2p = np.log(2) + np.log(np.pi)
eps = np.finfo(np.float32).eps


class EntropyMC(Entropy):
    """
    The EntropyMC contains the asymptotically exact, sampling based variant of the entropy search acquisition function.

    :param model: A model should have following methods:

        - predict(X)
        - predict_variance(X1, X2)
    :param X_lower: Lower bounds for the search, its shape should be 1xD (D = dimension of search space)
    :type X_lower: np.ndarray (1,D)
    :param X_upper: Upper bounds for the search, its shape should be 1xD (D = dimension of search space)
    :type X_upper: np.ndarray (1,D)
    :param Nb: Number of representer points.
    :type Nb: int
    :param sampling_acquisition: A function to be used in calculating the density that representer points are to be sampled from. It uses
    :type samping_acquisition: AcquisitionFunction
    :param sampling_acquisition_kw: Additional keyword parameters to be passed to sampling_acquisition
    :type sampling_acquisition_kw: dict
    :param Np: Number of prediction points at X to calculate stochastic changes of the mean for the representer points 
    :type Np: int
    :param Nf: Number of functions to be sampled.
    :type Nf: int
    :param loss_function: The loss function to be used in the calculation of the entropy. If not specified it deafults to log loss (cf. loss_functions module).

    """
    def __init__(self, model, X_lower, X_upper, compute_incumbent, Nb=50, Nf=1000, sampling_acquisition=None, sampling_acquisition_kw={"par": 0.0}, Np=300, loss_function=None, **kwargs):
        self.model = model
        self.Nb = Nb
        self.Nf = Nf
        self.X_lower = np.array(X_lower)
        self.X_upper = np.array(X_upper)
        self.D = self.X_lower.shape[0]
        self.BestGuesses = np.zeros((0, X_lower.shape[0]))
        if sampling_acquisition is None:
            sampling_acquisition = LogEI
        self.sampling_acquisition = sampling_acquisition(model, self.X_lower, self.X_upper, compute_incumbent, **sampling_acquisition_kw)
        if loss_function is None:
            loss_function = logLoss
        self.loss_function = loss_function
        self.Np = Np

    def __call__(self, X, derivative=False, **kwargs):
        """
        :param X: The point at which the function is to be evaluated. Its shape is (1,D), where n is the dimension of the search space.
        :type X: np.ndarray (1, n)
        :param derivative: Controls whether the derivative is calculated and returned.
        :type derivative: Boolean
        :return: The expected difference of the loss function at X and optionally its derivative.
        :rtype: np.ndarray(1, 1) or (np.ndarray(1, 1), np.ndarray(1, D)).
        :raises BayesianOptimizationError: if X.shape[0] > 1. Only single X can be evaluated.
        """
        if derivative:
            raise BayesianOptimizationError(BayesianOptimizationError.NO_DERIVATIVE,
                                            "EntropyMC does not support derivative calculation until now")
        return self.dh_fun(X)

    def update(self, model):
        self.model = model
        self.sampling_acquisition.update(model)
        # TODO: Implement
        self.update_representer_points()
        # Omega values which are needed for the innovations
        self.W = np.random.randn(1, self.Np)
        self.Mb, self.Vb = self.model.predict(self.zb, full_cov=True)
        # Draw random number for the hallucinated values they have to be the same for each innovation
        self.F = np.random.multivariate_normal(mean=np.zeros(self.Nb), cov=np.eye(self.Nb), size=self.Nf)
        if np.any(np.isnan(self.Vb)):
            raise Exception(self.Vb)
        try:
            self.cVb = np.linalg.cholesky(self.Vb)<commit_msg>calling super constructor now to set sn2<commit_after>import numpy as np
import emcee
from robo.util.loss_functions import logLoss

from robo.acquisition.LogEI import LogEI
from robo.acquisition.Entropy import Entropy
from robo import BayesianOptimizationError

sq2 = np.sqrt(2)
l2p = np.log(2) + np.log(np.pi)
eps = np.finfo(np.float32).eps


class EntropyMC(Entropy):
    """
    The EntropyMC contains the asymptotically exact, sampling based variant of the entropy search acquisition function.

    :param model: A model should have following methods:

        - predict(X)
        - predict_variance(X1, X2)
    :param X_lower: Lower bounds for the search, its shape should be 1xD (D = dimension of search space)
    :type X_lower: np.ndarray (1,D)
    :param X_upper: Upper bounds for the search, its shape should be 1xD (D = dimension of search space)
    :type X_upper: np.ndarray (1,D)
    :param Nb: Number of representer points.
    :type Nb: int
    :param sampling_acquisition: A function to be used in calculating the density that representer points are to be sampled from. It uses
    :type samping_acquisition: AcquisitionFunction
    :param sampling_acquisition_kw: Additional keyword parameters to be passed to sampling_acquisition
    :type sampling_acquisition_kw: dict
    :param Np: Number of prediction points at X to calculate stochastic changes of the mean for the representer points 
    :type Np: int
    :param Nf: Number of functions to be sampled.
    :type Nf: int
    :param loss_function: The loss function to be used in the calculation of the entropy. If not specified it deafults to log loss (cf. loss_functions module).

    """
    def __init__(self, model, X_lower, X_upper, compute_incumbent, Nb=50, Nf=1000, sampling_acquisition=None, sampling_acquisition_kw={"par": 0.0}, Np=300, loss_function=None, **kwargs):
        super(EntropyMC, self).__init__(model, X_lower, X_upper, Nb, sampling_acquisition, sampling_acquisition_kw, Np, loss_function, **kwargs)
        self.Nf = Nf
        self.Np = Np

    def __call__(self, X, derivative=False, **kwargs):
        """
        :param X: The point at which the function is to be evaluated. Its shape is (1,D), where n is the dimension of the search space.
        :type X: np.ndarray (1, n)
        :param derivative: Controls whether the derivative is calculated and returned.
        :type derivative: Boolean
        :return: The expected difference of the loss function at X and optionally its derivative.
        :rtype: np.ndarray(1, 1) or (np.ndarray(1, 1), np.ndarray(1, D)).
        :raises BayesianOptimizationError: if X.shape[0] > 1. Only single X can be evaluated.
        """
        if derivative:
            raise BayesianOptimizationError(BayesianOptimizationError.NO_DERIVATIVE,
                                            "EntropyMC does not support derivative calculation until now")
        return self.dh_fun(X)

    def update(self, model):
        self.model = model
        self.sampling_acquisition.update(model)
        self.update_representer_points()
        # Omega values which are needed for the innovations
        #self.W = np.random.randn(1, self.Np)
        self.W = norm.ppf(np.linspace(1. / (self.Np + 1),
                                    1 - 1. / (self.Np + 1),
                                    self.Np))
        self.Mb, self.Vb = self.model.predict(self.zb, full_cov=True)
        # Draw random number for the hallucinated values they have to be the same for each innovation
        self.F = np.random.multivariate_normal(mean=np.zeros(self.Nb), cov=np.eye(self.Nb), size=self.Nf)
        if np.any(np.isnan(self.Vb)):
            raise Exception(self.Vb)
        try:
            self.cVb = np.linalg.cholesky(self.Vb)
{'fraction_non_alphanumeric': 0.0843000773395205, 'fraction_numerical': 0.009667440061871617, 'mean_word_length': 2.930597771023303, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 7, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5805551', 'n_tokens_mistral': 2418, 'n_tokens_neox': 2279, 'n_words': 789}