--- title: "B-sets and interfering v-structures" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{B-sets and interfering v-structures} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) # Adjusting options to display wide R output old <- options(width = 120) ``` ```{r setup} library(PCBN) ``` # What are B-sets? For a node $v$ that has children, the B-sets are the intersections of the parents sets of the children of $v$ with $v$'s own parents sets. They can be obtained using the function ```{r} DAG = create_empty_DAG(6) DAG = bnlearn::set.arc(DAG, 'U1', 'U5') DAG = bnlearn::set.arc(DAG, 'U2', 'U5') DAG = bnlearn::set.arc(DAG, 'U3', 'U5') DAG = bnlearn::set.arc(DAG, 'U4', 'U5') DAG = bnlearn::set.arc(DAG, 'U1', 'U6') DAG = bnlearn::set.arc(DAG, 'U2', 'U6') DAG = bnlearn::set.arc(DAG, 'U5', 'U6') ``` ```{r, fig.height=8, fig.width=8} DAG |> bnlearn::as.igraph() |> igraph::plot.igraph(size = 10, label.cex = 1, layout = igraph::layout_as_tree ) ``` ```{r} find_B_sets_v(DAG, v = 'U5') ``` This means that for `v = U5`, the B-sets corresponding to `U6` is made up of `U1` and `U2`. By convention, the empty set and the full set of parents of `v` are always added. To obtain all the B-sets of the nodes of the graph, the following code can be used: ```{r} B_sets = find_B_sets(DAG) B_sets$B_sets ``` # Interfering v-structures An interfering v-structure is by definition a case when two B-sets of the same node are not comparable (for the inclusion order, i.e. neither of them is included in the other one). Here is an example of a graph with interfering v-structures. ```{r} DAG = create_empty_DAG(5) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') DAG = bnlearn::set.arc(DAG, 'U1', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') DAG = bnlearn::set.arc(DAG, 'U2', 'U5') DAG = bnlearn::set.arc(DAG, 'U3', 'U5') ``` ```{r, fig.height=6, fig.width=6} DAG |> bnlearn::as.igraph() |> igraph::plot.igraph() ``` ```{r} find_B_sets_v(DAG, v = 'U3') ``` To check automatically that the B-sets are not comparable (i.e. the existence of a v-structure), we can do: ```{r} find_B_sets_v(DAG, v = 'U3') |> B_sets_are_increasing() ``` More generally, the presence of v-structures can be automatically checked using the following function: ```{r} has_interfering_vstrucs(DAG) ``` To find the interfering v-structures at a given node, we can use: ```{r, results = "kable"} find_B_sets_v(DAG, v = 'U3') |> find_interfering_v_from_B_sets() |> print() ``` To fix this, we can add one of the missing arcs. This makes the interfering v-structure disappear. ```{r} DAG = bnlearn::set.arc(DAG, 'U1', 'U5') has_interfering_vstrucs(DAG) ``` In this case, the B-sets are: ```{r} find_B_sets_v(DAG, v = 'U3') ``` # B-sets cuts If there are no interfering v-structures, the B-sets are sorted. We can then get their increments as follows: ```{r} find_B_sets_v(DAG, v = 'U3') |> B_sets_cut_increments() ``` In this case, the B-sets of `U5` and the full B-set are identical. Therefore, the last increment is the empty character vector. It can be nice sometimes to make the B-sets unique so as to avoid this. ```{r} B_sets_unique = find_B_sets_v(DAG, v = 'U3') |> B_sets_make_unique() print(B_sets_unique) ``` ```{r} B_sets_cut_increments(B_sets_unique) ``` ```{r} # Setting back the options to what they were before (following CRAN's policy) options(old) ```