diff options
| author | hachem <im@hachem.wtf> | 2025-12-06 21:20:43 +0100 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2025-12-06 21:20:43 +0100 |
| commit | 609f7276fc1fb484be34b232d35426f91ddb9b71 (patch) | |
| tree | 8cfc9a68ac184cb01111ddbef1f3a77b0b62b91f /libpsi-visualizer/src/cli/horizontal_cli.rs | |
| parent | 1fef726728a14cc923c7cbaf80d337b4eb35db3c (diff) | |
[add]: complete horizonal renderer
Diffstat (limited to 'libpsi-visualizer/src/cli/horizontal_cli.rs')
| -rw-r--r-- | libpsi-visualizer/src/cli/horizontal_cli.rs | 279 |
1 files changed, 246 insertions, 33 deletions
diff --git a/libpsi-visualizer/src/cli/horizontal_cli.rs b/libpsi-visualizer/src/cli/horizontal_cli.rs index 3f02c59..b1b851b 100644 --- a/libpsi-visualizer/src/cli/horizontal_cli.rs +++ b/libpsi-visualizer/src/cli/horizontal_cli.rs @@ -1,44 +1,257 @@ -/* - NOTE(Hachem): This is what I would like the output to be like - - ┌───┐ ┌───────┐ ┌─────────┐ - |q0>: ─────┤ H ├────┤ C-NOT ├────┤ MEASURE ├───────────────────▓ - └───┘ └───┬───┘ └────┬────┘ - │ │ ┌─────────┐ - |q1>: ──────────────────■─────────────┼─────────┤ MEASURE ├────▓ - │ └────┬────┘ - │ │ - c0: ════════════════════════════════■══════════════╪═════════▓ - c1: ═══════════════════════════════════════════════■═════════▓ -*/ - use core::fmt; +use libpsi_core::{GateOp, QuantumCircuit}; -use crate::{renderer::*, Visualizer}; -use libpsi_core::QuantumCircuit; - -#[allow(unused)] -pub struct HorizontalCLIVisualizer<'a> { - circuit: &'a QuantumCircuit<'a>, - renderer: CLIRenderer, +pub struct HorizontalRenderer<'a> { + circuit: &'a QuantumCircuit, } -impl<'a> fmt::Display for HorizontalCLIVisualizer<'a> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.renderer.to_string()) +impl<'a> HorizontalRenderer<'a> { + pub fn new(circuit: &'a QuantumCircuit) -> Self { + HorizontalRenderer { circuit } } } -impl<'a> Visualizer<'a> for HorizontalCLIVisualizer<'a> { - fn new(circuit: &'a QuantumCircuit) -> HorizontalCLIVisualizer<'a> { - let terminal_width = term_size::dimensions().unwrap().0; - HorizontalCLIVisualizer { - circuit, - renderer: CLIRenderer::new(terminal_width), +impl<'a> fmt::Display for HorizontalRenderer<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let nq = self.circuit.num_qubits(); + let nc = self.circuit.num_classical(); + let ops = self.circuit.operations(); + + let mut q_lines: Vec<String> = (0..nq).map(|i| format!("q{}: ", i)).collect(); + let mut c_lines: Vec<String> = (0..nc).map(|i| format!("c{}: ", i)).collect(); + + let max_label = q_lines + .iter() + .chain(c_lines.iter()) + .map(|s| s.len()) + .max() + .unwrap_or(3); + + for line in &mut q_lines { + while line.len() < max_label { + line.insert(0, ' '); + } + } + for line in &mut c_lines { + while line.len() < max_label { + line.insert(0, ' '); + } + } + let mut gap_line = " ".repeat(max_label); + + if ops.is_empty() { + for line in &q_lines { + writeln!(f, "{}───", line)?; + } + if nc > 0 { + writeln!(f, "{} ", gap_line)?; + for line in &c_lines { + writeln!(f, "{}═══", line)?; + } + } + return Ok(()); + } + + for op in ops { + let q_targets = op.quantum_targets(); + + let min_q = q_targets.iter().min().copied().unwrap_or(0); + let max_q = q_targets.iter().max().copied().unwrap_or(0); + + match op { + GateOp::H(t) => { + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *t { + line.push_str("─[H]─"); + } else { + line.push_str("─────"); + } + } + for line in c_lines.iter_mut() { + line.push_str("═════"); + } + gap_line.push_str(" "); + } + GateOp::X(t) => { + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *t { + line.push_str("─[X]─"); + } else { + line.push_str("─────"); + } + } + for line in c_lines.iter_mut() { + line.push_str("═════"); + } + gap_line.push_str(" "); + } + GateOp::Y(t) => { + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *t { + line.push_str("─[Y]─"); + } else { + line.push_str("─────"); + } + } + for line in c_lines.iter_mut() { + line.push_str("═════"); + } + gap_line.push_str(" "); + } + GateOp::Z(t) => { + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *t { + line.push_str("─[Z]─"); + } else { + line.push_str("─────"); + } + } + for line in c_lines.iter_mut() { + line.push_str("═════"); + } + gap_line.push_str(" "); + } + GateOp::S(t) => { + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *t { + line.push_str("─[S]─"); + } else { + line.push_str("─────"); + } + } + for line in c_lines.iter_mut() { + line.push_str("═════"); + } + gap_line.push_str(" "); + } + GateOp::T(t) => { + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *t { + line.push_str("─[T]─"); + } else { + line.push_str("─────"); + } + } + for line in c_lines.iter_mut() { + line.push_str("═════"); + } + gap_line.push_str(" "); + } + GateOp::CNOT(c, t) => { + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *c { + line.push_str("──●──"); + } else if i == *t { + line.push_str("──⊕──"); + } else if i > min_q && i < max_q { + line.push_str("──│──"); + } else { + line.push_str("─────"); + } + } + for line in c_lines.iter_mut() { + line.push_str("═════"); + } + gap_line.push_str(" "); + } + GateOp::CZ(c, t) => { + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *c || i == *t { + line.push_str("──●──"); + } else if i > min_q && i < max_q { + line.push_str("──│──"); + } else { + line.push_str("─────"); + } + } + for line in c_lines.iter_mut() { + line.push_str("═════"); + } + gap_line.push_str(" "); + } + GateOp::SWAP(a, b) => { + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *a || i == *b { + line.push_str("──╳──"); + } else if i > min_q && i < max_q { + line.push_str("──│──"); + } else { + line.push_str("─────"); + } + } + for line in c_lines.iter_mut() { + line.push_str("═════"); + } + gap_line.push_str(" "); + } + GateOp::CCNOT(c1, c2, t) => { + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *c1 || i == *c2 { + line.push_str("──●──"); + } else if i == *t { + line.push_str("──⊕──"); + } else if i > min_q && i < max_q { + line.push_str("──│──"); + } else { + line.push_str("─────"); + } + } + for line in c_lines.iter_mut() { + line.push_str("═════"); + } + gap_line.push_str(" "); + } + GateOp::CSWAP(c, t1, t2) => { + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *c { + line.push_str("──●──"); + } else if i == *t1 || i == *t2 { + line.push_str("──╳──"); + } else if i > min_q && i < max_q { + line.push_str("──│──"); + } else { + line.push_str("─────"); + } + } + for line in c_lines.iter_mut() { + line.push_str("═════"); + } + gap_line.push_str(" "); + } + GateOp::Measure(q, c) => { + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *q { + line.push_str("─[M]─"); + } else if i > *q { + line.push_str("──║──"); + } else { + line.push_str("─────"); + } + } + for (i, line) in c_lines.iter_mut().enumerate() { + if i == *c { + line.push_str("══╩══"); + } else if i < *c { + line.push_str("══║══"); + } else { + line.push_str("═════"); + } + } + gap_line.push_str(" ║ "); + } + } + } + + for line in &q_lines { + writeln!(f, "{}", line)?; + } + if nc > 0 { + writeln!(f, "{}", gap_line)?; + for line in &c_lines { + writeln!(f, "{}", line)?; + } } - } - fn render(&mut self) { - println!("{}", self); + Ok(()) } } |
