use crate::brcd::brcd_boss_config::BossConfig;
use crate::brcd::brcd_boss_cpdag::dag_to_cpdag;
use crate::brcd::brcd_boss_score::BicScorer;
use crate::brcd::brcd_boss_search::best_order_search;
use crate::brcd::{BrcdError, BrcdErrorEnum};
use deep_causality_algebra::RealField;
use deep_causality_num::FromPrimitive;
use deep_causality_tensor::{CausalTensor, CausalTensorStatsExt};
use deep_causality_topology::MixedGraph;
pub fn boss_learn<T>(
data: &CausalTensor<T>,
config: &BossConfig<T>,
) -> Result<MixedGraph<()>, BrcdError>
where
T: RealField + FromPrimitive,
{
let (n, p) = match data.shape() {
[rows, cols] => (*rows, *cols),
_ => return Err(BrcdError(BrcdErrorEnum::DimensionMismatch)),
};
if p == 0 {
return Err(BrcdError(BrcdErrorEnum::DimensionMismatch));
}
if n < 2 {
return Err(BrcdError(BrcdErrorEnum::EmptyData));
}
let cov = data
.sample_covariance()
.map_err(|_| BrcdError(BrcdErrorEnum::DimensionMismatch))?;
let scorer = BicScorer::new(&cov, n, config)?;
let result = best_order_search(&scorer, config.seed)?;
dag_to_cpdag(&result.parents)
}