use rand::Rng;
use std::sync::Arc;
use crate::observation::Observation;
use crate::substrates::graph::{BinaryGraphState, MatchInfo};
use crate::universe::InformationUniverse;
use std::collections::HashMap;
pub type ObsOutput<U> = <<U as InformationUniverse>::Observation as Observation<
<U as InformationUniverse>::State,
>>::Output;
pub type NullEnsembles<U> = Vec<Vec<Vec<ObsOutput<U>>>>;
pub type RuleGenerator<U> = dyn FnMut(&mut dyn Rng) -> (Vec<<U as InformationUniverse>::Rule>, f64);
pub type BooleanTester<U> = dyn Fn(&[<U as InformationUniverse>::Rule]) -> HashMap<String, usize>;
pub type TestEnsembles<U> = Vec<Vec<Vec<ObsOutput<U>>>>;
pub type ConditionPredicate<R> = dyn Fn(&[R]) -> bool + Send + Sync;
pub type MetricFn<T> = dyn Fn(&[Vec<T>]) -> f64 + Send + Sync;
pub type GraphObserverFn = dyn Fn(&BinaryGraphState) -> Vec<u8> + Sync;
pub type ConditionFn = Arc<dyn Fn(&BinaryGraphState, usize) -> Option<MatchInfo> + Send + Sync>;
pub type ActionFn =
Arc<dyn Fn(&BinaryGraphState, &MatchInfo, &mut dyn Rng) -> BinaryGraphState + Send + Sync>;
pub type TruthTable = [((u8, u8), u8)];