PennyLaneAI / pennylane

PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Train a quantum computer the same way as a neural network.
https://pennylane.ai
Apache License 2.0
2.3k stars 592 forks source link

Circuit drawing to LaTeX #2480

Open cvjjm opened 2 years ago

cvjjm commented 2 years ago

Feature details

It would ne nice if PennyLane could "draw" circuits also to LaTeX format. This (relatively) new LaTeX package https://github.com/projekter/yquant could offer a nice "intermediate" language. There could be a qml.latex() function or a kwarg to qml.draw() that would make it output LaTeX code. A bonus feature would be if this could be done in a away that rendering this LaTeX code in jupyter notebooks were possible.

Implementation

No response

How important would you say this feature is?

1: Not important. Would be nice to have.

Additional information

No response

josh146 commented 2 years ago

Hey @cvjjm, out of curiosity, do you have an existing pipeline for rendering tkiz latex code in notebooks without needing a local latex compiler?

cvjjm commented 2 years ago

I have used the %%latex magic (which however uses an external compiler as far as I remember) and there is a good list of alternatives here: https://stackoverflow.com/questions/13208286/how-to-write-latex-in-ipython-notebook

But this would really just be a bonus. Being able to generate the source code to then copy into a manuscript and typeset there would be the most useful prat imho.

CatalinaAlbornoz commented 2 years ago

Hi @cvjjm, thank you for adding these details.

ankit27kh commented 2 years ago

Cirq outputs Qcircuit source code here. And it works very well.

CatalinaAlbornoz commented 2 years ago

Thank you for this suggestion @ankit27kh !

albi3ro commented 2 years ago

As a warm-up, I put together a prototype with QCircuit this morning and it mostly works (no measurements or controlled operations yet). I have other priorities for now, but it might be a possibility. I can keep it on a backburner, or someone else can continue with this prototype.

from .drawable_layers import drawable_layers
from .utils import convert_wire_order

def tape_latex(tape, wire_order=None, show_all_wires=False, decimals=None):

    wire_map = convert_wire_order(tape, wire_order=None, show_all_wires=True)
    op_layers = drawable_layers(tape.operations, wire_map=wire_map)

    layers = ["" for _ in wire_map]

    for ops in op_layers:
        new_layer = ["\\qw" for _ in wire_map]
        for op in ops:
            mapped_op_wires = [wire_map[w] for w in op.wires]
            min_w = min(mapped_op_wires)
            max_w = max(mapped_op_wires)

            if len(op.wires) > 1:
                new_layer[min_w] = f"\\multigate{{{max_w-min_w}}}{{{op.label()}}}"
                for w in range(min_w + 1, max_w + 1):
                    new_layer[w] = f"\\ghost{{{op.label()}}}"
            else:
                new_layer[min_w] = f"\\gate{{{op.label()}}}"

        layers = [" & ".join([t, s]) for t, s in zip(layers, new_layer)]

    center_bulk =  " \\\\ \n".join(layers) + " \\\\"
    return "\Qcircuit @C=1em @R=.7em { \n" + center_bulk + "\n }"