Checking network properties
bnlearn provides several functions to examine key graphical characteristics of bn
and
bn.fit
objects. Most are documented here and
here.
Nodes and arcs
The fundamental components of a graph are nodes and arcs, which are returned by the functions of the same name.
> graph = model2network("[A][C][F][B|A][D|A][E|B:F]") > graph = set.edge(graph, from = "A", to = "B") > nodes(graph)
[1] "A" "B" "C" "D" "E" "F"
> arcs(graph)
from to [1,] "A" "B" [2,] "A" "D" [3,] "B" "E" [4,] "F" "E" [5,] "B" "A"
In addition, bnlearn provides nnodes()
and narcs()
to count how many nodes
or arcs are in the graph.
> nnodes(graph)
[1] 6
> narcs(graph)
[1] 4
root.nodes()
and leaf.nodes()
list nodes with no parents or with no children, respectively.
isolated.nodes()
lists those nodes that have neither parents nor children because no arc connects them to
any other nodes.
> root.nodes(graph)
[1] "C" "F"
> leaf.nodes(graph)
[1] "C" "D" "E"
> isolated.nodes(graph)
[1] "C"
directed.arcs() lists arcs with a definite direction, while undirected.arcs()
lists arcs without a
definite direction with their possible orientations.
> directed.arcs(graph)
from to [1,] "A" "D" [2,] "B" "E" [3,] "F" "E"
> undirected.arcs(graph)
from to [1,] "A" "B" [2,] "B" "A"
Equivalence classes
Equivalence classes are described by completed partially directed acyclic graphs (CPDAGs). A CPDAG can be constructed from the corresponding graph with
> cpdag(graph)
Random/Generated Bayesian network model: [partially directed graph] nodes: 6 arcs: 4 undirected arcs: 2 directed arcs: 2 average markov blanket size: 1.67 average neighbourhood size: 1.33 average branching factor: 0.33 generation algorithm: Empty
and is characterized by the skeleton()
of the graph and its vstructs()
(v-structures).
> skeleton(graph)
Random/Generated Bayesian network model: [undirected graph] nodes: 6 arcs: 4 undirected arcs: 4 directed arcs: 0 average markov blanket size: 1.33 average neighbourhood size: 1.33 average branching factor: 0.00 generation algorithm: Empty
> vstructs(graph)
X Z Y [1,] "B" "E" "F"
vstructs()
can also list the arcs that are part of at least one v-structure instead of the v-structures
themselves.
> vstructs(graph, arcs = TRUE)
from to [1,] "B" "E" [2,] "F" "E"
Arcs that are not part of a v-structure can be either compelled.arcs()
if their direction is uniquely
determined, or reversible.arcs()
otherwise.
> compelled.arcs(cpdag(graph))
from to [1,] "B" "E" [2,] "F" "E"
> reversible.arcs(cpdag(graph))
from to [1,] "A" "B" [2,] "A" "D" [3,] "B" "A" [4,] "D" "A"
Directedness and acyclicity
Bayesian networks are defined by DAGs, which are directed()
and acyclic()
graphs.
> directed(graph)
[1] FALSE
> acyclic(graph)
[1] TRUE
A graph that is not a DAGs cannot directly be used as a Bayesian network, but we can modify its arcs to make it a
valid.dag()
.
> valid.dag(graph)
[1] FALSE
> graph = set.arc(graph, from = "A", to = "B") > valid.dag(graph)
[1] TRUE
Types of graphs
bnlearn also provides functions to check whether a graph is a valid CPDAG, and whether it is a completely undirected graph.
> valid.cpdag(graph)
[1] FALSE
> valid.cpdag(cpdag(graph))
[1] TRUE
> valid.ug(graph)
[1] FALSE
> valid.ug(skeleton(graph))
[1] TRUE
valid.cpdag()
also works with the CPDAGs of conditional Gaussian networks, which often do not satisfy
the classical definition of CPDAG.
> cgbn.cpdag = cpdag(hc(clgaussian.test[, c("F", "G", "C")])) > graphviz.plot(cgbn.cpdag)
> valid.cpdag(cgbn.cpdag)
[1] TRUE
Mon Aug 4 18:35:39 2025
with bnlearn
5.1
and R version 4.5.0 (2025-04-11)
.