diff options
| author | hachem <im@hachem.wtf> | 2026-08-24 14:48:36 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-08-24 14:48:36 +0200 |
| commit | 24d639224ca11112025289065d7538851606b56e (patch) | |
| tree | e7e26c89cd20099f03ff32727ba0af2cf4762088 /src/visualizer/horizontal_cli.rs | |
| parent | 548dc42d9f454cb8c29fddb88ca41f8b1b595882 (diff) | |
[chore]: unwrap project
Diffstat (limited to 'src/visualizer/horizontal_cli.rs')
| -rw-r--r-- | src/visualizer/horizontal_cli.rs | 463 |
1 files changed, 463 insertions, 0 deletions
diff --git a/src/visualizer/horizontal_cli.rs b/src/visualizer/horizontal_cli.rs new file mode 100644 index 0000000..28cdb5a --- /dev/null +++ b/src/visualizer/horizontal_cli.rs @@ -0,0 +1,463 @@ +use super::renderer::Visualizer; +use core::fmt; +use crate::{GateOp, QuantumCircuit}; + +pub struct HorizontalRenderer<'a> { + circuit: &'a QuantumCircuit, +} + +impl<'a> HorizontalRenderer<'a> { + pub fn new(circuit: &'a QuantumCircuit) -> Self { + HorizontalRenderer { circuit } + } +} + +impl<'a> Visualizer for HorizontalRenderer<'a> { + fn export(&self) -> String { + format!("{}", self) + } +} + +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::Sdg(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::Tdg(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::Sx(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::Sxdg(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::Rx(t, theta) => { + let label = format!("[Rx({:.2})]", theta); + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *t { + line.push_str(&format!("─{}─", label)); + } else { + line.push_str(&format!("─{}─", "─".repeat(label.len()))); + } + } + for line in c_lines.iter_mut() { + line.push_str(&format!("═{}═", "═".repeat(label.len()))); + } + gap_line.push_str(&format!(" {} ", " ".repeat(label.len()))); + } + GateOp::Ry(t, theta) => { + let label = format!("[Ry({:.2})]", theta); + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *t { + line.push_str(&format!("─{}─", label)); + } else { + line.push_str(&format!("─{}─", "─".repeat(label.len()))); + } + } + for line in c_lines.iter_mut() { + line.push_str(&format!("═{}═", "═".repeat(label.len()))); + } + gap_line.push_str(&format!(" {} ", " ".repeat(label.len()))); + } + GateOp::Rz(t, theta) => { + let label = format!("[Rz({:.2})]", theta); + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *t { + line.push_str(&format!("─{}─", label)); + } else { + line.push_str(&format!("─{}─", "─".repeat(label.len()))); + } + } + for line in c_lines.iter_mut() { + line.push_str(&format!("═{}═", "═".repeat(label.len()))); + } + gap_line.push_str(&format!(" {} ", " ".repeat(label.len()))); + } + GateOp::P(t, theta) => { + let label = format!("[P({:.2})]", theta); + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *t { + line.push_str(&format!("─{}─", label)); + } else { + line.push_str(&format!("─{}─", "─".repeat(label.len()))); + } + } + for line in c_lines.iter_mut() { + line.push_str(&format!("═{}═", "═".repeat(label.len()))); + } + gap_line.push_str(&format!(" {} ", " ".repeat(label.len()))); + } + GateOp::U1(t, lambda) => { + let label = format!("[U1({:.2})]", lambda); + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *t { + line.push_str(&format!("─{}─", label)); + } else { + line.push_str(&format!("─{}─", "─".repeat(label.len()))); + } + } + for line in c_lines.iter_mut() { + line.push_str(&format!("═{}═", "═".repeat(label.len()))); + } + gap_line.push_str(&format!(" {} ", " ".repeat(label.len()))); + } + GateOp::U2(t, _, _) => { + let label = "[U2]"; + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *t { + line.push_str(&format!("─{}─", label)); + } else { + line.push_str(&format!("─{}─", "─".repeat(label.len()))); + } + } + for line in c_lines.iter_mut() { + line.push_str(&format!("═{}═", "═".repeat(label.len()))); + } + gap_line.push_str(&format!(" {} ", " ".repeat(label.len()))); + } + GateOp::U3(t, _, _, _) => { + let label = "[U3]"; + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *t { + line.push_str(&format!("─{}─", label)); + } else { + line.push_str(&format!("─{}─", "─".repeat(label.len()))); + } + } + for line in c_lines.iter_mut() { + line.push_str(&format!("═{}═", "═".repeat(label.len()))); + } + gap_line.push_str(&format!(" {} ", " ".repeat(label.len()))); + } + GateOp::CRx(c, t, theta) | GateOp::CRy(c, t, theta) | GateOp::CRz(c, t, theta) | GateOp::CP(c, t, theta) => { + let label = match op { + GateOp::CRx(_, _, _) => format!("[CRx({:.2})]", theta), + GateOp::CRy(_, _, _) => format!("[CRy({:.2})]", theta), + GateOp::CRz(_, _, _) => format!("[CRz({:.2})]", theta), + GateOp::CP(_, _, _) => format!("[CP({:.2})]", theta), + _ => unreachable!(), + }; + for (i, line) in q_lines.iter_mut().enumerate() { + if i == *c { + line.push_str(&format!("─{}─", "●".to_string() + &"─".repeat(label.len() - 1))); + } else if i == *t { + line.push_str(&format!("─{}─", label)); + } else if i > min_q && i < max_q { + line.push_str(&format!("─{}─", "│".to_string() + &"─".repeat(label.len() - 1))); + } else { + line.push_str(&format!("─{}─", "─".repeat(label.len()))); + } + } + for line in c_lines.iter_mut() { + line.push_str(&format!("═{}═", "═".repeat(label.len()))); + } + gap_line.push_str(&format!(" {} ", " ".repeat(label.len()))); + } + 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(" ║ "); + } + GateOp::Custom(gate, targets) => { + let name = &gate.name; + let label = format!("[{}]", name); + + for (i, line) in q_lines.iter_mut().enumerate() { + if targets.contains(&i) { + if i == targets[0] { + line.push_str(&format!("─{}─", label)); + } else { + line.push_str(&format!("─{}─", "─".repeat(label.len()))); + } + } else if i > min_q && i < max_q { + line.push_str(&format!( + "─{}─", + "│".to_string() + &"─".repeat(label.len() - 1) + )); + } else { + line.push_str(&format!("─{}─", "─".repeat(label.len()))); + } + } + for line in c_lines.iter_mut() { + line.push_str(&format!("═{}═", "═".repeat(label.len()))); + } + gap_line.push_str(&format!(" {} ", " ".repeat(label.len()))); + } + } + } + + for line in &q_lines { + writeln!(f, "{}░", line)?; + } + if nc > 0 { + writeln!(f, "{}░", gap_line)?; + for line in &c_lines { + writeln!(f, "{}░", line)?; + } + } + + Ok(()) + } +} |
