use super::*;
use crate::bcd::Irrep;
use num_rational::Ratio;
fn ivec(entries: &[(usize, usize, i64)]) -> Vec<(usize, usize, i64)> {
let mut v = entries.to_vec();
v.sort_unstable();
v
}
fn sorted_sp(seed: &Seed, i: usize) -> Vec<(usize, usize, i64)> {
let mut v = seed.raising()[i].clone();
v.sort_unstable();
v
}
#[test]
fn excluded_low_ranks_rejected() {
assert!(matches!(
defining_seed(Series::B, 1),
Err(BcdError::ExcludedRank { .. })
));
assert!(matches!(
defining_seed(Series::C, 1),
Err(BcdError::ExcludedRank { .. })
));
assert!(matches!(
defining_seed(Series::D, 2),
Err(BcdError::ExcludedRank { .. })
));
assert!(defining_seed(Series::B, 2).is_ok());
assert!(defining_seed(Series::C, 2).is_ok());
assert!(defining_seed(Series::D, 3).is_ok());
}
#[test]
fn spn_c2_entries() {
let s = defining_seed(Series::C, 2).unwrap();
assert_eq!(s.dim(), 4);
assert_eq!(sorted_sp(&s, 0), ivec(&[(0, 1, 1), (2, 3, 1)]));
assert_eq!(sorted_sp(&s, 1), ivec(&[(1, 2, 1)]));
assert_eq!(s.cartan()[0], vec![1, -1, 1, -1]);
assert_eq!(s.cartan()[1], vec![1, 1, -1, -1]);
}
#[test]
fn spn_c3_entries() {
let s = defining_seed(Series::C, 3).unwrap();
assert_eq!(s.dim(), 6);
assert_eq!(sorted_sp(&s, 0), ivec(&[(0, 1, 1), (4, 5, 1)]));
assert_eq!(sorted_sp(&s, 1), ivec(&[(1, 2, 1), (3, 4, 1)]));
assert_eq!(sorted_sp(&s, 2), ivec(&[(2, 3, 1)]));
assert_eq!(s.cartan()[0], vec![1, -1, 0, 0, 1, -1]);
assert_eq!(s.cartan()[1], vec![1, 1, -2, 2, -1, -1]);
assert_eq!(s.cartan()[2], vec![1, 1, 1, -1, -1, -1]);
}
#[test]
fn son_b2_entries() {
let s = defining_seed(Series::B, 2).unwrap();
assert_eq!(s.dim(), 5);
assert_eq!(sorted_sp(&s, 0), ivec(&[(1, 3, 1), (2, 0, 1)]));
assert_eq!(sorted_sp(&s, 1), ivec(&[(0, 4, 1), (4, 1, 1)]));
assert_eq!(s.cartan()[0], vec![1, -1, 0, 0, 0]);
assert_eq!(s.cartan()[1], vec![0, 0, 1, -1, 0]);
}
#[test]
fn sen_d3_entries() {
let s = defining_seed(Series::D, 3).unwrap();
assert_eq!(s.dim(), 6);
assert_eq!(sorted_sp(&s, 0), ivec(&[(1, 3, 1), (2, 0, 1)]));
assert_eq!(sorted_sp(&s, 1), ivec(&[(3, 5, 1), (4, 2, 1)]));
assert_eq!(sorted_sp(&s, 2), ivec(&[(0, 3, 1), (2, 1, 1)]));
assert_eq!(s.cartan()[0], vec![1, -1, 0, 0, 0, 0]);
assert_eq!(s.cartan()[1], vec![0, 0, 1, -1, 0, 0]);
assert_eq!(s.cartan()[2], vec![0, 0, 0, 0, 1, -1]);
}
#[test]
fn dims_match_s30_defining_wdim() {
for (series, r, want) in [
(Series::B, 2usize, 5u32),
(Series::C, 2, 4),
(Series::D, 3, 6),
(Series::B, 3, 7),
(Series::C, 3, 6),
(Series::D, 4, 8),
(Series::B, 4, 9),
(Series::C, 4, 8),
] {
let s = defining_seed(series, r).unwrap();
assert_eq!(s.dim() as u32, want, "{series:?}_{r} dim");
let mut dynkin = vec![0i64; r];
dynkin[0] = 1;
let irr = Irrep::from_dynkin(series, &dynkin).unwrap();
assert_eq!(
irr.dim(),
num_bigint::BigInt::from(s.dim()),
"{series:?}_{r} vs S3.0 wdim"
);
}
}
#[test]
fn commutators_pass_all_series_and_ranks() {
for series in [Series::B, Series::C, Series::D] {
for r in series_ranks(series) {
let s = defining_seed(series, r).unwrap();
check_commutators(&s).unwrap_or_else(|e| panic!("{series:?}_{r}: {e}"));
}
}
}
fn series_ranks(series: Series) -> Vec<usize> {
match series {
Series::B => vec![2, 3, 4, 5],
Series::C => vec![2, 3, 4, 5],
Series::D => vec![3, 4, 5, 6],
}
}
#[test]
fn report_cartan_and_roots_are_exact() {
let rep = check_commutators(&defining_seed(Series::C, 2).unwrap()).unwrap();
let one = Ratio::from_integer(1);
let zero = Ratio::from_integer(0);
let half = Ratio::new(1, 2);
assert_eq!(rep.cartan_coeffs[0], vec![one, zero]);
assert_eq!(rep.cartan_coeffs[1], vec![-half, half]);
let two = Ratio::from_integer(2);
let mtwo = Ratio::from_integer(-2);
assert_eq!(rep.root_weights[0], vec![two, zero]); assert_eq!(rep.root_weights[1], vec![mtwo, two]);
let repb = check_commutators(&defining_seed(Series::B, 2).unwrap()).unwrap();
assert_eq!(repb.cartan_coeffs[1], vec![one, zero]);
}
fn weight_vectors(seed: &Seed) -> Vec<Vec<i64>> {
(0..seed.dim())
.map(|k| seed.cartan().iter().map(|z| z[k]).collect())
.collect()
}
#[test]
fn son_sen_weights_are_the_vector_rep_weight_set() {
for (series, r) in [(Series::B, 3usize), (Series::D, 4usize), (Series::B, 2)] {
let s = defining_seed(series, r).unwrap();
let mut got = weight_vectors(&s);
got.sort();
let mut want: Vec<Vec<i64>> = Vec::new();
for i in 0..r {
let mut p = vec![0i64; r];
p[i] = 1;
want.push(p.clone());
p[i] = -1;
want.push(p);
}
if series == Series::B {
want.push(vec![0i64; r]); }
want.sort();
assert_eq!(got, want, "{series:?}_{r} weight set");
}
}
#[test]
fn cartan_traceless_and_weights_negation_closed() {
for series in [Series::B, Series::C, Series::D] {
for r in series_ranks(series) {
let s = defining_seed(series, r).unwrap();
for z in s.cartan() {
assert_eq!(z.iter().sum::<i64>(), 0, "{series:?}_{r} traceless");
}
let mut w = weight_vectors(&s);
let mut neg: Vec<Vec<i64>> = w.iter().map(|v| v.iter().map(|x| -x).collect()).collect();
w.sort();
neg.sort();
assert_eq!(w, neg, "{series:?}_{r} weight set ±-closed");
}
}
}
fn mutated(series: Series, r: usize, f: impl FnOnce(&mut Seed)) -> Seed {
let mut s = defining_seed(series, r).unwrap();
f(&mut s);
s
}
#[test]
fn mutation_drop_paired_ladder_entry_fails() {
let s = mutated(Series::C, 3, |s| {
s.raising_mut()[0].truncate(1);
});
assert!(matches!(
check_commutators(&s),
Err(BcdError::CommutatorViolation { .. })
));
}
#[test]
fn mutation_flip_fork_entry_fails() {
let s = mutated(Series::D, 3, |s| {
let fork = &mut s.raising_mut()[2];
for e in fork.iter_mut() {
if e.0 == 2 && e.1 == 1 {
*e = (2, 0, 1);
}
}
});
assert!(matches!(
check_commutators(&s),
Err(BcdError::CommutatorViolation { .. })
));
}
#[test]
fn mutation_scale_ladder_entry_fails() {
let s = mutated(Series::B, 2, |s| {
s.raising_mut()[0][0].2 = 2;
});
assert!(matches!(
check_commutators(&s),
Err(BcdError::CommutatorViolation { .. })
));
}
#[test]
fn mutation_perturb_cartan_diagonal_fails() {
let s = mutated(Series::C, 2, |s| {
s.cartan_mut()[0][0] = 3;
});
assert!(matches!(
check_commutators(&s),
Err(BcdError::CommutatorViolation { .. })
));
}