graphs.rs
5.5 kB · rust · 205 lines
1use mrlycore::{Rng, Tensor};2use mrlymath::bang::factory::{corners_to_code, residue_corners};3use mrlynum::graph::core_graph;4use std::collections::HashMap;56pub struct Graph {7 pub adjacency: Vec<Vec<u32>>,8}910impl Graph {11 pub fn nodes(&self) -> usize {12 self.adjacency.len()13 }1415 pub fn edges(&self) -> usize {16 self.adjacency.iter().map(|row| row.len()).sum::<usize>() / 217 }1819 pub fn from_pairs(nodes: usize, pairs: &[(usize, usize)]) -> Graph {20 let mut adjacency = vec![Vec::new(); nodes];21 for (a, b) in pairs {22 adjacency[*a].push(*b as u32);23 adjacency[*b].push(*a as u32);24 }25 Graph { adjacency }26 }2728 pub fn of(grid: &Tensor) -> Graph {29 let network = core_graph(grid).expect("a grid has a core graph");30 let pairs: Vec<(usize, usize)> = network31 .branches32 .iter()33 .map(|b| (b.parent, b.child))34 .collect();35 Graph::from_pairs(network.nodes.len(), &pairs)36 }3738 pub fn components(&self) -> usize {39 let mut parent: Vec<usize> = (0..self.nodes()).collect();40 for (node, row) in self.adjacency.iter().enumerate() {41 for other in row {42 let (a, b) = (root(&mut parent, node), root(&mut parent, *other as usize));43 if a != b {44 parent[a] = b;45 }46 }47 }48 (0..self.nodes())49 .filter(|node| root(&mut parent, *node) == *node)50 .count()51 }52}5354fn root(parent: &mut [usize], mut node: usize) -> usize {55 while parent[node] != node {56 parent[node] = parent[parent[node]];57 node = parent[node];58 }59 node60}6162pub fn carpet(level: usize) -> Graph {63 Graph::of(64 mrlymath::two::create(495, 3, level, 0, 3)65 .expect("the carpet renders")66 .types(),67 )68}6970pub fn sierpinski(level: usize) -> Graph {71 Graph::of(72 mrlymath::two::create(7, 2, level, 0, 2)73 .expect("the gasket renders")74 .types(),75 )76}7778fn sponge_code() -> u128 {79 let filled: Vec<Vec<u8>> = residue_corners(3, 3)80 .into_iter()81 .filter(|corner| corner.iter().filter(|digit| **digit == 1).count() <= 1)82 .collect();83 corners_to_code(&filled, 3, 3)84}8586pub fn sponge(level: usize) -> Graph {87 Graph::of(88 mrlymath::three::create(sponge_code(), 3, level, 3)89 .expect("the sponge renders")90 .types(),91 )92}9394pub fn square(side: usize) -> Graph {95 Graph::of(&Tensor::of(vec![1; side * side], vec![side, side]))96}9798pub fn random(nodes: usize, p: f64, seed: u64) -> Graph {99 let mut rng = Rng::new(seed);100 let mut pairs = Vec::new();101 for a in 0..nodes {102 for b in a + 1..nodes {103 if rng.chance(p) {104 pairs.push((a, b));105 }106 }107 }108 Graph::from_pairs(nodes, &pairs)109}110111type Point = [i32; 3];112type Triangle = [Point; 3];113114fn sponge_cell(mut cell: [usize; 3], level: usize) -> bool {115 for _ in 0..level {116 let ones = cell.iter().filter(|c| **c % 3 == 1).count();117 if ones > 1 {118 return false;119 }120 cell = [cell[0] / 3, cell[1] / 3, cell[2] / 3];121 }122 true123}124125fn cut_points(cell: [usize; 3], d: i32) -> Vec<Point> {126 let base = [2 * cell[0] as i32, 2 * cell[1] as i32, 2 * cell[2] as i32];127 let mut out = Vec::new();128 for axis in 0..3 {129 let others: Vec<usize> = (0..3).filter(|b| *b != axis).collect();130 for b1 in [0, 2] {131 for b2 in [0, 2] {132 if d - b1 - b2 == 1 {133 let mut p = base;134 p[axis] += 1;135 p[others[0]] += b1;136 p[others[1]] += b2;137 out.push(p);138 }139 }140 }141 }142 out143}144145fn sorted(mut t: Triangle) -> Triangle {146 t.sort();147 t148}149150fn dist2(u: &Point, v: &Point) -> i32 {151 (0..3).map(|k| (u[k] - v[k]) * (u[k] - v[k])).sum()152}153154fn cell_pieces(cell: [usize; 3], d: i32) -> Vec<Triangle> {155 let pts = cut_points(cell, d);156 if pts.len() == 3 {157 return vec![sorted([pts[0], pts[1], pts[2]])];158 }159 let mid = [160 2 * cell[0] as i32 + 1,161 2 * cell[1] as i32 + 1,162 2 * cell[2] as i32 + 1,163 ];164 let mut out = Vec::new();165 for i in 0..pts.len() {166 for j in i + 1..pts.len() {167 if dist2(&pts[i], &pts[j]) == 2 {168 out.push(sorted([mid, pts[i], pts[j]]));169 }170 }171 }172 out173}174175pub fn slice(level: usize) -> Graph {176 let n = 3usize.pow(level as u32);177 let sigma = (3 * n - 1) / 2;178 let mut triangles: Vec<Triangle> = Vec::new();179 for i in 0..n {180 for j in 0..n {181 for s in [sigma - 2, sigma - 1, sigma] {182 if s < i + j || s - i - j >= n {183 continue;184 }185 let cell = [i, j, s - i - j];186 if !sponge_cell(cell, level) {187 continue;188 }189 triangles.extend(cell_pieces(cell, 3 * n as i32 - 2 * s as i32));190 }191 }192 }193 let mut owners: HashMap<(Point, Point), Vec<usize>> = HashMap::new();194 for (index, t) in triangles.iter().enumerate() {195 for (a, b) in [(0, 1), (0, 2), (1, 2)] {196 owners.entry((t[a], t[b])).or_default().push(index);197 }198 }199 let pairs: Vec<(usize, usize)> = owners200 .values()201 .filter(|o| o.len() == 2)202 .map(|o| (o[0], o[1]))203 .collect();204 Graph::from_pairs(triangles.len(), &pairs)205}