Ejemplo n.º 1
0
class gmix(object):

    def __init__(self, amps, funcs, limits=(d.min_x, d.max_x)):
        """
        Object to define a mixture probability distribution

        Parameters
        ----------
        amps: ndarray, float
            array with one relative amplitude per component
        funcs: list, chippr.gauss or chippr.discrete objects
            list of components
        limits: tuple or list or numpy.ndarray, float, optional
            minimum and maximum sample values to return
        """

        self.amps = amps/np.sum(amps)
        self.cumamps = np.cumsum(self.amps)
        self.n_comps = len(self.amps)

        self.funcs = funcs#[chippr.gauss(self.means[c], self.sigmas[c]**2) for c in range(self.n_comps)]
        # print('gmix before:')
        # for c in range(self.n_comps):
        #     print('gmix '+str((c, type(self.funcs[c]))))
        self.funcs = [func.dist for func in self.funcs]
        # print('gmix after:')
        # for c in range(self.n_comps):
        #     print('gmix '+str((c, type(self.funcs[c]))))

        self.dims = np.shape(np.array(limits).T)[0]
        self.min_x = limits[0]
        self.max_x = limits[1]
        # print("amps="+str(self.amps))
        self.dist = GMM(self.funcs, weights=self.amps)

    def pdf(self, xs):
        return self.evaluate(xs)

    def evaluate_one(self, x):
        """
        Function to evaluate Gaussian mixture
        once

        Parameters
        ----------
        x: float
            value at which to evaluate Gaussian mixture

        Returns
        -------
        p: float
            probability associated with x
        """
        # p = 0.
        # for c in range(self.n_comps):
        #     p += self.amps[c] * self.funcs[c].evaluate_one(x)
        p = self.dist.probability(x)
        return p

    def evaluate(self, xs):
        """
        Function to evaluate the Gaussian mixture probability distribution at many points

        Parameters
        ----------
        xs: ndarray, float
            values at which to evaluate Gaussian mixture probability distribution

        Returns
        -------
        ps: ndarray, float
            values of Gaussian mixture probability distribution at xs
        """
        # ps = np.zeros(len(xs))
        # for c in range(self.n_comps):
        #     ps += self.amps[c] * self.funcs[c].evaluate(xs)
        ps = self.dist.probability(xs)
        return ps

    def sample_one(self):
        """
        Function to sample a single value from Gaussian mixture probability distribution

        Returns
        -------
        x: float
            a single point sampled from the Gaussian mixture probability distribution
        """

        # x = -1. * np.ones(self.dims)
        # #don't do this every time!
        # min_x = self.min_x * np.ones(self.dims)
        # max_x = self.max_x * np.ones(self.dims)
        #
        # while np.any(np.less(x, min_x)) or np.any(np.greater(x, max_x)):
        #     r = np.random.uniform(0., self.cumamps[-1])
        #     c = 0
        #     for k in range(1, self.n_comps):
        #         if r > self.cumamps[k-1]:
        #             c = k
        #     x = self.funcs[c].sample_one()
        x = self.dist.sample(1)
        return x

    def sample(self, n_samps):
        """
        Function to take samples from Gaussian mixture probability distribution

        Parameters
        ----------
        n_samps: int
            number of samples to take

        Returns
        -------
        xs: ndarray, float
            array of points sampled from the Gaussian mixture probability distribution
        """
        # print('gmix trying to sample '+str(n_samps)+' from '+str(self.dist))
        # xs = np.array([self.sample_one() for n in range(n_samps)])
        # print(self.dist.to_json)
        xs = np.array(self.dist.sample(n_samps))
        # print('gmix sampled '+str(n_samps)+' from '+str(self.dist))
        return xs
Ejemplo n.º 2
0
class discrete(object):
    def __init__(self, bin_ends, weights):
        """
        Binned function class for any discrete function

        Parameters
        ----------
        bin_ends: numpy.ndarray, float
            endpoints of bins
        weights: numpy.ndarray, float
            relative weights associated with each bin

        Notes
        -----
        TO DO: Rename to piecewise constant or somesuch
        """
        self.bin_ends = bin_ends
        self.dbins = self.bin_ends[1:] - self.bin_ends[:-1]
        self.n_bins = len(self.bin_ends)-1
        self.bin_range = range(self.n_bins)

        self.weights = weights
        # print('dbins: '+str(self.dbins))
        # print('weights: '+str((self.weights)))
        # print('sumweights: '+str((np.sum(self.weights))))
        # print('dotweights: '+str((np.dot(self.weights, self.dbins))))
        self.normweights = np.cumsum(self.weights) / np.sum(self.weights)
        # print('normweights: '+str(self.normweights))
        self.distweights = np.cumsum(self.weights) / np.dot(self.weights, self.dbins)
        # print('distweights: '+str(self.distweights))

        self.funcs = [UD(self.bin_ends[i], self.bin_ends[i+1]) for i in self.bin_range]
        if self.n_bins > 1:
            self.dist = GMM(self.funcs, weights=self.weights)
        else:
            self.dist = self.funcs[0]

    def pdf(self, xs):
        return self.evaluate(xs)

    def evaluate_one(self, x):
        """
        Function to evaluate the discrete probability distribution at one point

        Parameters
        ----------
        x: float
            value at which to evaluate discrete probability distribution

        Returns
        -------
        p: float
            value of discrete probability distribution at x
        """
        p = self.dist.probability(x)
        return p

    def evaluate(self, xs):
        """
        Function to evaluate the discrete probability distribution at many points

        Parameters
        ----------
        xs: ndarray, float
            values at which to evaluate discrete probability distribution

        Returns
        -------
        ps: ndarray, float
            values of discrete probability distribution at xs
        """
        # ps = np.array([self.evaluate_one(x) for x in xs])
        ps = self.dist.probability(xs)
        return ps

    def sample_one(self):
        """
        Function to sample a single value from discrete probability distribution

        Returns
        -------
        x: float
            a single point sampled from the discrete probability distribution
        """
        # r = np.random.random()
        # k = bisect.bisect(self.normweights, r)
        #
        # x = np.random.uniform(low=self.bin_ends[k], high=self.bin_ends[k+1])
        x = self.dist.sample(1)
        return x

    def sample(self, n_samps):
        """
        Function to take samples from discrete probability distribution

        Parameters
        ----------
        n_samps: int
            number of samples to take

        Returns
        -------
        xs: ndarray, float
            array of points sampled from the discrete probability distribution
        """
        # print('discrete trying to sample '+str(n_samps)+' from '+str(self.dist))
        # xs = np.array([self.sample_one() for n in range(n_samps)])
        xs = np.array(self.dist.sample(n_samps))
        # print('discrete sampled '+str(n_samps)+' from '+str(self.dist))
        return xs