# Path: reggie/core/domains.py
# POSITIVE = 'positive'
# 
# Path: reggie/utils/misc.py
# def rstate(rng=None):
#     """
#     Return a RandomState object. This is just a simple wrapper such that if rng
#     is already an instance of RandomState it will be passed through, otherwise
#     it will create a RandomState object using rng as its seed.
#     """
#     if not isinstance(rng, np.random.RandomState):
#         rng = np.random.RandomState(rng)
#     return rng
# 
# Path: reggie/kernels/_core.py
# class RealKernel(Kernel):
#     """
#     Kernel defined over a real-valued input space.
#     """
#     def get_gradx(self, X1, X2=None):
#         """
#         Compute the gradient of the kernel k(x,y) with respect to the first
#         input x, and evaluate it on input points X1 and X2.
#         """
#         raise NotImplementedError
# 
# Path: reggie/kernels/_distances.py
# def rescale(ell, X1, X2=None):
#     """
#     Rescale the input data contained in X1 and X2 with lengthscales ell. Return
#     the tuple of rescaled data, or if X2 is None return (X1, None).
#     """
#     X1 = (X1 / ell)
#     X2 = (X2 / ell) if (X2 is not None) else None
#     return X1, X2
# 
# def dist(X1, X2=None, metric='sqeuclidean'):
#     """
#     Compute the pairwise distances between input data contained in X1 and X2
#     with some given metric (passed directly to scipy's cdist). If X2 is None
#     then compute the distances between X1 and itself.
#     """
#     X2 = X1 if (X2 is None) else X2
#     return ssd.cdist(X1, X2, metric)
# 
# def dist_foreach(X1, X2=None, metric='sqeuclidean'):
#     """
#     Return a generator which yields the pairwise distances between each
#     dimension of the data contained in X1 and X2.  If X2 is None then compute
#     the distances between X1 and itself.
#     """
#     X2 = X1 if (X2 is None) else X2
#     for i in xrange(X1.shape[1]):
#         yield ssd.cdist(X1[:, i, None], X2[:, i, None], metric)
# 
# def diff(X1, X2=None):
#     """
#     Compute the pairwise differences between input data contained in X1 and X2.
#     If X2 is None then compute the differences between X1 and itself.
#     """
#     X2 = X1 if (X2 is None) else X2
#     return X1[:, None, :] - X2[None, :, :]


import numpy as np
from ..core.domains import POSITIVE
from ..utils.misc import rstate
from ._core import RealKernel
from ._distances import rescale, dist, dist_foreach, diff
    """
    The squared-exponential kernel with lengthscales ell and signal variance
    rho. If ndim is None then this will be an ARD kernel over an input space
    whose dimensions are given by the size of ell; otherwise the kernel will be
    isotropic and ell must be a scalar.
    """
    def __init__(self, rho, ell, ndim=None):
        super(SE, self).__init__()

        # get the shape that ell should be
        shape = ('d',) if (ndim is None) else ()

        # register our parameters
        self._rho = self._register('rho', rho, POSITIVE)
        self._ell = self._register('ell', ell, POSITIVE, shape)

        # save flags for iso/ndim
        self._iso = ndim is not None
        self.ndim = ndim if self._iso else self._ell.size

    def __info__(self):
        info = []
        info.append(('rho', self._rho))
        info.append(('ell', self._ell))
        if self._iso:
            info.append(('ndim', self.ndim))
        return info

    def get_kernel(self, X1, X2=None):
        X1, X2 = rescale(self._ell, X1, X2)

# Path: reggie/core/domains.py
# POSITIVE = 'positive'
# 
# Path: reggie/utils/misc.py
# def rstate(rng=None):
#     """
#     Return a RandomState object. This is just a simple wrapper such that if rng
#     is already an instance of RandomState it will be passed through, otherwise
#     it will create a RandomState object using rng as its seed.
#     """
#     if not isinstance(rng, np.random.RandomState):
#         rng = np.random.RandomState(rng)
#     return rng
# 
# Path: reggie/kernels/_core.py
# class RealKernel(Kernel):
#     """
#     Kernel defined over a real-valued input space.
#     """
#     def get_gradx(self, X1, X2=None):
#         """
#         Compute the gradient of the kernel k(x,y) with respect to the first
#         input x, and evaluate it on input points X1 and X2.
#         """
#         raise NotImplementedError
# 
# Path: reggie/kernels/_distances.py
# def rescale(ell, X1, X2=None):
#     """
#     Rescale the input data contained in X1 and X2 with lengthscales ell. Return
#     the tuple of rescaled data, or if X2 is None return (X1, None).
#     """
#     X1 = (X1 / ell)
#     X2 = (X2 / ell) if (X2 is not None) else None
#     return X1, X2
# 
# def dist(X1, X2=None, metric='sqeuclidean'):
#     """
#     Compute the pairwise distances between input data contained in X1 and X2
#     with some given metric (passed directly to scipy's cdist). If X2 is None
#     then compute the distances between X1 and itself.
#     """
#     X2 = X1 if (X2 is None) else X2
#     return ssd.cdist(X1, X2, metric)
# 
# def dist_foreach(X1, X2=None, metric='sqeuclidean'):
#     """
#     Return a generator which yields the pairwise distances between each
#     dimension of the data contained in X1 and X2.  If X2 is None then compute
#     the distances between X1 and itself.
#     """
#     X2 = X1 if (X2 is None) else X2
#     for i in xrange(X1.shape[1]):
#         yield ssd.cdist(X1[:, i, None], X2[:, i, None], metric)
# 
# def diff(X1, X2=None):
#     """
#     Compute the pairwise differences between input data contained in X1 and X2.
#     If X2 is None then compute the differences between X1 and itself.
#     """
#     X2 = X1 if (X2 is None) else X2
#     return X1[:, None, :] - X2[None, :, :]


# Path: reggie/kernels/se.py
import numpy as np
from ..core.domains import POSITIVE
from ..utils.misc import rstate
from ._core import RealKernel
from ._distances import rescale, dist, dist_foreach, diff

    """
    The squared-exponential kernel with lengthscales ell and signal variance
    rho. If ndim is None then this will be an ARD kernel over an input space
    whose dimensions are given by the size of ell; otherwise the kernel will be
    isotropic and ell must be a scalar.
    """
    def __init__(self, rho, ell, ndim=None):
        super(SE, self).__init__()

        # get the shape that ell should be
        shape = ('d',) if (ndim is None) else ()

        # register our parameters
        self._rho = self._register('rho', rho, POSITIVE)
        self._ell = self._register('ell', ell, POSITIVE, shape)

        # save flags for iso/ndim
        self._iso = ndim is not None
        self.ndim = ndim if self._iso else self._ell.size

    def __info__(self):
        info = []
        info.append(('rho', self._rho))
        info.append(('ell', self._ell))
        if self._iso:
            info.append(('ndim', self.ndim))
        return info

    def get_kernel(self, X1, X2=None):
        X1, X2 = rescale(self._ell, X1, X2)

        D = dist(X1, X2)