## Interfacing with the graph R package

The graph package (link) is available from Bioconductor and it is one of the most popular packages to work on graphs (both directed and undirected). It implements a variety of algorithms for random graph generation, centrality statistics, graph distances, nodes and arcs manipulation utilities, and it provides a strong foundation for the Rgraphviz package (link). For this reason, bnlearn implements functions to import and export network structures to graph as:

• `graphNEL` objects, which encode the graph as a list in which each element refer to one of the nodes in the graph and contains a vector with its children;
• `graphAM` objects, which encode the graph as a matrix in which the (i, j) cell is equal to one if there is an arc from the ith node to the jth node and zero otherwise.

### Exporting a network structure to graph

Exporting the objects is achieved with the conversion methods `as.graphNEL()` and `as.graphAM()`.

```> library(bnlearn)
>
> dag.bnlearn = random.graph(LETTERS[1:10])
> dag.bnlearn
```
```
Random/Generated Bayesian network

model:
[A][B][C][F][D|C][E|C][G|A:B:E][H|A:D][I|C:F:H][J|C:F:I]
nodes:                                 10
arcs:                                  13
undirected arcs:                     0
directed arcs:                       13
average markov blanket size:           4.00
average neighbourhood size:            2.60
average branching factor:              1.30

generation algorithm:                  Full Ordering
arc sampling probability:              0.2222222
```
```> dag.graphNEL = as.graphNEL(dag.bnlearn)
> dag.graphNEL
```
```A graphNEL graph with directed edges
Number of Nodes = 10
Number of Edges = 13
```
```> dag.graphAM = as.graphAM(dag.bnlearn)
> dag.graphAM
```
```A graphAM graph with directed edges
Number of Nodes = 10
Number of Edges = 13
```

Both methods accept objects of class `bn.fit` as well as of class `bn`, and they implicitly call `bn.net()` (link) on the former to export them.

```> dag.test = hc(learning.test)
> dag.test
```
```
Bayesian network learned via Score-based methods

model:
[A][C][F][B|A][D|A:C][E|B:F]
nodes:                                 6
arcs:                                  5
undirected arcs:                     0
directed arcs:                       5
average markov blanket size:           2.33
average neighbourhood size:            1.67
average branching factor:              0.83

learning algorithm:                    Hill-Climbing
score:                                 BIC (disc.)
penalization coefficient:              4.258597
tests used in the learning procedure:  40
optimized:                             TRUE
```
```> fitted = bn.fit(dag.test, learning.test)
> as.graphNEL(fitted)
```
```A graphNEL graph with directed edges
Number of Nodes = 6
Number of Edges = 5
```
```> as.graphAM(fitted)
```
```A graphAM graph with directed edges
Number of Nodes = 6
Number of Edges = 5
```

Undirected arcs are exported as a pair of directed arcs, that is, Xi — Xj becomes {Xi → Xj, Xi ← Xj}.

```> as.graphNEL(skeleton(dag.test))
```
```A graphNEL graph with directed edges
Number of Nodes = 6
Number of Edges = 10
```

### Importing a network structure from graph

Importing network structures works in the same way, with a conversion method `as.bn()`.

```> as.bn(dag.graphAM)
```
```
Random/Generated Bayesian network

model:
[A][B][C][F][D|C][E|C][G|A:B:E][H|A:D][I|C:F:H][J|C:F:I]
nodes:                                 10
arcs:                                  13
undirected arcs:                     0
directed arcs:                       13
average markov blanket size:           4.00
average neighbourhood size:            2.60
average branching factor:              1.30

generation algorithm:                  Empty
```
```> as.bn(dag.graphNEL)
```
```
Random/Generated Bayesian network

model:
[A][B][C][F][D|C][E|C][G|A:B:E][H|A:D][I|C:F:H][J|C:F:I]
nodes:                                 10
arcs:                                  13
undirected arcs:                     0
directed arcs:                       13
average markov blanket size:           4.00
average neighbourhood size:            2.60
average branching factor:              1.30

generation algorithm:                  Empty
```

Note that as graphs are imported with `as.bn()` they are checked to be acyclic, unless the user specifies `check.cycles = FALSE`.

```> library(graph)
>
> m = matrix(rep(0, 9), nrow = 3, ncol = 3)
> m[1, 2] = m[2, 3] = m[3, 1] = 1
> cyclic = graphAM(m, edgemode = "directed")
> as.bn(cyclic)
```
```## Error: the graphAM object contains directed cycles.
```
```> as.bn(cyclic, check.cycles = FALSE)
```
```
Random/Generated Bayesian network

model:
[n1|n3][n2|n1][n3|n2]
nodes:                                 3
arcs:                                  3
undirected arcs:                     0
directed arcs:                       3
average markov blanket size:           2.00
average neighbourhood size:            2.00
average branching factor:              1.00

generation algorithm:                  Empty
```
Last updated on `Wed Nov 9 16:40:31 2022` with bnlearn `4.9-20221107` and `R version 4.2.2 (2022-10-31)`.