let causal_states significance_level discard_cell neighbourhoods past_depth pof_depth =
let length = Array.length neighbourhoods in
let plc_indexes = Array.init length
(fun i -> if discard_cell i then [||]
else Light_cones.build_lc_index neighbourhoods (succ past_depth) i
|> (ArrayLabels.sub ~pos:1 ~len:past_depth)) in
let flc_indexes = Array.init length
(fun i -> if discard_cell i then [||]
else Light_cones.build_lc_index neighbourhoods pof_depth i) in
let plc_identifiers = Light_cones.lc_identifiers plc_indexes in
let flc_identifiers = Light_cones.lc_identifiers flc_indexes in
fun past_configurations pof_configurations ->
let plcs, nb_plcs = plc_identifiers (Light_cones.lcState_of_lcIndex past_configurations) in
let flcs, nb_flcs = flc_identifiers (Light_cones.lcState_of_lcIndex pof_configurations) in
let unsorted_distributions = Array.make nb_plcs [] in
Femtolib.Array.iter2 (fun plc flc ->
if plc <> -1 && flc <> -1 then
unsorted_distributions.(plc) <- flc :: unsorted_distributions.(plc)) plcs flcs;
let sums unsorted_distribution output =
List.fold_left
(fun accu flc -> output.(flc) <- output.(flc) +1; succ accu)
0 unsorted_distribution in
let clusters = Clustering.create_clusters () in
let distribution = Array.make nb_flcs 0 in
let test = Statistic.Chi_square.close significance_level in
let add_unsorted_distribution unsorted_distribution =
for i=0 to pred nb_flcs do distribution.(i) <- 0 done;
let nb_samples = sums unsorted_distribution distribution in
Clustering.add clusters test distribution nb_samples in
let causal_state_of_plcId = Array.make nb_plcs (-2) in
let shuffle = Array.init nb_plcs identity in
Femtolib.Array.shuffle shuffle;
for i=0 to pred nb_plcs do
let i = shuffle.(i) in
causal_state_of_plcId.(i) <- add_unsorted_distribution unsorted_distributions.(i)
done;
let causal_states = Array.map (function -1 -> -1 | plc -> causal_state_of_plcId.(plc)) plcs in
let nbOccurences_of_causalStateId = Clustering.nb_samples clusters in
causal_states, nbOccurences_of_causalStateId