% BEGIN_FOLD Drawing wires % extends the wire of register #1. Assumes a node called yquantbox is set up, and it is a node with appropriate projections. \protected\def\yquant@circuit@extendwire#1{% \begingroup% \edef\wiretype{\yquant@register@get@type{#1}}% \dimdef\wireypos{\yquant@register@get@y{#1}}% \tikzset{/yquant/every wire}% \unless\ifnum\wiretype=\yquant@register@type@none{% \csname yquant@circuit@extendwire@\wiretype\endcsname{#1}% }\fi% % set the wire style to have the correct \pgflinewidth available (we don't allow individual line widths for different types of wires \tikzset{/yquant/every wire}% \pgfpointanchor{yquantbox}{east}% \@tempdima=\pgf@x% \pgfpointshapexproj{yquantbox}% {\pgfqpoint{\@tempdima} {\dimexpr\wireypos+2\pgflinewidth\relax}}% \edef\tmp{{(\the\pgf@x,\the\pgf@y)}}% % For multi-qubit registers, the east anchor is not necessarily accurate. \pgfpointshapexproj{yquantbox}{\pgfqpoint{\@tempdima}{\wireypos}}% \edef\tmp{\tmp{(\the\pgf@x,\the\pgf@y)}}% \pgfpointshapexproj{yquantbox} {\pgfqpoint{\@tempdima}% {\dimexpr\wireypos-2\pgflinewidth\relax}}% \yquant@register@set@lastwire{#1}{\tmp{(\the\pgf@x,\the\pgf@y)}}% \endgroup% } % finishes the wire of register #1 until x position \yquant@env@end@xpos \protected\def\yquant@circuit@endwire#1{% \begingroup% \edef\wiretype{\yquant@register@get@type{#1}}% \unless\ifnum\wiretype=\yquant@register@type@none\relax% % we don't have a yquantbox node but still want to extend the line; so just install a dummy projection \let\pgfpointshapexproj=\yquant@circuit@endwire@xproj% \dimdef\wireypos{\yquant@register@get@y{#1}}% \tikzset{/yquant/every wire}% \csname yquant@circuit@extendwire@\wiretype\endcsname{#1}% \fi% \endgroup% } \protected\def\yquant@circuit@endwire@xproj#1#2{% \pgf@process{% #2% \pgf@x=\yquant@env@end@xpos% }% } \def\yquant@circuit@extendwire@@extract(#1,#2){% #1% } % a bit faster than nested \@firstoftwo/\@secondoftwo % note \@thirdofthree is defined in the latex kernel already. \long\def\@firstofthree#1#2#3{#1}% \long\def\@secondofthree#1#2#3{#2}% % quantum wire \protected\csdef{yquant@circuit@extendwire@1}#1{% \edef\tmp{\yquant@register@get@lastwire{#1}}% \edef\tmp{\expandafter\@secondofthree\tmp}% \edef\lastx{\expandafter\yquant@circuit@extendwire@@extract\tmp}% \pgfpointshapexproj{yquantbox}{\pgfqpoint{\lastx}{\wireypos}}% \ifdim\lastx<\pgf@x% \edef\cmd{% \noexpand\path [/yquant/every wire, /yquant/every qubit wire] \tmp -- (\the\pgf@x,\the\pgf@y);% }% \cmd% \fi% } % classical wire \protected\csdef{yquant@circuit@extendwire@2}#1{% \edef\tmp{\yquant@register@get@lastwire{#1}}% \edef\tmpa{\expandafter\@firstofthree\tmp}% \edef\lastxa{\expandafter\yquant@circuit@extendwire@@extract\tmpa}% \edef\tmpb{\expandafter\@thirdofthree\tmp}% \edef\lastxb{\expandafter\yquant@circuit@extendwire@@extract\tmpb}% \let\cmd=\empty% \pgfpointshapexproj{yquantbox}{\pgfqpoint{\lastxa}% {\dimexpr\wireypos+2\pgflinewidth\relax}}% \ifdim\lastxa<\pgf@x% \edef\cmd{% \tmpa -- (\the\pgf@x,\the\pgf@y)% }% \fi% \pgfpointshapexproj{yquantbox}{\pgfqpoint{\lastxb}% {\dimexpr\wireypos-2\pgflinewidth\relax}}% \ifdim\lastxb<\pgf@x% \eappto\cmd{% \tmpb -- (\the\pgf@x,\the\pgf@y)% }% \fi% \unless\ifx\cmd\empty% \edef\cmd{\noexpand\path [/yquant/every wire, /yquant/every cbit wire] \cmd;}% \cmd% \fi% } % quantum-bundle \protected\csdef{yquant@circuit@extendwire@3}#1{% \edef\tmp{\yquant@register@get@lastwire{#1}}% \edef\tmpa{\expandafter\@firstofthree\tmp}% \edef\lastxa{\expandafter\yquant@circuit@extendwire@@extract\tmpa}% \edef\tmpb{\expandafter\@secondofthree\tmp}% \edef\lastxb{\expandafter\yquant@circuit@extendwire@@extract\tmpb}% \edef\tmpc{\expandafter\@thirdofthree\tmp}% \edef\lastxc{\expandafter\yquant@circuit@extendwire@@extract\tmpc}% \let\cmd=\empty% \pgfpointshapexproj{yquantbox}{\pgfqpoint{\lastxa}% {\dimexpr\wireypos+2\pgflinewidth\relax}}% \ifdim\lastxa<\pgf@x% \edef\cmd{% \tmpa -- (\the\pgf@x,\the\pgf@y)% }% \fi% \pgfpointshapexproj{yquantbox}{\pgfqpoint{\lastxb}{\wireypos}}% \ifdim\lastxb<\pgf@x% \eappto\cmd{% \tmpb -- (\the\pgf@x,\the\pgf@y)% }% \fi% \pgfpointshapexproj{yquantbox}{\pgfqpoint{\lastxc}% {\dimexpr\wireypos-2\pgflinewidth\relax}}% \ifdim\lastxc<\pgf@x% \eappto\cmd{% \tmpc -- (\the\pgf@x,\the\pgf@y)% }% \fi% \unless\ifx\cmd\empty% \edef\cmd{\noexpand\path [/yquant/every wire, /yquant/every qubits wire] \cmd;}% \cmd% \fi% } % END_FOLD % BEGIN_FOLD Drawing control lines % populates a drawing macro with the current control line with style #1 at position #2. Assumes a node called yquantbox is set up, and it is a node with appropriate projections. At the first call, \yquant@circuit@extendcontrolline@cmd must be \let to \empty and \yquant@circuit@extendcontrolline@prev to \relax. \protected\def\yquant@circuit@extendcontrolline#1#2{% \begingroup% \tikzset{/yquant/every control line}% \expandafter% \endgroup% \expandafter\@tempdima\the\pgflinewidth% \ifcase#1% % no control (or to a discarded target, which we don't do) \or% % qubit \unless\ifx\yquant@circuit@extendcontrolline@prev\relax% \pgfpointanchor{yquantbox}{north}% \pgfpointshapeyproj{yquantbox}{\pgf@x=#2\relax}% \eappto\yquant@circuit@extendcontrolline@cmd{% \expandafter\@secondofthree\yquant@circuit@extendcontrolline@prev% -- (\the\pgf@x,\the\pgf@y)% }% \fi% \yquant@circuit@extendcontrolline@store{#2}% \or% % cbit \unless\ifx\yquant@circuit@extendcontrolline@prev\relax% \pgfpointanchor{yquantbox}{north}% \pgfpointshapeyproj{yquantbox}% {\pgf@x=\dimexpr#2-2\@tempdima\relax}% \eappto\yquant@circuit@extendcontrolline@cmd{% \expandafter\@firstofthree\yquant@circuit@extendcontrolline@prev% -- (\the\pgf@x,\the\pgf@y)% }% \pgfpointshapeyproj{yquantbox}% {\pgf@x=\dimexpr#2+2\@tempdima\relax}% \eappto\yquant@circuit@extendcontrolline@cmd{% \expandafter\@thirdofthree\yquant@circuit@extendcontrolline@prev% -- (\the\pgf@x,\the\pgf@y)% }% \fi% \yquant@circuit@extendcontrolline@store{#2}% \or% % quantum-bundle (very unusual, but perhaps for transversal operations?) \unless\ifx\yquant@circuit@extendcontrolline@prev\relax% \pgfpointanchor{yquantbox}{north}% \pgfpointshapeyproj{yquantbox}% {\pgf@x=\dimexpr#2-2\@tempdima\relax}% \eappto\yquant@circuit@extendcontrolline@cmd{% \expandafter\@firstofthree\yquant@circuit@extendcontrolline@prev% -- (\the\pgf@x,\the\pgf@y)% }% \pgfpointshapeyproj{yquantbox}% {\pgf@x=\dimexpr#2\relax}% \eappto\yquant@circuit@extendcontrolline@cmd{% \expandafter\@secondofthree\yquant@circuit@extendcontrolline@prev% -- (\the\pgf@x,\the\pgf@y)% }% \pgfpointshapeyproj{yquantbox}% {\pgf@x=\dimexpr#2+2\@tempdima\relax}% \eappto\yquant@circuit@extendcontrolline@cmd{% \expandafter\@thirdofthree\yquant@circuit@extendcontrolline@prev% -- (\the\pgf@x,\the\pgf@y)% }% \fi% \yquant@circuit@extendcontrolline@store{#2}% \else% \PackageError{yquant.sty}{Invalid control line type `\the#1'}% {yquant encountered an internal error.}% \fi% } \protected\def\yquant@circuit@extendcontrolline@store#1{% \pgfpointanchor{yquantbox}{south}% \pgfpointshapeyproj{yquantbox}% {\pgf@x=\dimexpr#1-2\@tempdima\relax}% \edef\yquant@circuit@extendcontrolline@prev{{(\the\pgf@x,\the\pgf@y)}}% \pgfpointshapeyproj{yquantbox}% {\pgf@x=#1\relax}% \eappto\yquant@circuit@extendcontrolline@prev{{(\the\pgf@x,\the\pgf@y)}}% \pgfpointshapeyproj{yquantbox}% {\pgf@x=\dimexpr#1+2\@tempdima\relax}% \eappto\yquant@circuit@extendcontrolline@prev{{(\the\pgf@x,\the\pgf@y)}}% } % END_FOLD \newif\ifyquant@circuit@operator@hasControls% % sets up the relevant variables associated with an operator % #1: positive controls % #2: negative controls % #3: targets \protected\def\yquant@circuit@operator#1#2#3{% % convert all names to indices % targets \yquant@register@get@ids{#3}% \let\yquant@circuit@operator@targets=\yquant@register@get@ids@list% \let\yquant@circuit@operator@mintarget=\yquant@register@get@ids@min% \let\yquant@circuit@operator@maxtarget=\yquant@register@get@ids@max% \let\yquant@circuit@operator@numtarget=\yquant@register@get@ids@count% % For the targets, multi-qubit registers might have been allowed, but certainly not for % the controls! \yquant@register@get@allowmultifalse% % positive controls \yquant@register@get@ids{#1}% \let\yquant@circuit@operator@pctrls=\yquant@register@get@ids@list% \let\yquant@circuit@operator@minpctrl=\yquant@register@get@ids@min% \let\yquant@circuit@operator@maxpctrl=\yquant@register@get@ids@max% \let\yquant@circuit@operator@numpctrl=\yquant@register@get@ids@count% \ifnum\yquant@register@get@ids@count>0 % \yquant@circuit@operator@hasControlstrue% \fi% % negative controls \yquant@register@get@ids{#2}% \let\yquant@circuit@operator@nctrls=\yquant@register@get@ids@list% \let\yquant@circuit@operator@minnctrl=\yquant@register@get@ids@min% \let\yquant@circuit@operator@maxnctrl=\yquant@register@get@ids@max% \let\yquant@circuit@operator@numnctrl=\yquant@register@get@ids@count% \ifnum\yquant@register@get@ids@count>0 % \yquant@circuit@operator@hasControlstrue% \fi% % determine the qubits spanned \yquant@min\yquant@circuit@operator@minctrl% \yquant@circuit@operator@mintarget% \yquant@circuit@operator@minpctrl% \yquant@circuit@operator@minnctrl% \relax% \yquant@max\yquant@circuit@operator@maxctrl% \yquant@circuit@operator@maxtarget% \yquant@circuit@operator@maxpctrl% \yquant@circuit@operator@maxnctrl% \relax% % obtain the required minimal x position \yquant@register@get@maxxrange% \yquant@circuit@operator@x% \yquant@circuit@operator@minctrl% \yquant@circuit@operator@maxctrl% \dimdef\yquant@circuit@operator@x{% \yquant@circuit@operator@x+\yquant@config@operator@sep% }% } % BEGIN_FOLD Subcircuit-related % Does all necessary calculations for inserting a sub-circuit % #1: subcircuit code (should start with \begin{yquant}) %\newbox\yquant@circuit@subcircuit@box %\protected\long\def\yquant@circuit@subcircuit#1{% % % We need to place the inner circuit at the correct position; but for this, we need % % its extent. For this, we first place it within a box. But this box is then % % integrated seamlessly, in particular, named nodes must be re-placed. We use a lot of % % inspiration from pgf's matrix capabilities. % % First, we anticipate the macro that is used by our subcircuit to store the node % % names. % \edef\yquant@circuit@subcircuit@nodelist{yquant@env\the\numexpr\yquant@env+1\relax @circuit@subcircuit@nodelist}% % \global\cslet\yquant@circuit@subcircuit@nodelist\empty% % \pgfinterruptboundingbox% % % we make sure there are no conflicts by prefixing any named nodes in any case. % \ifx\yquant@lang@attr@name\empty% % \pgfkeys{/tikz/name prefix/.expanded={sub\yquant@prefix-}}% % \else% % \pgfkeys{/tikz/name prefix/.expanded={\pgfkeysvalueof{/tikz/name prefix}\yquant@lang@attr@name-}}% % \fi% % \let\pgf@nodecallback=\yquant@circuit@subcircuit@nodecallback% % \pgftransformreset% % \global\setbox\yquant@circuit@subcircuit@box=\hbox{{% % % bypass 'overlay' option % \pgf@relevantforpicturesizetrue% % \pgfsys@beginpicture% % #1% % \pgfsys@endpicture% % \ifdim\pgf@picmaxx=-16000pt % % \global\pgf@picmaxx=0pt % % \global\pgf@picminx=0pt % % \global\pgf@picmaxy=0pt % % \global\pgf@picminy=0pt % % \fi% % }}% % \wd\yquant@circuit@subcircuit@box=0pt % % \global\setbox\yquant@circuit@subcircuit@box=\hbox{{% % \hskip-\pgf@picminx% % \unhbox\yquant@circuit@subcircuit@box% % \hskip\pgf@picmaxx% % }}% % \ht\yquant@circuit@subcircuit@box=\pgf@picmaxy% % \dp\yquant@circuit@subcircuit@box=-\pgf@picminy% % % We need to remember the offset for the coordinate shifts % \dimgdef\yquant@circuit@subcircuit@shiftx{-\pgf@picminx}% % \endpgfinterruptboundingbox% % \ifx\yquant@lang@attr@name\empty% % % However, if the outer node was not named, no access to the inner nodes is desired, % % so we delete all nodes again. % \def\do##1{% % \csgundef{pgf@sh@ns@##1}% % \csgundef{pgf@sh@np@##1}% % \csgundef{pgf@sh@nt@##1}% % \csgundef{pgf@sh@pi@##1}% % \csgundef{pgf@sh@ma@##1}% % }% % \dolistcsloop\yquant@circuit@subcircuit@nodelist% % \global\cslet\yquant@circuit@subcircuit@nodelist\empty% % \else% % % But now access is desired, and probably we are deeply nested. Append the sublist to ours, so that our parent can re-map them again. % \ifx\pgf@nodecallback\yquant@circuit@subcircuit@nodecallback% % \csxappto{\yquant@prefix circuit@subcircuit@nodelist}% % {\csname\yquant@circuit@subcircuit@nodelist\endcsname}% % \fi% % \fi% %} % %\def\yquant@circuit@subcircuit@nodecallback#1{% % \listcsxadd{\yquant@prefix circuit@subcircuit@nodelist}{#1}% %} %\protected\def\yquant@circuit@subcircuit@shiftnodes#1{% % \expandafter\unless\expandafter\ifx\csname\yquant@circuit@subcircuit@nodelist\endcsname\empty{% % \pgftransformreset% % \pgf@process{\pgfpointanchor{#1}{text}}% % \edef\yquant@circuit@subcircuit@offset{% % \noexpand\pgfqpoint{\the\dimexpr\pgf@x+\yquant@circuit@subcircuit@shiftx\relax}% % {\the\dimexpr\pgf@y\relax}% % }% % \def\do##1{% % \pgf@shift@node{##1}\yquant@circuit@subcircuit@offset% % }% % \dolistcsloop\yquant@circuit@subcircuit@nodelist% % }\fi% %} % END_FOLD % BEGIN_FOLD Helpers for operator callbacks % turn a wire into a different type \def\yquant@circuit@settype#1{% \yquant@register@set@type{#1}\yquant@circuit@settype@to% } % performs an alignment of all registers specified in the argument; that is, the next operation on any of the listed registers will be after the maximum position of all of them % #1: arbitrary register list \protected\def\yquant@circuit@align#1{% \begingroup% \yquant@register@get@maxxlist\x{#1}% \def\do##1{% \yquant@register@set@x{##1}\x% }% \dolistloop{#1}% \endgroup% } % introduces a horizontal skip (= invisible operator of given width) among the registers; that is, those registers are first aligned, then skipped by the given amount. % #1: arbitrary register list % #2: skip width \protected\def\yquant@circuit@hspace#1#2{% \begingroup% \yquant@register@get@maxxlist\x{#1}% \dimdef\x{\x+#2}% \def\do##1{% \yquant@register@set@x{##1}\x% }% \dolistloop{#1}% \endgroup% } % sets the type of a list of registers % #1: arbitrary register list % #2: new type \protected\def\yquant@circuit@settypes#1#2{% \begingroup% \let\tmp=\empty% \def\do##1{% % We do not extend the wire: a register that is discarded somewhere does not make % sense, only right after some application (which is supposed to already have % extended the wire appropriately). \appto\tmp{\yquant@register@set@type{##1}#2}% }% \dolistloop{#1}% \csxappto{\yquant@prefix draw}{\tmp}% \endgroup% } % sets the output of wires % #1: arbitrary register list \protected\def\yquant@circuit@output#1{% \csxappto{\yquant@prefix outputs}% {\noexpand\yquant@circuit@output@do% {\noexpand#1}% there is nothing to expand - except the first token, which might be \yquant@register@multi, and we need to preserve this. {\yquant@attrs@remaining}% {\unexpanded\expandafter{\yquant@lang@attr@value}}% }% } \protected\long\def\yquant@circuit@output@do#1#2#3{% % this must only be called at the end of an environment, where \yquant@env@end@xpos is % set up properly! \def\do##1{% \ifyquant@firsttoken\yquant@register@multi{##1}{% \csxappto{\yquant@prefix draw}% {\noexpand\yquant@circuit@output@do@multi% \yquant@circuit@output@do@multi@@extract##1{\unexpanded{#3}}}% }{% \csgappto{\yquant@prefix draw}% {\yquant@circuit@output@do@single{##1}{#3}}% }% }% % \dolistloop will carry out one \expandafter on the argument; but this expansion step % is already done. If #1 starts with \yquant@register@multi, this will be expanded once % despite \protected, so insert some expand-to-nothing token first. \csgappto{\yquant@prefix draw}{% \yquant@circuit@output@group{#2}% } \dolistloop{\empty#1}% \csgappto{\yquant@prefix draw}{% \yquant@circuit@output@endgroup% }% } \def\yquant@circuit@output@do@multi@@extract#1#2#3#4#5{% {#2}{#3}% } \protected\long\def\yquant@circuit@output@group#1{% \begingroup% \def\idx{0}% \yquant@set{#1}% } \let\yquant@circuit@output@endgroup=\endgroup% \long\def\yquant@circuit@output@do@single#1#2{% \path (\yquant@env@end@xpos, \yquant@register@get@y{#1}) node[/yquant/every output, /yquant/every \ifcase\yquant@register@get@type{#1} qubit\or cbit\or qubits\fi\space output] {#2}; \numdef\idx{\idx+1}% } \long\def\yquant@circuit@output@do@multi#1#2#3{% \path[/yquant/every multi output] (\yquant@env@end@xpos, \yquant@register@get@y{#1}) -- (\yquant@env@end@xpos, \yquant@register@get@y{#2}) node {#3};% \numdef\idx{\idx+1}% } % END_FOLD