# Inference Library

## Importance Sampling

`Gen.importance_sampling`

— Function.```
(traces, log_norm_weights, lml_est) = importance_sampling(model::GenerativeFunction,
model_args::Tuple, observations::Assignment, num_samples::Int)
(traces, log_norm_weights, lml_est) = importance_sampling(model::GenerativeFunction,
model_args::Tuple, observations::Assignment,
proposal::GenerativeFunction, proposal_args::Tuple,
num_samples::Int)
```

Run importance sampling, returning a vector of traces with associated log weights.

The log-weights are normalized. Also return the estimate of the marginal likelihood of the observations (`lml_est`

). The observations are addresses that must be sampled by the model in the given model arguments. The first variant uses the internal proposal distribution of the model. The second variant uses a custom proposal distribution defined by the given generative function. All addresses of random choices sampled by the proposal should also be sampled by the model function.

`Gen.importance_resampling`

— Function.```
(trace, lml_est) = importance_resampling(model::GenerativeFunction,
model_args::Tuple, observations::Assignment, num_samples::Int)
(traces, lml_est) = importance_resampling(model::GenerativeFunction,
model_args::Tuple, observations::Assignment,
proposal::GenerativeFunction, proposal_args::Tuple,
num_samples::Int)
```

Run sampling importance resampling, returning a single trace.

Unlike `importance_sampling`

, the memory used constant in the number of samples.

## Markov Chain Monte Carlo

The following inference library methods take a trace and return a new trace.

`Gen.metropolis_hastings`

— Function.`(new_trace, accepted) = metropolis_hastings(trace, selection::AddressSet)`

Perform a Metropolis-Hastings update that proposes new values for the selected addresses from the internal proposal (often using ancestral sampling).

`(new_trace, accepted) = metropolis_hastings(trace, proposal::GenerativeFunction, proposal_args::Tuple)`

Perform a Metropolis-Hastings update that proposes new values for some subset of random choices in the given trace using the given proposal generative function.

The proposal generative function should take as its first argument the current trace of the model, and remaining arguments `proposal_args`

. If the proposal modifies addresses that determine the control flow in the model, values must be provided by the proposal for any addresses that are newly sampled by the model.

`(new_trace, accepted) = metropolis_hastings(trace, proposal::GenerativeFunction, proposal_args::Tuple, involution::Function)`

Perform a generalized Metropolis-Hastings update based on an involution (bijection that is its own inverse) on a space of assignments.

The `involution' Julia function has the following signature:

`(new_trace, bwd_assmt::Assignment, weight) = involution(trace, fwd_assmt::Assignment, fwd_ret, proposal_args::Tuple)`

The generative function `proposal`

is executed on arguments `(trace, proposal_args...)`

, producing an assignment `fwd_assmt`

and return value `fwd_ret`

. For each value of model arguments (contained in `trace`

) and `proposal_args`

, the `involution`

function applies an involution that maps the tuple `(get_assmt(trace), fwd_assmt)`

to the tuple `(get_assmt(new_trace), bwd_assmt)`

. Note that `fwd_ret`

is a deterministic function of `fwd_assmt`

and `proposal_args`

. When only discrete random choices are used, the `weight`

must be equal to `get_score(new_trace) - get_score(trace)`

.

**Including Continuous Random Choices** When continuous random choices are used, the `weight`

must include an additive term that is the determinant of the the Jacobian of the bijection on the continuous random choices that is obtained by currying the involution on the discrete random choices.

`Gen.mh`

— Function.```
(new_trace, accepted) = mh(trace, selection::AddressSet)
(new_trace, accepted) = mh(trace, proposal::GenerativeFunction, proposal_args::Tuple)
(new_trace, accepted) = mh(trace, proposal::GenerativeFunction, proposal_args::Tuple, involution::Function)
```

Alias for `metropolis_hastings`

. Perform a Metropolis-Hastings update on the given trace.

`Gen.mala`

— Function.`(new_trace, accepted) = mala(trace, selection::AddressSet, tau::Real)`

Apply a Metropolis-Adjusted Langevin Algorithm (MALA) update.

`Gen.hmc`

— Function.`(new_trace, accepted) = hmc(trace, selection::AddressSet, mass=0.1, L=10, eps=0.1)`

Apply a Hamiltonian Monte Carlo (HMC) update.

Neal, Radford M. "MCMC using Hamiltonian dynamics." Handbook of Markov Chain Monte Carlo 2.11 (2011): 2.

## Optimization over Random Choices

`Gen.map_optimize`

— Function.```
new_trace = map_optimize(trace, selection::AddressSet,
max_step_size=0.1, tau=0.5, min_step_size=1e-16, verbose=false)
```

Perform backtracking gradient ascent to optimize the log probability of the trace over selected continuous choices.

Selected random choices must have support on the entire real line.

## Particle Filtering

`Gen.initialize_particle_filter`

— Function.```
state = initialize_particle_filter(model::GenerativeFunction, model_args::Tuple,
observations::Assignment proposal::GenerativeFunction, proposal_args::Tuple,
num_particles::Int)
```

Initialize the state of a particle filter using a custom proposal for the initial latent state.

```
state = initialize_particle_filter(model::GenerativeFunction, model_args::Tuple,
observations::Assignment, num_particles::Int)
```

Initialize the state of a particle filter, using the default proposal for the initial latent state.

`Gen.particle_filter_step!`

— Function.```
particle_filter_step!(state::ParticleFilterState, new_args::Tuple, argdiff,
observations::Assignment, proposal::GenerativeFunction, proposal_args::Tuple)
```

Perform a particle filter update, where the model arguments are adjusted, new observations are added, and a custom proposal is used for new latent state.

```
particle_filter_step!(state::ParticleFilterState, new_args::Tuple, argdiff,
observations::Assignment)
```

Perform a particle filter update, where the model arguments are adjusted, new observations are added, and the default proposal is used for new latent state.

`Gen.maybe_resample!`

— Function.```
did_resample::Bool = maybe_resample!(state::ParticleFilterState;
ess_threshold::Float64=length(state.traces)/2, verbose=false)
```

Do a resampling step if the effective sample size is below the given threshold.

`Gen.log_ml_estimate`

— Function.`estimate = log_ml_estimate(state::ParticleFilterState)`

Return the particle filter's current estimate of the log marginal likelihood.

`Gen.get_traces`

— Function.`traces = get_traces(state::ParticleFilterState)`

Return the vector of traces in the current state, one for each particle.

`Gen.get_log_weights`

— Function.`log_weights = get_log_weights(state::ParticleFilterState)`

Return the vector of log weights for the current state, one for each particle.

The weights are not normalized, and are in log-space.

`Gen.sample_unweighted_traces`

— Function.`traces::Vector = sample_unweighted_traces(state::ParticleFilterState, num_samples::Int)`

Sample a vector of `num_samples`

traces from the weighted collection of traces in the given particle filter state.

## Supervised Training

`Gen.train!`

— Function.```
train!(gen_fn::GenerativeFunction, data_generator::Function,
update::ParamUpdate,
num_epoch, epoch_size, num_minibatch, minibatch_size; verbose::Bool=false)
```

Train the given generative function to maximize the expected conditional log probability (density) that `gen_fn`

generates the assignment `constraints`

given inputs, where the expectation is taken under the output distribution of `data_generator`

.

The function `data_generator`

is a function of no arguments that returns a tuple `(inputs, constraints)`

where `inputs`

is a `Tuple`

of inputs (arguments) to `gen_fn`

, and `constraints`

is an `Assignment`

. `conf`

configures the optimization algorithm used. `param_lists`

is a map from generative function to lists of its parameters. This is equivalent to minimizing the expected KL divergence from the conditional distribution `constraints | inputs`

of the data generator to the distribution represented by the generative function, where the expectation is taken under the marginal distribution on `inputs`

determined by the data generator.

## Variational Inference

`Gen.black_box_vi!`

— Function.```
black_box_vi!(model::GenerativeFunction, args::Tuple,
observations::Assignment,
proposal::GenerativeFunction, proposal_args::Tuple,
update::ParamUpdate;
iters=1000, samples_per_iter=100, verbose=false)
```

Fit the parameters of a generative function (`proposal`

) to the posterior distribution implied by the given model and observations using stochastic gradient methods.