diff --git a/Cargo.lock b/Cargo.lock index 30703cfb..0ce8ce0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + [[package]] name = "anes" version = "0.1.6" @@ -137,6 +146,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "criterion" version = "0.4.0" @@ -216,6 +231,19 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2 1.0.47", + "quote 1.0.21", + "rustc_version", + "syn 1.0.103", +] + [[package]] name = "dot-writer" version = "0.1.2" @@ -234,6 +262,18 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "enum-as-inner" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" +dependencies = [ + "heck", + "proc-macro2 1.0.47", + "quote 1.0.21", + "syn 1.0.103", +] + [[package]] name = "fastrand" version = "1.8.0" @@ -444,6 +484,29 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy-regex" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff63c423c68ea6814b7da9e88ce585f793c87ddd9e78f646970891769c8235d4" +dependencies = [ + "lazy-regex-proc_macros", + "once_cell", + "regex", +] + +[[package]] +name = "lazy-regex-proc_macros" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8edfc11b8f56ce85e207e62ea21557cfa09bb24a8f6b04ae181b086ff8611c22" +dependencies = [ + "proc-macro2 1.0.47", + "quote 1.0.21", + "regex", + "syn 1.0.103", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -616,9 +679,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.15.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "oorandom" @@ -754,9 +817,12 @@ name = "quil-rs" version = "0.16.0-rc.4" dependencies = [ "criterion", + "derive_more", "dot-writer", + "enum-as-inner", "indexmap", "insta", + "lazy-regex", "lexical", "nom", "nom_locate", @@ -862,18 +928,20 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ + "aho-corasick", + "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "remove_dir_all" diff --git a/Cargo.toml b/Cargo.toml index 51b28239..2f6eb742 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,9 +9,12 @@ keywords = ["Quil", "Quantum", "Rigetti"] categories = ["parser-implementations", "science", "compilers", "emulators"] [dependencies] +derive_more = { version = "0.99.17", optional = true } dot-writer = { version = "0.1.2", optional = true } +enum-as-inner = "0.5.1" indexmap = "1.6.1" -lexical = "6.1.1" +lazy-regex = { version = "2.5.0", optional = true } +lexical = "6.1.1" nom = "7.1.1" nom_locate = "4.0.0" num-complex = "0.4.0" @@ -29,6 +32,7 @@ rstest = "0.15.0" [features] graphviz-dot = ["dot-writer"] +latex = ["derive_more", "lazy-regex"] [profile.release] lto = true diff --git a/src/instruction.rs b/src/instruction.rs index 87600e54..b369ecef 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use enum_as_inner::EnumAsInner; use nom_locate::LocatedSpan; use serde::{Deserialize, Serialize}; use std::borrow::Cow; @@ -1077,7 +1078,7 @@ mod test_instruction_display { } } -#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, EnumAsInner)] pub enum Qubit { Fixed(u64), Variable(String), diff --git a/src/lib.rs b/src/lib.rs index a60ee34f..1a6b4585 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,7 @@ //! [constructor for timing graphs]: crate::program::graph::ScheduledProgram#method.get_dot_format //! [expressions]: crate::expression::Expression //! [instructions]: crate::instruction::Instruction +//! [latex]: crate::program::latex::Latex#method.to_latex //! [parser]: crate::program::Program#method.from_str //! [programs]: crate::program::Program //! [serializer]: crate::program::Program#method.to_string diff --git a/src/program/latex/diagram/cell.rs b/src/program/latex/diagram/cell.rs new file mode 100644 index 00000000..c5bc3976 --- /dev/null +++ b/src/program/latex/diagram/cell.rs @@ -0,0 +1,146 @@ +use lazy_regex::{Lazy, Regex}; + +use crate::instruction::{Gate, GateModifier}; + +use super::super::{LatexGenError, RenderCommand, RenderSettings, Symbol}; + +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +pub(crate) enum QuantikzCell { + Gate(QuantikzGate), + Control(i64), + #[default] + Empty, +} + +pub(crate) struct CellSettings { + pub(crate) texify_numerical_constants: bool, +} + +impl From for CellSettings { + fn from(render_settings: RenderSettings) -> Self { + Self { + texify_numerical_constants: render_settings.texify_numerical_constants, + } + } +} + +impl QuantikzCell { + pub(crate) fn to_latex(&self, settings: &CellSettings) -> Result { + match self { + QuantikzCell::Empty => Ok(RenderCommand::Qw.to_string()), + QuantikzCell::Control(target) => Ok(RenderCommand::Ctrl(*target).to_string()), + QuantikzCell::Gate(QuantikzGate { + name, + parameter, + dagger_count, + ctrl_count, + }) => { + let mut superscript = String::new(); + (0..*dagger_count).for_each(|_| { + superscript.push_str(&RenderCommand::Super(String::from("dagger")).to_string()); + }); + + let symbol = parameter.clone().map(|p| { + if settings.texify_numerical_constants { + p.texify() + } else { + p + } + }); + if name == "PHASE" { + Ok(RenderCommand::Phase( + symbol.ok_or(LatexGenError::MissingParameter)?, + superscript + ).to_string() + ) + // the conditional defines a target gate + } else if name == "X" && *ctrl_count > 0 { + if *dagger_count > 0 { + Ok( + RenderCommand::Gate(name.to_string(), superscript).to_string() + ) + } else { + Ok(RenderCommand::Targ.to_string()) + } + } else { + Ok(RenderCommand::Gate(name.to_string(), superscript).to_string() + ) + } + } + } + } +} + +#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +pub(crate) struct QuantikzGate { + pub(crate) name: String, + pub(crate) parameter: Option, + pub(crate) dagger_count: usize, + pub(crate) ctrl_count: usize, +} + +impl TryFrom for QuantikzGate { + type Error = LatexGenError; + + fn try_from(gate: Gate) -> Result { + // regex to match canonical controlled gates + static ABBREVIATED_CONTROLLED_GATE: Lazy = Lazy::new(|| { + Regex::new("(?PC+)(?PPHASE|X|Y|Z|NOT)").expect("regex should be valid") + }); + + let mut canonical_gate = gate.name.to_string(); + let mut ctrl_count = 0; + if let Some(captures) = ABBREVIATED_CONTROLLED_GATE.captures(&gate.name) { + let base = captures + .name("base") + .expect("capture group should have value") + .as_str(); + + ctrl_count = captures + .name("count") + .expect("capture group should have value") + .as_str() + .len(); + + match base { + // NOT is an alias for X + "NOT" => canonical_gate = "X".to_string(), + _ => canonical_gate = base.to_string(), + } + } + + let mut dagger_count = 0; + for modifier in gate.modifiers { + match modifier { + GateModifier::Forked => { + return Err(LatexGenError::UnsupportedModifierForked); + } + GateModifier::Dagger => { + dagger_count += 1; + } + GateModifier::Controlled => { + ctrl_count += 1; + } + } + } + + if gate.parameters.len() > 1 { + return Err(LatexGenError::UnsupportedParameterLength { + gate: gate.name, + length: gate.parameters.len(), + }); + } + + let mut parameter = None; + if !gate.parameters.is_empty() { + parameter = Some(Symbol::from_expression(gate.parameters[0].clone())) + } + + Ok(QuantikzGate { + name: canonical_gate, + parameter, + dagger_count, + ctrl_count, + }) + } +} diff --git a/src/program/latex/diagram/mod.rs b/src/program/latex/diagram/mod.rs new file mode 100644 index 00000000..a7310eae --- /dev/null +++ b/src/program/latex/diagram/mod.rs @@ -0,0 +1,178 @@ +use std::{ + collections::{BTreeMap, BTreeSet}, + fmt, +}; + +use crate::instruction::Gate; + +use self::cell::{CellSettings, QuantikzCell}; +use super::{LatexGenError, RenderCommand, RenderSettings}; + +pub(crate) mod cell; + +/// A Diagram represents a collection of wires in a Circuit. The size of the +/// Diagram can be measured by multiplying the number of Instructions in a +/// Program with the length of the Circuit. This is an [m x n] matrix where n, +/// is the number of Quil instructions (or columns), and m, is the number of +/// wires (or rows). Each individual element of the matrix represents an item +/// that is serializable into LaTeX using the ``Quantikz`` RenderCommands. +pub(crate) struct Diagram { + settings: RenderSettings, + wires: BTreeMap, + columns: Vec, +} + +struct DiagramColumn { + cells: Vec, +} + +impl Diagram { + pub(crate) fn new( + qubits: BTreeSet, + settings: RenderSettings, + ) -> Result { + let mut diagram = Self { + settings, + wires: BTreeMap::new(), + columns: Vec::new(), + }; + + diagram.build_wire_map(qubits)?; + + Ok(diagram) + } + + /// Adds missing qubits between the first qubit and last qubit in a + /// diagram's circuit. If a missing qubit is found, a new wire is created + /// and pushed to the diagram's circuit. + /// + /// # Arguments + /// `last_column` - total number of instructions from Program + /// `circuit` - the circuit of the diagram + /// + /// # Examples + /// ``` + /// use quil_rs::{Program, program::latex::RenderSettings}; + /// use std::str::FromStr; + /// let program = Program::from_str("H 0\nCNOT 0 1").expect(""); + /// let settings = RenderSettings { + /// impute_missing_qubits: true, + /// ..Default::default() + /// }; + /// program.to_latex(settings).expect(""); + /// ``` + pub(crate) fn build_wire_map(&mut self, qubits: BTreeSet) -> Result<(), LatexGenError> { + if qubits.is_empty() { + return Err(LatexGenError::RequiresQubits); + } + + if self.settings.impute_missing_qubits { + let first = *qubits.first().expect("qubits is not empty"); + let last = *qubits.last().expect("qubits is not empty"); + for (i, qubit) in (first..last + 1).enumerate() { + self.wires.insert(qubit, i); + } + } else { + for (i, qubit) in qubits.iter().enumerate() { + self.wires.insert(*qubit, i); + } + } + + Ok(()) + } + + /// Applies a gate from an instruction to the associated wires in the + /// circuit of this diagram. + /// + /// # Arguments + /// `gate` - the Gate of the Instruction from `to_latex`. + pub(crate) fn add_gate(&mut self, gate: &Gate) -> Result<(), LatexGenError> { + let mut cells: Vec = vec![QuantikzCell::Empty; self.wires.len()]; + + let quantikz_gate = cell::QuantikzGate::try_from(gate.clone())?; + + if gate.qubits.len() - quantikz_gate.ctrl_count > 1 { + return Err(LatexGenError::UnsupportedGate { + gate: gate.name.to_string(), + }); + } + + // parameterized non-PHASE gates are unsupported + if quantikz_gate.parameter.is_some() && !gate.name.contains("PHASE") { + return Err(LatexGenError::UnsupportedGate { + gate: gate.name.clone(), + }); + } + + let mut qubit_iterator = gate + .qubits + .iter() + .cloned() + .map(|q| { + q + .into_fixed() + .map_err(|_| LatexGenError::UnsupportedQubit) + }) + .rev(); + + let target_qubit = qubit_iterator + .next() + .ok_or(LatexGenError::RequiresQubits)??; + + let target_index = *self + .wires + .get(&target_qubit) + .ok_or(LatexGenError::QubitNotFound(target_qubit))?; + + cells[target_index] = QuantikzCell::Gate(quantikz_gate); + + for qubit in qubit_iterator { + let column_index = self + .wires + .get(&qubit?) + .copied() + .ok_or(LatexGenError::QubitNotFound(target_qubit))?; + cells[column_index] = QuantikzCell::Control(target_index as i64 - column_index as i64) + } + + self.columns.push(DiagramColumn { cells }); + + Ok(()) + } +} + +impl fmt::Display for Diagram { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let last = self.wires.keys().last().copied().unwrap_or_default(); + let cell_settings = CellSettings::from(self.settings); + + for (qubit, cell_index) in &self.wires { + if self.settings.label_qubit_lines { + write!(f, "{}", RenderCommand::LeftWireLabel(*qubit))?; + } else { + write!(f, "{}", RenderCommand::Qw)?; + } + + for column in &self.columns { + let command = &column.cells[*cell_index]; + write!( + f, + "{}{}", + &RenderCommand::Separate, + command.to_latex(&cell_settings).map_err(|_| fmt::Error)? + )?; + } + + write!(f, "{}{}", &RenderCommand::Separate, &RenderCommand::Qw)?; + + // omit LaTeX line break (`\\`) if this is the last qubit + if *qubit != last { + write!(f, " {}", &RenderCommand::Nr)?; + } + + writeln!(f)?; + } + + Ok(()) + } +} diff --git a/src/program/latex/mod.rs b/src/program/latex/mod.rs new file mode 100644 index 00000000..113dc919 --- /dev/null +++ b/src/program/latex/mod.rs @@ -0,0 +1,773 @@ +//! LaTeX circuit generation for quil programs. +//! +//! This module enables generating quantum circuits using the LaTeX subpackage +//! TikZ/[`Quantikz`] for a given quil [`Program`]. This feature is callable on +//! [`Program`] and returns a LaTeX string which can be rendered in a LaTeX +//! visualization tool. Be aware that not all Programs can be serialized as +//! LaTeX. If a [`Program`] contains a gate or modifier not mentioned in the +//! [Supported Gates and Modifiers](#supported-gates-and-modifiers) section +//! below, an error will be returned detailing which instruction or gate is +//! unsupported in the Program being processed. +//! +//! # Supported Gates and Modifiers +//! +//! - Pauli Gates: `I`, `X`, `Y`, `Z` +//! - Hadamard Gate: `H` +//! - Phase Gate: `PHASE`, `S`, `T` +//! - Controlled Phase Gate: `CZ`, `CPHASE` +//! - Controlled X Gates: `CNOT`, `CCNOT` +//! - User-Defined Gates: `DEFGATE` +//! - Modifiers: `CONTROLLED`, `DAGGER` +//! +//! [`Quantikz`]: https://arxiv.org/pdf/1809.03842.pdf + +mod diagram; + +use std::str::FromStr; +use std::{ + collections::{BTreeSet, HashSet}, + fmt, +}; + +use crate::expression::Expression; +use crate::instruction::{Instruction, Qubit}; +use crate::Program; + +use diagram::Diagram; +/// The structure of a LaTeX document. Typically a LaTeX document contains +/// metadata defining the setup and packages used in a document within a header +/// and footer while the body contains content and controls its presentation. +struct Document { + header: String, + body: String, + footer: String, +} + +impl Default for Document { + fn default() -> Self { + Self { + header: r"\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd}" + .to_string(), + body: String::new(), + footer: r"\end{tikzcd} +\end{document}" + .to_string(), + } + } +} + +impl fmt::Display for Document { + /// Returns the entire document in LaTeX string. + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}\n{}{}", self.header, self.body, self.footer) + } +} + +/// Available commands used for building circuits with the same names taken +/// from the ``Quantikz`` documentation for easy reference. LaTeX string denoted +/// inside `backticks`. +#[derive(Clone, Debug, derive_more::Display, PartialEq, Eq, Hash)] +pub(crate) enum RenderCommand { + /// Set a fixed qubit as the label to the left of wire. + #[display(fmt = "\\lstick{{\\ket{{q_{{{_0}}}}}}}")] + LeftWireLabel(u64), + /// Make a gate on the wire with an optional superscript. + #[display(fmt = "\\gate{{{_0}{_1}}}")] + Gate(String, String), + /// Make a phase on the wire with a rotation and optional superscript + #[display(fmt = "\\phase{{{_0}{_1}}}")] + Phase(Symbol, String), + /// Add a superscript to a gate + #[display(fmt = "^{{\\{_0}}}")] + Super(String), + /// Connect the current cell to the previous cell i.e. "do nothing". + #[display(fmt = "\\qw")] + Qw, + /// Start a new row + #[display(fmt = "\\\\")] + Nr, + /// Separates columns on the same row. + #[display(fmt = " & ")] + Separate, + /// Make a control qubit. + #[display(fmt = "\\ctrl{{{_0}}}")] + Ctrl(i64), + /// Make a target qubit. + #[display(fmt = "\\targ{{}}")] + Targ, +} + +impl Symbol { + pub(crate) fn from_expression(expression: Expression) -> Self { + // get the name of the supported expression + let text = match expression { + Expression::Address(mr) => mr.name, + Expression::Number(c) => c.re.to_string(), + expression => expression.to_string(), + }; + + Self::Text(text) + } + + /// Convert a text symbol to a LaTeX symbol. + pub(crate) fn texify(self) -> Self { + match &self { + Symbol::Text(text) => Symbol::from_str(text).unwrap_or(self), + _ => self, + } + } +} + +/// Supported Greek and alphanumeric symbols. +#[derive(Clone, Debug, strum::EnumString, derive_more::Display, PartialEq, Eq, Hash)] +#[strum(serialize_all = "lowercase")] +pub(crate) enum Symbol { + #[display(fmt = "\\alpha")] + Alpha, + #[display(fmt = "\\beta")] + Beta, + #[display(fmt = "\\gamma")] + Gamma, + #[display(fmt = "\\phi")] + Phi, + #[display(fmt = "\\pi")] + Pi, + #[display(fmt = "\\text{{{_0}}}")] + Text(String), +} + +/// RenderSettings contains the metadata that allows the user to customize how +/// the circuit is rendered or use the default implementation. +#[derive(Clone, Copy, Debug)] +pub struct RenderSettings { + /// Convert numerical constants, e.g. pi, to LaTeX form. + pub texify_numerical_constants: bool, + /// Include all qubits implicitly referenced in the Quil program. + pub impute_missing_qubits: bool, + /// Label qubit lines. + pub label_qubit_lines: bool, +} + +impl Default for RenderSettings { + /// Returns the default RenderSettings. + fn default() -> Self { + Self { + /// false: pi is π. + texify_numerical_constants: true, + /// true: `CNOT 0 2` would have three qubit lines: 0, 1, 2. + impute_missing_qubits: false, + /// false: remove Lstick/Rstick from latex. + label_qubit_lines: true, + } + } +} + +#[derive(Clone, Debug, thiserror::Error, PartialEq, Eq, Hash)] +pub enum LatexGenError { + #[error("Gate instruction has duplicate qubits.")] + DuplicateQubits, + #[error("Qubits are required to build a circuit.")] + RequiresQubits, + #[error("Circuit does not have qubit {0}")] + QubitNotFound(u64), + #[error("Parameterized gate has no parameter.")] + MissingParameter, + #[error("The FORKED modifier is unsupported.")] + UnsupportedModifierForked, + #[error("This instruction is unsupported: {instruction}.")] + UnsupportedInstruction { instruction: String }, + #[error("This gate is unsupported: {gate}.")] + UnsupportedGate { gate: String }, + #[error("The parameter length {length} of gate {gate} is unsupported")] + UnsupportedParameterLength { gate: String, length: usize }, + #[error("Only fixed qubits are supported")] + UnsupportedQubit, +} + +impl Program { + /// Returns a Result containing a quil [`Program`] as a LaTeX string or a + /// [`LatexGenError`]. + /// + /// This implementation of Latex can be viewed as a self-contained partial + /// implementation of ``Quantikz`` with all available commands listed as + /// variants in a Command enum. View ``Quantikz`` documentation for more + /// information. + /// + /// # Arguments + /// `settings` - Customizes the rendering of a circuit. + /// + /// # Examples + /// ``` + /// // To LaTeX for the Bell State Program. + /// use quil_rs::{Program, program::latex::RenderSettings}; + /// use std::str::FromStr; + /// let program = Program::from_str("H 0\nCNOT 0 1").expect(""); + /// let latex = program.to_latex(RenderSettings::default()).expect(""); + /// ``` + /// + /// ``` + /// // To LaTeX for the Toffoli Gate Program. + /// use quil_rs::{Program, program::latex::RenderSettings}; + /// use std::str::FromStr; + /// let program = Program::from_str("CONTROLLED CNOT 2 1 0").expect(""); + /// let latex = program.to_latex(RenderSettings::default()).expect(""); + /// ``` + pub fn to_latex(&self, settings: RenderSettings) -> Result { + let instructions = self.to_instructions(false); + + let qubits = self + .get_used_qubits() + .into_iter() + .map(|q| q.into_fixed()) + .collect::, _>>() + .map_err(|_| LatexGenError::UnsupportedQubit)?; + + let mut diagram = Diagram::new(qubits, settings)?; + + for instruction in instructions { + match instruction { + Instruction::Gate(gate) => { + if gate.qubits.len() + != gate + .qubits + .iter() + .cloned() + .collect::>() + .len() + { + return Err(LatexGenError::DuplicateQubits); + } + + diagram.add_gate(&gate)?; + } + // GateDefinition is supported but inserted into the circuit using its Gate instruction form + Instruction::GateDefinition(_) => continue, + _ => { + return Err(LatexGenError::UnsupportedInstruction { + instruction: instruction.to_string(), + }) + } + } + } + + let body = diagram.to_string(); + let document = Document { + body, + ..Default::default() + }; + Ok(document.to_string()) + } +} + +#[cfg(test)] +mod tests { + use super::{Program, RenderSettings}; + use std::str::FromStr; + + /// Helper function takes instructions and return the LaTeX using the + /// Latex::to_latex method. + fn get_latex(instructions: &str, settings: RenderSettings) -> String { + let program = Program::from_str(instructions).expect("Program should be returned"); + program + .to_latex(settings) + .expect("Program conversion to LaTeX should succeed") + } + + #[test] + /// Test functionality of to_latex using default settings. + fn test_to_latex() { + let latex = get_latex( + "H 0\nCNOT 0 1", + RenderSettings { + impute_missing_qubits: true, + ..Default::default() + }, + ); + + println!("{latex}"); + } + + /// Test module for the Document + mod document { + use crate::program::latex::{tests::get_latex, Document, RenderSettings}; + + #[test] + #[should_panic] + fn test_empty_program() { + get_latex("", RenderSettings::default()); + } + + #[test] + fn test_header() { + let document = Document::default(); + insta::assert_snapshot!(document.header); + } + + #[test] + fn test_body_default() { + let document = Document::default(); + insta::assert_snapshot!(document.body); + } + + #[test] + fn test_footer() { + let document = Document::default(); + insta::assert_snapshot!(document.footer); + } + } + + /// Test module for gates + mod gates { + use crate::program::latex::{tests::get_latex, RenderSettings}; + + #[test] + fn test_gate_x() { + insta::assert_snapshot!(get_latex("X 0", RenderSettings::default())); + } + + #[test] + fn test_gate_y() { + insta::assert_snapshot!(get_latex("Y 1", RenderSettings::default())); + } + + #[test] + fn test_gates_x_and_y_single_qubit() { + insta::assert_snapshot!(get_latex("X 0\nY 0", RenderSettings::default())); + } + + #[test] + fn test_gates_x_and_y_two_qubits() { + insta::assert_snapshot!(get_latex("X 0\nY 1", RenderSettings::default())); + } + + #[test] + fn test_gates_phase_pi_rotation() { + insta::assert_snapshot!(get_latex("PHASE(pi) 0", RenderSettings::default())); + } + + #[test] + fn test_gates_cnot_ctrl_0_targ_1() { + insta::assert_snapshot!(get_latex("CNOT 0 1", RenderSettings::default())); + } + + #[test] + fn test_gates_cnot_ctrl_1_targ_0() { + insta::assert_snapshot!(get_latex("CNOT 1 0", RenderSettings::default())); + } + + #[test] + #[should_panic] + fn test_gates_cnot_error_single_qubit() { + get_latex("CNOT 0 0", RenderSettings::default()); + } + + #[test] + fn test_gates_h_and_cnot_ctrl_0_targ_1() { + insta::assert_snapshot!(get_latex("H 0\nCNOT 0 1", RenderSettings::default())); + } + + #[test] + fn test_gates_h_and_cnot_ctrl_1_targ_0() { + insta::assert_snapshot!(get_latex("H 1\nCNOT 1 0", RenderSettings::default())); + } + + #[test] + fn test_gate_toffoli() { + insta::assert_snapshot!(get_latex("CCNOT 1 2 0", RenderSettings::default())); + } + + #[test] + fn test_gate_ccnot_and_controlled_cnot_equality() { + let ccnot = get_latex("CCNOT 1 2 0", RenderSettings::default()); + + let controlled = get_latex("CONTROLLED CNOT 1 2 0", RenderSettings::default()); + + assert_eq!(ccnot, controlled); + } + + #[test] + fn test_gate_cphase() { + insta::assert_snapshot!(get_latex("CPHASE(pi) 0 1", RenderSettings::default())); + } + + #[test] + fn test_gate_cz() { + insta::assert_snapshot!(get_latex("CZ 0 1", RenderSettings::default())); + } + + #[test] + #[should_panic] + fn test_gate_xy() { + get_latex("XY 0 1", RenderSettings::default()); + } + + #[test] + #[should_panic] + fn test_gate_controlled_xy() { + get_latex("CONTROLLED XY 0 1 2", RenderSettings::default()); + } + + #[test] + #[should_panic] + fn test_gate_swap() { + get_latex("SWAP 0 1", RenderSettings::default()); + } + + #[test] + #[should_panic] + fn test_gate_cswap() { + get_latex("CSWAP 0 1 2", RenderSettings::default()); + } + + #[test] + #[should_panic] + fn test_gate_controlled_swap() { + get_latex("CONTROLLED SWAP 0 1 2", RenderSettings::default()); + } + + #[test] + #[should_panic] + fn test_gate_iswap() { + get_latex("ISWAP 1 2", RenderSettings::default()); + } + + #[test] + #[should_panic] + fn test_gate_pswap() { + get_latex("PSWAP(gamma) 1 2", RenderSettings::default()); + } + } + + /// Test module for modifiers + mod modifiers { + use crate::program::latex::{tests::get_latex, RenderSettings}; + + #[test] + fn test_modifier_toffoli_gate() { + insta::assert_snapshot!(get_latex( + "CONTROLLED CNOT 2 1 0", + RenderSettings::default() + )); + } + + #[test] + fn test_modifier_controlled_cnot_and_ccnot_equality() { + let controlled = get_latex("CONTROLLED CNOT 2 1 0", RenderSettings::default()); + + let ccnot = get_latex("CCNOT 2 1 0", RenderSettings::default()); + + assert_eq!(controlled, ccnot); + } + + #[test] + fn test_modifier_dagger() { + insta::assert_snapshot!(get_latex("DAGGER X 0", RenderSettings::default())); + } + + #[test] + fn test_modifier_dagger_dagger() { + insta::assert_snapshot!(get_latex("DAGGER DAGGER Y 0", RenderSettings::default())); + } + + #[test] + fn test_modifier_phase_dagger() { + insta::assert_snapshot!(get_latex("DAGGER PHASE(pi) 0", RenderSettings::default())); + } + + #[test] + fn test_modifier_dagger_cz() { + insta::assert_snapshot!(get_latex("DAGGER CZ 0 1", RenderSettings::default())); + } + + #[test] + fn test_modifier_cphase_dagger() { + insta::assert_snapshot!(get_latex( + "DAGGER CPHASE(alpha) 0 1", + RenderSettings::default() + )); + } + } + + /// Test module for ``Quantikz`` Commands + mod commands { + use crate::program::latex::{RenderCommand, Symbol}; + + #[test] + fn test_command_left_ket() { + insta::assert_snapshot!(RenderCommand::LeftWireLabel(0).to_string()); + } + + #[test] + fn test_command_gate() { + insta::assert_snapshot!(RenderCommand::Gate("X".to_string(), String::new()).to_string()); + } + + #[test] + fn test_command_phase() { + insta::assert_snapshot!(RenderCommand::Phase(Symbol::Pi, String::new()).to_string()); + } + + #[test] + fn test_command_super() { + insta::assert_snapshot!(RenderCommand::Super("dagger".to_string()).to_string()); + } + + #[test] + fn test_command_qw() { + insta::assert_snapshot!(RenderCommand::Qw.to_string()); + } + + #[test] + fn test_command_nr() { + insta::assert_snapshot!(RenderCommand::Nr.to_string()); + } + + #[test] + fn test_command_control() { + insta::assert_snapshot!(RenderCommand::Ctrl(0).to_string()); + } + + #[test] + fn test_command_cnot_target() { + insta::assert_snapshot!(RenderCommand::Targ.to_string()); + } + } + + /// Test module for RenderSettings + mod settings { + use crate::program::latex::{tests::get_latex, RenderSettings}; + + #[test] + fn test_settings_texify_numerical_constants_true_supported_symbol() { + // default texify_numerical_constants is true + let settings = RenderSettings { + ..Default::default() + }; + insta::assert_snapshot!(get_latex("CPHASE(alpha) 0 1", settings)); + } + + #[test] + fn test_settings_texify_numerical_constants_false_supported_symbol() { + let settings = RenderSettings { + texify_numerical_constants: false, + ..Default::default() + }; + insta::assert_snapshot!(get_latex("CPHASE(alpha) 0 1", settings)); + } + + #[test] + fn test_settings_texify_numerical_constants_unsupported_symbol() { + // default texify_numerical_constants is true + let settings_true = RenderSettings { + ..Default::default() + }; + + let unsupported_true = get_latex("CPHASE(chi) 0 1", settings_true); + + let settings_false = RenderSettings { + texify_numerical_constants: false, + ..Default::default() + }; + + let unsupported_false = get_latex("CPHASE(chi) 0 1", settings_false); + + // unsupported symbols are treated as text regardless of setting + assert_eq!(unsupported_true, unsupported_false); + } + + #[test] + fn test_settings_label_qubit_lines_false() { + let settings = RenderSettings { + label_qubit_lines: false, + ..Default::default() + }; + insta::assert_snapshot!(get_latex("H 0\nCNOT 0 1", settings)); + } + + #[test] + fn test_settings_impute_missing_qubits_true_ctrl_less_than_targ() { + let settings = RenderSettings { + impute_missing_qubits: true, + ..Default::default() + }; + insta::assert_snapshot!(get_latex("H 0\nCNOT 0 3", settings)); + } + + #[test] + fn test_settings_impute_missing_qubits_true_ctrl_greater_than_targ() { + let settings = RenderSettings { + impute_missing_qubits: true, + ..Default::default() + }; + insta::assert_snapshot!(get_latex("H 5\nCNOT 5 2", settings)); + } + } + + /// Test various programs for LaTeX accuracy + mod programs { + use crate::program::latex::{tests::get_latex, RenderSettings}; + + #[test] + fn test_program_h0_cnot01_x1_cnot12() { + let settings = RenderSettings { + ..Default::default() + }; + insta::assert_snapshot!(get_latex("H 0\nCNOT 0 1\nX 1\nCNOT 1 2", settings)); + } + + #[test] + fn test_program_h5_cnot52_y2_cnot23() { + let settings = RenderSettings { + ..Default::default() + }; + insta::assert_snapshot!(get_latex("H 5\nCNOT 5 2\nY 2\nCNOT 2 3", settings)); + } + + #[test] + fn test_program_good_modifiers() { + let latex = get_latex( + r#"Y 0 +CONTROLLED Y 0 1 +CONTROLLED CONTROLLED Y 0 1 2 +CONTROLLED CONTROLLED CONTROLLED Y 0 1 2 3 + +DAGGER Y 0 +DAGGER DAGGER Y 0 +DAGGER DAGGER DAGGER Y 0 + +CONTROLLED DAGGER Y 0 1 +CONTROLLED DAGGER CONTROLLED Y 0 1 2 +CONTROLLED DAGGER CONTROLLED DAGGER Y 0 1 2 + +DEFGATE G: + 1, 0 + 0, 1 + +CONTROLLED G 0 1 +DAGGER G 0"#, + RenderSettings::default(), + ); + + insta::assert_snapshot!(latex); + } + + #[test] + fn test_program_good_simple_params() { + insta::assert_snapshot!(get_latex( + "CPHASE(1.0) 0 1\nCPHASE(1.0-2.0i) 1 0", + RenderSettings::default() + )); + } + + #[test] + fn test_program_good_complex_params() { + insta::assert_snapshot!(get_latex( + "CPHASE(pi/2) 1 0\nCPHASE(cos(sin(2*pi/3))*cis(-1)*exp(i*pi)) 3 4", + RenderSettings::default() + )); + } + + #[test] + fn test_program_good_basic_defgate() { + let latex = get_latex( + r#"DEFGATE H0: + 0.707, 0.707 + 0.707, -0.707 + +DEFGATE H1: + 1/sqrt(2), 1/sqrt(2) + 1/sqrt(2), -1/sqrt(2) + +H0 0 +H1 1"#, + RenderSettings::default(), + ); + + insta::assert_snapshot!(latex); + } + + #[test] + fn test_program_good_defgate_with_long_name() { + let latex = get_latex( + r#"DEFGATE ______________________________________ugly-python-convention______________________________________: + 1, 0 + 0, 1 + +______________________________________ugly-python-convention______________________________________ 0 +______________________________________ugly-python-convention______________________________________ 1"#, + RenderSettings::default(), + ); + + insta::assert_snapshot!(latex); + } + } + + /// Test module for unsupported programs + mod unsupported { + use crate::program::latex::{tests::get_latex, RenderSettings}; + + #[test] + #[should_panic] + fn test_supported_misc_instructions() { + get_latex("NOP\nWAIT\nRESET\nHALT", RenderSettings::default()); + } + + #[test] + #[should_panic] + fn test_supported_measure() { + get_latex( + "DECLARE ro BIT\nMEASURE 0\nMEASURE 1 ro[0]", + RenderSettings::default(), + ); + } + + #[test] + #[should_panic] + fn test_supported_program_defcircuit() { + get_latex( + r#"DEFCIRCUIT EULER(%alpha, %beta, %gamma) q: + RX(%alpha) q + RY(%beta) q + RZ(%gamma) q +EULER(pi, 2*pi, 3*pi/2) 0"#, + RenderSettings::default(), + ); + } + + #[test] + #[should_panic] + fn test_supported_gate_rotation() { + get_latex( + r#"DECLARE ro BIT[1] +DECLARE theta REAL[1] +RX(pi/2) 0 +RZ(theta) 0 +RY(-pi/2) 0"#, + RenderSettings::default(), + ); + } + + #[test] + #[should_panic] + fn test_supported_arithmetic_instruction() { + get_latex( + "DECLARE b BIT\nDECLARE theta REAL\nMOVE theta -3.14\nLT b theta -3.14", + RenderSettings::default(), + ); + } + + #[test] + #[should_panic] + fn test_supported_modifier_forked() { + get_latex( + "FORKED CONTROLLED FORKED RX(a,b,c,d) 0 1 2 3", + RenderSettings::default(), + ); + } + } +} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_cnot_target.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_cnot_target.snap new file mode 100644 index 00000000..b7baa2ee --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_cnot_target.snap @@ -0,0 +1,6 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 213 +expression: "Command::get_command(Command::Targ)" +--- +\targ{} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_control.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_control.snap new file mode 100644 index 00000000..2a762b12 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_control.snap @@ -0,0 +1,6 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 208 +expression: "Command::get_command(Command::Ctrl(0))" +--- +\ctrl{0} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_gate.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_gate.snap new file mode 100644 index 00000000..71a30ac3 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_gate.snap @@ -0,0 +1,6 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 311 +expression: "Command::get_command(Command::Gate(\"X\".to_string()))" +--- +\gate{X} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_left_ket.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_left_ket.snap new file mode 100644 index 00000000..1b0e0582 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_left_ket.snap @@ -0,0 +1,6 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 188 +expression: "Command::get_command(Command::Lstick(0))" +--- +\lstick{\ket{q_{0}}} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_nr.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_nr.snap new file mode 100644 index 00000000..85810332 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_nr.snap @@ -0,0 +1,6 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 473 +expression: "r\"\\\\\"" +--- +\\ diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_phase.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_phase.snap new file mode 100644 index 00000000..c39e71bf --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_phase.snap @@ -0,0 +1,6 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 903 +expression: "r#\"\\phase{\\pi}\"#" +--- +\phase{\pi} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_qw.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_qw.snap new file mode 100644 index 00000000..4c5f0b43 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_qw.snap @@ -0,0 +1,6 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 198 +expression: "Command::get_command(Command::Qw)" +--- +\qw diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_super.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_super.snap new file mode 100644 index 00000000..85b08907 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__commands__command_super.snap @@ -0,0 +1,6 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 909 +expression: "r#\"^{\\dagger}\"#" +--- +^{\dagger} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__document__body_default.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__document__body_default.snap new file mode 100644 index 00000000..4c720ae9 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__document__body_default.snap @@ -0,0 +1,6 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 219 +expression: "r\"\"" +--- + diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__document__footer.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__document__footer.snap new file mode 100644 index 00000000..a5a39950 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__document__footer.snap @@ -0,0 +1,7 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 224 +expression: "r\"\\end{tikzcd}\n\\end{document}\"" +--- +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__document__header.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__document__header.snap new file mode 100644 index 00000000..f5e7a774 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__document__header.snap @@ -0,0 +1,11 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 207 +expression: "r\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\"" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_controlled.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_controlled.snap new file mode 100644 index 00000000..14a6b082 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_controlled.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex.rs +assertion_line: 104 +expression: latex +--- +\[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{2}}} & \gate{H} & \qw \\ +\lstick{\ket{q_{3}}} & \ctrl{-1} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_cphase.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_cphase.snap new file mode 100644 index 00000000..491baf03 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_cphase.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 841 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\ctrl{1} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\phase{\\pi} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \ctrl{1} & \qw \\ +\lstick{\ket{q_{1}}} & \phase{\pi} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_cz.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_cz.snap new file mode 100644 index 00000000..414cf613 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_cz.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 846 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\ctrl{1} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\gate{Z} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \ctrl{1} & \qw \\ +\lstick{\ket{q_{1}}} & \gate{Z} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_toffoli.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_toffoli.snap new file mode 100644 index 00000000..5aaf5810 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_toffoli.snap @@ -0,0 +1,16 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 723 +expression: "get_latex(\"CCNOT 1 2 0\", Settings::default())" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \targ{} & \qw \\ +\lstick{\ket{q_{1}}} & \ctrl{-1} & \qw \\ +\lstick{\ket{q_{2}}} & \ctrl{-2} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_x.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_x.snap new file mode 100644 index 00000000..d0f3d928 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_x.snap @@ -0,0 +1,14 @@ +--- +source: src/program/latex.rs +assertion_line: 77 +expression: "r\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\gate{X} & \\qw\n\\end{tikzcd}\n\\end{document}\"" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \gate{X} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_y.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_y.snap new file mode 100644 index 00000000..ac88ea92 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gate_y.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex.rs +assertion_line: 82 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{1}}} & \\gate{Y} & \\qw\n\\end{tikzcd}\n\\end{document}\n\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{1}}} & \gate{Y} & \qw +\end{tikzcd} +\end{document} + diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_cnot_ctrl_0_targ_1.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_cnot_ctrl_0_targ_1.snap new file mode 100644 index 00000000..26753a91 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_cnot_ctrl_0_targ_1.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 449 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\ctrl{1} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\targ{} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \ctrl{1} & \qw \\ +\lstick{\ket{q_{1}}} & \targ{} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_cnot_ctrl_1_targ_0.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_cnot_ctrl_1_targ_0.snap new file mode 100644 index 00000000..380d94b2 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_cnot_ctrl_1_targ_0.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 532 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\targ{} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\ctrl{-1} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \targ{} & \qw \\ +\lstick{\ket{q_{1}}} & \ctrl{-1} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_h_and_cnot_ctrl_0_targ_1.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_h_and_cnot_ctrl_0_targ_1.snap new file mode 100644 index 00000000..0cbecae8 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_h_and_cnot_ctrl_0_targ_1.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 583 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\gate{H} & \\ctrl{1} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\qw & \\targ{} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \gate{H} & \ctrl{1} & \qw \\ +\lstick{\ket{q_{1}}} & \qw & \targ{} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_h_and_cnot_ctrl_1_targ_0.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_h_and_cnot_ctrl_1_targ_0.snap new file mode 100644 index 00000000..c8ff5398 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_h_and_cnot_ctrl_1_targ_0.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 588 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\qw & \\targ{} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\gate{H} & \\ctrl{-1} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \qw & \targ{} & \qw \\ +\lstick{\ket{q_{1}}} & \gate{H} & \ctrl{-1} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_phase_pi_rotation.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_phase_pi_rotation.snap new file mode 100644 index 00000000..aed319c5 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_phase_pi_rotation.snap @@ -0,0 +1,14 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 827 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\phase{\\pi} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \phase{\pi} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_x_and_y_single_qubit.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_x_and_y_single_qubit.snap new file mode 100644 index 00000000..ec23cf73 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_x_and_y_single_qubit.snap @@ -0,0 +1,14 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 434 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\gate{X} & \\gate{Y} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \gate{X} & \gate{Y} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_x_and_y_two_qubits.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_x_and_y_two_qubits.snap new file mode 100644 index 00000000..f8fc7c46 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__gates_x_and_y_two_qubits.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 978 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\gate{X} & \\qw & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\qw & \\gate{Y} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \gate{X} & \qw & \qw \\ +\lstick{\ket{q_{1}}} & \qw & \gate{Y} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__text_gates_x_and_y_single_qubit.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__text_gates_x_and_y_single_qubit.snap new file mode 100644 index 00000000..5f2c719e --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__gates__text_gates_x_and_y_single_qubit.snap @@ -0,0 +1,14 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 366 +expression: "r\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\gate{X} & \\gate{Y} & \\qw \\\\\n\\end{tikzcd}\n\\end{document}\".to_string()" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \gate{X} & \gate{Y} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_cphase_dagger.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_cphase_dagger.snap new file mode 100644 index 00000000..d8b2bb63 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_cphase_dagger.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 413 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\ctrl{1} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\phase{\\alpha^{\\dagger}} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \ctrl{1} & \qw \\ +\lstick{\ket{q_{1}}} & \phase{\alpha^{\dagger}} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_dagger.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_dagger.snap new file mode 100644 index 00000000..e1681412 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_dagger.snap @@ -0,0 +1,14 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 936 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\gate{X^{\\dagger}} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \gate{X^{\dagger}} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_dagger_cz.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_dagger_cz.snap new file mode 100644 index 00000000..70f79e41 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_dagger_cz.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 958 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\ctrl{1} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\gate{Z^{\\dagger}} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \ctrl{1} & \qw \\ +\lstick{\ket{q_{1}}} & \gate{Z^{\dagger}} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_dagger_dagger.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_dagger_dagger.snap new file mode 100644 index 00000000..80614e75 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_dagger_dagger.snap @@ -0,0 +1,14 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 942 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\gate{Y^{\\dagger}^{\\dagger}} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \gate{Y^{\dagger}^{\dagger}} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_phase_dagger.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_phase_dagger.snap new file mode 100644 index 00000000..c4a781ff --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_phase_dagger.snap @@ -0,0 +1,14 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 403 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\phase{\\pi^{\\dagger}} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \phase{\pi^{\dagger}} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_toffoli_gate.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_toffoli_gate.snap new file mode 100644 index 00000000..c56ba8ef --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__modifiers__modifier_toffoli_gate.snap @@ -0,0 +1,16 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 750 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\targ{} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\ctrl{-1} & \\qw \\\\\n\\lstick{\\ket{q_{2}}} & \\ctrl{-2} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \targ{} & \qw \\ +\lstick{\ket{q_{1}}} & \ctrl{-1} & \qw \\ +\lstick{\ket{q_{2}}} & \ctrl{-2} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_basic_defgate.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_basic_defgate.snap new file mode 100644 index 00000000..01fcbbcf --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_basic_defgate.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 1276 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\gate{H0} & \\qw & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\qw & \\gate{H1} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \gate{H0} & \qw & \qw \\ +\lstick{\ket{q_{1}}} & \qw & \gate{H1} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_complex_params.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_complex_params.snap new file mode 100644 index 00000000..15244560 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_complex_params.snap @@ -0,0 +1,17 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 1301 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\phase{\\text{(pi/2)}} & \\qw & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\ctrl{-1} & \\qw & \\qw \\\\\n\\lstick{\\ket{q_{3}}} & \\qw & \\ctrl{1} & \\qw \\\\\n\\lstick{\\ket{q_{4}}} & \\qw & \\phase{\\text{(cos(sin((2*(pi/3))))*(cis((-1))*exp((1i*pi))))}} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \phase{\text{(pi/2)}} & \qw & \qw \\ +\lstick{\ket{q_{1}}} & \ctrl{-1} & \qw & \qw \\ +\lstick{\ket{q_{3}}} & \qw & \ctrl{1} & \qw \\ +\lstick{\ket{q_{4}}} & \qw & \phase{\text{(cos(sin((2*(pi/3))))*(cis((-1))*exp((1i*pi))))}} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_defgate_with_long_name.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_defgate_with_long_name.snap new file mode 100644 index 00000000..1d20ddad --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_defgate_with_long_name.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 1318 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\gate{______________________________________ugly-python-convention______________________________________} & \\qw & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\qw & \\gate{______________________________________ugly-python-convention______________________________________} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \gate{______________________________________ugly-python-convention______________________________________} & \qw & \qw \\ +\lstick{\ket{q_{1}}} & \qw & \gate{______________________________________ugly-python-convention______________________________________} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_modifiers.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_modifiers.snap new file mode 100644 index 00000000..06daf2db --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_modifiers.snap @@ -0,0 +1,17 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 1005 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\gate{Y} & \\ctrl{1} & \\ctrl{2} & \\ctrl{3} & \\gate{Y^{\\dagger}} & \\gate{Y^{\\dagger}^{\\dagger}} & \\gate{Y^{\\dagger}^{\\dagger}^{\\dagger}} & \\ctrl{1} & \\ctrl{2} & \\ctrl{2} & \\ctrl{1} & \\gate{G^{\\dagger}} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\qw & \\gate{Y} & \\ctrl{1} & \\ctrl{2} & \\qw & \\qw & \\qw & \\gate{Y^{\\dagger}} & \\ctrl{1} & \\ctrl{1} & \\gate{G} & \\qw & \\qw \\\\\n\\lstick{\\ket{q_{2}}} & \\qw & \\qw & \\gate{Y} & \\ctrl{1} & \\qw & \\qw & \\qw & \\qw & \\gate{Y^{\\dagger}} & \\gate{Y^{\\dagger}^{\\dagger}} & \\qw & \\qw & \\qw \\\\\n\\lstick{\\ket{q_{3}}} & \\qw & \\qw & \\qw & \\gate{Y} & \\qw & \\qw & \\qw & \\qw & \\qw & \\qw & \\qw & \\qw & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \gate{Y} & \ctrl{1} & \ctrl{2} & \ctrl{3} & \gate{Y^{\dagger}} & \gate{Y^{\dagger}^{\dagger}} & \gate{Y^{\dagger}^{\dagger}^{\dagger}} & \ctrl{1} & \ctrl{2} & \ctrl{2} & \ctrl{1} & \gate{G^{\dagger}} & \qw \\ +\lstick{\ket{q_{1}}} & \qw & \gate{Y} & \ctrl{1} & \ctrl{2} & \qw & \qw & \qw & \gate{Y^{\dagger}} & \ctrl{1} & \ctrl{1} & \gate{G} & \qw & \qw \\ +\lstick{\ket{q_{2}}} & \qw & \qw & \gate{Y} & \ctrl{1} & \qw & \qw & \qw & \qw & \gate{Y^{\dagger}} & \gate{Y^{\dagger}^{\dagger}} & \qw & \qw & \qw \\ +\lstick{\ket{q_{3}}} & \qw & \qw & \qw & \gate{Y} & \qw & \qw & \qw & \qw & \qw & \qw & \qw & \qw & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_simple_params.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_simple_params.snap new file mode 100644 index 00000000..c80db06e --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_good_simple_params.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 1312 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\ctrl{1} & \\phase{\\text{(1-2i)}} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\phase{\\text{1}} & \\ctrl{-1} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \ctrl{1} & \phase{\text{(1-2i)}} & \qw \\ +\lstick{\ket{q_{1}}} & \phase{\text{1}} & \ctrl{-1} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_h0_cnot01_x1_cnot12.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_h0_cnot01_x1_cnot12.snap new file mode 100644 index 00000000..b5a11844 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_h0_cnot01_x1_cnot12.snap @@ -0,0 +1,16 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 799 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\gate{H} & \\ctrl{1} & \\qw & \\qw & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\qw & \\targ{} & \\gate{X} & \\ctrl{1} & \\qw \\\\\n\\lstick{\\ket{q_{2}}} & \\qw & \\qw & \\qw & \\targ{} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \gate{H} & \ctrl{1} & \qw & \qw & \qw \\ +\lstick{\ket{q_{1}}} & \qw & \targ{} & \gate{X} & \ctrl{1} & \qw \\ +\lstick{\ket{q_{2}}} & \qw & \qw & \qw & \targ{} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_h5_cnot52_y2_cnot23.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_h5_cnot52_y2_cnot23.snap new file mode 100644 index 00000000..75ed071b --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__programs__program_h5_cnot52_y2_cnot23.snap @@ -0,0 +1,16 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 804 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{2}}} & \\qw & \\targ{} & \\gate{Y} & \\ctrl{1} & \\qw \\\\\n\\lstick{\\ket{q_{3}}} & \\qw & \\qw & \\qw & \\targ{} & \\qw \\\\\n\\lstick{\\ket{q_{5}}} & \\gate{H} & \\ctrl{-2} & \\qw & \\qw & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{2}}} & \qw & \targ{} & \gate{Y} & \ctrl{1} & \qw \\ +\lstick{\ket{q_{3}}} & \qw & \qw & \qw & \targ{} & \qw \\ +\lstick{\ket{q_{5}}} & \gate{H} & \ctrl{-2} & \qw & \qw & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_impute_missing_qubits_true_ctrl_greater_than_targ.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_impute_missing_qubits_true_ctrl_greater_than_targ.snap new file mode 100644 index 00000000..a2725f66 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_impute_missing_qubits_true_ctrl_greater_than_targ.snap @@ -0,0 +1,17 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 777 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{2}}} & \\qw & \\targ{} & \\qw \\\\\n\\lstick{\\ket{q_{3}}} & \\qw & \\qw & \\qw \\\\\n\\lstick{\\ket{q_{4}}} & \\qw & \\qw & \\qw \\\\\n\\lstick{\\ket{q_{5}}} & \\gate{H} & \\ctrl{-3} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{2}}} & \qw & \targ{} & \qw \\ +\lstick{\ket{q_{3}}} & \qw & \qw & \qw \\ +\lstick{\ket{q_{4}}} & \qw & \qw & \qw \\ +\lstick{\ket{q_{5}}} & \gate{H} & \ctrl{-3} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_impute_missing_qubits_true_ctrl_less_than_targ.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_impute_missing_qubits_true_ctrl_less_than_targ.snap new file mode 100644 index 00000000..e0d93ceb --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_impute_missing_qubits_true_ctrl_less_than_targ.snap @@ -0,0 +1,17 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 712 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\gate{H} & \\ctrl{3} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\qw & \\qw & \\qw \\\\\n\\lstick{\\ket{q_{2}}} & \\qw & \\qw & \\qw \\\\\n\\lstick{\\ket{q_{3}}} & \\qw & \\targ{} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \gate{H} & \ctrl{3} & \qw \\ +\lstick{\ket{q_{1}}} & \qw & \qw & \qw \\ +\lstick{\ket{q_{2}}} & \qw & \qw & \qw \\ +\lstick{\ket{q_{3}}} & \qw & \targ{} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_label_qubit_lines_false.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_label_qubit_lines_false.snap new file mode 100644 index 00000000..ac3540f6 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_label_qubit_lines_false.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 689 +expression: "r#\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\qw & \\gate{H} & \\ctrl{1} & \\qw \\\\\n\\qw & \\qw & \\targ{} & \\qw\n\\end{tikzcd}\n\\end{document}\"#" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\qw & \gate{H} & \ctrl{1} & \qw \\ +\qw & \qw & \targ{} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_texify_numerical_constants_false_supported_symbol.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_texify_numerical_constants_false_supported_symbol.snap new file mode 100644 index 00000000..9e8e6df9 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_texify_numerical_constants_false_supported_symbol.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 1064 +expression: "r\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\ctrl{1} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\phase{\\text{alpha}} & \\qw\n\\end{tikzcd}\n\\end{document}\"" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \ctrl{1} & \qw \\ +\lstick{\ket{q_{1}}} & \phase{\text{alpha}} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_texify_numerical_constants_true_supported_symbol.snap b/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_texify_numerical_constants_true_supported_symbol.snap new file mode 100644 index 00000000..3e921b01 --- /dev/null +++ b/src/program/latex/snapshots/quil_rs__program__latex__tests__settings__settings_texify_numerical_constants_true_supported_symbol.snap @@ -0,0 +1,15 @@ +--- +source: src/program/latex/mod.rs +assertion_line: 1044 +expression: "r\"\\documentclass[convert={density=300,outext=.png}]{standalone}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{tikz}\n\\usetikzlibrary{quantikz}\n\\begin{document}\n\\begin{tikzcd}\n\\lstick{\\ket{q_{0}}} & \\ctrl{1} & \\qw \\\\\n\\lstick{\\ket{q_{1}}} & \\phase{\\alpha} & \\qw\n\\end{tikzcd}\n\\end{document}\"" +--- +\documentclass[convert={density=300,outext=.png}]{standalone} +\usepackage[margin=1in]{geometry} +\usepackage{tikz} +\usetikzlibrary{quantikz} +\begin{document} +\begin{tikzcd} +\lstick{\ket{q_{0}}} & \ctrl{1} & \qw \\ +\lstick{\ket{q_{1}}} & \phase{\alpha} & \qw +\end{tikzcd} +\end{document} diff --git a/src/program/mod.rs b/src/program/mod.rs index 9565237b..3a58fe8a 100644 --- a/src/program/mod.rs +++ b/src/program/mod.rs @@ -39,6 +39,9 @@ pub type Result = std::result::Result>; #[cfg(feature = "graphviz-dot")] pub mod graphviz_dot; +#[cfg(feature = "latex")] +pub mod latex; + /// A Quil Program instance describes a quantum program with metadata used in execution. /// /// This contains not only instructions which are executed in turn on the quantum processor, but