Skip to content

Networks

Index

Types

EnhancedBayesianNetworks.BayesianNetwork Type
julia
BayesianNetwork(nodes::AbstractVector{DiscreteNode})

A Bayesian network: a DAG of discrete, precise nodes.

  • nodes: the DiscreteNodes, positionally aligned with topology/A.

  • topology: maps each node name to its index (row/column in A).

  • A: sparse boolean adjacency matrix; A[i, j] == true iff i → j.

Validates that node names and states are globally unique and that every node is precise — any imprecise node requires a CredalNetwork. Edges are added afterwards with add_child!.

Examples

julia
W = DiscreteNode(:W); W[:W => :sunny] = 0.5; W[:W => :cloudy] = 0.5
S = DiscreteNode(:S, [:W])
S[:W => :sunny,  :S => :on] = 0.9; S[:W => :sunny,  :S => :off] = 0.1
S[:W => :cloudy, :S => :on] = 0.2; S[:W => :cloudy, :S => :off] = 0.8

bn = BayesianNetwork([W, S])
add_child!(bn, :W, :S)                      # wire parents to children
order!(bn)                                  # sort and validate
source
EnhancedBayesianNetworks.CredalNetwork Type
julia
CredalNetwork(nodes::AbstractVector{DiscreteNode})

A credal network: a DAG of discrete nodes whose CPTs may be imprecise (interval-valued). Same layout as BayesianNetwork (nodes, topology, A).

Validates that node names and states are globally unique; warns if every node is precise, since a BayesianNetwork is the better fit in that case.

Examples

julia
W = DiscreteNode(:W); W[:W => :sunny] = 0.5; W[:W => :cloudy] = 0.5
S = DiscreteNode(:S, [:W])
# imprecise (interval-valued) entries make this a credal, not a Bayesian, network:
S[:W => :sunny,  :S => :on]  = Interval(0.8, 0.95); S[:W => :sunny,  :S => :off] = Interval(0.05, 0.2)
S[:W => :cloudy, :S => :on]  = 0.2;                 S[:W => :cloudy, :S => :off] = 0.8

cn = CredalNetwork([W, S])
add_child!(cn, :W, :S); order!(cn)
source
EnhancedBayesianNetworks.EnhancedBayesianNetwork Type
julia
EnhancedBayesianNetwork(nodes::AbstractVector{<:AbstractNode})

An enhanced Bayesian network: the modelling front-end that may mix discrete, continuous, and functional nodes. Same layout as BayesianNetwork (nodes, topology, A).

Validates that node names are unique and that states across discrete nodes are globally unique. It is progressively transformed — via discretize!, _transfer_continuous_functional_node!, and reduce — into a BayesianNetwork or CredalNetwork for inference.

Examples

julia
# a network mixing a discrete, a continuous, and a functional node:
W = DiscreteNode(:W, [:sunny => [Parameter(1.0, :W)], :cloudy => [Parameter(2.0, :W)]])
W[:W => :sunny] = 0.5; W[:W => :cloudy] = 0.5
X = ContinuousNode(:X, Uniform(-1, 1), ExactDiscretization([-1.0, 0.0, 1.0]))
model = Model(df -> df.X .+ df.W, :Y)
F = DiscreteFunctionalNode(:F, [model], df -> df.Y, MonteCarlo(200))

ebn = EnhancedBayesianNetwork([W, X, F])
add_child!(ebn, :W, :F); add_child!(ebn, :X, :F); order!(ebn)
# reduce(ebn) then turns it into a BayesianNetwork / CredalNetwork for inference
source
EnhancedBayesianNetworks.DirectAcyclicGraph Type
julia
DirectAcyclicGraph()

A directed acyclic graph: network structure plus optional declared states, without any probabilities. It is the input to parameter learning (learn_parameters_mle) — declare the nodes and their parents with add_node! (edges are wired as you go), then learn the CPTs from data to obtain a fully-specified BayesianNetwork.

Each node's domain is taken from the data at learn time; any states passed to add_node! are added to that domain, letting a node keep states that never occur in the dataset (they end up in the learned CPT with probability 0). It is a standalone type (not an AbstractNetwork): it supports add_node!, parents, children, and gplot, but none of the network operations that require CPTs (order!, infer, sample).

Examples

julia
dag = DirectAcyclicGraph()
add_node!(dag, :W, [:Foggy])                     # :Sunny/:Cloudy come from data; :Foggy guaranteed
add_node!(dag, :R; parents = [:W])               # domain from data; edge :W -> :R wired here
add_node!(dag, :P; parents = [:W])
add_node!(dag, :G; parents = [:R, :P])

learned = learn_parameters_mle(dag, df)          # -> BayesianNetwork
order!(learned)
source

Methods

EnhancedBayesianNetworks.add_node! Function
julia
add_node!(dag::DirectAcyclicGraph, name::Symbol, states=Symbol[]; parents=Symbol[])

Declare a node in a DirectAcyclicGraph by name, recording parents as its CPT columns and wiring an edge from each parent (which must already be in the DAG — add nodes top-down, parents first). states are extra domain states — states to keep in the node's domain even when they never appear in the training data, so they end up in the learned CPT with probability 0. Omit states (or pass []) to take the node's domain entirely from the data at learn time.

Examples

julia
dag = DirectAcyclicGraph()
add_node!(dag, :W, [:Foggy])              # root; :Sunny/:Cloudy from data, :Foggy guaranteed
add_node!(dag, :R; parents = [:W])        # edge :W -> :R created here
add_node!(dag, :G; parents = [:R])
source
EnhancedBayesianNetworks.add_child! Function
julia
add_child!(net, parent, child)

Add directed edge(s) parent → child to net. Each of parent/child may be a single node or a vector, given as node objects or by name (Symbol). Validates that all referenced nodes exist, that no edge forms a self-loop, that a discrete parent appears in each non-functional child's CPT, and that continuous/functional parents feed only functional children.

Examples

julia
W = DiscreteNode(:W); W[:W => :sunny] = 0.5; W[:W => :cloudy] = 0.5
S = DiscreteNode(:S, [:W])
S[:W => :sunny,  :S => :on] = 0.9; S[:W => :sunny,  :S => :off] = 0.1
S[:W => :cloudy, :S => :on] = 0.2; S[:W => :cloudy, :S => :off] = 0.8
bn = BayesianNetwork([W, S])
add_child!(bn, :W, :S)                      # by name; also accepts node objects
source
EnhancedBayesianNetworks.order! Function
julia
order!(net::AbstractNetwork)

Topologically sort net's nodes in place and validate it. Errors if the network is cyclic or disconnected, if a node's CPT lists parents that were never linked with add_child!, or if a discrete node's CPT is not exhaustive over all parent/own-state combinations. Run it before inference or sampling.

Examples

julia
W = DiscreteNode(:W); W[:W => :sunny] = 0.5; W[:W => :cloudy] = 0.5
S = DiscreteNode(:S, [:W])
S[:W => :sunny,  :S => :on] = 0.9; S[:W => :sunny,  :S => :off] = 0.1
S[:W => :cloudy, :S => :on] = 0.2; S[:W => :cloudy, :S => :off] = 0.8
bn = BayesianNetwork([W, S]); add_child!(bn, :W, :S)
order!(bn)                                  # sorts nodes and validates the network
source
EnhancedBayesianNetworks.children Function
julia
children(net, name::Symbol)
children(net, node)

Return the names of the direct children of a node in net as a Vector{Symbol} (empty for a leaf). The counterpart of parents.

Examples

julia
W = DiscreteNode(:W); W[:W => :sunny] = 0.5; W[:W => :cloudy] = 0.5
S = DiscreteNode(:S, [:W])
S[:W => :sunny,  :S => :on] = 0.9; S[:W => :sunny,  :S => :off] = 0.1
S[:W => :cloudy, :S => :on] = 0.2; S[:W => :cloudy, :S => :off] = 0.8
bn = BayesianNetwork([W, S]); add_child!(bn, :W, :S); order!(bn)
children(bn, :W)                            # [:S]
source
EnhancedBayesianNetworks.discrete_ancestors Function
julia
discrete_ancestors(net, name::Symbol)
discrete_ancestors(net, node)

Return the nearest discrete ancestors of a node as a Vector{Symbol}: walking upstream, each branch stops at the first discrete node it meets, descending through continuous and functional nodes along the way. These are the discrete nodes that form the scenario grid of a functional node once the network is reduced.

Examples

julia
W = DiscreteNode(:W); W[:W => :sunny] = 0.5; W[:W => :cloudy] = 0.5
X = ContinuousNode(:X, [:W]); X[:W => :sunny] = Normal(); X[:W => :cloudy] = Normal(2, 1)
net = EnhancedBayesianNetwork([W, X]); add_child!(net, :W, :X); order!(net)
discrete_ancestors(net, :X)                 # [:W]  (nearest discrete ancestor of continuous X)
source
EnhancedBayesianNetworks.markov_blanket Function
julia
markov_blanket(net::AbstractNetwork, node)

Return the Markov blanket of node (given by name as a Symbol or as a node object) as a vector of node names: its parents, its children, and its children's other parents (co-parents). The node itself is excluded. Conditioned on its Markov blanket, a node is conditionally independent of every other node in the network.

Examples

julia
# A -> C -> D <- B
A = DiscreteNode(:A); A[:A => :a1] = 0.5; A[:A => :a2] = 0.5
B = DiscreteNode(:B); B[:B => :b1] = 0.5; B[:B => :b2] = 0.5
C = DiscreteNode(:C, [:A])
C[:A => :a1, :C => :c1] = 0.5; C[:A => :a1, :C => :c2] = 0.5
C[:A => :a2, :C => :c1] = 0.5; C[:A => :a2, :C => :c2] = 0.5
D = DiscreteNode(:D, [:C, :B])
for c in (:c1, :c2), b in (:b1, :b2)
    D[:C => c, :B => b, :D => :d1] = 0.5; D[:C => c, :B => b, :D => :d2] = 0.5
end
bn = BayesianNetwork([A, B, C, D])
add_child!(bn, :A, :C); add_child!(bn, :C, :D); add_child!(bn, :B, :D); order!(bn)

# blanket of C = its parent A, its child D, and D's other parent (co-parent) B:
markov_blanket(bn, :C)                      # [:B, :D, :A]
source
EnhancedBayesianNetworks.markov_envelope Function
julia
markov_envelope(net::EnhancedBayesianNetwork)

Return the Markov envelopes of net as a vector of node-name vectors. Continuous nodes linked through their Markov blankets are first collected into groups (_markov_continuous_group); each group's envelope is the union of its members' Markov blankets together with the members themselves. Envelopes that are a subset of another envelope are discarded, so only the maximal (non-redundant) envelopes remain.

Examples

julia
W = DiscreteNode(:W, [:sunny => [Parameter(1.0, :W)], :cloudy => [Parameter(2.0, :W)]])
W[:W => :sunny] = 0.5; W[:W => :cloudy] = 0.5
X = ContinuousNode(:X, Uniform(-1, 1), ExactDiscretization([-1.0, 0.0, 1.0]))
F = DiscreteFunctionalNode(:F, [Model(df -> df.X .+ df.W, :Y)], df -> df.Y, MonteCarlo(200))
ebn = EnhancedBayesianNetwork([W, X, F])
add_child!(ebn, :W, :F); add_child!(ebn, :X, :F); order!(ebn)

markov_envelope(ebn)                        # [[:F, :W, :X]]  (continuous X, its child F, co-parent W)
source
Base.reduce Function
julia
reduce(net::EnhancedBayesianNetwork, collect::Bool=true)

Transform an enhanced Bayesian network into a purely discrete one ready for inference, returning a BayesianNetwork (all nodes precise) or a CredalNetwork (some imprecise). The network is ordered, its continuous nodes discretized, and its functional nodes evaluated in dependency order — each functional node is simulated over the scenario grid of its discrete ancestors and replaced by the resulting node, eliminating the continuous parents that fed only it. With collect=true the intermediate simulation samples are kept on the evaluated nodes' results.

Examples

julia
W = DiscreteNode(:W, [:sunny => [Parameter(1.0, :W)], :cloudy => [Parameter(2.0, :W)]])
W[:W => :sunny] = 0.5; W[:W => :cloudy] = 0.5
X = ContinuousNode(:X, Uniform(-1, 1), ExactDiscretization([-1.0, 0.0, 1.0]))
model = Model(df -> df.X .+ df.W, :Y)
F = DiscreteFunctionalNode(:F, [model], df -> df.Y, MonteCarlo(200))

ebn = EnhancedBayesianNetwork([W, X, F])
add_child!(ebn, :W, :F); add_child!(ebn, :X, :F); order!(ebn)
reduce(ebn)                                 # -> BayesianNetwork
source