use open_hypergraphs::category::*;
use open_hypergraphs::{array::vec::*, finite_function::*};
use super::strategy::{
arrow_strategy, coequalizer_and_permutation_strategy, parallel_arrows_strategy,
};
use proptest::{prelude::Strategy, prop_assert_eq, proptest};
proptest! {
#[test]
fn test_coequalizer_commutes([f,g] in parallel_arrows_strategy(None,None,true)) {
let c = f.coequalizer(&g).expect("By construction same domain");
let lhs = f.compose(&c).expect("By construction composable");
let rhs = g.compose(&c).expect("By construction composable");
prop_assert_eq!(lhs, rhs);
}
#[test]
fn test_coequalize_zero_map(
f in arrow_strategy(None, None, false)
.prop_filter("0 domain", |f| f.source()>0)
) {
use std::collections::HashSet;
let im_f: HashSet<usize> = f.table.iter().copied().collect();
let zero_map : FiniteFunction<VecKind> = FiniteFunction::constant(f.source(),0,f.target()-1);
let coeq = f.coequalizer(&zero_map).expect("correct arguments");
let mut components_seen = HashSet::new();
for (q, &component) in coeq.table.iter().enumerate() {
if im_f.contains(&q) || q == 0 {
assert_eq!(component, 0);
} else {
assert!(component > 0);
assert!(components_seen.insert(component),
"Component {} was used multiple times", component);
}
}
}
#[test]
fn test_coequalizer_universal_identity([f,g] in parallel_arrows_strategy(None,None,true)) {
let q = f.coequalizer(&g).expect("By construction same domain");
let u = q.coequalizer_universal(&q).expect("coequalizer universal succeeds");
prop_assert_eq!(u, FiniteFunction::identity(q.target()));
}
#[test]
fn test_coequalizer_and_permutation([f,g,q,p] in coequalizer_and_permutation_strategy(true)) {
prop_assert_eq!(f.target,g.target);
prop_assert_eq!(f.target,q.source());
prop_assert_eq!(p.source(),q.target);
let q1 = q.compose(&p).expect("By construction composable");
let u = q.coequalizer_universal(&q1).expect("Coequalizer universal succeeds");
let lhs = q.compose(&u).expect("By construction composable");
prop_assert_eq!(lhs, q1);
}
}
#[test]
fn hardcoded_test_coequalizer_universal_identity() {
let common_source = 10;
let f: FiniteFunction<VecKind> =
FiniteFunction::new(VecArray(vec![0; common_source]), 7).unwrap();
let mut g_vec = VecArray(vec![0; common_source - 1]);
g_vec.push(1);
let g = FiniteFunction::new(g_vec, 7).unwrap();
let q = f.coequalizer(&g).expect("By construction same domain");
assert_eq!(q.table, VecArray(vec![0, 0, 1, 2, 3, 4, 5]));
assert_eq!(q.target, 6);
let u = q
.coequalizer_universal(&q)
.expect("coequalizer universal succeeds");
assert_eq!(u, FiniteFunction::identity(q.target));
}