| Title: | Inference of Pair-Copula Bayesian Networks |
|---|---|
| Description: | Creates, fits and samples Pair-Copula Bayesian Networks (PCBN) under some restrictions on the underlying Directed Acyclic Graph (DAG), that is, no active cycles nor interfering v-structures, following Derumigny, Horsman and Kurowicka (2025) <doi:10.48550/arXiv.2510.03518>. |
| Authors: | Alexis Derumigny [aut, cre] (ORCID: <https://orcid.org/0000-0002-6163-8097>), Niels Horsman [aut], Dorota Kurowicka [aut] |
| Maintainer: | Alexis Derumigny <[email protected]> |
| License: | GPL (>= 2) |
| Version: | 0.1.1 |
| Built: | 2026-05-17 08:03:20 UTC |
| Source: | https://github.com/alexisderumigny/pcbn |
Checks if a graph contains active cycles
active_cycles(DAG, early.stopping = FALSE) has_active_cycles(DAG) plot_active_cycles(DAG, active_cycles_list = NULL)active_cycles(DAG, early.stopping = FALSE) has_active_cycles(DAG) plot_active_cycles(DAG, active_cycles_list = NULL)
DAG |
Directed Acyclic |
early.stopping |
if |
active_cycles_list |
a list of active cycles as given by
|
active_cycles returns a list containing the active cycles.
Each active cycle is a character vector of the name of the nodes involved in
the active cycle. The first element of this vector is the converging node of
the active cycle.
has_active_cycles returns TRUE if at least 1 active cycle is
found. Otherwise, it returns FALSE.
plot_active_cycles is called for its side-effects only. It plots the
active cycles if any, and else prints a message.
the helper functions path_hasConvergingConnections,
path_hasChords that are used to find the active cycles.
is_restrictedDAG to check also whether the DAG contains
interfering v-structures.
DAG = create_empty_DAG(4) 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, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') active_cycles(DAG) # no active cycle DAG = create_empty_DAG(4) DAG = bnlearn::set.arc(DAG, 'U1', 'U2') DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') active_cycles(DAG) # 1 active cycle DAG = create_empty_DAG(5) DAG = bnlearn::set.arc(DAG, 'U1', 'U2') DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') DAG = bnlearn::set.arc(DAG, 'U2', 'U5') DAG = bnlearn::set.arc(DAG, 'U3', 'U5') active_cycles(DAG) # 2 active cycles active_cycles(DAG, early.stopping = TRUE) # The first active cycle # Plotting the active cycles plot_active_cycles(DAG) # which is the same as plot_active_cycles(DAG, active_cycles_list = active_cycles(DAG)) # We now fix the active cycles by adding the some arcs. fixedDAG = fix_active_cycles(DAG) # We can see that no active cycles is plotted anymore plot_active_cycles(fixedDAG) has_active_cycles(fixedDAG) # This is because two edges have been added, as can be seen on: plot(fixedDAG)DAG = create_empty_DAG(4) 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, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') active_cycles(DAG) # no active cycle DAG = create_empty_DAG(4) DAG = bnlearn::set.arc(DAG, 'U1', 'U2') DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') active_cycles(DAG) # 1 active cycle DAG = create_empty_DAG(5) DAG = bnlearn::set.arc(DAG, 'U1', 'U2') DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') DAG = bnlearn::set.arc(DAG, 'U2', 'U5') DAG = bnlearn::set.arc(DAG, 'U3', 'U5') active_cycles(DAG) # 2 active cycles active_cycles(DAG, early.stopping = TRUE) # The first active cycle # Plotting the active cycles plot_active_cycles(DAG) # which is the same as plot_active_cycles(DAG, active_cycles_list = active_cycles(DAG)) # We now fix the active cycles by adding the some arcs. fixedDAG = fix_active_cycles(DAG) # We can see that no active cycles is plotted anymore plot_active_cycles(fixedDAG) has_active_cycles(fixedDAG) # This is because two edges have been added, as can be seen on: plot(fixedDAG)
Checks if the B-sets for a particular node form an increasing sequence.
B_sets_are_increasing(B_sets)B_sets_are_increasing(B_sets)
B_sets |
a boolean matrix with |
TRUE if the B-sets form an ordered sequence,
otherwise returns FALSE.
B_sets = matrix(c(FALSE, FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , TRUE , FALSE, FALSE, TRUE , TRUE , TRUE , TRUE), nrow = 4, byrow = TRUE) B_sets_are_increasing(B_sets) B_sets = matrix(c(FALSE, FALSE, FALSE, FALSE, TRUE , FALSE, TRUE , FALSE, TRUE , TRUE , FALSE, FALSE, TRUE , TRUE , TRUE , TRUE), nrow = 4, byrow = TRUE) B_sets_are_increasing(B_sets)B_sets = matrix(c(FALSE, FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , TRUE , FALSE, FALSE, TRUE , TRUE , TRUE , TRUE), nrow = 4, byrow = TRUE) B_sets_are_increasing(B_sets) B_sets = matrix(c(FALSE, FALSE, FALSE, FALSE, TRUE , FALSE, TRUE , FALSE, TRUE , TRUE , FALSE, FALSE, TRUE , TRUE , TRUE , TRUE), nrow = 4, byrow = TRUE) B_sets_are_increasing(B_sets)
Find the decomposition of B-sets
B_sets_cut_increments(B_sets)B_sets_cut_increments(B_sets)
B_sets |
matrix of B-sets, assumed to be increasing.
This means |
a list of vectors of characters. Each element of the list
corresponds to one .
B_sets = matrix(c(FALSE, FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , TRUE , FALSE, FALSE, TRUE , TRUE , TRUE , TRUE), nrow = 4, byrow = TRUE) colnames(B_sets) <- c("U1", "U2", "U3", "U4") B_sets_cut_increments(B_sets)B_sets = matrix(c(FALSE, FALSE, FALSE, FALSE, TRUE , FALSE, FALSE, FALSE, TRUE , TRUE , FALSE, FALSE, TRUE , TRUE , TRUE , TRUE), nrow = 4, byrow = TRUE) colnames(B_sets) <- c("U1", "U2", "U3", "U4") B_sets_cut_increments(B_sets)
Compress a given collection of B-sets
B_sets_make_unique(B_sets)B_sets_make_unique(B_sets)
B_sets |
a boolean matrix with |
a 'data.frame' made of the unique rows of 'B_sets'.
An additional column 'nodes' is added at the start. It contains all the children
of v corresponding to this B-set.
DAG = create_empty_DAG(5) DAG = bnlearn::set.arc(DAG, 'U1', 'U4') DAG = bnlearn::set.arc(DAG, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') DAG = bnlearn::set.arc(DAG, 'U4', 'U5') B_sets = find_B_sets_v(DAG, v = 'U4') B_sets_make_unique(B_sets)DAG = create_empty_DAG(5) DAG = bnlearn::set.arc(DAG, 'U1', 'U4') DAG = bnlearn::set.arc(DAG, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') DAG = bnlearn::set.arc(DAG, 'U4', 'U5') B_sets = find_B_sets_v(DAG, v = 'U4') B_sets_make_unique(B_sets)
Complete an order and check whether these are valid orders on parents sets
complete_and_check_orders(DAG, order_hash)complete_and_check_orders(DAG, order_hash)
DAG |
the DAG |
order_hash |
the hashmaps of orders |
NULL. This function has only side-effects,
and modifies order_hash. It stops if the orders are not valid orders
on the parents sets.
DAG = create_empty_DAG(4) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') order_hash = r2r::hashmap() try({complete_and_check_orders(DAG, order_hash)}) # Error because the order of the parents on "U3" should be specified. order_hash[['U3']] = c("U1", "U2") complete_and_check_orders(DAG, order_hash) r2r::keys(order_hash) # We obtain "U3" and "U4" because they both have parentsDAG = create_empty_DAG(4) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') order_hash = r2r::hashmap() try({complete_and_check_orders(DAG, order_hash)}) # Error because the order of the parents on "U3" should be specified. order_hash[['U3']] = c("U1", "U2") complete_and_check_orders(DAG, order_hash) r2r::keys(order_hash) # We obtain "U3" and "U4" because they both have parents
Computes a conditional margin during sampling
compute_sample_margin( object, data, v, cond_set, check_PCBN = TRUE, verbose = 1 )compute_sample_margin( object, data, v, cond_set, check_PCBN = TRUE, verbose = 1 )
object |
PCBN object to sample from. This does not work if the PCBN does not abide by the B-sets. And in general, it does not work if the PCBN is outside of the class of restricted PCBNs. |
data |
data frame of observations of size |
v |
name of the node |
cond_set |
conditioning set. This is a vector containing the names of all the nodes in the conditioning set. |
check_PCBN |
check whether the given PCBN satisfies the restrictions.
If this is set to |
verbose |
if |
a vector of size of realizations
for .
DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) # Initialize data frame N = 100 nodes = bnlearn::nodes(my_PCBN$DAG) data = data.frame(matrix(ncol = length(nodes), nrow = N)) colnames(data) <- nodes data[, "U1"] = stats::runif(N) data[, "U2"] = stats::runif(N) u_1_given2 = compute_sample_margin(object = my_PCBN, data = data, v = "U1", cond_set = c("U2")) identical(data[, "U1"], u_1_given2)DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) # Initialize data frame N = 100 nodes = bnlearn::nodes(my_PCBN$DAG) data = data.frame(matrix(ncol = length(nodes), nrow = N)) colnames(data) <- nodes data[, "U1"] = stats::runif(N) data[, "U2"] = stats::runif(N) u_1_given2 = compute_sample_margin(object = my_PCBN, data = data, v = "U1", cond_set = c("U2")) identical(data[, "U1"], u_1_given2)
This function creates a directed graph with a total of 'N_nodes' nodes and no arcs. The nodes are named 'U1', 'U2', etc.
create_empty_DAG(N_nodes)create_empty_DAG(N_nodes)
N_nodes |
An integer equal to the number of nodes |
A bnlearn graph object with 'N_nodes' nodes and no arcs
[bnlearn::empty.graph()] which this function wraps.
create_empty_DAG(6) create_empty_DAG(10)create_empty_DAG(6) create_empty_DAG(10)
Turns a general graph into a restricted graph.
DAG_to_restrictedDAG(DAG) fix_active_cycles(DAG, active_cycles_list = NULL) fix_interfering_vstructs(DAG, all_B_sets = NULL)DAG_to_restrictedDAG(DAG) fix_active_cycles(DAG, active_cycles_list = NULL) fix_interfering_vstructs(DAG, all_B_sets = NULL)
DAG |
a directed acyclic graph object, of class |
active_cycles_list, all_B_sets
|
respective outputs of the functions
|
Restricted DAG.
is_restrictedDAG to check whether a given DAG is
restricted.
# DAG with an active cycle at node 5 DAG = create_empty_DAG(5) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U1', 'U2') DAG = bnlearn::set.arc(DAG, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U5') DAG = bnlearn::set.arc(DAG, 'U4', 'U5') # Fixed graph has extra arcs 1 -> 5, 2 -> 5 fixed_DAG = DAG_to_restrictedDAG(DAG) # DAG with an interfering v-structures node 3 DAG = create_empty_DAG(5) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U1', 'U4') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U5') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U5') # Fixed graph has extra arc 1 -> 5 fixed_DAG = DAG_to_restrictedDAG(DAG)# DAG with an active cycle at node 5 DAG = create_empty_DAG(5) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U1', 'U2') DAG = bnlearn::set.arc(DAG, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U5') DAG = bnlearn::set.arc(DAG, 'U4', 'U5') # Fixed graph has extra arcs 1 -> 5, 2 -> 5 fixed_DAG = DAG_to_restrictedDAG(DAG) # DAG with an interfering v-structures node 3 DAG = create_empty_DAG(5) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U1', 'U4') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U5') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U5') # Fixed graph has extra arc 1 -> 5 fixed_DAG = DAG_to_restrictedDAG(DAG)
Fits the copula joining w and v given cond_set abiding by the conditional independencies of the graph
default_envir() BiCopCondFit( data, DAG, v, w, cond_set, familyset, order_hash, e, verbose = 1, method ) ComputeCondMargin( data, DAG, v, cond_set, familyset, order_hash, e, verbose = 1, method = method )default_envir() BiCopCondFit( data, DAG, v, w, cond_set, familyset, order_hash, e, verbose = 1, method ) ComputeCondMargin( data, DAG, v, cond_set, familyset, order_hash, e, verbose = 1, method = method )
data |
data frame |
DAG |
Directed Acylic Graph |
v, w
|
nodes of the graph |
cond_set |
vector of nodes of DAG. They should all be parents of v. They should be ordered from the smallest to the biggest. |
familyset |
vector of copula families |
order_hash |
hashmap of parental orders |
e |
environment containing all the hashmaps |
verbose |
if |
method |
indicates the estimation method ( |
default_envir returns an environment to be passed
to BiCopCondFit or to ComputeCondMargin. BiCopCondFit
returns the fitted copula object of v, w given cond_set.
ComputeCondMargin returns the fitted conditional margins of v
given cond_set.
Both functions store all intermediary results in e to save computation
time.
DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) mydata = PCBN_sim(my_PCBN, N = 5) e = default_envir() ls(e) C_13 = BiCopCondFit(data = mydata, DAG = DAG, v = "U1", w = "U3", cond_set = c(), familyset = 1, order_hash = order_hash, e = e, method = "mle") C_23_1 = BiCopCondFit(data = mydata, DAG = DAG, v = "U2", w = "U3", cond_set = "U1", familyset = 1, order_hash = order_hash, e = e, method = "itau") U_2_13 = ComputeCondMargin(data = mydata, DAG = DAG, v = "U2", cond_set = c("U1", "U3"), familyset = 1, order_hash = order_hash, e = e, method = "mle")DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) mydata = PCBN_sim(my_PCBN, N = 5) e = default_envir() ls(e) C_13 = BiCopCondFit(data = mydata, DAG = DAG, v = "U1", w = "U3", cond_set = c(), familyset = 1, order_hash = order_hash, e = e, method = "mle") C_23_1 = BiCopCondFit(data = mydata, DAG = DAG, v = "U2", w = "U3", cond_set = "U1", familyset = 1, order_hash = order_hash, e = e, method = "itau") U_2_13 = ComputeCondMargin(data = mydata, DAG = DAG, v = "U2", cond_set = c("U1", "U3"), familyset = 1, order_hash = order_hash, e = e, method = "mle")
D-separation of two nodes given a set in a DAG
dsep_set(DAG, X, Y, Z = NULL)dsep_set(DAG, X, Y, Z = NULL)
DAG |
Directed Acyclic Graph |
X |
node |
Y |
node |
Z |
set |
TRUE if the sets are d-separated and FALSE if not
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, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') dsep_set(DAG, 'U1', 'U5')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, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') dsep_set(DAG, 'U1', 'U5')
Fills in all possible orders for the next node for each possible order
extend_orders(DAG, all_orders, node)extend_orders(DAG, all_orders, node)
DAG |
Directed Acyclic Graph |
all_orders |
list of orders |
node |
node |
list of order hashmaps
DAG = create_empty_DAG(4) 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, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') # Start with empty order order_hash = r2r::hashmap() all_orders_3 = find_all_orders_v(DAG, v = "U3", order_hash = order_hash) print(all_orders_3) # Two possible choices for node 3, let's use the first order_hash[['U3']] = all_orders_3[[1]] extended_orders = extend_orders(DAG, list(order_hash), node = 'U4') length(extended_orders) # We can extend this order in 4 ways: for (i in 1:length(extended_orders)){ print(extended_orders[[i]][['U4']]) } # We never pick U2 and U3 first, because their copula is not specifiedDAG = create_empty_DAG(4) 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, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') # Start with empty order order_hash = r2r::hashmap() all_orders_3 = find_all_orders_v(DAG, v = "U3", order_hash = order_hash) print(all_orders_3) # Two possible choices for node 3, let's use the first order_hash[['U3']] = all_orders_3[[1]] extended_orders = extend_orders(DAG, list(order_hash), node = 'U4') length(extended_orders) # We can extend this order in 4 ways: for (i in 1:length(extended_orders)){ print(extended_orders[[i]][['U4']]) } # We never pick U2 and U3 first, because their copula is not specified
Finds all possible copula assignments given a DAG
find_all_orders(DAG)find_all_orders(DAG)
DAG |
Directed Acyclic Graph |
a list of hashmaps containing the possible orders
DAG = create_empty_DAG(4) 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, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') all_orders = find_all_orders(DAG) length(all_orders) # 8 orders for (i in 1:length(all_orders)){ cat("Order ", i, ": \n") cat("U3:", all_orders[[i]][['U3']]) cat(" ; U4:", all_orders[[i]][['U4']], "\n") }DAG = create_empty_DAG(4) 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, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') all_orders = find_all_orders(DAG) length(all_orders) # 8 orders for (i in 1:length(all_orders)){ cat("Order ", i, ": \n") cat("U3:", all_orders[[i]][['U3']]) cat(" ; U4:", all_orders[[i]][['U4']], "\n") }
Finds all possible orders of node v given previous copula assignments
find_all_orders_v(DAG, v, order_hash)find_all_orders_v(DAG, v, order_hash)
DAG |
Directed Acyclic Graph |
v |
node |
order_hash |
hashmap of orders |
list of vectors containing all possible orders for v
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, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') 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') # Start with empty order order_hash = r2r::hashmap() all_orders_3 = find_all_orders_v(DAG, v = "U3", order_hash = order_hash) print(all_orders_3) # Two possible choices for node 3, let's use the first order_hash[['U3']] = all_orders_3[[1]] all_orders_4 = find_all_orders_v(DAG, v = "U4", order_hash = order_hash) print(all_orders_4) # Four possible choices for node 4, let's use the third order_hash[['U4']] = all_orders_4[[3]] all_orders_5 = find_all_orders_v(DAG, v = "U5", order_hash = order_hash) print(all_orders_5) # Eight possible orders for node 5; let's use the fourth order_hash[['U5']] = all_orders_5[[4]]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, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') 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') # Start with empty order order_hash = r2r::hashmap() all_orders_3 = find_all_orders_v(DAG, v = "U3", order_hash = order_hash) print(all_orders_3) # Two possible choices for node 3, let's use the first order_hash[['U3']] = all_orders_3[[1]] all_orders_4 = find_all_orders_v(DAG, v = "U4", order_hash = order_hash) print(all_orders_4) # Four possible choices for node 4, let's use the third order_hash[['U4']] = all_orders_4[[3]] all_orders_5 = find_all_orders_v(DAG, v = "U5", order_hash = order_hash) print(all_orders_5) # Eight possible orders for node 5; let's use the fourth order_hash[['U5']] = all_orders_5[[4]]
Find all the B-sets of a given DAG
Find the B sets for a given node v
find_B_sets(DAG) find_B_sets_v(DAG, v)find_B_sets(DAG) find_B_sets_v(DAG, v)
DAG |
A bnlearn graph object |
v |
node at which we want to find the B-sets |
find_B_sets returns a list with three elements
B_sets list of B-sets matrices for each node;
has_interfering_vstrucs a boolean specifying if the graph
contains interfering v-structures or not;
nodes_with_inter_vs a list containing nodes forming the
interfering v-structures.
find_B_sets_v returns a boolean matrix with (2 + length(children))
columns and length(parents) rows.
This is also true if length(parents) == 0 and length(parents) == 1.
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') find_B_sets_v(DAG, v = 'U5') B_sets = find_B_sets(DAG) B_sets$B_setsDAG = 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') find_B_sets_v(DAG, v = 'U5') B_sets = find_B_sets(DAG) B_sets$B_sets
Find among parents of a node, the one that has a conditional copula specified
find_cond_copula_specified(DAG, order_hash, v, cond)find_cond_copula_specified(DAG, order_hash, v, cond)
DAG |
Directed Acyclic Graph object corresponding to the model |
order_hash |
hashmap of orders of the parental sets |
v |
node in DAG |
cond |
vector of nodes in DAG. This must not be empty.
It is assumed that conditionally independent nodes have already been
removed by the function |
a list with
a node w such that the conditional copula
has been specified in the model.
If no such node can be found, an error message is raised.
the set cond[-v]
DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") find_cond_copula_specified(DAG = DAG, order_hash = order_hash, v = "U3", cond = c("U1")) # returns "U1" because the copula c_{1,3} is known find_cond_copula_specified(DAG = DAG, order_hash = order_hash, v = "U3", cond = c("U1", "U2")) # returns "U2" because the copula c_{2,3|1} is knownDAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") find_cond_copula_specified(DAG = DAG, order_hash = order_hash, v = "U3", cond = c("U1")) # returns "U1" because the copula c_{1,3} is known find_cond_copula_specified(DAG = DAG, order_hash = order_hash, v = "U3", cond = c("U1", "U2")) # returns "U2" because the copula c_{2,3|1} is known
Find all interfering v-structures for a given collection of B-sets
find_interfering_v_from_B_sets(B_sets)find_interfering_v_from_B_sets(B_sets)
B_sets |
a boolean matrix with |
NULL if there is no interfering v-structures.
Else, it returns a data.frame with 4 columns
A: a list of children of v
B: a list of children of v, disjoint from A
parents.A.but.not.parents.B: a list of common parents of
nodes of A, that are not parents of nodes of B
parents.B.but.not.parents.A: a list of common parents of
nodes of B, that are not parents of nodes of A
Each line correspond to 1 interfering v-structure.
DAG = create_empty_DAG(7) 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, 'U5', 'U6') DAG = bnlearn::set.arc(DAG, 'U2', 'U7') DAG = bnlearn::set.arc(DAG, 'U5', 'U7') B_sets = find_B_sets_v(DAG, v = 'U5') find_interfering_v_from_B_sets(B_sets) # Adding the missing arc DAG = bnlearn::set.arc(DAG, 'U1', 'U7') # Now no interfering v-structure B_sets = find_B_sets_v(DAG, v = 'U5') find_interfering_v_from_B_sets(B_sets)DAG = create_empty_DAG(7) 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, 'U5', 'U6') DAG = bnlearn::set.arc(DAG, 'U2', 'U7') DAG = bnlearn::set.arc(DAG, 'U5', 'U7') B_sets = find_B_sets_v(DAG, v = 'U5') find_interfering_v_from_B_sets(B_sets) # Adding the missing arc DAG = bnlearn::set.arc(DAG, 'U1', 'U7') # Now no interfering v-structure B_sets = find_B_sets_v(DAG, v = 'U5') find_interfering_v_from_B_sets(B_sets)
Fit the copulas of a PCBN given data
Fit all possible orders given a DAG
fit_copulas( data, DAG, order_hash, familyset = c(1, 3, 4, 5, 6), familyMatrix = NULL, e, verbose = 1, method = "mle" ) fit_all_orders( data, DAG, familyset = c(1, 3, 4, 5, 6), e, score_metric = "BIC", verbose = 1 )fit_copulas( data, DAG, order_hash, familyset = c(1, 3, 4, 5, 6), familyMatrix = NULL, e, verbose = 1, method = "mle" ) fit_all_orders( data, DAG, familyset = c(1, 3, 4, 5, 6), e, score_metric = "BIC", verbose = 1 )
data |
data frame |
DAG |
Directed Acyclic Graph |
order_hash |
hashmap of parental orders |
familyset |
vector of copula families |
familyMatrix |
matrix of families, with named rows and columns.
This should be used if the copula families are known/fixed.
This overrides |
e |
environment containing all the hashmaps |
verbose |
if |
method |
indicates the estimation method ( |
score_metric |
name of the metric used to choose the best order.
Possible choices are |
fit_copulas returns the fitted PCBN, with an additional
element called metrics which is a named vector of length 3 with names
c("logLik", "BIC", "AIC"), where
and ,
for a sample size n and nparameters is the number of parameters.
fit_all_orders returns a list containing:
best_fit the PCBN which is the best according to the metric
score_metric.
fitted_list the list of all fitted PCBNs.
metrics the matrix of metrics (logLik, BIC, AIC).
Each row i of this matrix corresponds to a PCBN with a different set
of parents' orderings, and corresponds to element i of
fitted_list.
BiCopCondFit which this function wraps.
DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) mydata = PCBN_sim(my_PCBN, N = 5) e = default_envir() result = fit_copulas(data = mydata, DAG = DAG, order_hash = order_hash, familyset = 1, e = e) result_all_orders = fit_all_orders(data = mydata, DAG = DAG, familyset = 1, e = e) # The two fitted PCBNs are: print(result_all_orders$fitted_list[[1]]) print(result_all_orders$fitted_list[[2]]) # and the metrics matrix is: print(result_all_orders$metrics) # The PCBN corresponding to the true order U1 < U2 is usually better # than the second one. This Will be more clear with a bigger sample size.DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) mydata = PCBN_sim(my_PCBN, N = 5) e = default_envir() result = fit_copulas(data = mydata, DAG = DAG, order_hash = order_hash, familyset = 1, e = e) result_all_orders = fit_all_orders(data = mydata, DAG = DAG, familyset = 1, e = e) # The two fitted PCBNs are: print(result_all_orders$fitted_list[[1]]) print(result_all_orders$fitted_list[[2]]) # and the metrics matrix is: print(result_all_orders$metrics) # The PCBN corresponding to the true order U1 < U2 is usually better # than the second one. This Will be more clear with a bigger sample size.
Checks if graph has interfering v-structures
has_interfering_vstrucs(DAG, verbose = 0)has_interfering_vstrucs(DAG, verbose = 0)
DAG |
Directed Acyclic Graph |
verbose |
if |
TRUE if graph contains (at least) an interfering v-structure,
and FALSE if it does not contain any interfering v-structure.
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') # There is one interfering v-structure has_interfering_vstrucs(DAG, verbose = 1) DAG = bnlearn::set.arc(DAG, 'U1', 'U5') # Now no interfering v-structure has_interfering_vstrucs(DAG)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') # There is one interfering v-structure has_interfering_vstrucs(DAG, verbose = 1) DAG = bnlearn::set.arc(DAG, 'U1', 'U5') # Now no interfering v-structure has_interfering_vstrucs(DAG)
Checks if a given (conditional) copula has already been specified
is_cond_copula_specified(DAG, order_hash, w, v, cond)is_cond_copula_specified(DAG, order_hash, w, v, cond)
DAG |
Directed Acyclic Graph object corresponding to the model |
order_hash |
hashmap of orders of the parental sets |
w |
node in DAG |
v |
node in DAG |
cond |
vector of nodes in DAG. It is assumed to have been already sorted. |
TRUE if the conditional copula
has been specified in the model
DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") is_cond_copula_specified(DAG = DAG, order_hash = order_hash, w = "U1", v = "U3", cond = c()) # returns TRUE because the copula c_{1,3} is known is_cond_copula_specified(DAG = DAG, order_hash = order_hash, w = "U2", v = "U3", cond = c()) # returns FALSE because the copula c_{2,3} is not known is_cond_copula_specified(DAG = DAG, order_hash = order_hash, w = "U2", v = "U3", cond = c("U1")) # returns TRUE because the copula c_{2,3 | 1} is knownDAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") is_cond_copula_specified(DAG = DAG, order_hash = order_hash, w = "U1", v = "U3", cond = c()) # returns TRUE because the copula c_{1,3} is known is_cond_copula_specified(DAG = DAG, order_hash = order_hash, w = "U2", v = "U3", cond = c()) # returns FALSE because the copula c_{2,3} is not known is_cond_copula_specified(DAG = DAG, order_hash = order_hash, w = "U2", v = "U3", cond = c("U1")) # returns TRUE because the copula c_{2,3 | 1} is known
Check whether a certain order abides by the B-sets
is_order_abiding_Bsets(DAG, order_hash) is_order_abiding_Bsets_v(B_sets, orderParents)is_order_abiding_Bsets(DAG, order_hash) is_order_abiding_Bsets_v(B_sets, orderParents)
DAG |
the considered DAG |
order_hash |
the hashmaps of parents ordering |
B_sets |
matrix of B-sets, assumed to be increasing.
This can be the output of |
orderParents |
a vector of characters, interpreted as the ordered parents |
It returns 'TRUE' if the order abides by the B-sets, and 'FALSE' else.
DAG = create_empty_DAG(4) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') DAG = bnlearn::set.arc(DAG, 'U1', 'U4') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") order_hash[['U4']] = c("U1", "U3") is_order_abiding_Bsets(DAG, order_hash) order_hash[['U3']] = c("U2", "U1") is_order_abiding_Bsets(DAG, order_hash)DAG = create_empty_DAG(4) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') DAG = bnlearn::set.arc(DAG, 'U1', 'U4') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") order_hash[['U4']] = c("U1", "U3") is_order_abiding_Bsets(DAG, order_hash) order_hash[['U3']] = c("U2", "U1") is_order_abiding_Bsets(DAG, order_hash)
This functions checks whether the DAG is restricted, i.e. whether it has no active cycles nor any interfering v-structures.
is_restrictedDAG(DAG, verbose = 2, check_both = TRUE)is_restrictedDAG(DAG, verbose = 2, check_both = TRUE)
DAG |
the DAG object |
verbose |
if |
check_both |
if |
TRUE if the PCBN satisfies both restrictions.
FALSE if at least one of the restrictions is not satisfies.
DAG_to_restrictedDAG for one way of making the DAG
to be restricted if it is not the case.
active_cycles to find all active cycles.
has_interfering_vstrucs to check only for interfering v-structures.
DAG = create_empty_DAG(4) DAG = bnlearn::set.arc(DAG, 'U1', 'U2') DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') is_restrictedDAG(DAG) # 1 active cycleDAG = create_empty_DAG(4) DAG = bnlearn::set.arc(DAG, 'U1', 'U2') DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') is_restrictedDAG(DAG) # 1 active cycle
This function computes the log-likelihood of the PCBN model given a dataset
of i.i.d. observations uniformly (or approximatively uniformly) distributed
on . This is the same as the logarithm of the density of the PCBN
at the observations.
## S3 method for class 'PCBN' logLik(object, data_uniform, ...)## S3 method for class 'PCBN' logLik(object, data_uniform, ...)
object |
the PCBN object |
data_uniform |
the dataset for which the log-likelihood is computed. It must have already been standardized to uniform margins. |
... |
other arguments, ignored for the moment |
the log-likelihood of the PCBN model for the given dataset
DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) mydata = PCBN_sim(my_PCBN, N = 10) logLik(my_PCBN, mydata)DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) mydata = PCBN_sim(my_PCBN, N = 10) logLik(my_PCBN, mydata)
Initializes PCBN class
new_PCBN(DAG, order_hash, copula_mat, verbose = 0)new_PCBN(DAG, order_hash, copula_mat, verbose = 0)
DAG |
the corresponding DAG (a 'bn' object) |
order_hash |
a hashmap of character vectors Each character vector corresponds to the order of the parents for the given node. |
copula_mat |
a list with at least two components:
They both should be matrices of size |
verbose |
If |
the new PCBN
DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam))DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam))
Checks a path for converging connections and chords.
path_hasConvergingConnections(DAG, path) path_hasChords(DAG, path)path_hasConvergingConnections(DAG, path) path_hasChords(DAG, path)
DAG |
Directed Acyclic Graph. |
path |
character vector of nodes in the DAG forming a trail. |
path_hasConvergingConnections returns TRUE
if the path contains a converging connection.
path_hasChords returns TRUE if the path contains a chord.
active_cycles which uses these two functions.
DAG = create_empty_DAG(4) DAG = bnlearn::set.arc(DAG, 'U1', 'U2') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') path_hasConvergingConnections(DAG, c('U1', 'U2', 'U3', 'U4') ) # FALSE path_hasChords(DAG, c('U1', 'U2', 'U3', 'U4') ) # FALSE DAG = bnlearn::set.arc(DAG, 'U1', 'U4') path_hasConvergingConnections(DAG, c('U1', 'U2', 'U3', 'U4') ) # FALSE path_hasChords(DAG, c('U1', 'U2', 'U3', 'U4') ) # TRUE: has a chord DAG = create_empty_DAG(4) DAG = bnlearn::set.arc(DAG, 'U1', 'U2') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') DAG = bnlearn::set.arc(DAG, 'U4', 'U3') path_hasConvergingConnections(DAG, c('U1', 'U2', 'U3', 'U4') ) # TRUE: has a converging connection path_hasChords(DAG, c('U1', 'U2', 'U3', 'U4') ) # FALSEDAG = create_empty_DAG(4) DAG = bnlearn::set.arc(DAG, 'U1', 'U2') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') path_hasConvergingConnections(DAG, c('U1', 'U2', 'U3', 'U4') ) # FALSE path_hasChords(DAG, c('U1', 'U2', 'U3', 'U4') ) # FALSE DAG = bnlearn::set.arc(DAG, 'U1', 'U4') path_hasConvergingConnections(DAG, c('U1', 'U2', 'U3', 'U4') ) # FALSE path_hasChords(DAG, c('U1', 'U2', 'U3', 'U4') ) # TRUE: has a chord DAG = create_empty_DAG(4) DAG = bnlearn::set.arc(DAG, 'U1', 'U2') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') DAG = bnlearn::set.arc(DAG, 'U4', 'U3') path_hasConvergingConnections(DAG, c('U1', 'U2', 'U3', 'U4') ) # TRUE: has a converging connection path_hasChords(DAG, c('U1', 'U2', 'U3', 'U4') ) # FALSE
This function computes the Probability Density Function of a PCBN model.
PCBN_PDF(PCBN, newdata)PCBN_PDF(PCBN, newdata)
PCBN |
PCBN object |
newdata |
new data on which the PDF should be computed |
This is a wrapper to logLik.PCBN.
the probability density at newdata.
DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) mydata = PCBN_sim(my_PCBN, N = 10) PCBN_PDF(my_PCBN, mydata)DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) mydata = PCBN_sim(my_PCBN, N = 10) PCBN_PDF(my_PCBN, mydata)
Simulate data from a specified PCBN
PCBN_sim(object, N, check_PCBN = TRUE, verbose = 1)PCBN_sim(object, N, check_PCBN = TRUE, verbose = 1)
object |
PCBN object to simulate from. This does not work if the PCBN does not abide by the B-sets. And in general, it does not work if the PCBN is outside of the class of restricted PCBNs. |
N |
sample size |
check_PCBN |
check whether the given PCBN satisfies the restrictions.
If this is set to |
verbose |
if |
a data frame of N samples
DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) mydata = PCBN_sim(my_PCBN, N = 5)DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) mydata = PCBN_sim(my_PCBN, N = 5)
Print and plot PCBN objects
## S3 method for class 'PCBN' plot(x, ...) ## S3 method for class 'PCBN' print(x, print.orders = "non-empty", ...)## S3 method for class 'PCBN' plot(x, ...) ## S3 method for class 'PCBN' print(x, print.orders = "non-empty", ...)
x |
PCBN object |
... |
other arguments, unused |
print.orders |
if |
No return value, both functions are called for side effects only.
DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) print(my_PCBN) plot(my_PCBN)DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") fam = matrix(c(0, 0, 1, 0, 0, 1, 0, 0, 0), byrow = TRUE, ncol = 3) tau = 0.2 * fam my_PCBN = new_PCBN( DAG, order_hash, copula_mat = list(tau = tau, fam = fam)) print(my_PCBN) plot(my_PCBN)
When given a partial order of a PCBN, one can complete it by adding one of the parents' node to the partial order. Some nodes can be added; they are then called "possible candidates".
possible_candidates(DAG, v, order_v, order_hash, B_minus_O) possible_candidate_incoming_arc(DAG, w, v, order_v, order_hash) possible_candidate_outgoing_arc(DAG, w, v, order_v, order_hash)possible_candidates(DAG, v, order_v, order_hash, B_minus_O) possible_candidate_incoming_arc(DAG, w, v, order_v, order_hash) possible_candidate_outgoing_arc(DAG, w, v, order_v, order_hash)
DAG |
Directed Acyclic Graph. |
order_v |
partial order for node v. |
order_hash |
hashmap of parental orders |
B_minus_O |
this is the current B-set, without the elements of
|
w, v
|
nodes in DAG. |
possible_candidate_incoming_arc returns a node o such w
is a parent of o, and w can be used as an incoming arc to
v by the node o. If no such o can be found, w
cannot be used as a potential candidate for the order of v by incoming
arc. Then, the function possible_candidate_incoming_arc returns
NULL.
In the same way, possible_candidate_outgoing_arc returns a node
o such o is a parent of w, and w can be used as
an outgoing arc to v by the node o.
possible_candidates returns a vector of possible candidates,
potentially empty.
Both possible_candidate_incoming_arc and
possible_candidate_outgoing_arc return either a node o, or
NULL if they could not find such a node.
dsep_set for checking whether two sets of nodes are d-separated
by another set.
find_B_sets to find the B-sets.
DAG = create_empty_DAG(4) 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, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") # Node of interest v = "U4" # If we start by 1, then the arc 1 -> 3 cannot be used as an incoming arc # (it is actually an outgoing arc) possible_candidate_incoming_arc( DAG = DAG, w = "U3", v = v, order_v = c("U1"), order_hash = order_hash) possible_candidate_outgoing_arc( DAG = DAG, w = "U3", v = v, order_v = c("U1"), order_hash = order_hash) possible_candidates( DAG = DAG, v = v, order_v = c("U1"), order_hash = order_hash, B_minus_O = "U2")DAG = create_empty_DAG(4) 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, 'U2', 'U4') DAG = bnlearn::set.arc(DAG, 'U3', 'U4') order_hash = r2r::hashmap() order_hash[['U3']] = c("U1", "U2") # Node of interest v = "U4" # If we start by 1, then the arc 1 -> 3 cannot be used as an incoming arc # (it is actually an outgoing arc) possible_candidate_incoming_arc( DAG = DAG, w = "U3", v = v, order_v = c("U1"), order_hash = order_hash) possible_candidate_outgoing_arc( DAG = DAG, w = "U3", v = v, order_v = c("U1"), order_hash = order_hash) possible_candidates( DAG = DAG, v = v, order_v = c("U1"), order_hash = order_hash, B_minus_O = "U2")
Remove elements from a conditioning set by using conditional independence
remove_CondInd(DAG, node, cond_set)remove_CondInd(DAG, node, cond_set)
DAG |
Directed Acyclic Graph |
node |
node |
cond_set |
vector of nodes in conditioning set |
a vector containing the nodes that cannot be removed from the conditioning set.
DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') remove_CondInd(DAG = DAG, node = "U1", cond_set = c("U2")) remove_CondInd(DAG = DAG, node = "U3", cond_set = c("U1"))DAG = create_empty_DAG(3) DAG = bnlearn::set.arc(DAG, 'U1', 'U3') DAG = bnlearn::set.arc(DAG, 'U2', 'U3') remove_CondInd(DAG = DAG, node = "U1", cond_set = c("U2")) remove_CondInd(DAG = DAG, node = "U3", cond_set = c("U1"))