Skip to main content
5 of 5
Fixed error in the circuit diagram (and the code snippet) itself
Niel de Beaudrap
  • 12.4k
  • 1
  • 32
  • 72

Edit —

  1. I've revised this answer to make some small improvements in the commands, to tidy up the commands for drawing the wires for instance, because it seemed worthwhile.

  2. Flattering as it is to have this answer be the accepted one for the time being, I think I should point out that the quantikz package (see Daftwullie's answer below) and the qpic package (as pointed out in cnada's answer below) are both libraries with reasonably complete interfaces, and so better for people looking for a quick and simple solution. The code below is probably more suitable for people who are comfortable with TiKZ, and might like to tweak their circuit diagrams with TiKZ commands, but who wouldn't mind having some macros to streamline drawing their diagrams. — Nice as it might be to, for the moment I have no ambition to write a LaTeX package to make these macros available with a nice interface for all purposes (but anyone else who would like to is welcome if they give me some of the credit).

Snippet

See below for all of the code used to generate this example: the following commands are just the ones used to draw the circuit itself. (This snippet involves macros which I have defined for the purpose of this post, which I also define below.)

  % define initial positions of the quantum wires
  \xdef\dy{1.25}
  \defwire (A) at (0);
  \defwire (B) at ({-\dy});
  \defwire (C) at ({-2*\dy});
  % draw wires
  \xdef\dt{0.8}
  \drawwires [\dt] (15);
  \node  at ($(B-0)!0.5!(B-1)$) {$/$};
  \node  at ($(C-0)!0.5!(C-1)$) {$/$};
  % draw gates
  \gate     (B-2)         [H^{\otimes n}];
  \ctrlgate (B-3) (C-3)   [U];
  \virtgate (A-3);
  \gate     (B-4)         [\mathit{FT}^\dagger];
  \ctrlgate (B-7) (A-7)   [R];
  \virtgate (C-7);
  \gate     (B-10)        [\mathit{FT}];
  \ctrlgate (B-11) (C-11) [U^\dagger];
  \gate     (B-12)        [H^{\otimes n}];
  \virtgate (A-12);
  \meas     (A-14)        [Z];
  % draw input and output labels
  \inputlabel  (A-0)  [\lvert 0 \rangle];
  \inputlabel  (B-0)  [\lvert 0 \rangle^{\otimes n}];
  \inputlabel  (C-0)  [\lvert b \rangle];
  \outputlabel (A-15) [\lvert 1 \rangle];
  \outputlabel (B-15) [\lvert 0 \rangle^{\otimes n}];
  \outputlabel (C-15) [\lvert x \rangle];

Result

Circuit diagram

Preamble

You will need a pre-amble which contains at least the amsmath package, as well as the tikz package. You may not need all of the tikz libraries below, but they don't hurt. Be sure to include the commands involving layers.

\documentclass[a4paper,10pt]{article}

\usepackage{amsmath}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows,calc,positioning,fit}
\pgfdeclarelayer{background}
\pgfsetlayers{background,main}

For the purposes of this post, I've defined some ad-hoc macros to make reading the coded circuit easier for public consumption. (The macro format is not exactly good LaTeX practise, but I define them this way in order for the syntax to be more easily read and for it to stand out.) The parameters for dimensions in these gates were chosen to look good in your sample-circuit, and were found by trial-and-error: you can change them to change the appearance of your circuit.

The first is a simple macro to draw a gate.

\def\gate (#1) [#2]{%
  \node [
    draw=black,fill=white, inner sep=0pt,
    minimum width=2.5em, minimum height=2em, outer sep=1ex
  ] (#1) at (#1) {$#2$}%
}

The second is a macro to draw an 'invisible' gate. This is not really a command which is important for the circuit itself, but helps for the placement of background frames.

\def\virtgate (#1){%
  \node [
    draw=none, fill=none,
    minimum width=2.5em, minimum height=2em, outer sep=1ex
  ] (#1) at (#1) {};
}

The third is a macro to draw a controlled gate. This command works well enough for your example circuit, but doesn't allow you to draw a CNOT. (Exercise for the reader proficient in TiKZ: make a \CNOT command.)

\def\ctrlgate (#1) (#2) [#3]{%
  \filldraw [black] (#1) circle (2pt) -- (#2);
  \gate (#2) [#3]
}

The fourth is a macro to draw a "measurement" box. I think it is perfectly reasonable to want to specify an explicit basis or observable for the measurement, so I allow an argument to specify that.

\def\meas (#1) [#2]{%
  \node [
    draw=black, fill=white, inner sep=2pt,
    label distance=-5mm, minimum height=2em, minimum width=2em
  ] (meas) at (#1) {};
  \draw ($(meas.south) + (-.75em,1.5mm)$) arc (150:30:.85em);
  \draw ($(meas.south) + (0,1mm)$) -- ++(.8em,1em);
  \node [
    anchor=north west, inner sep=1.5pt, font=\small
  ] at (meas.north west) {#2};
}

I define two short macros to produce the labels for the inputs and outputs of wires.

\def\inputlabel (#1) [#2]{%
  \node at (#1) [anchor=east] {$#2$}
}
\def\outputlabel (#1) [#2]{%
  \node at (#1) [anchor=west] {$#2$}
}

The macros above are all looking for co-ordinates at which to place the gates. I also define macros to define "wires", which have regularly spaced co-ordinates where gates can be located. The first is a macro which allows you to define a named wire (such as A, B, x3, etc.) and its vertical position in the circuit diagram (these diagrams are left-to-right by default, which you can change most easily using the rotate option of the tikzpicture environment.)

\def\defwire (#1) at (#2){%
  \ifx\qmwires\empty
    \edef\qmwires{#1}%
  \else
    \edef\qmwires{\qmwires,#1}%
  \fi
  \coordinate (#1-0) at ($(0,#2)$)%
}

Having defined a collection of wires, the following command then draws all of them, starting from the same left-most starting point and ending at the same right-most ending point, with increments by a fixed amount (given in the square brackets) and for a given number of time slices. This defines a sequence of 'time-slice' co-ordinates for each wire: for a wire A, it defines the co-ordinates A-0, A-1, and so forth up until A-t (where t is the value of the second argument).

\def\drawwires [#1] (#2);{%
  \xdef\u{0}
  \foreach \t in {0,...,#2} {%
    \foreach \l in \qmwires {%
      \coordinate (\l-\t) at ($(\l-\u) + (#1,0)$);
      \draw (\l-\u) -- (\l-\t);
    }
    \xdef\u{\t}
  }
}

The final macro is one to draw a background frame for different stages in your circuit. It takes an argument specifying which gates (including the invisible virtual 'gates') are meant to belong to the frame.

\def\bgframe [#1]{%
  \node [%
    draw=black, fill=yellow!40!gray!30!white, fit=#1
  ] {}%
}

The circuit diagram itself

Now to begin drawing your circuit.

\begin{document}
\begin{tikzpicture}

We start by defining the relative positions of the wires. (For convenience, I do this using a macro to define the spacing between them, that I can quickly change to adjust the spacing.) Below, I define three wires: A, B, and C.

  \let\qmwires\empty
  % define initial positions of the quantum wires
  \xdef\dy{1.25}
  \defwire (A) at (0);
  \defwire (B) at ({-\dy});
  \defwire (C) at ({-2*\dy});

We now draw the circuit, using the command to draw the wires and define the co-ordinates on the wire, and placing gates independently of one another according to those co-ordinates.

  % draw circuit
  \xdef\dt{0.8}
  \drawwires [\dt] (15);
  \node  at ($(B-0)!0.5!(B-1)$) {$/$};
  \node  at ($(C-0)!0.5!(C-1)$) {$/$};
  \gate     (B-2)         [H^{\otimes n}];
  \ctrlgate (B-3) (C-3)   [U];
  \virtgate (A-3);
  \gate     (B-4)         [\mathit{FT}^\dagger];
  \ctrlgate (B-7) (A-7)   [R];
  \virtgate (C-7);
  \gate     (B-10)        [\mathit{FT}];
  \ctrlgate (B-11) (C-11) [U^\dagger];
  \gate     (B-12)        [H^{\otimes n}];
  \virtgate (A-12);
  \meas     (A-14)        [Z];
  % draw input and output labels
  \inputlabel  (A-0)  [\lvert 0 \rangle];
  \inputlabel  (B-0)  [\lvert 0 \rangle^{\otimes n}];
  \inputlabel  (C-0)  [\lvert b \rangle];
  \outputlabel (A-15) [\lvert 1 \rangle];
  \outputlabel (B-15) [\lvert 0 \rangle^{\otimes n}];
  \outputlabel (C-15) [\lvert x \rangle];

Annotations for the circuit

The rest of the circuit diagram is literally commentary. We can do this using a combination of plain-old TiKZ nodes, and the \bgframe macro which I defined above. (Annotations are a little less predictable, so I don't have a good way of making them as systematic as the earlier parts of the circuit, so general TiKZ commands are a reasonable approach unless you know how to make your annotations uniform.)

First the annotations for the stages of the circuit:

  % draw annotations
  \node [minimum height=4ex] (annotate-1) at ($(A-3) + (0,1)$)
        {\textit{Phase estimation}};
  \node [minimum height=4ex] (annotate-2) at ($(A-7) + (0,1)$)
        {\textit{$\smash{R(\tilde\lambda^{-1}})$ rotation}};
  \node [minimum height=4ex] (annotate-3) at ($(A-11) + (0,1)$)
        {\textit{Uncompute}};
  \node (annotate-a) at ($(C-3) + (0,-1.25)$)  {\textit{(a)}}; 
  \node (annotate-b) at ($(C-7) + (0,-1.25)$)  {\textit{(b)}}; 
  \node (annotate-c) at ($(C-11) + (0,-1.25)$) {\textit{(c)}};

Next, the annotations for the registers, at the input:

  \node (A-in-annotate) at ($(A-0) + (-3em,0)$) [anchor=east]
    {\parbox{4.5em}{\centering  Ancilla register $S$ }};
  \node (B-in-annotate) at ($(B-0) + (-3em,0)$) [anchor=east]
    {\parbox{4.5em}{\centering Clock \\ register $C$ }};
  \node (C-in-annotate) at ($(C-0) + (-3em,0)$) [anchor=east]
    {\parbox{4.5em}{\centering Input \\ register $I$ }};

Finally, the frames for the stages of the circuit.

  % draw frames for stages of the circuit
  \begin{pgfonlayer}{background}
    \bgframe [(annotate-1)(B-2)(B-4)(C-3)];
    \bgframe [(annotate-2)(B-7)(C-7)];
    \bgframe [(annotate-3)(B-10)(B-12)(C-11)];
  \end{pgfonlayer}

And that's the end of the circuit.

\end{tikzpicture}
\end{document}
Niel de Beaudrap
  • 12.4k
  • 1
  • 32
  • 72