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}