From 88ae20ff8254dd60c3de252e49369d4125f9e1a2 Mon Sep 17 00:00:00 2001 From: hachem Date: Sun, 29 Sep 2024 16:10:02 +0200 Subject: ASCII rendering engine --- examples/visualizers/src/main.rs | 15 +++- libpsi-visualizer/Cargo.toml | 3 +- libpsi-visualizer/src/cli/horizontal_cli.rs | 33 ++++---- libpsi-visualizer/src/cli/mod.rs | 2 + libpsi-visualizer/src/cli/renderer.rs | 116 ++++++++++++++++++++++++++++ libpsi-visualizer/src/lib.rs | 2 +- 6 files changed, 154 insertions(+), 17 deletions(-) create mode 100644 libpsi-visualizer/src/cli/renderer.rs diff --git a/examples/visualizers/src/main.rs b/examples/visualizers/src/main.rs index f328e4d..ed5755a 100644 --- a/examples/visualizers/src/main.rs +++ b/examples/visualizers/src/main.rs @@ -1 +1,14 @@ -fn main() {} +use libpsi_core::*; +use libpsi_visualizer::*; + +fn main() { + let mut circuit = QuantumCircuit::new(2, 2); + circuit.apply(&gates::HADAMARD, &[], &[0]); + circuit.apply(&gates::CNOT, &[0], &[1]); + + let mut visualizer = HorizontalCLIVisualizer::new(&circuit); + visualizer.render(); + + let runtime = BasicRT::new(&circuit); + runtime.execute(1024); +} diff --git a/libpsi-visualizer/Cargo.toml b/libpsi-visualizer/Cargo.toml index ecc31a2..aae9e45 100644 --- a/libpsi-visualizer/Cargo.toml +++ b/libpsi-visualizer/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" edition = "2021" [dependencies] -libpsi-core = { path = "../libpsi-core" } \ No newline at end of file +libpsi-core = { path = "../libpsi-core" } +term_size = "0.3.2" diff --git a/libpsi-visualizer/src/cli/horizontal_cli.rs b/libpsi-visualizer/src/cli/horizontal_cli.rs index ad551ae..151dae1 100644 --- a/libpsi-visualizer/src/cli/horizontal_cli.rs +++ b/libpsi-visualizer/src/cli/horizontal_cli.rs @@ -12,29 +12,34 @@ c1: ═══════════════════════════════════════════════■═════════▓ */ -use crate::Visualizer; +use crate::{renderer::*, Visualizer}; use libpsi_core::QuantumCircuit; +#[allow(unused)] pub struct HorizontalCLIVisualizer<'a> { circuit: &'a QuantumCircuit, + renderer: CLIRenderer, } impl<'a> Visualizer<'a> for HorizontalCLIVisualizer<'a> { fn new(circuit: &'a QuantumCircuit) -> HorizontalCLIVisualizer<'a> { - HorizontalCLIVisualizer { circuit } + let terminal_width = term_size::dimensions().unwrap().0; + HorizontalCLIVisualizer { + circuit, + renderer: CLIRenderer::new(terminal_width), + } } - // NOTE(Hachem): This is a temporary function - fn render(&self) { - for instruction in self.circuit.get_instructions() { - print!("Applied {} on ", &instruction.gate.0); - for bit_index in instruction.control_indices { - print!("q{} ", bit_index); - } - for bit_index in instruction.target_indices { - print!("q{} ", bit_index); - } - println!(); - } + fn render(&mut self) { + self.renderer.draw_quad(Quad::new(2, 2, 2, 2), false); + self.renderer.draw_quad(Quad::new(5, 10, 6, 3), true); + self.renderer.draw_quad(Quad::new(17, 4, 17, 10), true); + self.renderer.draw_quad(Quad::new(15, 7, 7, 4), false); + + self.renderer.draw_vline(4, 4, 5, true); + self.renderer.draw_hline(3, 6, 5, false); + + self.renderer.draw_text(4, 15, "This is some text."); + println!("{}", self.renderer.to_string()); } } diff --git a/libpsi-visualizer/src/cli/mod.rs b/libpsi-visualizer/src/cli/mod.rs index fe10249..e1c8736 100644 --- a/libpsi-visualizer/src/cli/mod.rs +++ b/libpsi-visualizer/src/cli/mod.rs @@ -1,2 +1,4 @@ pub mod horizontal_cli; +pub mod renderer; + pub use horizontal_cli::*; diff --git a/libpsi-visualizer/src/cli/renderer.rs b/libpsi-visualizer/src/cli/renderer.rs new file mode 100644 index 0000000..d95d609 --- /dev/null +++ b/libpsi-visualizer/src/cli/renderer.rs @@ -0,0 +1,116 @@ +pub struct Quad { + pub x: usize, + pub y: usize, + pub width: usize, + pub height: usize, +} + +impl Quad { + pub fn new(x: usize, y: usize, width: usize, height: usize) -> Quad { + Quad { + x, + y, + width, + height, + } + } +} + +pub struct CLIRenderer { + buffer: Vec>, +} + +impl CLIRenderer { + pub fn new(width: usize) -> CLIRenderer { + CLIRenderer { + buffer: vec![vec![' '; width]; 1], + } + } + + pub fn to_string(&self) -> String { + self.buffer + .clone() + .into_iter() + .map(|inner| inner.into_iter().collect::()) + .collect::>() + .join("\n") + } + + pub fn place(&mut self, x: usize, y: usize, character: char) { + if y >= self.buffer.len() { + self.buffer.resize( + y + 1, + vec![' '; self.buffer.get(0).map_or(0, |row| row.len())], + ); + } + + if x >= self.buffer[y].len() { + self.buffer[y].resize(x + 1, ' '); + } + self.buffer[y][x] = character; + } + + pub fn get(&mut self, x: usize, y: usize) -> char { + if y >= self.buffer.len() { + self.buffer.resize( + y + 1, + vec![' '; self.buffer.get(0).map_or(0, |row| row.len())], + ); + } + + if x >= self.buffer[y].len() { + self.buffer[y].resize(x + 1, ' '); + } + self.buffer[y][x] + } + + pub fn draw_text(&mut self, x: usize, y: usize, text: &'static str) { + for i in 0..text.len() { + self.place(x + i, y, text.as_bytes()[i].into()); + } + } + + pub fn draw_vline(&mut self, x: usize, y: usize, height: usize, thick: bool) { + for i in y..y + height { + if self.get(x, i) == '─' { + self.place(x, i, if thick { '╫' } else { '┼' }); + } else if self.get(x, i) == '═' { + self.place(x, i, if thick { '║' } else { '╫' }); + } else { + self.place(x, i, if thick { '║' } else { '│' }) + } + } + } + + pub fn draw_hline(&mut self, x: usize, y: usize, width: usize, thick: bool) { + for i in x..x + width { + if self.get(i, y) == '│' { + self.place(i, y, if thick { '╪' } else { '┼' }); + } else if self.get(i, y) == '║' { + self.place(i, y, if thick { '║' } else { '╫' }); + } else { + self.place(i, y, if thick { '═' } else { '─' }) + } + } + } + + pub fn draw_quad(&mut self, quad: Quad, thick: bool) { + for x in quad.x..quad.x + quad.width { + for y in quad.y..quad.y + quad.height { + if x == quad.x && y == quad.y { + self.place(x, y, if thick { '╔' } else { '┌' }); + } else if x == quad.x + quad.width - 1 && y == quad.y { + self.place(x, y, if thick { '╗' } else { '┐' }); + } else if x == quad.x && y == quad.y + quad.height - 1 { + self.place(x, y, if thick { '╚' } else { '└' }); + } else if x == quad.x + quad.width - 1 && y == quad.y + quad.height - 1 { + self.place(x, y, if thick { '╝' } else { '┘' }); + } else if y == quad.y || y == quad.y + quad.height - 1 { + self.draw_hline(x, y, 1, thick); + } else if x == quad.x || x == quad.x + quad.width - 1 { + self.draw_vline(x, y, 1, thick); + } + } + } + } +} diff --git a/libpsi-visualizer/src/lib.rs b/libpsi-visualizer/src/lib.rs index 72bb588..f880436 100644 --- a/libpsi-visualizer/src/lib.rs +++ b/libpsi-visualizer/src/lib.rs @@ -5,5 +5,5 @@ pub use cli::*; pub trait Visualizer<'a> { fn new(circuit: &'a QuantumCircuit) -> Self; - fn render(&self); + fn render(&mut self); } -- cgit v1.3