Choice Maps

Maps from the addresses of random choices to their values are stored in associative tree-structured data structures that have the following abstract type:

Gen.ChoiceMap — Type
abstract type ChoiceMap end

Abstract type for maps from hierarchical addresses to values.

source

Choice maps are constructed by users to express observations and/or constraints on the traces of generative functions. Choice maps are also returned by certain Gen inference methods, and are used internally by various Gen inference methods.

Choice maps provide the following methods:

Gen.has_value — Function
has_value(choices::ChoiceMap, addr)

Return true if there is a value at the given address.

source
Gen.get_value — Function
value = get_value(choices::ChoiceMap, addr)

Return the value at the given address in the assignment, or throw a KeyError if no value exists. A syntactic sugar is Base.getindex:

value = choices[addr]
source
Gen.has_submap — Function
has_submap(choices::ChoiceMap, addr)

Return true if there is a non-empty sub-assignment at the given address.

source
Gen.get_submap — Function
submap = get_submap(choices::ChoiceMap, addr)

Return the sub-assignment containing all choices whose address is prefixed by addr.

It is an error if the assignment contains a value at the given address. If there are no choices whose address is prefixed by addr then return an EmptyChoiceMap.

source
Gen.get_values_shallow — Function
key_submap_iterable = get_values_shallow(choices::ChoiceMap)

Return an iterator over tuples of the form (key, value) for each top-level key associated with a value.

source
Gen.get_submaps_shallow — Function
key_submap_iterable = get_submaps_shallow(choices::ChoiceMap)

Return an iterator over tuples of the form (key, submap::ChoiceMap) for each top-level key that has a non-empty sub-assignment.

source
Gen.to_array — Function
arr::Vector{T} = to_array(choices::ChoiceMap, ::Type{T}) where {T}

Populate an array with values of choices in the given assignment.

It is an error if each of the values cannot be coerced into a value of the given type.

Implementation

To support to_array, a concrete subtype T <: ChoiceMap should implement the following method:

n::Int = _fill_array!(choices::T, arr::Vector{V}, start_idx::Int) where {V}

Populate arr with values from the given assignment, starting at start_idx, and return the number of elements in arr that were populated.

source
Gen.from_array — Function
choices::ChoiceMap = from_array(proto_choices::ChoiceMap, arr::Vector)

Return an assignment with the same address structure as a prototype assignment, but with values read off from the given array.

The order in which addresses are populated is determined by the prototype assignment. It is an error if the number of choices in the prototype assignment is not equal to the length the array.

Implementation

To support from_array, a concrete subtype T <: ChoiceMap should implement the following method:

(n::Int, choices::T) = _from_array(proto_choices::T, arr::Vector{V}, start_idx::Int) where {V}

Return an assignment with the same address structure as a prototype assignment, but with values read off from arr, starting at position start_idx, and the number of elements read from arr.

source
Gen.get_selected — Function
selected_choices = get_selected(choices::ChoiceMap, selection::Selection)

Filter the choice map to include only choices in the given selection.

Returns a new choice map.

source

Note that none of these methods mutate the choice map.

Choice maps also implement:

  • Base.isempty, which tests of there are no random choices in the choice map

  • Base.merge, which takes two choice maps, and returns a new choice map containing all random choices in either choice map. It is an error if the choice maps both have values at the same address, or if one choice map has a value at an address that is the prefix of the address of a value in the other choice map.

  • ==, which tests if two choice maps have the same addresses and values at those addresses.

Gen.jl defines the following concrete types for choice maps:

Gen.choicemap — Function
choices = choicemap()

Construct an empty mutable choice map.

source
choices = choicemap(tuples...)

Construct a mutable choice map initialized with given address, value tuples.

source

A mutable choice map can be constructed with choicemap, and then populated:

choices = choicemap()
choices[:x] = true
choices["foo"] = 1.25
choices[:y => 1 => :z] = -6.3

There is also a constructor that takes initial (address, value) pairs:

choices = choicemap((:x, true), ("foo", 1.25), (:y => 1 => :z, -6.3))
Gen.set_value! — Function
set_value!(choices::DynamicChoiceMap, addr, value)

Set the given value for the given address.

Will cause any previous value or sub-assignment at this address to be deleted. It is an error if there is already a value present at some prefix of the given address.

The following syntactic sugar is provided:

choices[addr] = value
source
Gen.set_submap! — Function
set_submap!(choices::DynamicChoiceMap, addr, submap::ChoiceMap)

Replace the sub-assignment rooted at the given address with the given sub-assignment. Set the given value for the given address.

Will cause any previous value or sub-assignment at the given address to be deleted. It is an error if there is already a value present at some prefix of address.

source
Base.merge — Method
choices = Base.merge(choices1::ChoiceMap, choices2::ChoiceMap)

Merge two choice maps.

It is an error if the choice maps both have values at the same address, or if one choice map has a value at an address that is the prefix of the address of a value in the other choice map.

source
Base.isempty — Method
Base.isempty(choices::ChoiceMap)

Return true if there are no values in the assignment.

source
Gen.pair — Function
choices = pair(choices1::ChoiceMap, choices2::ChoiceMap, key1::Symbol, key2::Symbol)

Return an assignment that contains choices1 as a sub-assignment under key1 and choices2 as a sub-assignment under key2.

source
Gen.unpair — Function
(choices1, choices2) = unpair(choices::ChoiceMap, key1::Symbol, key2::Symbol)

Return the two sub-assignments at key1 and key2, one or both of which may be empty.

It is an error if there are any top-level values, or any non-empty top-level sub-assignments at keys other than key1 and key2.

source
Gen.ChoiceMapNestedView — Type

Wrapper for a ChoiceMap that provides nested-dict–like syntax, rather than the default syntax which looks like a flat dict of full keypaths.

julia> using Gen
julia> c = choicemap((:a, 1),
                     (:b => :c, 2));
julia> cv = nested_view(c);
julia> c[:a] == cv[:a]
true
julia> c[:b => :c] == cv[:b][:c]
true
julia> length(cv)
2
julia> length(cv[:b])
1
julia> sort(collect(keys(cv)))
[:a, :b]
julia> sort(collect(keys(cv[:b])))
[:c]
source