projekter / yquant

Typesetting quantum circuits in a human-readable language
LaTeX Project Public License v1.3c
56 stars 5 forks source link

Unable to access node in subcircuit #10

Closed engeljh closed 3 years ago

engeljh commented 3 years ago

This is probably not a bug, but I don't know how to give a name to a subcircuit so that tikz can access it with (subcircuit name-node name). Tikz says that no shape with that name is available. What do I have to do to properly name the subcircuit? Thanks.

projekter commented 3 years ago

Please always submit some example code, so that I know what you do, expect and what does not work. I tried to reproduce this problem, but for me, it works:

\documentclass{article}

\usepackage[compat=0.4]{yquant}
\usepackage{braket}

\begin{document}
   \begin{tikzpicture}
      \begin{yquant}
         qubit a[3];

         h a;
         [name=sub]
         subcircuit {
            qubit q;
            [ancilla]
            qubit {$\ket0$} r;
            qubit s;

            cnot q | r;
            [name=inner]
            cnot r | s;
         } (a[1, 2]);
         [name=outer]
         h a;
      \end{yquant}
      \draw (sub-0-inner-p0) to[in=20, out=50] (outer-0);
   \end{tikzpicture}
\end{document}

image

Here, TikZ is perfectly able to draw the line between the first positive control (-p0) of the CNOT named inner (so the "local" name within the subcircuit is inner-p0) and the first target register (-0) in the outer circuit (which gives the name outer-0). To make the step from the inner name inner-p0 to the outer name, you prepend the name of the subcircuit. Maybe here was the problem, and I should probably make this more explicit in the manual. The name of the subcircuit is sub. However, whenever you use a gate - and a subcircuit is a gate, though a pretty special one - and assign a name, then there are lots of possible nodes that could receive the name, which is why yquant introduces all those suffixes. So in general, the name sub will not be the actual name, but sub-0, sub-1, ... for the targets, sub-p0, ... for the positive and sub-n0, ... for the negative controls. So the actual name of your subcircuit is sub-0, not sub. Whenever there is just a single (target|positive control|negative control) present, yquant additionally creates an alias of the zero-suffixed node to the name without the suffix. This is why you can refer to the target of the CNOT as inner-0 or just inner, or its positive control as inner-p0 or just inner-p. However, this aliasing behavior is not aware of the fact that subcircuits are special, it just aliases the "outer" enclosing subcircuit node itself (so the rectangle with the name sub-0 is also available as sub), not all the included nodes (which would potentially be a lot of aliases). Hence, you must always specify the full name. In this case, it is sub-0-inner-p0 (or just sub-0-inner-p).

engeljh commented 3 years ago

I'm sorry for not including code, but I tried many different things and didn't know which to use as an example. In any event, you diagnosed my problem; thank you. I was not able to glean the naming convention for subcircuits from the manual, so I agree with you that an explanation there would be useful.


From: Benjamin Desef @.> Sent: Friday, July 2, 2021 4:28 AM To: projekter/yquant @.> Cc: Engel, Jonathan @.>; Author @.> Subject: Re: [projekter/yquant] Unable to access node in subcircuit (#10)

Please always submit some example code, so that I know what you do, expect and what does not work. I tried to reproduce this problem, but for me, it works:

\documentclass{article}

\usepackage[compat=0.4]{yquant} \usepackage{braket}

\begin{document} \begin{tikzpicture} \begin{yquant} qubit a[3];

     h a;
     [name=sub]
     subcircuit {
        qubit q;
        [ancilla]
        qubit {$\ket0$} r;
        qubit s;

        cnot q | r;
        [name=inner]
        cnot r | s;
     } (a[1, 2]);
     [name=outer]
     h a;
  \end{yquant}
  \draw (sub-0-inner-p0) to[in=20, out=50] (outer-0);

\end{tikzpicture} \end{document}

[image]https://user-images.githubusercontent.com/2815453/124244737-8febda80-db1f-11eb-8462-695fe8bbf9c3.png

Here, TikZ is perfectly able to draw the line between the first positive control (-p0) of the CNOT named inner (so the "local" name within the subcircuit is inner-p0) and the first target register (-0) in the outer circuit (which gives the name outer-0). To make the step from the inner name inner-p0 to the outer name, you prepend the name of the subcircuit. Maybe here was the problem, and I should probably make this more explicit in the manual. The name of the subcircuit is sub. However, whenever you use a gate - and a subcircuit is a gate, though a pretty special one - and assign a name, then there are lots of possible nodes that could receive the name, which is why yquant introduces all those suffixes. So in general, the name sub will not be the actual name, but sub-0, sub-1, ... for the targets, sub-p0, ... for the positive and sub-n0, ... for the negative controls. So the actual name of your subcircuit is sub-0, not sub. Whenever there is just a single (target|positive control|negative control) present, yquant additionally creates an alias of the zero-suffixed node to the name without the suffix. This is why you can refer to the target of the CNOT as inner-0 or just inner, or its positive control as inner-p0 or just inner-p. However, this aliasing behavior is not aware of the fact that subcircuits are special, it just aliases the "outer" enclosing subcircuit node itself (so the rectangle with the name sub-0 is also available as sub), not all the included nodes (which would potentially be a lot of aliases). Hence, you must always specify the full name. In this case, it is sub-0-inner-p0 (or just sub-0-inner-p).

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/projekter/yquant/issues/10#issuecomment-872819213, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AL3DBE7EV2NCAHQDL6CC66TTVV2BNANCNFSM47VCZMYQ.

projekter commented 3 years ago

So the last commit contains two changes:

Additionally, I think it would be nice to add another section of examples that specifically showcase yquant's unique features, which definitely includes subcircuits. So I'd appreciate it if you want to contribute an actually meaningful quantum circuit that makes use of named nodes in subcircuits, which I can then include in the documentation before version 0.4.1 goes to CTAN.

engeljh commented 3 years ago

Here is the example with circuit equations for which I needed subcircuit names. You can shorten the code significantly by deleting parts of the equations, and I'm sure there are more efficient ways of obtaining the result I did. But as long as I'm submitting this, perhaps I can note that I had to play some tricks to obtain it. In particular, I had to make the vertical dots qubits in the subcircuts rather than nobits, and later discard them, in order to align the leftmost ones with the initial kets. I also had to include explicit hspaces to make the wires in the second "equation row" extend past the cnots but not all the way to the end of the figure. Are there better ways to do these things? And is there a better way to make circuit equations that contain more the one row of circuits?

\documentclass[tikz]{standalone} \usetikzlibrary{fit} \usepackage{braket} \usepackage[compat=0.4]{yquant} \yquantdefinebox{dots}[inner sep=0pt]{$\vdots$}

\begin{document}

\begin{tikzpicture} \begin{yquant}[operator/separation=3.5mm,register/separation=2mm,% operators/subcircuit/frameless]

     [register/minimum depth=4mm]
     nobit dab[1];
     nobit a[4];
     nobit b[1];
     [register/minimum depth=4mm]
     nobit dcd[1];
     nobit c[4];
     nobit d[1];

     subcircuit {
        [out]
        qubit {$\vdots$} dab[1];
        [out]
        qubit {$\ket 0$} a[4];
        [out]
        qubit {$\ket 1$} b[1];
        discard dab;
        h a;
        h b;
        align dab, b;
        dots dab;
        cnot b | a[3];
        cnot b | a[0];
        align dab, a;
        dots dab;
        h a;
        h b;
     } (dab, a, b);

     discard -;
     align a,c;
     [draw=none]
     box {$=$} (a);
     [draw=none]
     box {$=$} (c);

     [name=s]
     subcircuit {
        [out]
        qubit {$\vdots$} dab[1];
        [out]
        qubit {$\ket 0$} a[4];
        [out]
        qubit {$\ket 1$} b[1];
        [out,register/minimum height=7mm]
        qubit {$\vdots$} dcd[1];
        [out]
        qubit {$\ket 0$} c[4];
        [out]
        qubit {$\ket 1$} d[1];
        discard dab;
        discard dcd;
        h a[1-2];
        [name=Alt]
        h a[3];
        h b;
        align dab, a;
        dots dab;
        h a[1-2];
        cnot b | a[3];
        h a[3];
        [name=Arb]
        h b;
        align dab, a, b;
        dots dab;
        [name=Blt]
        h a[0];
        h b;
        cnot b | a[0];
        align dab,a[0];
        dots dab;
        h a[0];
        [name=Brb]
        h b;

%Second row cnot c[3] | d; align dcd,d; dots dcd; cnot c[0] | d; hspace {3.5mm} c; hspace {3.5mm} d; discard c; discard d; } (-);

     discard -;
  \end{yquant}

  \node[draw,dashed,red,semithick, fit=(s-0-Alt) (s-0-Arb)]{};
  \node[draw,dashed,red,semithick, fit=(s-0-Blt) (s-0-Brb)]{};

\end{tikzpicture}

\end{document}


From: Benjamin Desef @.> Sent: Saturday, July 3, 2021 7:10 AM To: projekter/yquant @.> Cc: Engel, Jonathan @.>; Author @.> Subject: Re: [projekter/yquant] Unable to access node in subcircuit (#10)

So the last commit contains two changes:

Note that here, is the full name of the subcircuit, which includes the -\idx suffix, unless there is only a single target register.

Additionally, I think it would be nice to add another section of examples that specifically showcase yquant's unique features, which definitely includes subcircuits. So I'd appreciate it if you want to contribute an actually meaningful quantum circuit that makes use of named nodes in subcircuits, which I can then include in the documentation before version 0.4.1 goes to CTAN.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/projekter/yquant/issues/10#issuecomment-873391087, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AL3DBE2HFCAZ4B74G25CLVLTV3VZFANCNFSM47VCZMYQ.

projekter commented 3 years ago

Wow, this is interesting. Here's something that I came up with and which I hope focuses much more on what is actually happening logically.

First solution, which does not use subcircuits at all.

% \usetikzlibrary{fit,calc}
   \begin{tikzpicture}[highlight/.style={draw, dashed, red, semithick},
                       equals/.style={draw=none, inner xsep=5mm}]
      \yquantset{operator/separation=3.5mm, register/separation=2mm}
      \coordinate (dotpos) at (0, .5);
      \begin{yquant}
         [name=dot0]
         qubit {$\ket0$} a[4];
         qubit {$\ket1$} b;

         h -;
         [name=dot1]
         cnot b | a[3];
         cnot b | a[0];
         [name=dot2]
         h -;

         [name=alignposition, equals]
         box {$=$} (-);
         discard -;

         [name=dot3, operator/separation=0pt]
         init {$\ket0$} a;
         [operator/separation=0pt]
         init {$\ket1$} b;

         [name=box1L]
         h a[1-], b;
         [name=dot4]
         h a[1-2];
         cnot b | a[3];
         [name=box1R]
         h a[3], b;
         [name=dot5]
         h a[0], b;
         cnot b | a[0];
         [name=dot6]
         h a[0], b;
      \end{yquant}
      \node[highlight, fit=(box1L-2) (box1R-1)] {};
      \node[highlight, fit=(dot5-0) (dot6-1)] {};
      \foreach \i in {0, ..., 6} {
         \node at (dotpos -| dot\i-0) {$\vdots$};
      }
      \begin{scope}[shift={($(alignposition.south west)-(0,1.4)$)}]
         \coordinate (dotpos) at (0, .5);
         \begin{yquant}
            nobit a[4];
            nobit b;

            [name=alignposition, equals, operator/separation=0pt]
            box {$=$} (-);
            discard -;

            [name=dot0, operator/separation=0pt]
            init {$\ket0$} a;
            [operator/separation=0pt]
            init {$\ket1$} b;

            cnot a[3] | b;
            [name=dot1]
            cnot a[0] | b;
         \end{yquant}
         \foreach \i in {0, ..., 1} {
            \node at (dotpos -| dot\i-0) {$\vdots$};
         }
      \end{scope}
   \end{tikzpicture}

Second solution, which uses subcircuits for the first line.

   \begin{tikzpicture}[highlight/.style={draw, dashed, red, semithick}]
      \yquantset{operator/separation=3.5mm, register/separation=2mm}
      \coordinate (dotpos) at (0, .6);

      \begin{yquant}[operators/subcircuit/frameless]
         nobit x[5];
         [name=sub]
         subcircuit {
            [name=dot0, out]
            qubit {$\ket0$} a[4];
            [out]
            qubit {$\ket1$} b;

            h -;
            [name=dot1]
            cnot b | a[3];
            cnot b | a[0];
            [name=dot2]
            h -;
         } (-);

         discard -;
         [name=alignposition, draw=none]
         box {$=$} (-);

         [name=sub]
         subcircuit {
            [name=dot3, out]
            qubit {$\ket0$} a[4];
            [out]
            qubit {$\ket1$} b;

            [name=box1L]
            h a[1-], b;
            [name=dot4]
            h a[1-2];
            cnot b | a[3];
            [name=box1R]
            h a[3], b;
            [name=dot5]
            h a[0], b;
            cnot b | a[0];
            [name=dot6]
            h a[0], b;
         } (-);
      \end{yquant}
      \node[highlight, fit=(sub-box1L-2) (sub-box1R-1)] {};
      \node[highlight, fit=(sub-dot5-0) (sub-dot6-1)] {};
      \foreach \i in {0, ..., 6} {
         \node at (dotpos -| sub-dot\i-0) {$\vdots$};
      }
      \begin{scope}[shift={($(alignposition.south west)-(0,1.4)$)}]
         \coordinate (dotpos) at (0, .5);
         \begin{yquant}
            nobit a[4];
            nobit b;

            [name=alignposition, operator/separation=0pt, draw=none]
            box {$=$} (-);
            discard -;

            [name=dot0]
            init {$\ket0$} a;
            init {$\ket1$} b;

            cnot a[3] | b;
            [name=dot1]
            cnot a[0] | b;
         \end{yquant}
         \foreach \i in {0, ..., 1} {
            \node at (dotpos -| dot\i-0) {$\vdots$};
         }
      \end{scope}
   \end{tikzpicture}

What did I do?

It would probably be worth thinking about some convenience macros that facilitate writing circuit equations without having to repeat so much...

engeljh commented 3 years ago

Thanks, that's quite helpful. I had drawn many circuit equations (none with ancillas) with subcircuits and they are all much simpler without them, especially with a predefined 'equals' box.


From: Benjamin Desef @.> Sent: Saturday, July 3, 2021 1:22 PM To: projekter/yquant @.> Cc: Engel, Jonathan @.>; Author @.> Subject: Re: [projekter/yquant] Unable to access node in subcircuit (#10)

Wow, this is interesting. Here's something that I came up with and which I hope focuses much more on what is actually happening logically.

First solution, which does not use subcircuits at all.

% \usetikzlibrary{fit,calc} \begin{tikzpicture}[highlight/.style={draw, dashed, red, semithick}, equals/.style={draw=none, inner xsep=5mm}] \yquantset{operator/separation=3.5mm, register/separation=2mm} \coordinate (dotpos) at (0, .5); \begin{yquant} [name=dot0] qubit {$\ket0$} a[4]; qubit {$\ket1$} b;

     h -;
     [name=dot1]
     cnot b | a[3];
     cnot b | a[0];
     [name=dot2]
     h -;

     [name=alignposition, equals]
     box {$=$} (-);
     discard -;

     [name=dot3, operator/separation=0pt]
     init {$\ket0$} a;
     [operator/separation=0pt]
     init {$\ket1$} b;

     [name=box1L]
     h a[1-], b;
     [name=dot4]
     h a[1-2];
     cnot b | a[3];
     [name=box1R]
     h a[3], b;
     [name=dot5]
     h a[0], b;
     cnot b | a[0];
     [name=dot6]
     h a[0], b;
  \end{yquant}
  \node[highlight, fit=(box1L-2) (box1L-3) (box1R-0) (box1R-1)] {};
  \node[highlight, fit=(dot5-0) (dot5-1) (dot6-0) (dot6-1)] {};
  \foreach \i in {0, ..., 6} {
     \node at (dotpos -| dot\i-0) {$\vdots$};
  }
  \begin{scope}[shift={($(alignposition.south west)-(0,1.4)$)}]
     \coordinate (dotpos) at (0, .5);
     \begin{yquant}
        nobit a[4];
        nobit b;

        [name=alignposition, equals, operator/separation=0pt]
        box {$=$} (-);
        discard -;

        [name=dot0, operator/separation=0pt]
        init {$\ket0$} a;
        [operator/separation=0pt]
        init {$\ket1$} b;

        cnot a[3] | b;
        [name=dot1]
        cnot a[0] | b;
     \end{yquant}
     \foreach \i in {0, ..., 1} {
        \node at (dotpos -| dot\i-0) {$\vdots$};
     }
  \end{scope}

\end{tikzpicture}

Second solution, which uses subcircuits for the first line.

\begin{tikzpicture}[highlight/.style={draw, dashed, red, semithick}] \yquantset{operator/separation=3.5mm, register/separation=2mm} \coordinate (dotpos) at (0, .6);

  \begin{yquant}[operators/subcircuit/frameless]
     nobit x[5];
     [name=sub]
     subcircuit {
        [name=dot0, out]
        qubit {$\ket0$} a[4];
        [out]
        qubit {$\ket1$} b;

        h -;
        [name=dot1]
        cnot b | a[3];
        cnot b | a[0];
        [name=dot2]
        h -;
     } (-);

     discard -;
     [name=alignposition, draw=none]
     box {$=$} (-);

     [name=sub]
     subcircuit {
        [name=dot3, out]
        qubit {$\ket0$} a[4];
        [out]
        qubit {$\ket1$} b;

        [name=box1L]
        h a[1-], b;
        [name=dot4]
        h a[1-2];
        cnot b | a[3];
        [name=box1R]
        h a[3], b;
        [name=dot5]
        h a[0], b;
        cnot b | a[0];
        [name=dot6]
        h a[0], b;
     } (-);
  \end{yquant}
  \node[highlight, fit=(sub-box1L-2) (sub-box1L-3) (sub-box1R-0) (sub-box1R-1)] {};
  \node[highlight, fit=(sub-dot5-0) (sub-dot5-1) (sub-dot6-0) (sub-dot6-1)] {};
  \foreach \i in {0, ..., 6} {
     \node at (dotpos -| sub-dot\i-0) {$\vdots$};
  }
  \begin{scope}[shift={($(alignposition.south west)-(0,1.4)$)}]
     \coordinate (dotpos) at (0, .5);
     \begin{yquant}
        nobit a[4];
        nobit b;

        [name=alignposition, operator/separation=0pt, draw=none]
        box {$=$} (-);
        discard -;

        [name=dot0]
        init {$\ket0$} a;
        init {$\ket1$} b;

        cnot a[3] | b;
        [name=dot1]
        cnot a[0] | b;
     \end{yquant}
     \foreach \i in {0, ..., 1} {
        \node at (dotpos -| dot\i-0) {$\vdots$};
     }
  \end{scope}

\end{tikzpicture}

What did I do?

It would probably be worth thinking about some convenience macros that facilitate writing circuit equations without having to repeat so much...

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/projekter/yquant/issues/10#issuecomment-873440494, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AL3DBE2IYG3JVACFLMUEWWLTV5BLZANCNFSM47VCZMYQ.

projekter commented 3 years ago

The latest release 0.5 (currently on master) again addresses both issues: