Developers guide

This page is aimed at developers of inference backends who aim to integrate GraphPPL into their packages. GraphPPL uses the MetaGraphsNext package to represent a factor graph model as a graph. In GraphPPL, both variables and factors are represented by nodes, and the edges denote the inclusion of variables in factors.

Model Creation

A model in GraphPPL is represented by the GraphPPL.Model structure.

GraphPPL.ModelType
Model(graph::MetaGraph)

A structure representing a probabilistic graphical model. It contains a MetaGraph object representing the factor graph and a Base.RefValue{Int64} object to keep track of the number of nodes in the graph.

Fields:

  • graph: A MetaGraph object representing the factor graph.
  • plugins: A PluginsCollection object representing the plugins enabled in the model.
  • backend: A Backend object representing the backend used in the model.
  • counter: A Base.RefValue{Int64} object keeping track of the number of nodes in the graph.
source

Any model is a bipartite graph of variable and factor nodes, with edges denoting which variables are used in which factors. Models can be indexed with GraphPPL.NodeLabel structures, which is a unique identifier of every variable and factor node composed of its name and a global counter. Every GraphPPL.NodeLabel points to a GraphPPL.NodeData, which contains all relevant information to do Bethe Free Energy minimization in the factor graph. Edges in the graph can be accessed by querying the model with a NodeLabel pair of an edge that exists. Note that both variable and factor nodes are represented by GraphPPL.NodeData structures. To retrieve whether or not a node is a variable or a factor, we can use the is_variable and is_factor functions:

Contexts, Submodels and retrieving NodeLabels

After creating a GraphPPL.Model structure, it is important to know about the attached Context. The Context structure contains all variable and factor nodes in the scope of the model, and contains a Context stucture for all submodels. The context of a model can be accessed by the GraphPPL.getcontext() function:

GraphPPL.getcontextFunction
getcontext(model::Model)

Retrieves the context of a model. The context of a model contains the complete hierarchy of variables and factor nodes. Additionally, contains all child submodels and their respective contexts. The Context supplies a mapping from symbols to GraphPPL.NodeLabel structures with which the model can be queried.

source

Contexts can be accessed like dictionaries, and will point to NodeLabel structures that can be used to query the graph. As a variable with the same name can also live in submodels, we nest the Context structures in the same hierarchy as the submodels themselves. Variables can be retrieved from the Context using a Symbol, whereas factors and submodels can be retrieved with their type and index. For example, to access the first Normal factor in the context, we can use the following syntax:

context[Normal, 1]
Distributions.Normal_6

Because on any level, submodels are treated as factors, we can also access submodels in the same way. For example, to access the Normal factor in the first submodel, we can use the following syntax:

context[submodel_name, 1][Normal, 1]

Variable Creation

Variables in the graph can be created by the GraphPPL.getorcreate! function, that takes the model, the context, the name and the index of the variable, as well as node creation options (such as additional information that should be saved in nodes).

GraphPPL.getorcreate!Function
getorcreate!(model::Model, context::Context, options::NodeCreationOptions, name, index)

Get or create a variable (name) from a factor graph model and context, using an index if provided.

This function searches for a variable (name) in the factor graph model and context specified by the arguments model and context. If the variable exists, it returns it. Otherwise, it creates a new variable and returns it.

Arguments

  • model::Model: The factor graph model to search for or create the variable in.
  • context::Context: The context to search for or create the variable in.
  • options::NodeCreationOptions: Options for creating the variable. Must be a NodeCreationOptions object.
  • name: The variable (name) to search for or create. Must be a symbol.
  • index: Optional index for the variable. Can be an integer, a collection of integers, or nothing. If the index is nothing creates a single variable.

If the index is an integer creates a vector-like variable. If the index is a collection of integers creates a tensor-like variable.

Returns

The variable (name) found or created in the factor graph model and context.

source

Model macro

The GraphPPL.jl does not export the @model macro by default. For interactive usages (e.g. testing or plotting) GraphPPL.jl implements GraphPPL.DefaultBackend, but any downstream packages must define their own @model macro and implement their custom backend.

import GraphPPL: @model

Piecing everying together

In this section we will create a factor graph from scratch, materializing the underlying factor graph and applying constraints. First, let's define a model, we'll use the gcv model from the Nested Models section:

using GraphPPL, Distributions

@model function gcv(κ, ω, z, x, y)
    log_σ := κ * z + ω
    σ := exp(log_σ)
    y ~ Normal(x, σ)
end

Let's also define a mean-field constraint around the Normal node:

constraints = @constraints begin
    q(x, y, σ) = q(x)q(y)q(σ)
end
Constraints: 
  q(x, y, σ) = q(x)q(y)q(σ)

This defines the gcv submodel, but now we have to materialize this model. Let's greate a model and hook up all interfaces to variables that will later have to be supplied by the user.

GraphPPL.create_modelFunction
create_model([callback], generator::ModelGenerator)

Create a model from the ModelGenerator. Accepts an optional callback that can be used to inject extra keyword arguments into the model creation process by downstream packages. For example:

using GraphPPL, Distributions

GraphPPL.@model function beta_bernoulli(y, a, b)
    θ ~ Beta(a, b)
    for i in eachindex(y)
        y[i] ~ Bernoulli(θ)
    end
end

data_y = rand(Bernoulli(0.5), 100)

model = GraphPPL.create_model(beta_bernoulli(a = 1, b = 1)) do model, ctx 
    # Inject the data into the model
    y = GraphPPL.getorcreate!(model, ctx, GraphPPL.NodeCreationOptions(kind = :data), :y, GraphPPL.LazyIndex(data_y))
    return (; y = y, )
end

model isa GraphPPL.Model
# output
true
source
model = GraphPPL.create_model(GraphPPL.with_plugins(gcv(), GraphPPL.PluginsCollection(GraphPPL.VariationalConstraintsPlugin(constraints)))) do model, context
    return (;
        κ = GraphPPL.getorcreate!(model, context, GraphPPL.NodeCreationOptions(kind = :data, factorized = true), :κ, nothing),
        ω = GraphPPL.getorcreate!(model, context, GraphPPL.NodeCreationOptions(kind = :data, factorized = true), :ω, nothing),
        z = GraphPPL.getorcreate!(model, context, GraphPPL.NodeCreationOptions(kind = :data, factorized = true), :z, nothing),
        x = GraphPPL.getorcreate!(model, context, GraphPPL.NodeCreationOptions(kind = :data, factorized = true), :x, nothing),
        y = GraphPPL.getorcreate!(model, context, GraphPPL.NodeCreationOptions(kind = :data, factorized = true), :y, nothing)
    )
end;
GraphPPL.Model{MetaGraphsNext.MetaGraph{Int64, Graphs.SimpleGraphs.SimpleGraph{Int64}, GraphPPL.NodeLabel, GraphPPL.NodeData, GraphPPL.EdgeLabel, GraphPPL.Context, MetaGraphsNext.var"#4#8", Float64}, GraphPPL.PluginsCollection{Tuple{GraphPPL.VariationalConstraintsPlugin{GraphPPL.Constraints{Vector{GraphPPL.FactorizationConstraint}, Vector{GraphPPL.MarginalFormConstraint}, Vector{GraphPPL.MessageFormConstraint}, Dict{Function, GraphPPL.GeneralSubModelConstraints}, Dict{GraphPPL.FactorID, GraphPPL.SpecificSubModelConstraints}}}}}, GraphPPL.DefaultBackend}(Meta graph based on a Graphs.SimpleGraphs.SimpleGraph{Int64} with vertex labels of type GraphPPL.NodeLabel, vertex metadata of type GraphPPL.NodeData, edge metadata of type GraphPPL.EdgeLabel, graph metadata given by GraphPPL.Context(0, Main.var"Main".gcv, "", nothing, {Distributions.Normal = 1, + = 1, exp = 1}, {}, {(exp, 1) = exp_10, (+, 1) = +_8, (Distributions.Normal, 1) = Distributions.Normal_11}, {:σ = σ_9, :anonymous_var_graphppl = anonymous_var_graphppl_7, :y = y_5, :κ = κ_1, :ω = ω_2, :log_σ = log_σ_6, :z = z_3, :x = x_4}, {}, {}, {}, Base.RefValue{Any}(y_5)), and default weight 1.0, GraphPPL.PluginsCollection{Tuple{GraphPPL.VariationalConstraintsPlugin{GraphPPL.Constraints{Vector{GraphPPL.FactorizationConstraint}, Vector{GraphPPL.MarginalFormConstraint}, Vector{GraphPPL.MessageFormConstraint}, Dict{Function, GraphPPL.GeneralSubModelConstraints}, Dict{GraphPPL.FactorID, GraphPPL.SpecificSubModelConstraints}}}}}((GraphPPL.VariationalConstraintsPlugin{GraphPPL.Constraints{Vector{GraphPPL.FactorizationConstraint}, Vector{GraphPPL.MarginalFormConstraint}, Vector{GraphPPL.MessageFormConstraint}, Dict{Function, GraphPPL.GeneralSubModelConstraints}, Dict{GraphPPL.FactorID, GraphPPL.SpecificSubModelConstraints}}}(Constraints: 
  q(x, y, σ) = q(x)q(y)q(σ)
),)), GraphPPL.DefaultBackend(), Base.RefValue{Int64}(11))

Now we have a fully materialized model that can be passed to an inference engine. Factorization constraints are saved in two ways: as a tuple of lists of indices of interfaces that represent the individual clusters (e.g. ([1], [2, 3])) and as a BoundedBitSetTuple. The BoundedBitSetTuple is a more efficient way to store the factorization constraints, which stores a BitMatrix under the hood representing the factorization clusters. Both can be accessed by the GraphPPL.getextra function:

context = GraphPPL.getcontext(model)
node = context[Normal, 1]
@show GraphPPL.getextra(model[node], :factorization_constraint_indices)
@show GraphPPL.getextra(model[node], :factorization_constraint_bitset)
GraphPPL.getextra(model[node], :factorization_constraint_indices) = ([1], [2], [3])
GraphPPL.getextra(model[node], :factorization_constraint_bitset) = BitSetTuples.BoundedBitSetTuple(Bool[1 0 0; 0 1 0; 0 0 1])

ResizableArrays

GraphPPL uses ResizableArrays to store arrays of random variables. A ResizableArray is a mutable array that can grow dynamically when data is assigned to it. This is why the x[i] ~ Normal(0, 1) syntax is allowed in GraphPPL; the ResizableArray x will check if i is a valid index and grow the array if necessary.

GraphPPL.ResizableArrayType
ResizableArray{T, V, N} <: AbstractArray{T, N}

A ResizableArray is an array that can grow in any dimension. It handles like a regular AbstractArray when calling getindex, but for setindex! it will automatically resize the array if the index is out of bounds. It is also possible to iterate over the array in the same way as for a regular array. The data is stored internally as a recursive vector. The depth of the recursion is fixed at construction time and cannot be changed.

Constructor

  • ResizableArray(::Type{T}): Create an empty resizable array of type T with depth 1, similar to a vector.
  • ResizableArray(::Type{T}, ::Val{N}): Create an empty resizable array of type T with depth N, similar to AbstractArray{T, N}.
source

ResizableArray is a subtype of AbstractArray, and implements all the functions that are expected from an array. Note that size returns the largest size of the array across each dimension, so an array of size (2, 3) does not necessarily has to have an element stored at index (2, 3), instead there exists a vector of length 3 along the second dimension.

Model creation engine internal

GraphPPL.ContextType
Context

Contains all information about a submodel in a probabilistic graphical model.

source
GraphPPL.ModelGeneratorType
ModelGenerator(model, kwargs, plugins)

The ModelGenerator structure is used to lazily create the model with the given model and kwargs and plugins.

source
GraphPPL.FactorIDType
FactorID(fform, index)

A unique identifier for a factor node in a probabilistic graphical model.

source
GraphPPL.NodeDataType
NodeData(context, properties, plugins)

Data associated with a node in a probabilistic graphical model. The context field stores the context of the node. The properties field stores the properties of the node. The plugins field stores additional properties of the node depending on which plugins were enabled.

source
GraphPPL.NodeLabelType
NodeLabel(name, global_counter::Int64)

Unique identifier for a node (factor or variable) in a probabilistic graphical model.

source
GraphPPL.EdgeLabelType
EdgeLabel(symbol, index)

A unique identifier for an edge in a probabilistic graphical model.

source
GraphPPL.ProxyLabelType
ProxyLabel(name, index, proxied)

A label that proxies another label in a probabilistic graphical model.

source
GraphPPL.LazyIndexType

LazyIndex is used to track the usage of a variable in the model without explicitly specifying its dimensions. getorcreate! function will return a LazyNodeLabel which will materialize itself upon first usage with the correct dimensions. E.g. y[1] will materialize vector variable y and y[1, 1] will materialize tensor variable y. Optionally the LazyIndex can be associated with a collection, in which case it not only redirects most of the common collection methods to the underlying collection, but also checks that the dimensions and usage match of such labels in the model specification is correct.

source
GraphPPL.VarDictType
VarDict

A recursive dictionary structure that contains all variables in a probabilistic graphical model. Iterates over all variables in the model and their children in a linear fashion, but preserves the recursive nature of the actual model.

source
GraphPPL.AnonymousVariableType
AnonymousVariable(model, context)

Defines a lazy structure for anonymous variables. The actual anonymous variables materialize only in make_node! upon calling, because it needs arguments to the make_node! in order to create proper links.

source
GraphPPL.DeterministicType
Deterministic

Deterministic object used to parametrize factor node object with determinstic type of relationship between variables.

source
GraphPPL.StochasticType
Stochastic

Stochastic object used to parametrize factor node object with stochastic type of relationship between variables.

source
GraphPPL.AtomicType
Atomic

Atomic object used as a trait of structs and functions that are composed of a single node and are therefore materialized as a single node in the factor graph.

source
GraphPPL.CompositeType
Composite

Composite object used as a trait of structs and functions that are composed of multiple nodes and therefore implement make_node!.

source
GraphPPL.NodeCreationOptionsType
NodeCreationOptions(namedtuple)

Options for creating a node in a probabilistic graphical model. These are typically coming from the where {} block in the @model macro, but can also be created manually. Expects a NamedTuple as an input.

source
GraphPPL.variable_nodesFunction

A version variable_nodes(model) that uses a callback function to process the variable nodes. The callback function accepts both the label and the node data.

source
GraphPPL.factor_nodesFunction

A version factor_nodes(model) that uses a callback function to process the factor nodes. The callback function accepts both the label and the node data.

source
GraphPPL.missing_interfacesFunction
missing_interfaces(node_type, val, known_interfaces)

Returns the interfaces that are missing for a node. This is used when inferring the interfaces for a node that is composite.

Arguments

  • node_type: The type of the node as a Function object.
  • val: The value of the amount of interfaces the node is supposed to have. This is a Static.StaticInt object.
  • known_interfaces: The known interfaces for the node.

Returns

  • missing_interfaces: A Vector of the missing interfaces.
source
GraphPPL.hasextraFunction
hasextra(node::NodeData, key::Symbol)

Checks if NodeData has an extra property with the given key.

source
GraphPPL.getextraFunction
getextra(node::NodeData, key::Symbol, [ default ])

Returns the extra property with the given key. Optionally, if the property does not exist, returns the default value.

source
GraphPPL.setextra!Function
setextra!(node::NodeData, key::Symbol, value)

Sets the extra property with the given key to the given value.

source
GraphPPL.make_node!Function
make_node!

Make a new factor node in the Model and specified Context, attach it to the specified interfaces, and return the interface that is on the lhs of the ~ operator.

Arguments

  • model::Model: The model to add the node to.
  • ctx::Context: The context in which to add the node.
  • fform: The function that the node represents.
  • lhs_interface: The interface that is on the lhs of the ~ operator.
  • rhs_interfaces: The interfaces that are the arguments of fform on the rhs of the ~ operator.
  • __parent_options__::NamedTuple = nothing: The options to attach to the node.
  • __debug__::Bool = false: Whether to attach debug information to the factor node.
source
GraphPPL.add_atomic_factor_node!Function
add_atomic_factor_node!(model::Model, context::Context, options::NodeCreationOptions, fform)

Add an atomic factor node to the model with the given name. The function generates a new symbol for the node and adds it to the model with the generated symbol as the key and a FactorNodeData struct.

Args: - model::Model: The model to which the node is added. - context::Context: The context to which the symbol is added. - options::NodeCreationOptions: The options for the creation process. - fform::Any: The functional form of the node.

Returns: - The generated label for the node.

source
GraphPPL.add_toplevel_model!Function

Add the fform as the toplevel model to the model and context with the specified interfaces. Calls the postprocess logic for the attached plugins of the model. Should be called only once for a given Model object.

source
GraphPPL.add_variable_node!Function
add_variable_node!(model::Model, context::Context, options::NodeCreationOptions, name::Symbol, index)

Add a variable node to the model with the given name and index. This function is unsafe (doesn't check if a variable with the given name already exists in the model).

Args: - model::Model: The model to which the node is added. - context::Context: The context to which the symbol is added. - options::NodeCreationOptions: The options for the creation process. - name::Symbol: The ID of the variable. - index: The index of the variable.

Returns: - The generated symbol for the variable.

source
GraphPPL.add_composite_factor_node!Function

Add a composite factor node to the model with the given name.

The function generates a new symbol for the node and adds it to the model with the generated symbol as the key and a NodeData struct with is_variable set to false and node_name set to the given name.

Args: - model::Model: The model to which the node is added. - parent_context::Context: The context to which the symbol is added. - context::Context: The context of the composite factor node. - node_name::Symbol: The name of the node.

Returns: - The generated id for the node.

source
GraphPPL.copy_markov_blanket_to_child_contextFunction
copy_markov_blanket_to_child_context(child_context::Context, interfaces::NamedTuple)

Copy the variables in the Markov blanket of a parent context to a child context, using a mapping specified by a named tuple.

The Markov blanket of a node or model in a Factor Graph is defined as the set of its outgoing interfaces. This function copies the variables in the Markov blanket of the parent context specified by the named tuple interfaces to the child context child_context, by setting each child variable in child_context.individual_variables to its corresponding parent variable in interfaces.

Arguments

  • child_context::Context: The child context to which to copy the Markov blanket variables.
  • interfaces::NamedTuple: A named tuple that maps child variable names to parent variable names.
source
GraphPPL.generate_nodelabelFunction
generate_nodelabel(model::Model, name::Symbol)

Generate a new NodeLabel object with a unique identifier based on the specified name and the number of nodes already in the model.

Arguments:

  • model: A Model object representing the probabilistic graphical model.
  • name: A symbol representing the name of the node.
  • variable_type: A UInt8 representing the type of the variable. 0 = factor, 1 = individual variable, 2 = vector variable, 3 = tensor variable
  • index: An integer or tuple of integers representing the index of the variable.
source
GraphPPL.FunctionalIndexType
FunctionalIndex

A special type of an index that represents a function that can be used only in pair with a collection. An example of a FunctionalIndex can be firstindex or lastindex, but more complex use cases are possible too, e.g. firstindex + 1. Important part of the implementation is that the resulting structure is isbitstype(...) = true, that allows to store it in parametric type as valtype. One use case for this structure is to dispatch on and to replace begin or end (or more complex use cases, e.g. begin + 1).

source
GraphPPL.FunctionalRangeType
FunctionalRange(left, range)

A range can handle FunctionalIndex as one of (or both) the bounds.

julia> first = GraphPPL.FunctionalIndex{:begin}(firstindex)
(begin)

julia> last = GraphPPL.FunctionalIndex{:end}(lastindex)
(end)

julia> range = GraphPPL.FunctionalRange(first + 1, last - 1)
((begin) + 1):((end) - 1)

julia> [ 1.0, 2.0, 3.0, 4.0 ][range]
2-element Vector{Float64}:
 2.0
 3.0
source

Model macro internals

GraphPPL.combine_argsFunction
combine_args(args::Vector, kwargs::Nothing)

Combines a vector of arguments into a single expression.

Arguments

  • args::Vector: The vector of arguments.
  • kwargs::Nothing: The keyword arguments. This argument is always nothing.

Returns

An Expr with the combined arguments.

source
combine_args(args::Vector, kwargs::Vector)

Combines a vector of arguments and a vector of keyword arguments into a single expression.

Arguments

  • args::Vector: The vector of arguments.
  • kwargs::Vector: The vector of keyword arguments.

Returns

An Expr with the combined arguments and keyword arguments.

source
combine_args(args::Nothing, kwargs::Nothing)

Returns nothing.

Arguments

  • args::Nothing: The arguments. This argument is always nothing.
  • kwargs::Nothing: The keyword arguments. This argument is always nothing.
source
GraphPPL.convert_local_statementFunction
convert_local_statement(expr::Expr)

Converts a statement with the local keyword to the creation of an additional variable and the inclusion of thie variable in the subsequent tilde expression.

source
GraphPPL.add_get_or_create_expressionFunction
add_get_or_create_expression(e::Expr)

Add code to get or create a variable in the graph. The code generated by this function ensures that the left-hand-side is always defined in the local scope and can be used in make_node! afterwards.

Arguments

  • e::Expr: The expression to modify.

Returns

A quote block with the modified expression.

source
GraphPPL.keyword_expressions_to_named_tupleFunction
keyword_expressions_to_named_tuple(keywords::Vector)

Converts a vector of keyword expressions to a named tuple.

Arguments

  • keywords::Vector: The vector of keyword expressions.

Returns

  • NamedTuple: The named tuple.

Examples

julia> keyword_expressions_to_named_tuple([:($(Expr(:kw, :in1, :y))), :($(Expr(:kw, :in2, :z)))])
(in1 = y, in2 = z)
source
GraphPPL.convert_anonymous_variablesFunction
convert_anonymous_variables(e::Expr)

Convert a function argument in the right-hand side of an expression to an anonymous variable. This function is used to convert function calls in the arguments of node creations to anonymous variables in the graph.

Example

```jldoctest
julia> convert_anonymous_variables(:(x ~ Normal(μ, sqrt(σ2)) where {created_by=:(Normal(μ, sqrt(σ2)))}))
:(x ~ (Normal(μ, anon_1 ~ (sqrt(σ2) where {anonymous = true, created_by = :(Normal(μ, sqrt(σ2)))})) where (created_by = :(Normal(μ, sqrt(σ2))))))
```
source
GraphPPL.is_kwargs_expressionFunction
is_kwargs_expression(e::Expr)

Returns true if the given expression e is a keyword argument expression, i.e., if its head is either :kw or :parameters.

source
GraphPPL.convert_to_kwargs_expressionFunction
convert_to_kwargs_expression(expr::Expr)

Convert an expression to a keyword argument expression. This function is used in the conversion of tilde and dot-tilde expressions to ensure that the arguments are passed as keyword arguments.

source
GraphPPL.proxy_argsFunction

Converts an expression into its proxied equivalent. Used to pass variables in sub-models and create a chain of proxied labels.

julia> x = GraphPPL.NodeLabel(:x, 1)
x_1
julia> GraphPPL.proxy_args(:(y = x))
:(y = GraphPPL.proxylabel(:x, nothing, x))
source
GraphPPL.save_expression_in_tildeFunction
save_expression_in_tilde(expr::Expr)

Save the expression found in the tilde syntax in the created_by field of the expression. This function also ensures that the where clause is always present in the tilde syntax.

source
GraphPPL.convert_meta_objectFunction
convert_meta_object(e::Expr)

Converts a variable meta or a factor meta call on the left hand side of a meta specification to a GraphPPL.MetaObject.

Arguments

  • e::Expr: The expression to convert.

Returns

  • Expr: The resulting expression with the variable reference or factor function call converted to a GraphPPL.MetaObject.

Examples

source
GraphPPL.get_boilerplate_functionsFunction
get_boilerplate_functions(ms_name, ms_args, num_interfaces)

Returns a quote block containing boilerplate functions for a model macro.

Arguments

  • ms_name: The name of the model macro.
  • ms_args: The arguments of the model macro.
  • num_interfaces: The number of interfaces of the model macro.

Returns

  • quote: A quote block containing the boilerplate functions for the model macro.
source
GraphPPL.apply_pipeline_collectionFunction
apply_pipeline_collection(e::Expr, collection)

Similar to apply_pipeline, but applies a collection of pipeline functions to an expression.

Arguments

  • e::Expr: An expression to apply the pipeline to.
  • collection: A collection of functions to apply to the expressions in e.

Returns

The result of applying the pipeline function to e.

source
GraphPPL.convert_tilde_expressionFunction
convert_tilde_expression(e::Expr)

Converts a tilde expression to a make_node! call. Converts broadcasted tile expressions to make_node! calls with nothing as the lhs to indicate that a variable should be created on every broadcasted pass.

Arguments

  • e::Expr: The expression to convert.

Returns

  • Expr: The converted expression.

Examples

julia> convert_tilde_expression(:(x ~ Normal(0, 1) where {created_by = (x~Normal(0,1))}))
quote
    GraphPPL.make_node!(__model__, __context__, Normal, x, [0, 1]; options = Dict{Any, Any}(:created_by => :(x ~ Normal(0, 1))), debug = debug)
end
source
GraphPPL.check_reserved_variable_names_modelFunction
check_reserved_variable_names_model(expr::Expr)

Check if any of the variable names in the given expression are reserved in the model macro. Reserved variable names are:

  • __parent_options__
  • __debug__
  • __model__
  • __context__
  • __parent_context__
  • __lhs_interface__
  • __rhs_interfaces__
  • __interfaces__

Arguments

  • expr::Expr: The expression to check for reserved variable names.

Examples

jldoctest julia> check_reserved_variable_names_model(:(__parent_options__ ~ Normal(μ, σ)) ERROR: Variable name in __parent_options__ ~ Normal(μ, σ) cannot be used as it is a reserved variable name in the model macro.`

source
GraphPPL.generate_get_or_createFunction
generate_get_or_create(s::Symbol, lhs::Symbol, index::Nothing)

Generates code to get or create a variable in the graph. This function is used to generate code for variables that are not indexed.

Arguments

  • s::Symbol: The symbol representing the variable.
  • index::Nothing: The index of the variable. This argument is always nothing.

Returns

A quote block with the code to get or create the variable in the graph.

source
generate_get_or_create(s::Symbol, lhs::Expr, index::AbstractArray)

Generates code to get or create a variable in the graph. This function is used to generate code for variables that are indexed.

Arguments

  • s::Symbol: The symbol representing the variable.
  • index::AbstractArray: The index of the variable.

Returns

A quote block with the code to get or create the variable in the graph.

source
GraphPPL.add_meta_constructionFunction
add_meta_construction(e::Expr)

Add a meta construction to the given expression e. This function creates a new GraphPPL.MetaSpecification object and assigns it to the __meta__ variable. It then evaluates the given expression e in the context of this new GraphPPL.MetaSpecification object, and returns the resulting GraphPPL.MetaSpecification object.

Arguments

  • e::Expr: The expression to evaluate in the context of the new GraphPPL.MetaSpecification object.

Returns

  • e::Expr: The expression that will generate the GraphPPL.MetaSpecification object.
source
GraphPPL.apply_pipelineFunction
apply_pipeline(e::Expr, pipeline)

Apply a pipeline function to an expression.

The apply_pipeline function takes an expression e and a pipeline function and applies the function in the pipeline to e when walking over it. The walk utilized can be specified by implementing what_walk for a pipeline funciton.

Arguments

  • e::Expr: An expression to apply the pipeline to.
  • pipeline: A function to apply to the expressions in e.

Returns

The result of applying the pipeline function to e.

source
GraphPPL.options_vector_to_named_tupleFunction
options_vector_to_named_tuple(options::AbstractArray)

Converts the array found by pattern matching on the where clause in a tilde expression into a named tuple.

Arguments

  • options::AbstractArray: An array of options.

Returns

  • result: A named tuple of options.
source
GraphPPL.get_created_byFunction
get_created_by(options::AbstractArray)

Retrieve the created_by option from the given options. Expects the options to be retrieved using the MacroTools.@capture macro.

source
GraphPPL.convert_to_anonymousFunction
convert_to_anonymous(e::Expr, created_by)

Convert an expression to an anonymous variable. This function is used to convert function calls in the arguments of node creations to anonymous variables in the graph.

source

Auxiliary functionality

GraphPPL.prune!Function
prune!(m::Model)

Remove all nodes from the model that are not connected to any other node.

source