Closed tigerjack closed 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:
\idx
as your loop variable. yquant provides this macro for use within arguments to the gates, where it is filled with the current index of the register in a gate that acts on multiple registers. So while it is safe to use in register names (as you did), it is totally unsafe to use in arguments (as I did). Better not to use it at all.[name/.expanded=...]
, but apparently, the handler does not work well with attributes. I'll have to check whether this is a bug in yquant or the pgfkeys filtering library that I use. For this reason, I call the attribute with its full name /yquant/global attrs/name
(which usually should never be done). Anyway, this results in all the gates being assigned names.name mangling=transparent
.\foreach \i in {\numexpr\rowidx+1, ..., 2}
by \yquant@for \i := \numexpr\rowidx+1 to 2
(and also had to say \makeatletter
before so that this internal macro is usable). I did not plan to do this, but I got errors when using \i
within the attribute names with the \foreach
loop. Apparently, pgf (which provides \foreach
) does some bad things when being passed something like {2, ..., 2}
. Looks like a pgf bug, but I didn't investigate too much, I just replaced the loop by the one that yquant internally provides.\rowidx <> 2
outside of the inner loop, which is more efficient.backgrounds
library - we want the backgrounds to appear behind the gates, not on top (and using opacity for this would be a bad way). Then, I just fit
all the background nodes to the appropriate named shapes. The name sw1/2/1
describes the "main" part of the gate, i.e., the NOT operation itself (if there was more than a single operation, I'd have to use sw/1/2/1-0
, ... to select the correct one), the name sw1/2/1-p1
is the second positive control. Basically, you could add all the controls in here, but I chose just to select the absolutely necessary ones.~
in order to negate it. This is not the correct syntax. Instead, the tilde is the separator that starts the list of negative controls. (And in fact, it is not even necessary to write |
if you don't have positive controls.)@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?
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:
nobit above;
and a nobit below;
as the first and last registers and give them the attributes [register/minimum height=0pt, register/minimum depth=0pt]
. Also add them to the subcircuits. This will ensure that all boxes are aligned, although there is a bit more space than strictly necessary.[x radius=0pt, draw=none] not r0[0];
. However:
draw=none
, the line width of the NOT
gate is not taken into account, therefore the height is not exactly as you want it to be.draw=none
by opacity=0
. The line is gone, but now you will see an interruption in the circuit wire that is exactly one linewidth large.draw=none
, so that the wire continues, but we need the height to be larger by one linewidth. So just look up the dimensions. yquant has a default radius for the NOT
of 1.3mm
, TikZ has a default line width of 0.4pt
, so you could just use y radius=1.3mm+0.2pt
. This will do the job and work as your fake phantom gate: [x radius=0pt, y radius=1.3mm+0.2pt, draw=none] not r0[0];
@projekter thank you! I ended up using the nobit
solution: easy and effective. But thank you again for all the accurate answers you provide!
I am trying to port a
quantikz
circuit (picture below) toyquant
. The great news is that I was able to useforeach
andifthenelse
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.