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)
Loading required namespace: igraph
[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)
Loading required namespace: Rgraphviz
plot of chunk unnamed-chunk-13
> valid.cpdag(cgbn.cpdag)
[1] TRUE
Last updated on Mon Aug 4 18:35:39 2025 with bnlearn 5.1 and R version 4.5.0 (2025-04-11).