use ndarray::{arr1, arr2};
use rand::SeedableRng;
use rand::rngs::StdRng;
use crate::schedule::Schedule;
use crate::substrates::graph::rules::RewriteRule;
use crate::substrates::graph::schedule::AllVerticesSchedule;
use crate::substrates::graph::state::BinaryGraphState;
use crate::types::TruthTable;
pub fn test_boolean_function(
rules: &[RewriteRule],
truth_table: &TruthTable,
steps: usize,
n_trials: usize,
) -> bool {
let schedule = AllVerticesSchedule::new();
for &((a, b), expected) in truth_table {
let mut results = Vec::new();
for trial in 0..n_trials {
let adj = arr2(&[[0, 0, 1], [0, 0, 1], [0, 0, 0]]);
let labels = arr1(&[a as i8, b as i8, 0i8]);
let mut state = BinaryGraphState::new(3, adj.view(), labels.view())
.expect("Boolean test state creation");
let mut rng = StdRng::seed_from_u64((trial * 100) as u64);
for _ in 0..steps {
state = schedule.step(&state, rules, &mut rng);
}
results.push(state.label(2));
}
let ones = results.iter().filter(|&&x| x == 1).count();
let observed = if ones > results.len() / 2 { 1 } else { 0 };
if observed != expected {
return false;
}
}
true
}
pub fn verify_boolean_functions(
rules: &[RewriteRule],
steps: usize,
n_trials: usize,
) -> Vec<String> {
let gates: &[(&str, &TruthTable)] = &[
(
"NAND",
&[((0, 0), 1), ((0, 1), 1), ((1, 0), 1), ((1, 1), 0)],
),
("NOR", &[((0, 0), 1), ((0, 1), 0), ((1, 0), 0), ((1, 1), 0)]),
("AND", &[((0, 0), 0), ((0, 1), 0), ((1, 0), 0), ((1, 1), 1)]),
("OR", &[((0, 0), 0), ((0, 1), 1), ((1, 0), 1), ((1, 1), 1)]),
("XOR", &[((0, 0), 0), ((0, 1), 1), ((1, 0), 1), ((1, 1), 0)]),
];
let mut verified = Vec::new();
for (name, truth_table) in gates {
if test_boolean_function(rules, truth_table, steps, n_trials) {
verified.push(name.to_string());
}
}
verified
}