The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

B-sets and interfering v-structures

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

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')
DAG |> bnlearn::as.igraph() |>
  igraph::plot.igraph(size = 10, label.cex = 1, layout = igraph::layout_as_tree
  )

find_B_sets_v(DAG, v = 'U5')
#>                U1    U2    U3    U4
#> Empty B-set FALSE FALSE FALSE FALSE
#> U6           TRUE  TRUE FALSE FALSE
#> Full B-set   TRUE  TRUE  TRUE  TRUE

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:

B_sets = find_B_sets(DAG)
B_sets$B_sets
#> $U1
#>     
#> [1,]
#> [2,]
#> [3,]
#> [4,]
#> 
#> $U2
#>     
#> [1,]
#> [2,]
#> [3,]
#> [4,]
#> 
#> $U3
#>     
#> [1,]
#> [2,]
#> [3,]
#> 
#> $U4
#>     
#> [1,]
#> [2,]
#> [3,]
#> 
#> $U5
#>                U1    U2    U3    U4
#> Empty B-set FALSE FALSE FALSE FALSE
#> U6           TRUE  TRUE FALSE FALSE
#> Full B-set   TRUE  TRUE  TRUE  TRUE
#> 
#> $U6
#>                U1    U2    U5
#> Empty B-set FALSE FALSE FALSE
#> Full B-set   TRUE  TRUE  TRUE

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.

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')
DAG |> bnlearn::as.igraph() |> igraph::plot.igraph()

find_B_sets_v(DAG, v = 'U3')
#>                U1    U2
#> Empty B-set FALSE FALSE
#> U4           TRUE FALSE
#> U5          FALSE  TRUE
#> Full B-set   TRUE  TRUE

To check automatically that the B-sets are not comparable (i.e. the existence of a v-structure), we can do:

find_B_sets_v(DAG, v = 'U3') |>
  B_sets_are_increasing()
#> [1] FALSE

More generally, the presence of v-structures can be automatically checked using the following function:

has_interfering_vstrucs(DAG)
#> [1] TRUE

To find the interfering v-structures at a given node, we can use:

find_B_sets_v(DAG, v = 'U3') |>
  find_interfering_v_from_B_sets() |>
  print()
#>    A  B parents.A.but.not.parents.B parents.B.but.not.parents.A
#> 1 U4 U5                          U1                          U2

To fix this, we can add one of the missing arcs. This makes the interfering v-structure disappear.

DAG = bnlearn::set.arc(DAG, 'U1', 'U5')
has_interfering_vstrucs(DAG)
#> [1] FALSE

In this case, the B-sets are:

find_B_sets_v(DAG, v = 'U3')
#>                U1    U2
#> Empty B-set FALSE FALSE
#> U4           TRUE FALSE
#> U5           TRUE  TRUE
#> Full B-set   TRUE  TRUE

B-sets cuts

If there are no interfering v-structures, the B-sets are sorted. We can then get their increments as follows:

find_B_sets_v(DAG, v = 'U3') |>
  B_sets_cut_increments()
#> [[1]]
#> [1] "U1"
#> 
#> [[2]]
#> [1] "U2"
#> 
#> [[3]]
#> character(0)

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.

B_sets_unique = find_B_sets_v(DAG, v = 'U3') |>
  B_sets_make_unique()

print(B_sets_unique)
#>                    nodes    U1    U2
#> Empty B-set  Empty B-set FALSE FALSE
#> U4                    U4  TRUE FALSE
#> U5          U5, Full....  TRUE  TRUE
B_sets_cut_increments(B_sets_unique)
#> [[1]]
#> [1] "U1"
#> 
#> [[2]]
#> [1] "U2"
# Setting back the options to what they were before (following CRAN's policy)

options(old)

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.