projekter / yquant

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

Frames around subcircuits obtained through foreach loops #19

Closed tigerjack closed 2 years ago

tigerjack commented 2 years ago

I am trying to port a quantikz circuit (picture below) to yquant. The great news is that I was able to use foreach and ifthenelse to obtain a few lines of codes. The bad one is that I don't know how to add, inside the circuit, the rectangular frames around part of the subcircuits (colored or not). Do you have any suggestion?

The code is shown below. Note that there are tiny differences between the two circuits. For example, instead of the X CNOT X gate of the original quantikz circuit, I simply used a CNOT gate with an inverted control. But this is not the relevant point of the discussion, just a tiny difference.

\documentclass[tikz]{standalone}
\usepackage{expl3} % load latex3 packages 
\usepackage[compat=0.4]{yquant}
\usepackage{ifthen}
\begin{document}
\begin{tikzpicture}
  \begin{yquant}
    qubit {$H[0,\idx]$} r0[4];
    qubit {$H[1,\idx]$} r1[4];
    qubit {$H[2,\idx]$} r2[4];
    qubit {$H[3,\idx]$} r3[4];
    qubit {$S[\idx]$} fs[3];
    qubit {$C[\idx]$} ca[6];

    \newcounter{fsn}
    \setcounter{fsn}{0}
    \newcounter{can}
    \setcounter{can}{0}

    \foreach \idx in {0,...,2} {
      \foreach \i in {\the\numexpr\idx+1, ..., 2} {
        \ifthenelse{\NOT \idx = 2}{
          \yquant
          cnot fs[\thefsn] | ~r\idx[\idx];
          \foreach \col in {0,...,3} {
            \yquant
            cnot r\idx[\col] | r\i[\col], fs[\thefsn];
          }
          \stepcounter{fsn}
        }
        {}
      }
      \foreach \i in {0, ..., 2} {
      \ifthenelse{\NOT \i = \idx}{
        \yquant
        cnot ca[\thecan] | r\i[\idx];
          \foreach \col in {0,...,3} {
            \yquant
            cnot r\i[\col] | r\idx[\col], ca[\thecan];
          }
        \stepcounter{can}
      }
        {}
      }
    }
  \end{yquant}
\end{tikzpicture}
\end{document}                                                                                                                                                                                                                                                                     

image

projekter commented 2 years ago

I do have some suggestions. Note that this is not a complete solution, but it should contain all the necessary ideas:

\documentclass[tikz]{standalone}
\usepackage[compat=0.6]{yquant}
\usetikzlibrary{backgrounds,quotes,fit}
\begin{document}
   \begin{tikzpicture}
      \begin{yquant}[operators/subcircuit/name mangling=transparent]
         qubit {$H[0,\idx]$} r0[4];
         qubit {$H[1,\idx]$} r1[4];
         qubit {$H[2,\idx]$} r2[4];
         qubit {$H[3,\idx]$} r3[4];
         qubit {$S[\idx]$} fs[3];
         qubit {$C[\idx]$} ca[6];

         \newcounter{fsn}
         \newcounter{can}
         \makeatletter

         \foreach \rowidx in {0, ..., 2} {
            \unless\ifnum\rowidx=2 %
               \yquant [this subcircuit box style={dashed, "Row \rowidx\space swaps"}] subcircuit {
                  qubit {} r0[4]; qubit {} r1[4]; qubit {} r2[4]; qubit {} r3[4];
                  qubit {} fs[3]; qubit {} ca[6];
                  \yquant@for \i := \numexpr\rowidx+1\relax to 2 {
                     \yquant cnot fs[\thefsn] ~ r\rowidx[\rowidx];
                     \foreach \colidx in {0, ..., 3} {
                        \yquant [global attrs/name/.expanded={sw\rowidx/\i/\colidx}]
                           cnot r\rowidx[\colidx] | r\i[\colidx], fs[\thefsn];
                     }
                     \stepcounter{fsn}
                  }
               } (-);
            \fi
            \yquant [this subcircuit box style={dashed, "Row \rowidx\space additions"}] subcircuit {
               qubit {} r0[4]; qubit {} r1[4]; qubit {} r2[4]; qubit {} r3[4];
               qubit {} fs[3]; qubit {} ca[6];
               \foreach \i in {0, ..., 2} {
                  \unless\ifnum\i=\rowidx\space
                     \yquant cnot ca[\thecan] | r\i[\rowidx];
                     \foreach \colidx in {0, ..., 3} {
                        \yquant [global attrs/name/.expanded={add\rowidx/\i/\colidx}]
                           cnot r\i[\colidx] | r\rowidx[\colidx], ca[\thecan];
                     }
                     \stepcounter{can}
                  \fi
               }
            } (-);
         }
      \end{yquant}
      \begin{scope}[on background layer, every node/.style={fill=red!10!white, draw, dashed}]
         \node[fit=(sw1/2/1) (sw1/2/1-p1)] {};
         \node[fit=(add1/0/1) (add1/0/1-p1)] {};
         \node[fit=(add1/2/1) (add1/2/1-p1) (add1/2/1-p0)] {};
         \node[fit=(add2/0/1) (add2/0/2) (add2/0/2-p1)] {};
         \node[fit=(add2/1/1) (add2/1/2) (add2/1/2-p1)] {};
      \end{scope}
   \end{tikzpicture}
\end{document}

So let me summarize the main points:

tigerjack commented 2 years ago

@projekter Thanks for the detailed answer! It took me some time to absorb all the changes you made, but this is definitely pure gold. For the alignment of the boxes, maybe it could be solved by adding a phantom X gate to the first qubit for every subcircuit? Is it possibile?

projekter commented 2 years ago

Yes and no. There is no such thing as an inbuilt phantom gate, so you'd have to fake it in some way. I can think of various ways to achieve this:

tigerjack commented 2 years ago

@projekter thank you! I ended up using the nobit solution: easy and effective. But thank you again for all the accurate answers you provide!