Primitive Stochastic Procedure Interface: module venture.lite.psp

class venture.lite.psp.DeterministicMakerAAAPSP

Bases: venture.lite.psp.DeterministicPSP

Provides good default implementations of PSP methods for PSPs that are deterministic makers whose children can absorb at applications.

childrenCanAAA()
getAAALKernel()
class venture.lite.psp.DeterministicPSP

Bases: venture.lite.psp.PSP

Provides good default implementations of PSP methods for deterministic PSPs.

canAbsorb(_trace, _appNode, _parentNode)

Return whether this PSP, which is the operator of the given application node, can absorb a change to the value of the given parent node.

If this returns True, then logDensity must return a finite value for any proposed new value of the given parent node. canAbsorb calls are assumed to be cumulative: if a PSP claims to be able to absorb changes to two of its parents individually, that amounts to claiming to absorb changes to both of them simultaneously.

gradientOfLogDensity(_value, args)

Return the gradient of this PSP’s logDensity function. This method is needed only for gradient-based methods (currently Hamiltonian Monte Carlo and Meanfield).

The gradient should be returned as a 2-tuple of the partial derivative with respect to the value and a list of the partial derivatives with respect to the arguments.

isRandom()

Return whether this PSP is stochastic or not. This is important because only nodes whose operators are random PSPs can be principal.

logDensity(_value, _args)

Return the log-density of simulating the given value from the given args.

If the output space is discrete, return the log-probability.

Note: Venture does not ensure that the given value actually was simulated from the given args. The ability to measure the density of other values (or of the same value at other args) is invaluable for many inference methods.

Implementing this method is not strictly necessary for a valid PSP, but is very helpful for many purposes if the density information is available. See also canAbsorb.

logDensityBound(_value, _args)

Return an upper bound on the possible log density of this PSP holding the given values fixed. This method is needed only for rejection sampling.

Specifically, the value and any or all of the operands present in the IArgs instance may be None. Return an upper bound on the value the logDensity function could take for any values substituted for the None arguments, but holding fixed the given non-None arguments. See NormalOutputPSP for an example implementation.

This method is used only when this PSP is the operator of an absorbing node under rejection sampling. Tighter upper bounds lead to more efficient rejection sampling.

TODO maybe allow the logDensityBound to return None to indicate no bound, and in this case do not try to absorb at this node when doing rejection sampling? Or should that be a separate method called logDensityBounded?

class venture.lite.psp.DispatchingPSP(f_types, psps)

Bases: venture.lite.psp.PSP

canAbsorb(trace, appNode, parentNode)

Return whether this PSP, which is the operator of the given application node, can absorb a change to the value of the given parent node.

If this returns True, then logDensity must return a finite value for any proposed new value of the given parent node. canAbsorb calls are assumed to be cumulative: if a PSP claims to be able to absorb changes to two of its parents individually, that amounts to claiming to absorb changes to both of them simultaneously.

canEnumerate()

Return whether this PSP can enumerate the space of its possible return values. Enumeration is used only for principal nodes in enumerative Gibbs.

childrenCanAAA()
description(name)

Return a string describing this PSP. The string may include the name argument, which is the symbol that the enclosing SP is bound to.

description_rst_format(name)
enumerateValues(args)

Return a list of all the values this PSP can return given the arguments. Enumeration is used only for principal nodes in enumerative Gibbs.

For enumerative Gibbs to work, logDensity must return a finite number for the probability of every value returned from this method, given the same arguments.

getAAALKernel()
getDeltaKernel(args)
getVariationalLKernel(args)
gradientOfLogDensity(value, args)

Return the gradient of this PSP’s logDensity function. This method is needed only for gradient-based methods (currently Hamiltonian Monte Carlo and Meanfield).

The gradient should be returned as a 2-tuple of the partial derivative with respect to the value and a list of the partial derivatives with respect to the arguments.

gradientOfSimulate(args, value, direction)

Return the gradient of this PSP’s simulation function. This method is needed only for Hamiltonian Monte Carlo.

Specifically, the gradient of the simulation function must be with respect to the given direction on the output space, at the point given by the args struct (the input space is taken to be the full list of parents). In other words, the Jacobian-vector product

direction^T J_simulate(args).

For PSPs with one scalar output, the direction will be a number, and the correct answer is the gradient of simulate multiplied by that number.

The gradient should be returned as a list of the partial derivatives with respect to each parent node represented in the args.

We circumvent problems with trying to compute derivatives of stochastic functions by mixing over the randomness consumed. What this practically means is that the gradient to be computed is the gradient of the deterministic function of the arguments that is this process, if its randomness is fixed at some particular stream of bits. The gradient will, in general, depend on what those bits are. Pending a better interface for communicating it, the value argument of this method is the value that simulating this PSP outputs when using the fixed randomness with respect to which the gradient is to be computed. We hope that, for sufficiently simple PSPs, this proxy is sufficient.

The exact circumstances when this method is needed for HMC are this PSP appearing as the operator of a non-principal, non-absorbing scaffold node (that is, in the non-principal part of the DRG, or in the brush).

hasDeltaKernel()
hasSimulationKernel()
hasVariationalLKernel()
incorporate(value, args)

Register that an application of this PSP produced the given value at the given args. This is relevant only if the SP needs to maintain statistics about results of its applications (e.g., for collapsed models, or for external inference schemes that need to maintain statistics).

isRandom()

Return whether this PSP is stochastic or not. This is important because only nodes whose operators are random PSPs can be principal.

logDensity(value, args)

Return the log-density of simulating the given value from the given args.

If the output space is discrete, return the log-probability.

Note: Venture does not ensure that the given value actually was simulated from the given args. The ability to measure the density of other values (or of the same value at other args) is invaluable for many inference methods.

Implementing this method is not strictly necessary for a valid PSP, but is very helpful for many purposes if the density information is available. See also canAbsorb.

logDensityBound(value, args)

Return an upper bound on the possible log density of this PSP holding the given values fixed. This method is needed only for rejection sampling.

Specifically, the value and any or all of the operands present in the IArgs instance may be None. Return an upper bound on the value the logDensity function could take for any values substituted for the None arguments, but holding fixed the given non-None arguments. See NormalOutputPSP for an example implementation.

This method is used only when this PSP is the operator of an absorbing node under rejection sampling. Tighter upper bounds lead to more efficient rejection sampling.

TODO maybe allow the logDensityBound to return None to indicate no bound, and in this case do not try to absorb at this node when doing rejection sampling? Or should that be a separate method called logDensityBounded?

logDensityOfData(aux)

Return the log-density of simulating a dataset with the given collected statistics.

This is relevant only for PSPs that collect statistics about their uses via incorporate and unincorporate that are sufficient to bulk absorb at all applications of the PSP, without traversing them.

Specifically return the sum of the log-density at each application of this PSP; which is also the joint log-density of producing any one permutation of the observed output sequence. For some distributions (e.g., Poisson), this may not be computable from the traditional sufficient statisitc; in such a case, the sufficient statistic should be augmented with sufficient information to compute this. For rationales for this specification, see doc/on-log-density-of-counts.md.

simulate(args)

Simulate this process with the given parameters and return the result.

unincorporate(value, args)

Unregister one instance of an application of this PSP producing the given value at the given args. This is the inverse of incorporate.

class venture.lite.psp.ESRRefOutputPSP

Bases: venture.lite.psp.DeterministicPSP

canAbsorb(trace, appNode, parentNode)

Return whether this PSP, which is the operator of the given application node, can absorb a change to the value of the given parent node.

If this returns True, then logDensity must return a finite value for any proposed new value of the given parent node. canAbsorb calls are assumed to be cumulative: if a PSP claims to be able to absorb changes to two of its parents individually, that amounts to claiming to absorb changes to both of them simultaneously.

gradientOfLogDensity(_value, args)

Return the gradient of this PSP’s logDensity function. This method is needed only for gradient-based methods (currently Hamiltonian Monte Carlo and Meanfield).

The gradient should be returned as a 2-tuple of the partial derivative with respect to the value and a list of the partial derivatives with respect to the arguments.

gradientOfSimulate(args, _value, direction)

Return the gradient of this PSP’s simulation function. This method is needed only for Hamiltonian Monte Carlo.

Specifically, the gradient of the simulation function must be with respect to the given direction on the output space, at the point given by the args struct (the input space is taken to be the full list of parents). In other words, the Jacobian-vector product

direction^T J_simulate(args).

For PSPs with one scalar output, the direction will be a number, and the correct answer is the gradient of simulate multiplied by that number.

The gradient should be returned as a list of the partial derivatives with respect to each parent node represented in the args.

We circumvent problems with trying to compute derivatives of stochastic functions by mixing over the randomness consumed. What this practically means is that the gradient to be computed is the gradient of the deterministic function of the arguments that is this process, if its randomness is fixed at some particular stream of bits. The gradient will, in general, depend on what those bits are. Pending a better interface for communicating it, the value argument of this method is the value that simulating this PSP outputs when using the fixed randomness with respect to which the gradient is to be computed. We hope that, for sufficiently simple PSPs, this proxy is sufficient.

The exact circumstances when this method is needed for HMC are this PSP appearing as the operator of a non-principal, non-absorbing scaffold node (that is, in the non-principal part of the DRG, or in the brush).

simulate(args)

Simulate this process with the given parameters and return the result.

class venture.lite.psp.IArgs

Bases: object

The evaluation context against which a (P)SP is executed.

This class serves as a container for documentation about the evaluation context interface Lite (P)SPs expect.

env = None

The lexical environment of the application.

This is only used by SPs that need to access it, like the implementation of lambda, and get_current_environment.

esrNodes()

The identities of the evaluations of requests the request stage made, if any.

esrValues()

The results of evaluation of requests the request stage made, if any.

madeSPAux()

The made SP’s saved auxiliary state, if this is an AAA maker application.

node = None

The identity of the current application itself.

This is used mainly as a unique key to prevent auto-caching of requests that are supposed to be generative.

np_prng()

PRNG with Numpy’s RandomState interface that may be used.

Mutable reference.

operandNodes = None

The identities of the arguments passed to the PSP.

These are used primarily by parametrically polymorphic PSPs, like the RequestPSP in the implementation of lambda and the maker corresponding to mem.

operandValues()

The actual arguments this SP is called with.

py_prng()

PRNG with Python’s standard random.Random interface that may be used.

Mutable refence.

requestValue()

The request the requesting stage made, if any. Rarely used.

spaux()

The SP’s saved auxiliary state.

class venture.lite.psp.LikelihoodFreePSP

Bases: venture.lite.psp.RandomPSP

Provides good default implementations of (two) PSP methods for likelihood-free stochastic PSPs.

canAbsorb(_trace, _appNode, _parentNode)

Return whether this PSP, which is the operator of the given application node, can absorb a change to the value of the given parent node.

If this returns True, then logDensity must return a finite value for any proposed new value of the given parent node. canAbsorb calls are assumed to be cumulative: if a PSP claims to be able to absorb changes to two of its parents individually, that amounts to claiming to absorb changes to both of them simultaneously.

class venture.lite.psp.NullRequestPSP

Bases: venture.lite.psp.DeterministicPSP

canAbsorb(_trace, _appNode, _parentNode)

Return whether this PSP, which is the operator of the given application node, can absorb a change to the value of the given parent node.

If this returns True, then logDensity must return a finite value for any proposed new value of the given parent node. canAbsorb calls are assumed to be cumulative: if a PSP claims to be able to absorb changes to two of its parents individually, that amounts to claiming to absorb changes to both of them simultaneously.

gradientOfSimulate(args, _value, _direction)

Return the gradient of this PSP’s simulation function. This method is needed only for Hamiltonian Monte Carlo.

Specifically, the gradient of the simulation function must be with respect to the given direction on the output space, at the point given by the args struct (the input space is taken to be the full list of parents). In other words, the Jacobian-vector product

direction^T J_simulate(args).

For PSPs with one scalar output, the direction will be a number, and the correct answer is the gradient of simulate multiplied by that number.

The gradient should be returned as a list of the partial derivatives with respect to each parent node represented in the args.

We circumvent problems with trying to compute derivatives of stochastic functions by mixing over the randomness consumed. What this practically means is that the gradient to be computed is the gradient of the deterministic function of the arguments that is this process, if its randomness is fixed at some particular stream of bits. The gradient will, in general, depend on what those bits are. Pending a better interface for communicating it, the value argument of this method is the value that simulating this PSP outputs when using the fixed randomness with respect to which the gradient is to be computed. We hope that, for sufficiently simple PSPs, this proxy is sufficient.

The exact circumstances when this method is needed for HMC are this PSP appearing as the operator of a non-principal, non-absorbing scaffold node (that is, in the non-principal part of the DRG, or in the brush).

simulate(_args)

Simulate this process with the given parameters and return the result.

class venture.lite.psp.PSP

Bases: object

A Primitive Stochastic Procedure.

PSPs are the basic units of computation in Venture. A PSP represents a (potentially) stochastic process that computes a value conditioned on some arguments (A PSP may instead compute a set of requests for further evaluation by Venture – this is how compound Venture procedures are implemented – but this is an advanced topic).

The PSP interface is for people wishing to extend Venture with bindings to additional external computations (including traditional foreign functions, as well as things like a custom inference method for a particular model type). Users of Venture who do not wish to extend it need not learn the PSP interface.

The main part of the PSP interface is about providing information about the stochastic process the PSP represents – simulating from it, computing log densities, etc. Generally only the ability to simulate is required to define a valid PSP, but implementing the other methods may improve efficiency and/or permit the application of additional inference methods to scaffolds containing the PSP in question.

The PSP interface also currently contains several methods used for the selection of lkernels, pending the invention of a better mechanism. If you don’t know what lkernels are, don’t worry about it – the defaults will do.

The general pattern of PSP methods is that they accept an IArgs instance (and possibly some additional arguments) and compute something about the stochastic process in the context given by that IArgs instance. The main thing the IArgs object contains is the list of arguments this stochastic process is applied to, but it also has a bunch of additional contextual information that can be useful for special PSPs. See below for the definition of IArgs.

The data members of the IArgs object will generally be represented as Venture values (instances of the venture.lite.value.VentureValue class). The data returned from psp methods should generally also be instances of the VentureValue class, except methods that yield information for direct consumption by the engine itself (such as the isRandom method). See doc/type-system.md for the design.

Most of the time, the requisite marshalling between VentureValues and corresponding Python representations is mechanical boilerplate, which can be taken care of for you by the TypedPSP class, which see.

canAbsorb(_trace, _appNode, _parentNode)

Return whether this PSP, which is the operator of the given application node, can absorb a change to the value of the given parent node.

If this returns True, then logDensity must return a finite value for any proposed new value of the given parent node. canAbsorb calls are assumed to be cumulative: if a PSP claims to be able to absorb changes to two of its parents individually, that amounts to claiming to absorb changes to both of them simultaneously.

canEnumerate()

Return whether this PSP can enumerate the space of its possible return values. Enumeration is used only for principal nodes in enumerative Gibbs.

childrenCanAAA()
description(_name)

Return a string describing this PSP. The string may include the name argument, which is the symbol that the enclosing SP is bound to.

description_rst_format(_name)
enumerateValues(_args)

Return a list of all the values this PSP can return given the arguments. Enumeration is used only for principal nodes in enumerative Gibbs.

For enumerative Gibbs to work, logDensity must return a finite number for the probability of every value returned from this method, given the same arguments.

getAAALKernel()
getVariationalLKernel(args)
gradientOfLogDensity(_value, _args)

Return the gradient of this PSP’s logDensity function. This method is needed only for gradient-based methods (currently Hamiltonian Monte Carlo and Meanfield).

The gradient should be returned as a 2-tuple of the partial derivative with respect to the value and a list of the partial derivatives with respect to the arguments.

gradientOfLogDensityOfData(_aux, _args)

Return the gradient of the made PSP’s logDensityOfData function. This method is needed only for gradient-based methods and is relevant only for makers of PSPs that collect sufficient statistics via incorporate and unincorporate.

The gradient should be returned as a list of the partial derivatives with respect to the arguments.

gradientOfSimulate(_args, _value, _direction)

Return the gradient of this PSP’s simulation function. This method is needed only for Hamiltonian Monte Carlo.

Specifically, the gradient of the simulation function must be with respect to the given direction on the output space, at the point given by the args struct (the input space is taken to be the full list of parents). In other words, the Jacobian-vector product

direction^T J_simulate(args).

For PSPs with one scalar output, the direction will be a number, and the correct answer is the gradient of simulate multiplied by that number.

The gradient should be returned as a list of the partial derivatives with respect to each parent node represented in the args.

We circumvent problems with trying to compute derivatives of stochastic functions by mixing over the randomness consumed. What this practically means is that the gradient to be computed is the gradient of the deterministic function of the arguments that is this process, if its randomness is fixed at some particular stream of bits. The gradient will, in general, depend on what those bits are. Pending a better interface for communicating it, the value argument of this method is the value that simulating this PSP outputs when using the fixed randomness with respect to which the gradient is to be computed. We hope that, for sufficiently simple PSPs, this proxy is sufficient.

The exact circumstances when this method is needed for HMC are this PSP appearing as the operator of a non-principal, non-absorbing scaffold node (that is, in the non-principal part of the DRG, or in the brush).

hasDeltaKernel()
hasSimulationKernel()
hasVariationalLKernel()
incorporate(value, args)

Register that an application of this PSP produced the given value at the given args. This is relevant only if the SP needs to maintain statistics about results of its applications (e.g., for collapsed models, or for external inference schemes that need to maintain statistics).

isRandom()

Return whether this PSP is stochastic or not. This is important because only nodes whose operators are random PSPs can be principal.

logDensity(_value, _args)

Return the log-density of simulating the given value from the given args.

If the output space is discrete, return the log-probability.

Note: Venture does not ensure that the given value actually was simulated from the given args. The ability to measure the density of other values (or of the same value at other args) is invaluable for many inference methods.

Implementing this method is not strictly necessary for a valid PSP, but is very helpful for many purposes if the density information is available. See also canAbsorb.

logDensityBound(_value, _args)

Return an upper bound on the possible log density of this PSP holding the given values fixed. This method is needed only for rejection sampling.

Specifically, the value and any or all of the operands present in the IArgs instance may be None. Return an upper bound on the value the logDensity function could take for any values substituted for the None arguments, but holding fixed the given non-None arguments. See NormalOutputPSP for an example implementation.

This method is used only when this PSP is the operator of an absorbing node under rejection sampling. Tighter upper bounds lead to more efficient rejection sampling.

TODO maybe allow the logDensityBound to return None to indicate no bound, and in this case do not try to absorb at this node when doing rejection sampling? Or should that be a separate method called logDensityBounded?

logDensityOfData(_aux)

Return the log-density of simulating a dataset with the given collected statistics.

This is relevant only for PSPs that collect statistics about their uses via incorporate and unincorporate that are sufficient to bulk absorb at all applications of the PSP, without traversing them.

Specifically return the sum of the log-density at each application of this PSP; which is also the joint log-density of producing any one permutation of the observed output sequence. For some distributions (e.g., Poisson), this may not be computable from the traditional sufficient statisitc; in such a case, the sufficient statistic should be augmented with sufficient information to compute this. For rationales for this specification, see doc/on-log-density-of-counts.md.

madeSpLogDensityOfDataBound(_aux)

Upper bound the logDensityOfData the made SP may report for the given aux, up to arbitrary changes to the args wherewith the maker is simulated.

TODO Communicate the maker’s fixed parameters here to enable more precise bounds.

marginalLogDensityOfData(_aux, _args)

Return the marginal of the made PSP’s logDensityOfData function, integrating over the output distribution of the maker for the given args. This method is relevant only for random makers of PSPs that collect sufficient statistics via incorporate and unincorporate.

simulate(_args)

Simulate this process with the given parameters and return the result.

unincorporate(value, args)

Unregister one instance of an application of this PSP producing the given value at the given args. This is the inverse of incorporate.

class venture.lite.psp.RandomPSP

Bases: venture.lite.psp.PSP

Provides good default implementations of (two) PSP methods for (assessable) stochastic PSPs.

canAbsorb(_trace, _appNode, _parentNode)

Return whether this PSP, which is the operator of the given application node, can absorb a change to the value of the given parent node.

If this returns True, then logDensity must return a finite value for any proposed new value of the given parent node. canAbsorb calls are assumed to be cumulative: if a PSP claims to be able to absorb changes to two of its parents individually, that amounts to claiming to absorb changes to both of them simultaneously.

isRandom()

Return whether this PSP is stochastic or not. This is important because only nodes whose operators are random PSPs can be principal.

class venture.lite.psp.TypedLKernel(kernel, f_type)

Bases: venture.lite.lkernel.LKernel

forwardSimulate(trace, oldValue, args)

Compute a proposed new value.

In general, the proposal may depend on the old value (delta kernels).

forwardWeight(trace, newValue, oldValue, args)

The M-H acceptance term regen should include for this local proposal.

For general kernels that depend on the former value (“delta kernels”), this should be the full M-H term

Prior(oldValue) Kernel(newValue|oldValue)

and the reverseWeight should be 0 (since the reverse probability cannot be computed before the new value is available in this case).

Note that the likelihood is accounted for by later recursive calls to regen.

gradientOfReverseWeight(trace, value, args)
reverseWeight(trace, oldValue, args)

The M-H acceptance term detach should include for this local proposal.

For general kernels that depend on the former value, the reverse probability cannot be computed until a new value is simulated, and this method should return 0. This method exists to interface with simulation kernels, that _can_ profitably compute the reverse weight without access to the value that will be proposed.

weightBound(trace, value, args)
class venture.lite.psp.TypedPSP(psp, f_type)

Bases: venture.lite.psp.PSP

Wrapper that implements the PSP interface by marshalling and unmarshalling according to a type signature, delegating to an internal PSP.

The interface offered to the delegate of this class has all the same methods as the PSP interface, with all the same semantics, except that the values being operated upon and returned are native Python objects rather than Venture Values. TODO: Perhaps delegates of TypedPSP should not be subclasses of PSP, but of another base class named something like PythonPSP.

canAbsorb(trace, appNode, parentNode)

Return whether this PSP, which is the operator of the given application node, can absorb a change to the value of the given parent node.

If this returns True, then logDensity must return a finite value for any proposed new value of the given parent node. canAbsorb calls are assumed to be cumulative: if a PSP claims to be able to absorb changes to two of its parents individually, that amounts to claiming to absorb changes to both of them simultaneously.

canEnumerate()

Return whether this PSP can enumerate the space of its possible return values. Enumeration is used only for principal nodes in enumerative Gibbs.

childrenCanAAA()
description(name)

Return a string describing this PSP. The string may include the name argument, which is the symbol that the enclosing SP is bound to.

description_rst_format(name)
enumerateValues(args)

Return a list of all the values this PSP can return given the arguments. Enumeration is used only for principal nodes in enumerative Gibbs.

For enumerative Gibbs to work, logDensity must return a finite number for the probability of every value returned from this method, given the same arguments.

getAAALKernel()
getDeltaKernel(args)
getVariationalLKernel(args)
gradientOfLogDensity(value, args)

Return the gradient of this PSP’s logDensity function. This method is needed only for gradient-based methods (currently Hamiltonian Monte Carlo and Meanfield).

The gradient should be returned as a 2-tuple of the partial derivative with respect to the value and a list of the partial derivatives with respect to the arguments.

gradientOfSimulate(args, value, direction)

Return the gradient of this PSP’s simulation function. This method is needed only for Hamiltonian Monte Carlo.

Specifically, the gradient of the simulation function must be with respect to the given direction on the output space, at the point given by the args struct (the input space is taken to be the full list of parents). In other words, the Jacobian-vector product

direction^T J_simulate(args).

For PSPs with one scalar output, the direction will be a number, and the correct answer is the gradient of simulate multiplied by that number.

The gradient should be returned as a list of the partial derivatives with respect to each parent node represented in the args.

We circumvent problems with trying to compute derivatives of stochastic functions by mixing over the randomness consumed. What this practically means is that the gradient to be computed is the gradient of the deterministic function of the arguments that is this process, if its randomness is fixed at some particular stream of bits. The gradient will, in general, depend on what those bits are. Pending a better interface for communicating it, the value argument of this method is the value that simulating this PSP outputs when using the fixed randomness with respect to which the gradient is to be computed. We hope that, for sufficiently simple PSPs, this proxy is sufficient.

The exact circumstances when this method is needed for HMC are this PSP appearing as the operator of a non-principal, non-absorbing scaffold node (that is, in the non-principal part of the DRG, or in the brush).

hasDeltaKernel()
hasSimulationKernel()
hasVariationalLKernel()
incorporate(value, args)

Register that an application of this PSP produced the given value at the given args. This is relevant only if the SP needs to maintain statistics about results of its applications (e.g., for collapsed models, or for external inference schemes that need to maintain statistics).

isRandom()

Return whether this PSP is stochastic or not. This is important because only nodes whose operators are random PSPs can be principal.

logDensity(value, args)

Return the log-density of simulating the given value from the given args.

If the output space is discrete, return the log-probability.

Note: Venture does not ensure that the given value actually was simulated from the given args. The ability to measure the density of other values (or of the same value at other args) is invaluable for many inference methods.

Implementing this method is not strictly necessary for a valid PSP, but is very helpful for many purposes if the density information is available. See also canAbsorb.

logDensityBound(value, args)

Return an upper bound on the possible log density of this PSP holding the given values fixed. This method is needed only for rejection sampling.

Specifically, the value and any or all of the operands present in the IArgs instance may be None. Return an upper bound on the value the logDensity function could take for any values substituted for the None arguments, but holding fixed the given non-None arguments. See NormalOutputPSP for an example implementation.

This method is used only when this PSP is the operator of an absorbing node under rejection sampling. Tighter upper bounds lead to more efficient rejection sampling.

TODO maybe allow the logDensityBound to return None to indicate no bound, and in this case do not try to absorb at this node when doing rejection sampling? Or should that be a separate method called logDensityBounded?

logDensityOfData(aux)

Return the log-density of simulating a dataset with the given collected statistics.

This is relevant only for PSPs that collect statistics about their uses via incorporate and unincorporate that are sufficient to bulk absorb at all applications of the PSP, without traversing them.

Specifically return the sum of the log-density at each application of this PSP; which is also the joint log-density of producing any one permutation of the observed output sequence. For some distributions (e.g., Poisson), this may not be computable from the traditional sufficient statisitc; in such a case, the sufficient statistic should be augmented with sufficient information to compute this. For rationales for this specification, see doc/on-log-density-of-counts.md.

simulate(args)

Simulate this process with the given parameters and return the result.

unincorporate(value, args)

Unregister one instance of an application of this PSP producing the given value at the given args. This is the inverse of incorporate.

class venture.lite.psp.TypedVariationalLKernel(kernel, f_type)

Bases: venture.lite.psp.TypedLKernel

gradientOfLogDensity(value, args)
updateParameters(gradient, gain, stepSize)