Networks
Index
EnhancedBayesianNetworks.BayesianNetworkEnhancedBayesianNetworks.CredalNetworkEnhancedBayesianNetworks.DirectAcyclicGraphEnhancedBayesianNetworks.EnhancedBayesianNetworkBase.reduceEnhancedBayesianNetworks.add_child!EnhancedBayesianNetworks.add_node!EnhancedBayesianNetworks.childrenEnhancedBayesianNetworks.discrete_ancestorsEnhancedBayesianNetworks.markov_blanketEnhancedBayesianNetworks.markov_envelopeEnhancedBayesianNetworks.order!
Types
EnhancedBayesianNetworks.BayesianNetwork Type
BayesianNetwork(nodes::AbstractVector{DiscreteNode})A Bayesian network: a DAG of discrete, precise nodes.
nodes: theDiscreteNodes, positionally aligned withtopology/A.topology: maps each node name to its index (row/column inA).A: sparse boolean adjacency matrix;A[i, j] == trueiffi → 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
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 validateEnhancedBayesianNetworks.CredalNetwork Type
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
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)EnhancedBayesianNetworks.EnhancedBayesianNetwork Type
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
# 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 inferenceEnhancedBayesianNetworks.DirectAcyclicGraph Type
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
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)Methods
EnhancedBayesianNetworks.add_node! Function
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
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])EnhancedBayesianNetworks.add_child! Function
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
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 objectsEnhancedBayesianNetworks.order! Function
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
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 networkEnhancedBayesianNetworks.children Function
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
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]EnhancedBayesianNetworks.discrete_ancestors Function
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
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)EnhancedBayesianNetworks.markov_blanket Function
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
# 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]EnhancedBayesianNetworks.markov_envelope Function
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
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)Base.reduce Function
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
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