%\VignetteIndexEntry{grain-intro}
%\VignetteDepends{gRbase}
%\VignetteKeyword{Bayesian networks}
%\VignetteKeyword{Graphical Models}
%\VignetteKeyword{Probabilistic networks}
%\VignetteEngine{knitr::knitr} 

\documentclass[10pt]{article}
\usepackage{boxedminipage,color,a4wide,url}
\usepackage[utf8]{inputenc}

\usepackage[authoryear,round]{natbib}
\bibliographystyle{plainnat}

<<include=FALSE,echo=FALSE,warning=FALSE>>=
library(knitr)
dir.create("figures")
opts_chunk$set(fig.height=2.5,
               fig.path='figures/grain-',
               warning=FALSE, message=FALSE
)
options("prompt"="> ","width"=85)
@

\usepackage{etoolbox} 
\makeatletter 
\preto{\@verbatim}{\topsep=0pt \partopsep=-25pt } 
\makeatother

\usepackage{alltt}
\AtBeginEnvironment{alltt}{\setlength{\topsep}{-25pt}}



\def\pkg#1{{\bf #1}}
\def\grbn{{\bf gRain}}
\def\grain{\texttt{grain}}
\def\code#1{{\texttt{#1}}}
\def\R{\texttt{R}}

<<echo=FALSE>>=
require(gRain)
prettyVersion <- packageDescription("gRain")$Version
prettyDate <- format(Sys.Date())
@

\author{S{\o}ren H{\o}jsgaard\\Aalborg University, Denmark}
\title{Bayesian networks in R with the \pkg{gRain} package}
\date{\pkg{gRain} version \Sexpr{prettyVersion} as of \Sexpr{prettyDate}}

\begin{document}
\maketitle
\tableofcontents
\parindent0pt\parskip5pt

\section{Introduction}

The \grbn\ package implements Bayesian Networks (hereafter often
abbreviated BNs). The name \grbn\ is an acronym for [gra]phical
[i]ndependence [n]etworks. The main reference for \grbn\ to cite is
\cite{hoj:12}, see also

<< >>= 
citation("gRain")
@

Moreover, \cite{hoj:edw:lau:12} gives a broad treatment of graphical
models (including Bayesian networks) More information about the
package, other graphical modelling packages and development versions
is available from

\begin{quote}
\url{http://people.math.aau.dk/~sorenh/software/gR}
\end{quote}

%% \section{Two worked examples}
%% \label{sec:two-worked-examples}

%% \subsection{Wet grass}
%% \label{sec:wet-grass}

%% The `wet grass` example is motivated by the following narrative (taken from 
%% \url{https://en.wikipedia.org/wiki/Bayesian_network})
%% \begin{quote}
%%   Two events can cause grass to be wet: an active sprinkler or
%%   rain. Rain has a direct effect on the use of the sprinkler (namely
%%   that when it rains, the sprinkler usually is not active).
%% \end{quote}

%% <<echo=F, results='hide'>>=
%% p.R    <- cptable(~R, values=c(2, 8), levels=yn)
%% p.S_R  <- cptable(~S:R, values=c(1, 99, 4, 6), levels=yn)
%% p.G_SR <- cptable(~G:S:R, values=c(99, 1, 8, 2, 9, 1, 0, 1), levels=yn)
%% grass_bn <- compileCPT(p.R, p.S_R, p.G_SR)  %>% grain
%% @ 

%% <<chest-grass, fig.height=2, echo=F, fig.cap="Wet graph example; taken from Wikipedia.">>=
%% plot(grass_bn)
%% @ %def


\section{Example: Chest clinic}
\label{sec:chest-clinic}
\label{sec:chest}

<<echo=F, results='hide'>>=
yn <- c("yes","no")
a    <- cptable(~asia, values=c(1,99),levels=yn)
t.a  <- cptable(~tub|asia, values=c(5,95,1,99),levels=yn)
s    <- cptable(~smoke, values=c(5,5), levels=yn)
l.s  <- cptable(~lung|smoke, values=c(1,9,1,99), levels=yn)
b.s  <- cptable(~bronc|smoke, values=c(6,4,3,7), levels=yn)
e.lt <- cptable(~either|lung:tub,values=c(1,0,1,0,1,0,0,1),levels=yn)
x.e  <- cptable(~xray|either, values=c(98,2,5,95), levels=yn)
d.be <- cptable(~dysp|bronc:either, values=c(9,1,7,3,8,2,1,9), levels=yn)
plist <- compileCPT(list(a, t.a, s, l.s, b.s, e.lt, x.e, d.be))
plist
chest_bn <- grain(plist)
chest_bn
@ %def

This section reviews the chest clinic example of \cite{lau/spieg:88}
(illustrated in Figure~\ref{fig:chest-LS}) and shows one way of
specifying the model in \grbn{}.  \cite{lau/spieg:88} motivate the
chest clinic example with the following narrative:

\begin{quote}
  ``Shortness--of--breath (dyspnoea) may be due to tuberculosis, lung
  cancer or bronchitis, or none of them, or more than one of them. A
  recent visit to Asia increases the chances of tuberculosis, while
  smoking is known to be a risk factor for both lung cancer and
  bronchitis. The results of a single chest X--ray do not discriminate
  between lung cancer and tuberculosis, as neither does the presence or
  absence of dyspnoea.''
\end{quote}


<<chest-LS, echo=F, fig.cap="Chest clinic example from Lauritzen and Spiegelhalter (1988).">>=
plot(chest_bn)
@ %def

\subsection{Building a network}

The description above involves the following binary variables:
$\alpha=\mbox{asia}$,
$\sigma=\mbox{smoker}$,
$\tau=\mbox{tuberculosis}$,
$\lambda=\mbox{lung cancer}$,
$\beta=\mbox{bronchitis}$,
$\epsilon=\mbox{either tuberculosis or lung cancer}$,
$\delta=\mbox{dyspnoea}$ and
$\xi=\mbox{xray}$. 
Each variable is binary and can take the values ``yes'' and ``no'':
Note that $\epsilon$ is a logical variable which is
true (yes) if either $\tau$ or $\lambda$ are true (yes) and false (no) otherwise.
The connection between the variables is displayed by the DAG (directed acyclic graph) in
Figure~\ref{fig:chest-LS}.

A joint probability density factorising accoring to a DAG with nodes
$V$ can be constructed as follows: Each node $v\in V$ has a set $pa(v)$ of parents and each node
$v\in V$ has a finite set of states. A joint distribution
over the variables $V$ can be given as
\begin{equation}
  \label{eq:dagfact1}
  p(V) = \prod_{v\in V} p(v|pa(v))
\end{equation}
where $p(v|pa(v))$ is a function defined on $(v,pa(v))$. This function
satisfies that $\sum_{v^*} p(v=v^*|pa(v))=1$, i.e.\ that
for each configuration of the parents $pa(v)$, the sum
over the levels of $v$ equals one. Hence $p(v|pa(v))$ becomes the
conditional distribution of $v$ given $pa(v)$.
In practice $p(v|pa(v))$ is specified as a table called a conditional
probability table or a CPT for short.
Thus, a Bayesian network can be regarded as a complex stochastic model built up by
putting together simple components (conditional probability
distributions).
A joint probability density for all eight variables in
Figure~\ref{fig:chest-LS}
can be constructed as 
\begin{equation}
  \label{eq:chestfact1}
  p(V) =
  p(\alpha)p(\sigma)p(\tau|\alpha)p(\lambda|\sigma)p(\beta|\sigma)p(\epsilon|\tau,\lambda)
  p(\delta|\epsilon, \beta)p(\xi|\epsilon).
\end{equation}



\subsection{Queries to networks}
\label{sec:xxx}

Suppose we are given the evidence (sometimes also called ``finding'')
that a set of variables $E\subset V$
have a specific value $e^*$.
With this evidence, we are often interested in the conditional
distribution $p(v|E=e^*)$
for some of the variables $v \in V \setminus E$
or in $p(U|E=e^*)$
for a set $U\subset V \setminus E$. Interest might also be in
calculating the probability of a specific event, e.g.\ the probability
of seeing a specific evidence, i.e.\ $p(E=e^*)$.
Other types of evidence (called soft evidence, virtual evidence or likelihood evidence) are discussed in
Section~\ref{sec:hard-virt-likel}.

For
example that a person has recently visited Asia and suffers from
dyspnoea, i.e.\ $\alpha=\mbox{yes}$ and $\delta=\mbox{yes}$.
In the chest clinic example, interest might be in $p(\lambda|e^*)$, $p(\tau|e^*)$
and  $p(\beta|e^*)$, or possibly in the joint (conditional) distribution
$p(\lambda,\tau,\beta|e^*)$.


\section{A one--minute version of  \grbn{}}
\label{sec:oneminute}

\subsection{Specifying a network}
\label{sec:specifying-network}

A simple way of  specifying the model for the chest clinic
example is as follows.

\begin{enumerate}
\item Specify conditional probability tables (with values as given in
  \cite{lau/spieg:88}) (there are other ways of specifying conditional
  probability tables, see the package documentation):

<<>>=
yn <- c("yes", "no")
a    <- cptable(~asia, values=c(1, 99), levels=yn)
t.a  <- cptable(~tub|asia, values=c(5, 95, 1, 99), levels=yn)
s    <- cptable(~smoke, values=c(5, 5), levels=yn)
l.s  <- cptable(~lung|smoke, values=c(1, 9, 1, 99), levels=yn)
b.s  <- cptable(~bronc|smoke, values=c(6, 4, 3, 7), levels=yn)
e.lt <- cptable(~either|lung:tub, values=c(1, 0, 1, 0, 1, 0, 0, 1), levels=yn)
x.e  <- cptable(~xray|either, values=c(98, 2, 5, 95), levels=yn)
d.be <- cptable(~dysp|bronc:either, values=c(9, 1, 7, 3, 8, 2, 1, 9), levels=yn)
@ %def

\item Compile list of conditional probability tables.

<<>>=
chest_cpt <- compileCPT(a, t.a, s, l.s, b.s, e.lt, x.e, d.be)
summary(chest_cpt)
@ %def

The components are arrays, but coercion into dataframes sometimes makes it easier to digest the components.
<<>>=
chest_cpt$tub
chest_cpt$tub  %>% as.data.frame.table
@ 

Notice: \code{either} is a logical node
<<>>=
chest_cpt$either  %>% as.data.frame.table
@ 


\item Create the network:\footnote{SH: Rethink print method}
<< >>= 
chest_bn <- grain(chest_cpt)
chest_bn
@

Compile the network (see references for details about
this):\footnote{SH: Maybe change so that default is that a network is
  compiled on creation time.}

<< >>= 
chest_bn <- compile(chest_bn)
@

\end{enumerate}

\subsection{Querying a network}
\label{sec:querying-network}

\begin{enumerate}
\item The network can be queried to give marginal
  probabilities:\footnote{\code{querygrain()} can be abbreviated
    \code{qgrain()}.}

<<>>=
querygrain(chest_bn, nodes=c("lung", "bronc"), type="marginal")
@ %def

%% <<>>=
%% querygrain(chest_bn, nodes=c("lung", "bronc"), type="marginal")  %>% lapply(as.data.frame.table) 
%% @ %def

\item Likewise, a joint distribution can be obtained:

<<>>=
querygrain(chest_bn, nodes=c("lung", "bronc"), type="joint")
@ %def

\item Evidence can be entered in one of these two equivalent forms:

<<>>=
chest_bn2  <- setEvidence(chest_bn, evidence=list(asia="yes", dysp="yes"))
chest_bn2  <- setEvidence(chest_bn,
                      nodes=c("asia", "dysp"), states=c("yes", "yes"))
@ %def

\item The probability of observing this evidence under the model is
<<>>=
pEvidence(chest_bn2)
@ %def

\item The network can be queried again:\footnote{SH: FIXME; joint is wrong}
<<>>=
querygrain(chest_bn2, nodes=c("lung", "bronc"))
querygrain(chest_bn2, nodes=c("lung", "bronc"), type="joint")
@ %def
\end{enumerate}


Notice a small shortcut: A common usage of a Bayesian network is to
enter evidence and then ask for the conditional distribtion of some
variables: This can be accomplished in one simple step as follows:\footnote{SH: FIXME}
<< >>= 
querygrain(chest_bn, evidence=list(asia="yes", dysp="yes"),
           nodes=c("lung", "bronc"), type="joint")
@



\subsection{Conditioning on evidence with zero probability}
\label{sec:zero-probabilities}

Consider setting the evidence
<<>>=
chest_bn3 <- setEvidence(chest_bn, evidence=list(either="no", tub="yes"))
@ %def

Under the model, this specific evidence has zero probability:
\verb|either| is true if \verb|tub| is true or \verb|lung| is true (or
both). Hence the specific evidence is impossible and therefore, all
conditional probabilities are (under the model) undefined:

<<>>=
pEvidence(chest_bn3)
querygrain(chest_bn3, nodes=c("lung", "bronc"), type="joint")
@ %def



Zero probailities (or almost zero probabilities) also arise in a
different in a different setting. Consider this example

<<>>=
yn <- c("yes","no")
eps <- 1e-100
a    <- cptable(~a,   values=c(1, eps), levels=yn)
b.a  <- cptable(~b+a, values=c(1, eps, eps, 1), levels=yn)
c.b  <- cptable(~c+b, values=c(1, eps, eps, 1), levels=yn)
plist <- compileCPT(list(a, b.a, c.b))
bn   <- grain(plist)
tt   <- querygrain(bn, type="joint")
ftable(tt)
querygrain(setEvidence(bn, evidence=list(a="no", c="yes")))
@ %def

No problem so far, but if \code{eps} is made smaller numerical
problems arise:\footnote{Her vil det netop vaere smart at laegge tabeller ind separat!!}
<<>>=
eps  <- 1e-200
a    <- cptable(~a,   values=c(1, eps),levels=yn)
b.a  <- cptable(~b+a, values=c(1, eps, eps, 1),levels=yn)
c.b  <- cptable(~c+b, values=c(1, eps, eps, 1),levels=yn)
plist <- compileCPT(list(a, b.a, c.b))
bn   <- grain(plist)
tt   <- querygrain(bn, type="joint")
ftable(tt)
querygrain(setEvidence(bn, evidence=list(a="no", c="yes")))
@ %def


\subsection{Brute force computations and why they fail}
\label{sec:brute-force-comp}


The \grbn\ package makes computations as those outlined above in a
very efficient way; please see the references.  However, it is in this
small example also possible to make the computations directly: We can
construct the joint distribution (an array with $2^8=256$ entries) directly as:
<< >>= 
joint <- tabListMult(chest_cpt)
dim(joint)
joint  %>% as.data.frame.table %>% head
@

This will clearly fail even moderate size problems: For example, a
model with $80$
nodes each with $10$
levels will give a joint state space with $10^{80}$
states; that is about the number of atoms in the universe. Similarly,
$265$
binary variables will result in a joint state space of about the same
size. Yet, \grbn\ has been used succesfully in models with tens of
thousand variables.  The ``trick'' in \grbn\ is to make all
computations without ever forming the joint distribution. 

However, we
can do all the computations by brute force methods as we will
illustrate here:

Marginal distributions are
<< >>= 
tabMarg(joint, "lung")
tabMarg(joint, "bronc")
@

Conditioning on evidence can be done in different ways: The conditional density is a $6$--way slice of the original $8$--way joint distribution:
<< >>= 
ev <- list(asia="yes", dysp="yes")
cond1 <- tabSlice(joint, slice=ev)
cond1 <- cond1 / sum(cond1)
dim(cond1)
tabMarg(cond1, "lung")
tabMarg(cond1, "bronc")
@

Alternatively, multiply all entries not consistent by zero and all other entries by one and then marginalize:
<< >>= 
cond2 <- tabSliceMult(joint, slice=ev)
cond2 <- cond2 / sum(cond2)
dim(cond2)
tabMarg(cond2, "lung")
tabMarg(cond2, "bronc")
@



% << >>= 
% f1 <- function(){
%     cond1 <- ar_slice(joint, slice=ev)
%     cond1 <- cond1 / sum(cond1)
%     dim(cond1)
%     tabMarg(cond1, "lung")    
% }
% f2 <- function(){
%     cond2 <- ar_slice_mult(joint, slice=ev)
%     cond2 <- cond2 / sum(cond2)
%     dim(cond2)
%     tabMarg(cond2, "lung")    
% }
% f1()
% f2()
% querygrain(chest_bn, nodes="lung", evidence=ev)
% chest_bn1 <- propagate(chest_bn)
% if (require(microbenchmark)){
%     microbenchmark(f1(), f2(),
%                    f3=querygrain(chest_bn, nodes="lung", evidence=ev),
%                    f4=querygrain(chest_bn, nodes="lung", evidence=ev)                   
%                    )                   
% }
% @

\section{Hard  and virtual (likelihood) evidence}
\label{sec:hard-virt-likel}

Below we describe  how to work with virtual evidence (also known
as likelihood evidence) in \grbn. This is done via the function
\code{setEvidence()}.

The clique potential representation in a Bayesian network gives
\begin{displaymath}
  p(x) \propto \psi(x) = \prod_{C} \psi_C(x_C)
\end{displaymath}
where we recall that the whole idea in computations with Bayesian
networks is to avoid calculation the product on the right hand
side. Instead computations are based on propagation (multiplying,
dividing and summing clique potentials $\psi_C$ in an appropriate
order, and such an appropriate order comes from a junction tree).
The normalizing constant, say $c=\sum_x \psi(x)$, comes out of
propagation as a ``by product''.

Suppose a set of nodes $E$ are known to have a specific value,
i.e. $x_E=x^*_E$. This is called hard evidence. The probability of
the event $x_E=x^*_E$ is
\begin{displaymath}
  p(x_E=x^*_E)=E_p\{I(x_E=x^*_E)\} = \sum_x I(x_E=x^*_E) p(x)
  = \frac{1}{c} \sum_x I(x_E=x^*_E) \psi(x)
\end{displaymath}

The computations are based on modifying the clique potentials $\psi_C$
by giving value zero to states in $\psi_C$ which are not consistent
with $x_E=x^*_E$. This can be achieved with an indicator function, say
$L_C(x_C)$ such that we obtain a set of new potentials $\tilde \psi_C
= L_C(x_C) \psi_C(x_C)$. Propagation with these new potentials gives,
as a by product, $\tilde c=\sum \tilde \psi(x)$ where
$\tilde\psi(x)= \prod_C \tilde\psi_C(x_C)$. Consequently, we have
$p(x_E=x^*_E)=\tilde c / c$.

In a more general setting we may have non--negative weights $L(x)$ for
each value of $x$. We may calculate
\begin{displaymath}
  E_p\{L(X)\} = \sum_x L(x)p(x)
\end{displaymath}
If $L(X)$ factorizes as $L(X)=L_C(X_C)$ then the computations are
carried out as outlined above, i.e.\ by the message passing scheme.


\subsection{An excerpt of the chest clinic network}
\label{sec:an-excerpt-chest}


Consider the following excerpt of
the chest clinic network which is described in the paper mentioned
above.

<<>>=
yn <- c("yes","no")
a    <- cptable(~asia, values=c(1,99),levels=yn)
t.a  <- cptable(~tub|asia, values=c(5,95,1,99),levels=yn)

(plist1 <- compileCPT(list(a, t.a)))
plist1[[1]]
plist1[[2]]
(chest1 <- grain(plist1))
querygrain(chest1)
@ %def

\subsection{Specifying hard evidence}
\label{sec:hard-evidence}

Suppose we want to make a diagnosis about tuberculosis given the
evidence that a person has recently been to Asia. The functions
\code{setFinding()} (which has been in \grbn\ for years) and
\code{setEvidence()} (which is a recent addition to \grbn) can both be used for this
purpose. The following forms are equivalent (\verb|setFinding()| is kept in \grbn\ for backward compatibility):

<<>>=
setEvidence(chest1, evidence=list(asia="yes"))
setEvidence(chest1, nodes="asia", states="yes")
## setFinding(chest1, nodes="asia", states="yes")
@ %def

<<>>=
querygrain(setEvidence(chest1, evidence=list(asia="yes")))
@ %def

\subsection{What is virtual evidence (also called likelihood evidence)
?}
\label{sec:virt-evid-likel}

Suppose we do not know with certainty whether a patient has
recently been to Asia (perhaps the patient is too ill to
tell). However the patient (if he/she is Caucasian) may be unusually
tanned and this lends support to the hypothesis of a recent visit to
Asia.

To accommodate we create an extended network with an extra
node for which we enter evidence.  However, it is NOT necessary to do
so in practice, because we may equivalently enter the virtual evidence
in the original network.

We can then introduce a new variable
\code{guess.asia} with \code{asia} as its only parent.\footnote{FIXME: Hvorfor vil parray ikke gaa vaek...}

<<>>=
g.a <- parray(c("guess.asia", "asia"), levels=list(yn, yn),
              values=c(.8,.2, .1,.9))
@ %def

This reflects the assumption that for patients who have recently been
to Asia we would guess so in 80\% of the cases, whereas for patients who have
not recently been to A we would (erroneously) guess that they have
recently been to Asia in 10\% of the cases.

<<>>=
(plist2 <- compileCPT(list(a, t.a, g.a )))
(chest2 <- grain(plist2))
querygrain( chest2 )
@ %def


Now specify the guess or judgment, that the person has recently been
to Asia:

<<>>=
querygrain(setEvidence(chest2, evidence=list(guess.asia="yes")))
@ %def

\subsection{Specifying virtual evidence}
\label{sec:spec-virt-evid}

The same guess or judgment can be specified as virtual evidence
(also called likelihood evidence) for the original network:

<<>>=
querygrain(setEvidence(chest1, evidence=list(asia=c(.8, .1))))
@ %def

This also means that specifying that specifying \code{asia='yes'} can
be done as
<<>>=
querygrain(setEvidence(chest1, evidence=list(asia=c(1, 0))))
@ %def


\subsection{A mixture of a discrete and a continuous variable}
\label{sec:ixture}

\grbn\ only handles discrete variables with a finite state space, but
using likelihood evidence it is possible to work with networks with
both discrete and continuous variables (or other types of variables).
This is possible only when he networks
have a specific structure. This is possible when no discrete variable
has non--discrete parents.\footnote{SH: Expand this.}

Take a simple example: $x$ is a discrete variable with levels $1$ and
$2$; $y_1|x=k \sim N(\mu_k, \sigma^2_k)$ and $y_2|x=k \sim
Poi(\lambda_k)$ where $k=1,2$. The joint distribution is
\begin{displaymath}
  p(x,y_1, y_2) = p(x)p(y_1|x)p(y_2|x)
\end{displaymath}

Suppose the interest is in the distribution of $x$ given
$y_1=y_1^*$ and $y_2=y_2^*$. We then have
\begin{displaymath}
  p(x|y_1^*, y_2^*) \propto p(x) p(y_1^*|x)p(y_2^*|x) =
  p(x) L_1(x) L_2(x)
\end{displaymath}







\section{Building networks from data}
\label{sec:using-textttsm-argum}

The following two graphs specify the same model:
<<>>=
dG  <- dag(~A:B + B:C)
uG  <- ug(~A:B + B:C)
par(mfrow=c(1,2)); plot( dG ); plot( uG )
@ %def

Suppose data is
<<>>=
dat <- tabNew(c("A", "B", "C"), levels=c(2, 2, 2), values=c(0, 0, 2, 3, 1, 2, 1, 4))
class(dat)
@ %def

A network can be built from data using:

<<>>=
gr.dG <- compile( grain( dG, data=dat ) )
gr.uG <- compile( grain( uG, data=dat ) )
@ %def

However, when there are zeros in the table, care must be taken.

\subsection{Extracting information from tables}
\label{sec:extr-inform-from}

In the process of creating networks, conditional probability tables
are extracted when the graph is a dag and clique potentials are
extracted when the graph is a chordal (i.e.\ triangulated) undirected
graph. This takes place as follows (internally):

<<>>=
extractCPT(dat, dG)
c(extractPOT(dat, uG ))
@ %def

The conditional probability table $P(A|B)$ contains \code{NaN}s
because
\begin{displaymath}
  P(A|B=B1)=\frac{n(A,B=B1)}{\sum_A n(A,B=B1)} = \frac{0}{0} = \mbox{NaN}
\end{displaymath}

For this reason the network \code{gr.dG} above will fail to compile
whereas \code{gr.uG} will work, but it may not give the expected results.

\subsection{Using smooth}
\label{sec:using-smooth}

To illustrate what goes on, we can extract the distributions from data
as follows:\footnote{SH: FIXME Use new functions from gRbase.}

<<>>=
p.A.g.B <- tableDiv(dat, tableMargin(dat, "B"))
p.B     <- tableMargin(dat, "B") / sum(dat)
p.AB    <- tableMult( p.A.g.B, p.B)
@ %def

However, the result is slightly misleading because \code{tableDiv}
sets $0/0=0$.

In \grain\ there is a \code{smooth} argument that will add a small
number to the cell entries before extracting tables, i.e.
\begin{displaymath}
  P(A|B=B1)=\frac{n(A,B=B1)+\epsilon}{\sum_A ( n(A,B=B1) + \epsilon) }
  = \frac{\epsilon}{2\epsilon} = 0.5
\end{displaymath}
and
\begin{displaymath}
  P(B)= \frac{\sum_A (n(A,B)+\epsilon)}{\sum_{AB} (n(A,B)+\epsilon)}
\end{displaymath}

We can mimic this as follows:
<<>>=
e <- 1e-2
(dat.e <- dat + e)
@ %def

<<>>=
pe.A.g.B <- tableDiv(dat.e, tableMargin(dat, "B"))
pe.B <- tableMargin(dat.e, "B")/sum(dat.e)
pe.AB  <- tableMult( pe.A.g.B, pe.B )
@ %def

However this resulting joint distribution is different from what is
obtained from the adjusted table itself
<<>>=
dat.e / sum(dat.e)
@ %def

This difference appears in the \grbn\ networks.

\subsection{Extracting tables}
\label{sec:extracting-tables}

One can do
<<>>=
gr.dG <- compile(grain(dG, data=dat, smooth=e))
@ %def

which (internally) corresponds to
<<>>=
extractCPT(dat, dG, smooth=e)
@ %def

We get
<<>>=
querygrain(gr.dG)
querygrain(gr.uG)
@ %def

However, if we condition on \code{B=B1} we get:
<<>>=
querygrain(setFinding(gr.dG, nodes="B", states="B1"))
querygrain(setFinding(gr.uG, nodes="B", states="B1"))
@ %def

so the ``problem'' with zero entries shows up in a different
place. However, the answer is not necessarily wrong; the answer simply
states that $P(A|B=B1)$ is undefined.
To ``remedy'' we can use the \code{smooth} argument:
<<>>=
gr.uG <- compile(grain(uG, data=dat, smooth=e))
@ %def
which (internally) corresponds to
<<>>=
c(extractPOT(dat, uG, smooth=e))
@ %def

Notice that the results are not exactly identical:

<<>>=
querygrain(gr.uG)
querygrain(gr.dG)
@ %def


<<>>=
querygrain(setFinding(gr.uG, nodes="B", states="B1"))
querygrain(setFinding(gr.dG, nodes="B", states="B1"))
@ %def


\bibliography{grain}

\end{document}


%%\SweaveInput{Rmarkup.STY}
%% ------------------------
%% \definecolor{darkred}{rgb}{.7,0,0}
%% \definecolor{midnightblue}{rgb}{0.098,0.098,0.439}
%% 
%% \DefineVerbatimEnvironment{Sinput}{Verbatim}{
%%   fontfamily=tt,
%%   %%fontseries=b,
%%   %% xleftmargin=2em,
%%   formatcom={\color{midnightblue}}
%% }
%% \DefineVerbatimEnvironment{Soutput}{Verbatim}{
%%   fontfamily=tt,
%%   %%fontseries=b,
%%   %% xleftmargin=2em,
%%   formatcom={\color{darkred}}
%% }
%% \DefineVerbatimEnvironment{Scode}{Verbatim}{
%%   fontfamily=tt,
%%   %%fontseries=b,
%%   %% xleftmargin=2em,
%%   formatcom={\color{blue}}
%% }
%% 
%% \fvset{listparameters={\setlength{\topsep}{-2pt}}}
%% \renewenvironment{Schunk}{\linespread{.90}}{}
%% %% ------------------------
%% 




% We can look closer into this zero--probability issue. Because the node
% \code{either} is logical, half of the configurations will have zero probability:

% <<>>=
% tt <- querygrain(chest_bn, type="joint")
% sum(tt == 0) / length(tt)
% @ %def

% In particular the configuration above has zero probability
% <<>>=
% sum(ar_slice(tt, list(either="no", tub="yes")))
% @ %def
