wiki-graph-laplacian.rs

2.2 kB · rust · 72 lines

1use mrlycore::errors::Result;2use mrlyfig::{ink, plot, save, Board, Color, Frame};3use std::f64::consts::PI;45const VERTICES: usize = 32;6const CEILING: f64 = 4.0;78fn path() -> Vec<f64> {9    (0..VERTICES)10        .map(|k| 2.0 - 2.0 * (PI * k as f64 / VERTICES as f64).cos())11        .collect()12}1314fn cycle() -> Vec<f64> {15    let mut out: Vec<f64> = (0..VERTICES)16        .map(|k| 2.0 - 2.0 * (2.0 * PI * k as f64 / VERTICES as f64).cos())17        .collect();18    out.sort_by(|a, b| a.partial_cmp(b).expect("a finite spectrum"));19    out20}2122fn distinct(values: &[f64]) -> usize {23    let mut count = 1;24    for pair in values.windows(2) {25        if pair[1] - pair[0] > 1e-9 {26            count += 1;27        }28    }29    count30}3132fn steps(board: &mut Board, frame: Frame, values: &[f64], thick: f64, paint: Color) {33    let slot = frame.w / values.len() as f64;34    let mut pts = Vec::with_capacity(values.len() * 2);35    for (index, value) in values.iter().enumerate() {36        let y = frame.y + frame.h * (1.0 - value / CEILING);37        pts.push((frame.x + index as f64 * slot, y));38        pts.push((frame.x + (index + 1) as f64 * slot, y));39    }40    board.polyline(&pts, thick, paint);41    for (index, value) in values.iter().enumerate() {42        let y = frame.y + frame.h * (1.0 - value / CEILING);43        board.disc(frame.x + (index as f64 + 0.5) * slot, y, thick * 0.9, paint);44    }45}4647fn main() -> Result<()> {48    let line = path();49    let ring = cycle();50    assert_eq!((line.len(), ring.len()), (VERTICES, VERTICES));51    assert_eq!((distinct(&line), distinct(&ring)), (32, 17));52    assert!(line[0].abs() < 1e-12 && ring[0].abs() < 1e-12);53    assert!((ring[VERTICES - 1] - CEILING).abs() < 1e-12);5455    let mut board = Board::square();56    let frame = board.frame(0.08);57    let stage = frame.inset(frame.w * 0.04);58    plot::baseline(&mut board, stage, ink::line());59    for k in 1..4 {60        let y = stage.y + stage.h * (1.0 - k as f64 / CEILING);61        board.segment(62            (stage.x, y),63            (stage.x + stage.w, y),64            1.5,65            ink::fade(ink::dim(), 0.7),66        );67    }68    steps(&mut board, stage, &ring, 7.0, ink::orange());69    steps(&mut board, stage, &line, 7.0, ink::blue());70    save("wiki-graph-laplacian", &board)?;71    Ok(())72}