Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement LaTeX generation #145

Open
wants to merge 127 commits into
base: main
Choose a base branch
from
Open

Conversation

hiyaryan
Copy link

@hiyaryan hiyaryan commented Feb 6, 2023

This draft PR transfers the pyQuil LaTeX generation feature to quil-rs.

The initial commit,

  1. Adds a new latex.rs to the program crate.
  2. Exposes it as a feature to the project in Cargo.toml and mod.rs.
  3. Includes an initial snapshot test for the simple Program CONTROLLED H 3 2.

program/latex.rs
This file has two sections with some initial code,

  1. LaTeX Implementation
  2. Testing Suite

LaTeX Implementation
The LaTeX implementation section of latex.rs is where the LaTeX generation will occur. The current template was used to generate the first snapshot test. It includes DiagramSettings, directly taken from pyQuil, that will allow users to customize the LaTeX for their Program following the Builder design pattern in Rust. The template also contains an outline for displaying various Result::Err using thiserror on a LatexGenError enum.

Testing Suite
The first test in the testing module containing the suite of LaTeX unit tests is a simple snapshot test for CONTROLLED H 3 2. The snap file for this test is program/snapshots/quil_rs__program__latex__tests__controlled_gate.snap. It was generated by passing the following expected LaTeX to the unit test test_controlled_gate as the initial snapshot assertion.

\[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}

Main Tasks and Sub Tasks lists will be used to help keep track of the work. Once all tasks are marked as complete in the Main Tasks the stage of this PR can be changed from draft to ready for review.

Main Tasks

  • I. Implement all LaTeX generation features currently available in pyQuil.
  • II. Implement new CCNOT and CPHASE features.

Sub Tasks (live list)

I. Implement all LaTeX generation features currently available in pyQuil.

  • Research external LaTeX generation crates.
  • Create simple snapshot tests for single qubit Programs.
  • Implement LaTeX generation for single qubit Programs.
  • Implement LaTeX generation for multi-qubit Programs passing through single qubit gates.
  • Implement LaTeX generation for multi-qubit Programs with control and target qubits.
  • Pass assertion for multi-qubit test_controlled_gate test.

II. Implement new CCNOT and CPHASE features

  • Determine *canonical forms of all instructions that are to be implemented in V1 of this feature.
  • Implement method to decompose "composite" gates into canonical form.
  • Pass all TDD tests
  • Test common quil programs from good-test-files
  • Create method to handle unsupported instructions and gates.
  • Update docs.

*Canonical Forms
CNOT -> CONTROLLED X
CCNOT -> CONTROLLED CONTROLLED X
CPHASE -> CONTROLLED PHASE

@hiyaryan

This comment was marked as outdated.

@hiyaryan

This comment was marked as outdated.

src/program/latex/mod.rs Outdated Show resolved Hide resolved
@hiyaryan

This comment was marked as outdated.

Copy link
Contributor

@Shadow53 Shadow53 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments on how to make this more Rusty.

I'd also like to suggest looking into the builder pattern in Rust, which is (1) more conventional than a Java-like Factory setup and (2) may help avoid errors from bad user input by just not allowing it.

src/program/latex.rs Outdated Show resolved Hide resolved
src/program/latex.rs Outdated Show resolved Hide resolved
src/program/latex/generation.rs Outdated Show resolved Hide resolved
src/program/latex/generation/diagram/tikz.rs Outdated Show resolved Hide resolved
src/program/latex.rs Outdated Show resolved Hide resolved
src/program/latex/generation/diagram/tikz.rs Outdated Show resolved Hide resolved
@hiyaryan

This comment was marked as resolved.

@hiyaryan

This comment was marked as outdated.

src/program/latex/diagram/mod.rs Outdated Show resolved Hide resolved
src/program/latex/diagram/mod.rs Outdated Show resolved Hide resolved
src/program/latex/diagram/mod.rs Outdated Show resolved Hide resolved
src/program/latex/diagram/wire.rs Outdated Show resolved Hide resolved
src/program/latex/settings.rs Outdated Show resolved Hide resolved
src/program/latex/mod.rs Outdated Show resolved Hide resolved
@hiyaryan hiyaryan marked this pull request as draft April 10, 2023 18:09
@MarquessV MarquessV linked an issue Apr 10, 2023 that may be closed by this pull request
@hiyaryan hiyaryan marked this pull request as ready for review April 11, 2023 18:33
Cargo.toml Outdated Show resolved Hide resolved
src/program/latex/mod.rs Outdated Show resolved Hide resolved
src/program/latex/diagram/wire.rs Outdated Show resolved Hide resolved
src/program/latex/diagram/wire.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@Shadow53 Shadow53 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking really good and I like how things have simplified and been split into modules with their own concerns.

Some high level suggestions, some of which are repeats of comments I left:

First, make sure you run cargo clippy --all-features -- there are some things like format!("{}", value) that would be caught by it.

Second, there's an odd mix of to_latex and fmt::Display, which leads to things like erasing errors that may be useful to the end user. My suggestion for this is to follow a pattern I've seen in a few places, where you have the "real" struct, e.g. QuantikzCell, and a function that creates a new struct, e.g. QuantikzCellDisplay<'a>, which is known to be in a good state and implements fmt::Display. This:

  • Helps decrease the number of owned strings being passed around, which should optimize the runtime a little
  • Separates the validation of the input from printing the output, so there's no more replacing a useful error with fmt::Error
    • The benefit of this over a function that combines actual writing with validation is that all validation happens before any files get modified
  • Can be combined to build larger structs that also implement fmt::Display, e.g.
    struct ProgramDisplay<'a> {
        cells: Vec<QuantikzCellDisplay<'a>>,
        // etc.
    }

src/program/latex/diagram/cell.rs Outdated Show resolved Hide resolved
src/program/latex/diagram/mod.rs Outdated Show resolved Hide resolved
src/program/latex/diagram/mod.rs Outdated Show resolved Hide resolved
src/program/latex/diagram/mod.rs Outdated Show resolved Hide resolved
f,
"{}{}",
&RenderCommand::Separate,
command.to_latex(&cell_settings).map_err(|_| fmt::Error)?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of erasing errors like this. See my note above about having a display_latex function, which avoids this.

From the docs for std::fmt::Error:

This type does not support transmission of an error other than that an error occurred. Any extra information must be arranged to be transmitted through some other means.

IMO, the only error that should come from Display is to do with the actual writing of text, not validating the thing to write

Co-authored-by: Michael Bryant <shadow53@shadow53.com>
@hiyaryan
Copy link
Author

First, make sure you run cargo clippy --all-features -- there are some things like format!("{}", value) that would be caught by it.

That's strange, doesn't look like clippy catches the issues you mentioned @Shadow53. I have clippy --fix set automatically whenever I save. I also ran cargo clippy --all-features --fix --allow-dirty just to check and still, the same.

@Shadow53
Copy link
Contributor

First, make sure you run cargo clippy --all-features -- there are some things like format!("{}", value) that would be caught by it.

That's strange, doesn't look like clippy catches the issues you mentioned @Shadow53. I have clippy --fix set automatically whenever I save. I also ran cargo clippy --all-features --fix --allow-dirty just to check and still, the same.

Odd. Might be something that I'm used to having enabled in my projects that isn't enabled by default or in src/lib.rs

@hiyaryan
Copy link
Author

Second, there's an odd mix of to_latex and fmt::Display, which leads to things like erasing errors that may be useful to the end user. My suggestion for this is to follow a pattern I've seen in a few places, where you have the "real" struct, e.g. QuantikzCell, and a function that creates a new struct, e.g. QuantikzCellDisplay<'a>, which is known to be in a good state and implements fmt::Display. This:

@Shadow53 I haven't heard from anyone on the team on the feedback you requested from them on this. Is this something worth pursuing on this PR?

@kalzoo kalzoo mentioned this pull request Jun 24, 2024
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Generate quantum circuit diagrams using LaTeX
6 participants