Beispiel #1
0
    def initializeParticlesInsideBox(
        self,
        lfBoxLower,
        lfBoxUpper,
        random01=DREAM.RandomGenerator(sType="default")):
        '''
        Initialize the particle swarm state with randomized particles (determined by gen_random01) inside a box bounded by the
        parameters box_lower and box_upper. The i-th entry in these parameters respectively represent the lower and upper
        bounds on the particle position values for the i-th dimension. The parameter random01 controls the distribution of
        the particles.

        lfBoxLower : a one-dimensional NumPy array with lfBoxLower.shape[0] = self.getNumDimensions()
        lfBoxUpper : a one-dimensional NumPy array with lfBoxLower.shape[0] = self.getNumDimensions()
        random01   : a DREAM.RandomGenerator instance that produces floats in [0,1]
        '''
        iNumDims = self.getNumDimensions()
        if (lfBoxLower.shape != (iNumDims, )):
            raise InputError(
                "lfBoxLower",
                "lfBoxLower.shape should be (self.getNumDimensions(),)")
        if (lfBoxUpper.shape != (iNumDims, )):
            raise InputError(
                "lfBoxUpper",
                "lfBoxUpper.shape should be (self.getNumDimensions(),)")
        pLibDTSG.tsgParticleSwarmState_InitializeParticlesInsideBox(
            self.pStatePntr, as_ctypes(lfBoxLower), as_ctypes(lfBoxUpper),
            c_char_p(random01.sType), c_int(random01.iSeed),
            type_dream_random(random01.pCallable))
Beispiel #2
0
def genGaussianSamples(lfMean,
                       lfDeviation,
                       iNumSamples,
                       random01=RandomGenerator(sType="default")):
    '''
    Wrapper around TasDREAM::tsgGenGaussianSamples()

    Using the one dimensional numpy.ndarrays lfMean and lfVariance,
    which describe the mean and standard deviation of a Gaussian distribution,
    generate iNumSamples from a normal (Gaussian) distribution using
    the random01 engine.
    The lengths of lfMean and lfDeviation must match.

    Returns a two dimensional numpy.ndarray of shape = (iNumSamples, len(lfLower)),
    '''
    if len(lfMean) != len(lfDeviation):
        raise InputError("lfDeviation",
                         "The length of lfMean and lfDeviation do not match.")

    aMean = np.array(lfMean)
    aDeviation = np.array(lfDeviation)
    iNumDims = len(lfMean)

    aResult = np.empty((iNumDims * iNumSamples, ), np.float64)

    pLibDTSG.tsgGenGaussianSamples(iNumDims, iNumSamples,
                                   np.ctypeslib.as_ctypes(aMean),
                                   np.ctypeslib.as_ctypes(aDeviation),
                                   c_char_p(random01.sType), random01.iSeed,
                                   random01.pCallable,
                                   np.ctypeslib.as_ctypes(aResult))
    return aResult.reshape((iNumSamples, iNumDims))
Beispiel #3
0
def genUniformSamples(lfLower,
                      lfUpper,
                      iNumSamples,
                      random01=RandomGenerator(sType="default")):
    '''
    Wrapper around TasDREAM::genUniformSamples()

    Using the one dimensional numpy.ndarrays lfLower and lfUpper,
    which describe the upper and lower bounds of a hypercube,
    generate iNumSamples from a uniform distribution using
    the random01 engine.
    The lengths of lfLower and lfUpper must match.

    Returns a two dimensional numpy.ndarray of shape = (iNumSamples, len(lfLower)),
    '''
    if len(lfLower) != len(lfUpper):
        raise InputError("lfUpper",
                         "The length of lfLower and lfUpper do not match.")

    aLower = np.array(lfLower)
    aUpper = np.array(lfUpper)
    iNumDims = len(lfLower)

    aResult = np.empty((iNumDims * iNumSamples, ), np.float64)

    pLibDTSG.tsgGenUniformSamples(iNumDims, iNumSamples,
                                  np.ctypeslib.as_ctypes(aLower),
                                  np.ctypeslib.as_ctypes(aUpper),
                                  c_char_p(random01.sType), random01.iSeed,
                                  random01.pCallable,
                                  np.ctypeslib.as_ctypes(aResult))
    return aResult.reshape((iNumSamples, iNumDims))
Beispiel #4
0
    def __init__(self, sType, callableOrMagnitude=0.0):
        '''
        Constructor that translates the input arguments into inputs
        to the internal Tasmanian API.

        See help(Tasmanian.DREAM.IndependentUpdate)
        '''
        self.TasmanianDreamIndependentUpdate = True
        if not (
            (sys.version_info.major == 3 and isinstance(sType, str)) or
            (sys.version_info.major == 2 and isinstance(sType, basestring))):
            if not callable(sType):
                raise InputError(
                    "sType",
                    "DREAM.IndependentUpdate() the sType must be either a string or a callable object"
                )
            self.sType = "null"
            self.fMagnitude = 0.0
            self.pCallable = type_dream_iupdate(
                lambda n, x, err: iupdateWrapper(sType, n, x, err))
        else:
            self.sType = sType
            self.fMagnitude = callableOrMagnitude
            self.pCallable = type_dream_iupdate(lambda: 1)
        if (sys.version_info.major == 3):
            self.sType = bytes(self.sType, encoding='utf8')
Beispiel #5
0
    def __init__(self, sType, *args):
        '''
        Constructor that translates the input arguments into inputs
        to the internal Tasmanian API.

        See help(Tasmanian.DREAM.Domain)
        '''
        self.TasmanianDreamDomain = True
        if hasattr(sType, "TasmanianSparseGridObject"):
            self.pGrid = sType.pGrid
            self.pLower = None
            self.pUpper = None
            self.pCallable = type_dream_domain(lambda: 1)
        elif sType == "hypercube":
            self.pGrid = None
            self.pLower = np.ctypeslib.as_ctypes(args[0])
            self.pUpper = np.ctypeslib.as_ctypes(args[1])
            self.pCallable = type_dream_domain(lambda: 1)
        elif sType == "unbounded":
            self.pGrid = None
            self.pLower = None
            self.pUpper = None
            self.pCallable = type_dream_domain(
                lambda n, x: domainWrapper(lambda x: True, n, x))
        elif sType == "custom":
            self.pGrid = None
            self.pLower = None
            self.pUpper = None
            self.pCallable = type_dream_domain(
                lambda n, x: domainWrapper(args[0], n, x))
        else:
            raise InputError(
                "Domain", "DREAM.Domain() was given an unknown domain type")
    def setState(self, llfNewState):
        '''
        Set a new state for the DREAM chains.

        llfNewState: is a two dimensional numpy.ndarray with
            .shape[0] = .getNumChains()
            .shape[1] = .getNumDimensions()
        '''
        iNumChains = self.getNumChains()
        iNumDims = self.getNumDimensions()
        if (llfNewState.shape[0] != iNumChains):
            raise InputError("llfNewState", "llfNewState.shape[0] should match the number of chains")
        if (llfNewState.shape[1] != iNumDims):
            raise InputError("llfNewState", "llfNewState.shape[1] should match the number of dimensions")
        pLibDTSG.tsgDreamStateSet(self.pStatePntr,
                                  np.ctypeslib.as_ctypes(llfNewState.reshape((iNumChains * iNumDims,))))
Beispiel #7
0
    def __init__(self, model, likelihood, prior, typeForm=typeRegform):
        '''
        Constructor that translates the input arguments into inputs
        to the internal Tasmanian API.

        See help(Tasmanian.DREAM.Posterior)
        '''
        self.TasmanianPosterior = True

        self.typeForm = typeForm
        if self.typeForm not in [typeRegform, typeLogform]:
            raise InputError(
                "typeForm",
                "unknown sampling form, must use typeRegform or typeLogform")

        self.model = model
        if hasattr(self.model, "TasmanianSparseGridObject"):
            self.bUseSparsegrid = True
        elif callable(self.model):
            self.bUseSparsegrid = False
        else:
            raise InputError(
                "model",
                "model should be either an instance of Tasmanian.SparseGrid() or a callable object."
            )

        self.likelihood = likelihood
        if hasattr(self.likelihood, "TasmanianLikelihood"):
            self.bUseTasLikely = True
        elif callable(self.likelihood):
            self.bUseTasLikely = False
        else:
            raise InputError(
                "likelihood",
                "likelihood should be either derived from TasmanianLikelihood() or a callable object."
            )

        if prior == "uniform":
            self.typePrior = typePriorUniform
        elif callable(prior):
            self.typePrior = typePriorCallable
            self.prior = prior
        else:
            raise InputError(
                "prior",
                "prior should be either 'uniform' or a callable object.")
Beispiel #8
0
    def __init__(self, sType="default", iSeed=-1, callableRNG=lambda: 1):
        '''
        Constructor that translates the input arguments into inputs
        to the internal Tasmanian API.

        See help(Tasmanian.DREAM.RandomGenerator)
        '''
        if sType not in ["default", "minstd_rand"]:
            raise InputError("sType",
                             "DREAM.RandomGenerator() the sType is invalid")
        if not callable(callableRNG):
            raise InputError(
                "callableRNG",
                "DREAM.RandomGenerator() the callableRNG must be a callable object"
            )
        self.TasmanianDreamRandomGenerator = True
        self.sType = sType
        if (sys.version_info.major == 3):
            self.sType = bytes(self.sType, encoding='utf8')
        self.iSeed = iSeed
        self.pCallable = type_dream_random(callableRNG)
Beispiel #9
0
    def setParticleVelocities(self, llfNewPVelcs):
        '''
        Set new particle velocities from a NumPy array.

        llfNewPVelcs : a two-dimensional numpy.ndarray with
            llfNewPVelcs.shape[0] = self.getNumParticles()
            llfNewPVelcs.shape[1] = self.getNumDimensions()
        '''
        iNumPart = self.getNumParticles()
        iNumDims = self.getNumDimensions()
        if (llfNewPVelcs.shape[0] != iNumPart):
            raise InputError(
                "llfNewPVelcs",
                "llfNewPVelcs.shape[0] should match the number of particles")
        if (llfNewPVelcs.shape[1] != iNumDims):
            raise InputError(
                "llfNewPVelcs",
                "llfNewPVelcs.shape[1] should match the number of dimensions")
        llfNewPVelcs.resize((iNumDims * iNumPart, ))
        pLibDTSG.tsgParticleSwarmState_SetParticleVelocities(
            self.pStatePntr, as_ctypes(llfNewPVelcs))
Beispiel #10
0
    def setBestParticlePositions(self, llfNewBPPosns):
        '''
        Set new best particle positions from a NumPy array.

        llfNewBPPosns : a two-dimensional numpy.ndarray with
            llfNewPVelcs.shape[0] = self.getNumParticles() + 1
            llfNewPVelcs.shape[1] = self.getNumDimensions()
        '''
        iNumPart = self.getNumParticles()
        iNumDims = self.getNumDimensions()
        if (llfNewBPPosns.shape[0] != iNumPart + 1):
            raise InputError(
                "llfNewBPPosns",
                "llfNewBPPosns.shape[0] should match the number of particles + 1"
            )
        if (llfNewBPPosns.shape[1] != iNumDims):
            raise InputError(
                "llfNewBPPosns",
                "llfNewBPPosns.shape[1] should match the number of dimensions")
        llfNewBPPosns.resize(((iNumPart + 1) * iNumDims, ))
        pLibDTSG.tsgParticleSwarmState_SetBestParticlePositions(
            self.pStatePntr, as_ctypes(llfNewBPPosns))
    def __init__(self, lfVariance, lfData, iNumSamples=1):
        '''
        Make a new likelihood with the given data.

        lfVariance:  one dimensional ndarray with the data variance
        lfData:      one dimensional ndarray with the data
        iNumSamples: number of samples used for the data
        '''
        super(LikelihoodGaussAnisotropic, self).__init__()
        if (len(lfVariance) != len(lfData)):
            raise InputError("lfVariance",
                             "Mismatch in size of variance and data vectors.")
        iNumOutputs = len(lfData)
        self.pClassPntr = pLibDTSG.tsgMakeLikelihoodGaussAnisotropic(
            iNumOutputs, np.ctypeslib.as_ctypes(lfVariance),
            np.ctypeslib.as_ctypes(lfData), iNumSamples)
Beispiel #12
0
    def __init__(self, callableOrMagnitude):
        '''
        Constructor that translates the input arguments into inputs
        to the internal Tasmanian API.

        See help(Tasmanian.DREAM.DifferentialUpdate)
        '''
        self.TasmanianDreamDifferentialUpdate = True
        if (((sys.version_info.major == 3)
             and isinstance(callableOrMagnitude, int))
                or ((sys.version_info.major == 2)
                    and isinstance(callableOrMagnitude, (int, long)))):
            self.iPercent = callableOrMagnitude
            self.pCallable = type_dream_dupdate(lambda: 1)
        else:
            if not callable(callableOrMagnitude):
                raise InputError(
                    "callableOrMagnitude",
                    "DREAM.DifferentialUpdate() the callableOrMagnitude must be either an integer or a callable object"
                )
            self.iPercent = -1
            self.pCallable = type_dream_dupdate(callableOrMagnitude)
Beispiel #13
0
def Sample(iNumBurnup,
           iNumCollect,
           probability_distibution,
           domain_description,
           dream_state,
           independent_update=IndependentUpdate("none"),
           differential_update=DifferentialUpdate(100),
           random01=RandomGenerator(sType="default"),
           typeForm=typeRegform):
    '''
    Wrapper to TasDREAM::SampleDREAM().
    The Markov Chain Monte Carlo algorithms generate chains of samples
    with distribution that converges to the target probability density.
    The current state of the chains (i.e., the last vector) is updated by
    first generating a set of proposals and then accepting/rejecting randomly
    but with the constraint that the only accepted vectors belong to the
    specified domain. The proposals are constructed from two components,
    the independent component that is iid random with zero mean and
    the differential component that is takes from the scaled difference
    between the state of two randomly selected chains.

    iNumBurnup: is a non-negative integer that indicates the number of
                iterations to discard, i.e., samples that have no statistical
                significance because the chain state has not converged to
                the target probability distribution.
    iNumCollect: is a non-negative integer that indicates the number of
                iterations to store in the state history.

    probability_distibution: is either an instance of DREAM.Posterior() or
                a callable object that accepts a two dimensional numpy.ndarray
                and then returns a one dimensional numpy.ndarray.
                See help(Tasmanian.DREAM.Posterior)
                Can also use a lambda to capture a Tasmanian sparse grid, i.e.,
                lambda x : grid.evaluateBatch(x).reshape((x.shape[0],))

    domain_description: is an instance of DREAM.Domain()
                See help(Tasmanian.DREAM.Domain)

    dream_state: is an instance of DREAM.State() with number of dimensions
                that match the dimensions used by the probability_distibution.
                See help(Tasmanian.DREAM.State)
                On input the state chains have to be initialized, on output
                the history will be populated with the iNumCollect samples.
                (if the history is not empty, the new samples will be appended)

    independent_update: is an instance of DREAM.IndependentUpdate()
                See help(Tasmanian.DREAM.IndependentUpdate)

    differential_update: is an instance of DREAM.DifferentialUpdate()
                See help(Tasmanian.DREAM.DifferentialUpdate)

    random01: is an instance of DREAM.RandomGenerator()
                See help(Tasmanian.DREAM.RandomGenerator)

    typeForm: is either DREAM.typeRegform or DREAM.typeLogform
               The form modifies the accept/reject criteria based on whether
               the probability_distibution returns the actual distribution
               of interest or the logarithm of that (which is sometimes more
               stable and/or easier to approximate with a sparse grid).

    Note: the typeForm must match the return of the probability_distibution.
    '''
    if not hasattr(domain_description, "TasmanianDreamDomain"):
        raise InputError(
            "domain_description",
            "domain_description must be an instance of DREAM.Domain()")
    if not hasattr(dream_state, "TasmanainDreamState"):
        raise InputError("dream_state",
                         "dream_state must be an instance of DREAM.State()")
    if not hasattr(independent_update, "TasmanianDreamIndependentUpdate"):
        raise InputError(
            "independent_update",
            "independent_update must be an instance of DREAM.IndependentUpdate()"
        )
    if not hasattr(differential_update, "TasmanianDreamDifferentialUpdate"):
        raise InputError(
            "differential_update",
            "differential_update must be an instance of DREAM.DifferentialUpdate()"
        )
    if not hasattr(random01, "TasmanianDreamRandomGenerator"):
        raise InputError(
            "random01",
            "random01 must be an instance of DREAM.RandomGenerator()")
    if typeForm not in [typeRegform, typeLogform]:
        raise InputError(
            "typeForm",
            "unknown sampling form, must use typeRegform or typeLogform")

    pErrorCode = (c_int * 1)()

    if hasattr(probability_distibution, "TasmanianPosterior"):
        pLibDTSG.tsgDreamSample(
            typeForm, c_int(iNumBurnup), c_int(iNumCollect),
            type_dream_pdf(lambda m, n, x, y, err: pdfWrapper(
                probability_distibution.distribution(), m, n, x, y, err)),
            dream_state.pStatePntr, domain_description.pGrid,
            domain_description.pLower,
            domain_description.pUpper, domain_description.pCallable,
            c_char_p(independent_update.sType), independent_update.fMagnitude,
            independent_update.pCallable,
            differential_update.iPercent, differential_update.pCallable,
            c_char_p(random01.sType), random01.iSeed, random01.pCallable,
            pErrorCode)
    elif callable(probability_distibution):
        pLibDTSG.tsgDreamSample(
            typeForm, c_int(iNumBurnup), c_int(iNumCollect),
            type_dream_pdf(lambda m, n, x, y, err: pdfWrapper(
                probability_distibution, m, n, x, y, err)),
            dream_state.pStatePntr, domain_description.pGrid,
            domain_description.pLower,
            domain_description.pUpper, domain_description.pCallable,
            c_char_p(independent_update.sType), independent_update.fMagnitude,
            independent_update.pCallable,
            differential_update.iPercent, differential_update.pCallable,
            c_char_p(random01.sType), random01.iSeed, random01.pCallable,
            pErrorCode)
    else:
        raise InputError(
            "probability_distibution",
            "probability_distibution must be a callable object that takes a 2D numpy.ndarray and returns a 1D ndarray"
        )

    if pErrorCode[0] != 0:
        raise InputError("Sample",
                         "An error occurred during the call to Tasmanian.")