table.rs

4.3 kB · rust · 149 lines

1use crate::groups::{group, orbit, Elem};2use crate::rules::RULES;3use mrlymath::bang::universe::degree;4use mrlynum::boolean::walsh_spectrum;5use std::collections::BTreeSet;67pub fn levelset(code: usize) -> bool {8    let mut value = [-1i8; 4];9    for i in 0..8usize {10        let bit = ((code >> i) & 1) as i8;11        let w = i.count_ones() as usize;12        if value[w] != -1 && value[w] != bit {13            return false;14        }15        value[w] = bit;16    }17    true18}1920pub fn pin(code: usize) -> bool {21    let cells: Vec<usize> = (0..8).filter(|i| (code >> i) & 1 == 1).collect();22    if cells.is_empty() {23        return false;24    }25    let fixed = (0..3)26        .filter(|axis| {27            cells28                .iter()29                .map(|c| (c >> axis) & 1)30                .collect::<BTreeSet<_>>()31                .len()32                == 133        })34        .count();35    cells.len() == 1 << (3 - fixed)36}3738pub fn genus(code: usize, b3: &[Elem]) -> &'static str {39    let cls = orbit(code, b3);40    if cls.iter().any(|&c| levelset(c)) {41        "iso"42    } else if cls.iter().any(|&c| pin(c)) {43        "axis"44    } else {45        "comp"46    }47}4849pub fn levels(code: usize) -> [i64; 4] {50    let spectrum = walsh_spectrum(code as u128, 3);51    let mut out = [0i64; 4];52    for (s, w) in spectrum.iter().enumerate() {53        out[s.count_ones() as usize] += w;54    }55    out56}5758pub struct Row {59    pub code: usize,60    pub rep_b3: usize,61    pub rep_h: usize,62    pub rep_both: usize,63    pub size_b3: usize,64    pub size_h: usize,65    pub size_both: usize,66    pub pop: u32,67    pub degree: i32,68    pub genus: &'static str,69    pub levels: [i64; 4],70    pub affine: bool,71}7273pub fn rows() -> Vec<Row> {74    let b3 = group("B3");75    let h = group("H");76    let both = group("B3xZ2");77    (0..RULES)78        .map(|code| {79            let ob = orbit(code, &b3);80            let oh = orbit(code, &h);81            let oz = orbit(code, &both);82            let d = degree(code as u128, 3);83            Row {84                code,85                rep_b3: *ob.iter().next().expect("nonempty"),86                rep_h: *oh.iter().next().expect("nonempty"),87                rep_both: *oz.iter().next().expect("nonempty"),88                size_b3: ob.len(),89                size_h: oh.len(),90                size_both: oz.len(),91                pop: (code as u32).count_ones(),92                degree: d,93                genus: genus(code, &b3),94                levels: levels(code),95                affine: d <= 1,96            }97        })98        .collect()99}100101pub fn report() {102    println!("PER-RULE TABLE");103    println!("code repB3 repH repB3xZ2 sizeB3 sizeH sizeB3xZ2 pop deg genus S0 S1 S2 S3 affine");104    let rows = rows();105    for row in &rows {106        println!(107            "{} {} {} {} {} {} {} {} {} {} {} {} {} {} {}",108            row.code,109            row.rep_b3,110            row.rep_h,111            row.rep_both,112            row.size_b3,113            row.size_h,114            row.size_both,115            row.pop,116            row.degree,117            row.genus,118            row.levels[0],119            row.levels[1],120            row.levels[2],121            row.levels[3],122            if row.affine { 1 } else { 0 }123        );124    }125    for row in &rows {126        assert_eq!(127            row.levels[0],128            8 - 2 * row.pop as i64,129            "the weight-zero Walsh sum of {} is not 8 - 2 pop",130            row.code131        );132    }133    let affine = rows.iter().filter(|r| r.affine).count();134    let iso = rows.iter().filter(|r| r.genus == "iso").count();135    let axis = rows.iter().filter(|r| r.genus == "axis").count();136    let comp = rows.iter().filter(|r| r.genus == "comp").count();137    println!("affine rules {affine}; genus counts iso {iso} axis {axis} comp {comp}");138    let mut classes: Vec<&Row> = rows.iter().filter(|r| r.code == r.rep_b3).collect();139    classes.sort_by_key(|r| r.code);140    let ci = classes.iter().filter(|r| r.genus == "iso").count();141    let ca = classes.iter().filter(|r| r.genus == "axis").count();142    let cc = classes.iter().filter(|r| r.genus == "comp").count();143    println!(144        "B3 classes {} with genus iso {ci} axis {ca} comp {cc}",145        classes.len()146    );147    let sizes: BTreeSet<usize> = classes.iter().map(|r| r.size_b3).collect();148    println!("B3 orbit sizes {sizes:?}");149}