summaryrefslogtreecommitdiff
path: root/graphics/pgf/contrib/yquant/tex/yquant-circuit.tex
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/pgf/contrib/yquant/tex/yquant-circuit.tex')
-rw-r--r--graphics/pgf/contrib/yquant/tex/yquant-circuit.tex476
1 files changed, 476 insertions, 0 deletions
diff --git a/graphics/pgf/contrib/yquant/tex/yquant-circuit.tex b/graphics/pgf/contrib/yquant/tex/yquant-circuit.tex
new file mode 100644
index 0000000000..993455cbeb
--- /dev/null
+++ b/graphics/pgf/contrib/yquant/tex/yquant-circuit.tex
@@ -0,0 +1,476 @@
+% 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 \ No newline at end of file