## Interfacing with the **gRain** R package

The **gRain** package
(link)
is available from CRAN and provides the only implementation of exact inference in R; currently it
only supports discrete Bayesian networks. The main data structure in **gRain** is the
`grain`

class, which stores a fitted Bayesian network as a list of conditional
probability tables (much like **bnlearn**'s `bn.fit`

objects) and makes it
possible for `setEvidence()`

and `querygrain()`

to perform posterior inference
via belief propagation.

### Exporting a fitted Bayesian networks to **gRain**

`bn.fit`

objects can be exported with the conversion method `as.grain()`

.

> library(bnlearn) > > dag = hc(learning.test) > fitted.bnlearn = bn.fit(dag, learning.test) > fitted.grain = as.grain(fitted.bnlearn) > fitted.grain

Independence network: Compiled: TRUE Propagated: FALSE Nodes: chr [1:6] "A" "B" "C" "D" "E" "F"

Only discrete networks can be exported, since **gRain** does not support networks
with other parametric assumptions.

> dag.gbn = hc(gaussian.test) > fitted.gbn = bn.fit(dag.gbn, gaussian.test) > as.grain(fitted.gbn)

## Error: the gRain package only supports discrete networks.

The other important limitation of **gRain**, compared to **bnlearn**,
is that it does not allow for conditional probabilities to be `NaN`

. (This happens when
estimating them via maximum likelihood and some parent configurations are not observed in the data.)
In that case `as.grain()`

will give a warning and replace the `NaN`

s with
uniform distributions, much like the Bayesian posterior estimator would.

> fitted.sparse = bn.fit(dag, learning.test[1:10, ]) > as.grain(fitted.sparse)

## Warning in from.bn.fit.to.grain(x): NaN conditional probabilities in D, replaced ## with a uniform distribution.

Independence network: Compiled: TRUE Propagated: FALSE Nodes: chr [1:6] "A" "B" "C" "D" "E" "F"

### Importing a network structure from **gRain**

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

.

> fitted.import = as.bn.fit(fitted.grain) > all.equal(fitted.bnlearn, fitted.import)

[1] TRUE

For convenience, **bnlearn** also provides an `as.bn()`

conversion function
that returns the network structure underlying the `grain`

object as a `bn`

object.

> dag.import = as.bn(fitted.grain) > all.equal(dag, dag.import)

[1] TRUE

Note that by default `as.bn.fit()`

disregards any evidence that has been set in the `grain`

object with `setEvidence()`

. So, for instance, setting `B`

equal to `b`

does not
have any effect on the conditional probability table for node `B`

in the returned `bn.fit`

object.

> library(gRain) > fitted.with.evidence = setEvidence(fitted.grain, node = "B", state = "b") > as.bn.fit(fitted.with.evidence)$B

Parameters of node B (multinomial distribution) Conditional probability table: A B a b c a 0.85611511 0.44491018 0.11492178 b 0.02517986 0.22095808 0.09446450 c 0.11870504 0.33413174 0.79061372

Using the argument `including.evidence`

will modify the conditional probability table to reflect the
evidence in the `grain`

object.

> as.bn.fit(fitted.with.evidence, including.evidence = TRUE)$B

Parameters of node B (multinomial distribution) Conditional probability table: A B a b c a 0 0 0 b 1 1 1 c 0 0 0

`Wed Nov 9 16:40:00 2022`

with **bnlearn**

`4.9-20221107`

and `R version 4.2.2 (2022-10-31)`

.