Run the BOSS (Best Order Score Search) algorithm for causal discovery using one of several engines.
Details
For specific details on the supported scores, and parameters for each engine, see:
TetradSearch for Tetrad.
Recommendation
While it is possible to call the function returned directly with a data frame,
we recommend using disco(). This provides a consistent interface and handles knowledge
integration.
Value
A function that takes a single argument data (a data frame). When called,
this function returns a list containing:
knowledgeAKnowledgeobject with the background knowledge used in the causal discovery algorithm. Seeknowledge()for how to construct it.caugiAcaugi::caugiobject (of classPDAG) representing the learned causal graph from the causal discovery algorithm.
References
Andrews, B., Ramsey, J., Sánchez-Romero, R., Camchong, J., & Kummerfeld, E. (2023, December). Fast scalable and accurate discovery of DAGs using the Best Order Score Search and Grow-Shrink Trees. Advances in Neural Information Processing Systems, 36, 63945-63956. Epub 2024 May 30. PMID: 39280091; PMCID: PMC11393735.
See also
Other causal discovery algorithms:
boss_fci(),
fci(),
ges(),
gfci(),
grasp(),
grasp_fci(),
gs(),
iamb-family,
pc(),
rfci(),
sp_fci(),
tfci(),
tges(),
tpc()
Examples
data(tpc_example)
# Requires Tetrad to be installed
if (verify_tetrad()$installed && verify_tetrad()$java_ok) {
# Recommended path using disco()
boss_tetrad <- boss(engine = "tetrad", score = "sem_bic")
disco(tpc_example, boss_tetrad)
# or using boss_tetrad directly
boss_tetrad(tpc_example)
}
#> <Disco UNKNOWN: 6 nodes | 6 edges>
#> nodes: child_x2, child_x1, youth_x4, youth_x3, oldage_x6, oldage_x5
#> edges: child_x2---child_x1, child_x2-->oldage_x5, child_x2---youth_x4
#> oldage_x5-->oldage_x6, youth_x3-->oldage_x5, youth_x4-->oldage_x6
#### With tier knowledge ####
if (verify_tetrad()$installed && verify_tetrad()$java_ok) {
kn <- knowledge(
tpc_example,
tier(
child ~ tidyselect::starts_with("child"),
youth ~ tidyselect::starts_with("youth"),
oldage ~ tidyselect::starts_with("oldage")
)
)
# Recommended path using disco()
boss_tetrad <- boss(engine = "tetrad", score = "sem_bic")
disco(tpc_example, boss_tetrad, knowledge = kn)
# or using boss_tetrad directly
boss_tetrad <- boss_tetrad |> set_knowledge(kn)
boss_tetrad(tpc_example)
}
#> <Disco UNKNOWN: 6 nodes | 6 edges>
#> nodes: child_x2, child_x1, youth_x4, youth_x3, oldage_x6, oldage_x5
#> edges: child_x2---child_x1, child_x2-->oldage_x5, child_x2-->youth_x4
#> oldage_x5-->oldage_x6, youth_x3-->oldage_x5, youth_x4-->oldage_x6
# With all algorithm arguments specified
if (verify_tetrad()$installed && verify_tetrad()$java_ok) {
boss_tetrad <- boss(
engine = "tetrad",
score = "gic",
num_starts = 2,
use_bes = FALSE,
use_data_order = FALSE,
output_cpdag = FALSE
)
disco(tpc_example, boss_tetrad)
}
#> The learned graph is not a valid CPDAG because of conflicting edge orientations, which can happen due to statistical errors in finite samples, violations of faithfulness, or latent confounding; it is reported as PDAG instead.
#> <Disco PDAG: 6 nodes | 6 edges>
#> nodes: child_x2, child_x1, youth_x4, youth_x3, oldage_x6, oldage_x5
#> edges: child_x2-->child_x1, child_x2-->oldage_x5, child_x2-->youth_x4
#> oldage_x5-->oldage_x6, youth_x3-->oldage_x5, youth_x4-->oldage_x6
