diff options
author | Karl Berry <karl@freefriends.org> | 2021-10-15 22:13:43 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-10-15 22:13:43 +0000 |
commit | cc132c618fc7756487b972a2954ea75bf91af266 (patch) | |
tree | 6ecab7f1fc87f47b48bd90447bcb2bb2d06f39b8 /Master/texmf-dist/tex | |
parent | a92301bb094f194a117620c2d3e3aebd1f442448 (diff) |
zx-calculus (16oct21)
git-svn-id: svn://tug.org/texlive/trunk@60768 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex')
-rw-r--r-- | Master/texmf-dist/tex/latex/zx-calculus/tikzlibraryzx-calculus.code.tex | 945 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/zx-calculus/zx-calculus.sty | 9 |
2 files changed, 954 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/zx-calculus/tikzlibraryzx-calculus.code.tex b/Master/texmf-dist/tex/latex/zx-calculus/tikzlibraryzx-calculus.code.tex new file mode 100644 index 00000000000..d73c1ad0bd7 --- /dev/null +++ b/Master/texmf-dist/tex/latex/zx-calculus/tikzlibraryzx-calculus.code.tex @@ -0,0 +1,945 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Version: 2021/10/15 +%%% License: MIT +%%% Author: Léo Colisson +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% A tikzlibrary[libraryName].code.tex is loaded automatically by tikz when using +% \usetikzlibrary{libraryName}. Therefore, you should just use +% \usetikzlibrary{zx} to load this library. We also provide a package to +% directly load this library using \usepackage{zx}. + +\RequirePackage{amssymb} % For short minus +\RequirePackage{etoolbox} +\RequirePackage{ifthen} % For conditions +\RequirePackage{xparse} % For NewDocumentComments +\RequirePackage{bm} % For bold math fonts + +\usetikzlibrary{cd,backgrounds,positioning,shapes,calc} +% Declare layers. +\pgfdeclarelayer{background} % Fox boxes using "fit" to group parts of the graph. +\pgfdeclarelayer{edgelayer} % For edges that are explicitely defined "wc" +\pgfdeclarelayer{nodelayer} % For nodes... in theory, this fails for now. https://tex.stackexchange.com/questions/618823/node-on-layer-style-in-tikz-matrix-tikzcd +\pgfdeclarelayer{main} +\pgfdeclarelayer{box} % For boxes using "fit" to fake multi-column boxes +\pgfdeclarelayer{labellayer} % For labels... in theory, this fails for now. https://tex.stackexchange.com/questions/618823/node-on-layer-style-in-tikz-matrix-tikzcd +\pgfdeclarelayer{foreground} % For the user, if they want to put anything really above everything. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% User modifiable variables +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Define colors, can be redefine by user +\definecolor{colorZxZ}{RGB}{204,255,204} +\definecolor{colorZxX}{RGB}{255,136,136} +\definecolor{colorZxH}{RGB}{255,255,0} + +%%% Some wires (the one having an intermediate H, X, or S gate) may need some additional space for +%%% specific columns. +%%% Use these spaces like &[\zxHCol] or \\[\zxHRow] in that case +%% Defines the space to add for columns and rows containing a connection with Hadamard +% This is for "curved" wires +\newcommand{\zxHCol}{1mm} +\newcommand{\zxHRow}{1mm} +% This is for "flat" wires (usually takes more space) +\newcommand{\zxHColFlat}{1.5mm} +\newcommand{\zxHRowFlat}{1.5mm} +%% Defines the space to add for columns and rows containing a connection with small X/Z +\newcommand{\zxSCol}{1mm} +\newcommand{\zxSRow}{1mm} +\newcommand{\zxSColFlat}{1.5mm} +\newcommand{\zxSRowFlat}{1.5mm} +%% Defines the space to add for columns having both H and Spiders +\newcommand{\zxHSCol}{1mm} +\newcommand{\zxHSRow}{1mm} +\newcommand{\zxHSColFlat}{1mm} +\newcommand{\zxHSRowFlat}{1mm} +%% Wires only: when adding only wires with empty nodes, the space between columns can be too small. Useful not to shrink swap gates... +\newcommand{\zxWCol}{.55em} +\newcommand{\zxWRow}{.55em} +%% When vdots/dots are used in lines +\newcommand{\zxDotsCol}{3mm} +\newcommand{\zxDotsRow}{3mm} + + +% Angles by default for s and o related arrows +\def\zxDefaultSoftAngleS{30} +\def\zxDefaultSoftAngleN{60} +\def\zxDefaultSoftAngleO{40} +\def\zxDefaultSoftAngleChevron{60} + +% Scale to use when scaling 3 dots +\def\zxScaleDots{.7} + +% 0.4pt is default in tikz. Also used to ensure it has not been modified document wise by other libraries +% (quantikz notably changes this parameter). +\newcommand{\zxDefaultLineWidth}{0.4pt} + +% For phase in content: How to convert sign ("-" for minus, nothing for "+", anything else should be inserted directly), +% above fraction (no parens), below fraction (no parens), above fraction (with parens), below fraction (with parens) +\NewExpandableDocumentCommand{\zxConvertToFracInContent}{mmmmm}{% + \ifthenelse{\equal{#1}{-}}{\zxMinus}{#1}\frac{#2}{#3}% +} + +% For phase in label: How to convert sign ("-" for minus, nothing for "+", anything else should be inserted directly), +% above fraction (no parens), below fraction (no parens), above fraction (with parens), below fraction (with parens) +\NewExpandableDocumentCommand{\zxConvertToFracInLabel}{mmmmm}{% + \ifthenelse{\equal{#1}{-}}{\zxMinus}{#1}#4/#5% +} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Tikz styles +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Styles. User should not modify "wires definition", but is free to change: +% - "/zx/default style nodes/" to change completely the node style +% - "/zx/user overlay nodes" to add stuff on current node style +% - "/zx/default style wires" to change the wire style +% - "/zx/user overlay wires/" to add stuff on wire style +% The user is not supposed to use node styles directly (use \zxZ{}, \zxZ{\alpha+\beta}, \zxFrac-{\pi}{4}...) +% but is free (and encouraged) to use the styles in "wires definition" like \ar[r,o']. +\tikzset{ + /zx/wires definition/.style={ + %%% Basic default properties + draw, + -, + line width=\zxDefaultLineWidth, + %%% Useful shortcut (shorter lines means easy "align" of & symbols. Love M-x align in emacs btw.) + ls/.style={looseness=##1}, + looseness wires only/.style={% Looseness used for wires only. + looseness=1.2, + }, + lw/.style={looseness wires only}, + % Use this when you are drawing lines between none nodes only (like swap gates...) + between none/.style={ + looseness wires only, + wire centered + }, + bn/.style={ + between none + }, + % ------------------------------ + % Practical stuff to draw lines easily: + % Prefer to use these are they can be easily customized for each style and shorter to type. + % Note that the letter is supposed to represent the shape of the link + % dots/dashes are used to specify the position of the arrow. + % Typically ' means top, . bottom, X- is right to X (or should arrive with angle 0), + % -X is left to X (or should leave with angle zero). These shapes are usually designed to + % work when the starting node is left most (or above of both nodes have the same column). + % But they may work both way for some of them. + % ------------------------------ + %%% Cup/Cap + % Like a C shape (with without a perfect half circle). Useful maybe when perfect circles are too big. + % If only tex was a functional language... https://tex.stackexchange.com/questions/618955 + C@generic/.style n args={8}{ % min/max, angle1, angle2, anchor, \x or \y, \y or \x, where to move,radius code (for circle should be "radius=\n3") + to path={ + \pgfextra{ %% <- we will use def... so need to "exit" a few seconds pgf + % Test if tikztostart is a point or a node, and define StartPoint accordingly. + \ifPgfpointOrNode{\tikztostart}{% + \def\StartPoint{\tikztostart}% + }{% + \def\StartPoint{\tikztostart.##4}% + }% + % Test if tikztostart is a point or a node, and define StartPoint accordingly. + \ifPgfpointOrNode{\tikztotarget}{% + \def\TargetPoint{\tikztotarget}% + }{% + \def\TargetPoint{\tikztotarget.##4}% + }% + }% + (\StartPoint) % <- the path starts at StartPoint + %%% Get x coordinate of left-most point + let \p1=(\StartPoint), + \p2=(\TargetPoint), + \n1={##1(##51,##52)}, % coordinate of the most left part (when ##1=min and ##5=\x: ##52 goes to \x2) + \n3={abs(##61-##62)/2} % Radius of circle + in % Warning: no comma after last line before in + %%%% We go on the left if needed (we check that we do move, otherwise we break the arrows tip if + %%%% we stay on place + %%%% First go to the left if needed + \pgfextra{% + %% We check if we are moving or not (required to preserve arrow tip direction) + \pgfmathapproxequalto{##51}{\n1}% + }% + \ifpgfmathcomparison\else -- ##7\fi + %%%% Version 1: + \pgfextra{ + \pgfmathparse{ + ifthenelse(##61<##62, % if end angle < angle, draw clockwis + "arc[start angle=##3,end angle=##2,##8]",% + "arc[start angle=##2,end angle=##3,##8]"% + )% + } + } + \pgfmathresult + \pgfextra{% + %% We check if we are moving or not (required to preserve arrow tip direction) + \pgfmathapproxequalto{##52}{\n1}% + }% + \ifpgfmathcomparison\else -- (\TargetPoint)\fi + \tikztonodes % All to path finishes with that to deal with futur nodes I think + } + }, + %% + C/.style={C@generic={min}{90}{180+90}{west}{\x}{\y}{(\n1,\y1)}{y radius=\n3, x radius=##1*\n3}}, + C/.default=1, + % Like C, but rotated + C-/.style={C@generic={max}{90}{-90}{east}{\x}{\y}{(\n1,\y1)}{y radius=\n3, x radius=##1*\n3}}, + C-/.default=1, + C'/.style={C@generic={max}{0}{180}{north}{\y}{\x}{(\x1,\n1)}{x radius=\n3, y radius=##1*\n3}}, + C'/.default=1, + C./.style={C@generic={min}{0}{-180}{south}{\y}{\x}{(\x1,\n1)}{x radius=\n3, y radius=##1*\n3}}, + C./.default=1, + % Like a C shape (with without a perfect half circle). This was the old definition of C... + % Hopefully not useful anymore. + c/.style={/tikz/in=180,/tikz/out=180,looseness=2}, + % Like C, but symetric + c-/.style={/tikz/in=0,/tikz/out=0,looseness=2}, + c'/.style={/tikz/in=90,/tikz/out=90,looseness=2}, + c./.style={/tikz/in=-90,/tikz/out=-90,looseness=2}, + % Similar to C, but with a softer angle. The '.- marker represents the portion of + % the circle (hence the o) to keep (top, bottom,left/right). + % Angle is customizable, for instance o'=50. + o'/.style={/tikz/out=##1,/tikz/in=180-##1}, + o'/.default=\zxDefaultSoftAngleO, + o./.style={/tikz/out=-##1,/tikz/in=180+##1}, + o./.default=\zxDefaultSoftAngleO, + -o/.style={/tikz/out=-90-##1,/tikz/in=90+##1}, + -o/.default=\zxDefaultSoftAngleO, + o-/.style={/tikz/out=-90+##1,/tikz/in=90-##1}, + o-/.default=\zxDefaultSoftAngleO, + % Similar to o, but can be used also for diagonal items. + % Why ()? Visualize fixing the top part and moving the bottom part. + (/.style={bend right=##1}, + (/.default=30, + )/.style={bend left=##1}, + )/.default=30, + ('/.style={bend left=##1}, + ('/.default=30, + (./.style={bend right=##1}, + (./.default=30, + <'/.style={out=##1,in=180,looseness=0.65}, + <'/.default=\zxDefaultSoftAngleChevron, + <./.style={out=-##1,in=180,looseness=0.65}, + <./.default=\zxDefaultSoftAngleChevron, + '>/.style={out=0,in=180-##1,looseness=0.65}, + '>/.default=\zxDefaultSoftAngleChevron, + .>/.style={out=0,in=180+##1,looseness=0.65}, + .>/.default=\zxDefaultSoftAngleChevron, + ^./.style={out=-90+##1,in=90,looseness=0.65}, + ^./.default=\zxDefaultSoftAngleChevron, + .^/.style={out=-90-##1,in=90,looseness=0.65}, + .^/.default=\zxDefaultSoftAngleChevron, + 'v/.style={out=90+##1,in=-90,looseness=0.65}, + 'v/.default=\zxDefaultSoftAngleChevron, + v'/.style={out=90-##1,in=-90,looseness=0.65}, + v'/.default=\zxDefaultSoftAngleChevron, + % Links with a s-like shape. + s/.style={/tikz/out=0,/tikz/in=180,looseness=0.6}, + % -s'.- shapes are like s, but with a soften (customizable like o) angle. + % The '. say if you are going up or down, and - forces a sharp angle (- is flat) on the side of the - + s'/.style={/tikz/out=##1,/tikz/in=180+##1}, + s'/.default=\zxDefaultSoftAngleS, + s./.style={/tikz/out=-##1,/tikz/in=180-##1}, + s./.default=\zxDefaultSoftAngleS, + -s'/.style={/tikz/out=0,/tikz/in=180+##1}, + -s'/.default=\zxDefaultSoftAngleS, + -s./.style={/tikz/out=0,/tikz/in=180-##1}, + -s./.default=\zxDefaultSoftAngleS, + s'-/.style={/tikz/out=##1,/tikz/in=180}, + s'-/.default=\zxDefaultSoftAngleS, + s.-/.style={/tikz/out=-##1,/tikz/in=180}, + s.-/.default=\zxDefaultSoftAngleS, + % Links with a s-like shape... but read from top to bottom + ss/.style={/tikz/out=0-90,/tikz/in=180-90,looseness=0.6}, + % -s'.- shapes are like s, but with a soften (customizable like o) angle. + % The '. say if you are going up or down, and - forces a sharp angle (- is flat) on the side of the - + ss./.style={/tikz/out=##1-90,/tikz/in=180-90+##1}, + ss./.default=\zxDefaultSoftAngleS, + .ss/.style={/tikz/out=-##1-90,/tikz/in=180-90-##1}, + .ss/.default=\zxDefaultSoftAngleS, + sIs./.style={/tikz/out=0-90,/tikz/in=180-90+##1}, + sIs./.default=\zxDefaultSoftAngleS, + .sIs/.style={/tikz/out=0-90,/tikz/in=180-90-##1}, + .sIs/.default=\zxDefaultSoftAngleS, + ss.I/.style={/tikz/out=##1-90,/tikz/in=180-90}, + ss.I/.default=\zxDefaultSoftAngleS, + I.ss/.style={/tikz/out=-##1-90,/tikz/in=180-90}, + I.ss/.default=\zxDefaultSoftAngleS, + %%%% Links with a N-shape, i.e. like s shape, but symetric against the diagonal. Equivalently, it's a soft 's' shape with a much wider angle (>45). + N'/.style={/tikz/out=##1,/tikz/in=180+##1}, + N'/.default=\zxDefaultSoftAngleN, + N./.style={/tikz/out=-##1,/tikz/in=180-##1}, + N./.default=\zxDefaultSoftAngleN, + -N'/.style={/tikz/out=0,/tikz/in=180+##1}, + -N'/.default=\zxDefaultSoftAngleN, + -N./.style={/tikz/out=0,/tikz/in=180-##1}, + -N./.default=\zxDefaultSoftAngleN, + N'-/.style={/tikz/out=##1,/tikz/in=180}, + N'-/.default=\zxDefaultSoftAngleN, + N.-/.style={/tikz/out=-##1,/tikz/in=180}, + N.-/.default=\zxDefaultSoftAngleN, + % No line but vdots/dots in between. + 3 vdots/.style={draw=none, "\makebox[0pt][r]{##1}\scalebox{\zxScaleDots}{$\cvdots$}" anchor=center}, + 3 vdots/.default={}, + 3 dots/.style={draw=none, "\makebox[0pt][r]{##1}\scalebox{\zxScaleDots}{$\chdots$}" anchor=center}, + 3 dots/.default={}, + % Add a Hadmard/Z/X (no phase) in the middle of the line. Practical to add small nodes without creating + % a new column/row. However, make sure the corresponding row/column is larger, using &[\zxHCol] + % for columns and \\[\zxHRow] for rows (for Z/X style, use zxSCol and sxSRow), if you have both spiders + % and Hadamard, use \zxHSCol and \zxHSRow. + H/.style={"" {zxHSmall,anchor=center}}, + Z/.style={"" {zxNoPhaseSmallZ,anchor=center}}, + X/.style={"" {zxNoPhaseSmallX,anchor=center}}, + % Arrow will go out from the center of the shape instead of from the border. Useful + % when connecting nodes with different shapes, it will give back a symetric connection. + wire centered/.style={ + on layer=edgelayer, + /tikz/commutative diagrams/start anchor=center, + /tikz/commutative diagrams/end anchor=center, + }, + wire centered start/.style={ + on layer=edgelayer, + /tikz/commutative diagrams/start anchor=center, + }, + wire centered end/.style={ + on layer=edgelayer, + /tikz/commutative diagrams/end anchor=center, + }, + wc/.style={wire centered}, + wcs/.style={wire centered start}, + wce/.style={wire centered end}, + wire not centered/.style={ + /tikz/commutative diagrams/start anchor=, + /tikz/commutative diagrams/end anchor=, + }, + }, + /zx/styles/rounded style/.style={ + %% Can be redefined by user + % Style for empty nodes + zxAllNodes/.style={ + shape=rectangle, % Otherwise nodes are asymetrical rectangle, which is not practical in our case. Gives notably anchor "center" which is really centered compared to asymatrical rectangles + anchor=center, % Center cells + line width=\zxDefaultLineWidth, + execute at begin node={\thinmuskip=0mu\medmuskip=0mu\thickmuskip=0mu}, % Reduce space around +/-... + }, + % Use this to denote an empty diagram + zxEmptyDiagram/.style={ + zxAllNodes, + draw, + dashed, + minimum size=4mm, + }, + % Style to use when no node is drawn + zxNone/.style={ + zxAllNodes, + shape=coordinate, % A coordinate has just a center. Nothing more. + }, + % Style to use when no node is drawn, but a bit of space is required not to make the diagram too small + zxNone+/.style={ + zxAllNodes, + inner sep=1mm, + outer sep=0mm + }, + % Like zxNone+, but without width (wold prefer |, but special car in |[]|... + zxNoneI/.style={ + zxNone+, + inner xsep=0mm, + }, + % Like zxNone+, but without height + zxNone-/.style={ + zxNone+, + inner ysep=0mm, + }, + % Style to use when no node is drawn, but a large space must be reserved (typically used to fake two + % nodes on a single line) (for +I- versions) + zxNoneDouble/.style={ + shape=coordinate + }, + % Style to use when no node is drawn, but a bit of space is required not to make the diagram too small + zxNoneDouble+/.style={ + zxAllNodes, + inner sep=.6em, + outer sep=0mm + }, + % Like zxNoneDouble+, but without width (wold prefer |, but special car in |[]|... + zxNoneDoubleI/.style={ + zxNoneDouble+, + inner xsep=0mm, + }, + % Like zxNoneDouble+, but without height + zxNoneDouble-/.style={ + zxNoneDouble+, + inner ysep=0mm, + }, + % Will be specific to all spiders + zxSpiders/.style={ + draw=black, + }, + % Will use this style when drawing a X/Z node without phase (not for end user directly) + zxNoPhase/.style={ + zxAllNodes, + zxSpiders, + inner sep=0mm, + minimum size=2mm, + shape=circle, + }, + % Used only in decoration of wires, to add small empty X/Z nodes. + zxNoPhaseSmall/.style={ + zxNoPhase + }, + % Style for nodes that are small enough to fit in a circle, like $\zxMinus \frac{\pi}{4}$ + zxShort/.style={ + zxAllNodes, + zxSpiders, + minimum size=5mm, + font={\fontsize{8}{10}\selectfont\boldmath}, + rounded rectangle, + inner sep=0.0mm, + scale=0.8, + }, % negative outer sep would draw lines from inside... + % Style for nodes that are bigger, like $\alpha+\beta$ or $(a\oplus b)\pi$ + zxLong/.style={zxShort, inner xsep=1.2mm}, + %%% Styles of the label when |phase in label| is used + stylePhaseInLabel/.style={ + font={\fontsize{8}{10}\selectfont\boldmath}, + inner sep=2pt, + outer sep=0pt, + rounded rectangle, + % node on layer=labellayer, %% Fails in tikzcd: https://tex.stackexchange.com/questions/618823/node-on-layer-style-in-tikz-matrix-tikzcd + }, + stylePhaseInLabelZ/.style={ + stylePhaseInLabel, + fill=green!20!white + }, + stylePhaseInLabelX/.style={ + stylePhaseInLabel, + fill=red!20!white + }, + %%%%%%%%%%% Style defined depending on above ones. Feel free to redefine. + zxNoPhaseZ/.style={zxNoPhase,fill=colorZxZ}, + zxNoPhaseX/.style={zxNoPhase,fill=colorZxX}, + zxNoPhaseSmallZ/.style={zxNoPhaseSmall,fill=colorZxZ}, + zxNoPhaseSmallX/.style={zxNoPhaseSmall,fill=colorZxX}, + zxShortZ/.style={zxShort,fill=colorZxZ}, + zxShortX/.style={zxShort,fill=colorZxX}, + zxLongZ/.style={zxLong,fill=colorZxZ}, + zxLongX/.style={zxLong,fill=colorZxX}, + %%%%%%%%%%% + %%% Instead of adding directly the style as the node's content (which would make + %%% impossible styles that adds the phase in a label outside of the node) + %%% add@Phase@Spider{,Z,X}={phase of the node} will be in charge of adding it. + add@Phase@Spider/.style n args={4}{ % add@Phase@Spider{emptyStyle}{NotEmptyStyle}{node content} + zx@emptyStyle/.style={##1}, + zx@notEmptyStyle/.style={##2}, + zx@labelStyle/.style={##3}, + /zx/zx@content/.initial={##4}, + phase in content, + }, + add@Phase@Spider@Frac/.style n args={8}{ % add@Phase@Spider{emptyStyle}{NotEmptyStyle}{labelstyle}{sign}{above fraction (no parens)}{below fraction (no parens)}{above fraction (parens)}{below fraction (parens)} + zx@emptyStyle/.style={##1}, + zx@notEmptyStyle/.style={##2}, + zx@labelStyle/.style={##3}, + % Useful to help "phase in content" to know if we are in Frac or not. + /zx/zx@isInFrac/.initial={true}, + phase in content, + }, + % #1 is the node content. Seems that storing it in /zx/zx@content is not enough because keys + % seems to be local to nodes and are not transfered to label. + zx@Execute@Very@End/.style n args={4}{ + zx@commandToExecuteVeryEnd/.try={##1}{##2}{##3}{##4}, + }, + zx@Execute@Very@End/.default={}{}{}{}, + %% zx@Execute@Very@End@Frac={emptystyle}{contentstyle}{labelstyle}{sign}{above frac (no parens)}{below frac (no parens)}{above frac (parens)}{below frac (parens)} + zx@Execute@Very@End@Frac/.style n args={8}{ + zx@commandToExecuteVeryEndFrac/.try={##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8}, + }, + zx@Execute@Very@End@Frac/.default={}{}{}{}{}{}{}{}, + %% /!\ WARNING: the following styles "phase..." must be loaded by or *after* add@Phase@Spider... + %% To load it on the whole picture, prefer to do: + %% \zx[/zx/user post preparation labels/.style={phase in label}]{ + %% \zxZ{\alpha} + %% } + phase in content/.code={% + % Check if we are in a Frac or not + \ifthenelse{\equal{\pgfkeysvalueof{/zx/zx@isInFrac}}{true}}{% + %%% ### We are in a fraction node! + %% Modifies zx@commandToExecuteVeryEnd (which is executed at the very end by zx@Execute@Very@End) + %% in order to add the good style + \pgfkeysalso{ + % zx@commandToExecuteVeryEndFrac{emptystyle}{contentstyle}{labelstyle}{sign}{above frac (no parens)}{below frac (no parens)}{above frac (parens)}{below frac (parens)} + zx@commandToExecuteVeryEndFrac/.style n args={8}{% + execute at begin node={\zxConvertToFracInContent{####4}{####5}{####6}{####7}{####8}},% + },% + % Adds the style: + zx@notEmptyStyle, + }% + }{ %%% ### We are NOT in a fraction node. + %% Modifies zx@commandToExecuteVeryEnd (which is executed at the very end by zx@Execute@Very@End) + %% in order to add the good style + \pgfkeysalso{ + zx@commandToExecuteVeryEnd/.style n args={4}{% + execute at begin node={####4},% ####4 = content + }% + }% + % Checks if the content (stored by add@Phase@Spider in /zx/zx@content) is empty or not + \ifthenelse{\equal{\pgfkeysvalueof{/zx/zx@content}}{}}{% + \pgfkeysalso{% + zx@emptyStyle,% + }% + }{% + \pgfkeysalso{% + zx@notEmptyStyle,% + }% + }% + }% + }, + phase in label/.code={ + % Check if we are in a Frac or not + \ifthenelse{\equal{\pgfkeysvalueof{/zx/zx@isInFrac}}{true}}{% + %%% ### We are in a fraction node! + \pgfkeysalso{% + % zx@commandToExecuteVeryEndFrac{emptystyle}{contentstyle}{labelstyle}{sign}{above frac (no parens)}{below frac (no parens)}{above frac (parens)}{below frac (parens)} + zx@commandToExecuteVeryEndFrac/.code n args={8}{% + \pgfkeysalso{ + label={[####3,##1] \zxConvertToFracInLabel{####4}{####5}{####6}{####7}{####8}},% + }% + },% + zx@emptyStyle, + }% + }{% + \pgfkeysalso{% + % ##1 is the argument of "phase in label", i.e. the style of the label + zx@commandToExecuteVeryEnd/.code n args={4}{% ####3: label style, ####4: content + % Checks if the content (stored by add@Phase@Spider in /zx/zx@content) is empty or not + \ifthenelse{\equal{####4}{}}{% Content is empty + }{% Content is not empty + \pgfkeysalso{ + label={[####3,##1] ####4},% + }% + }% + },% + zx@emptyStyle, + }% + }% + }, + pil/.style={phase in label=##1}, + phase in label below/.style={ + phase in label={label position=below,##1} + }, + pilb/.style={phase in label below=##1}, + phase in label above/.style={ + phase in label={label position=above,##1} + }, + pila/.style={phase in label above=##1}, + phase in label right/.style={ + phase in label={label position=right,##1} + }, + pilr/.style={phase in label right=##1}, + phase in label left/.style={ + phase in label={label position=left,##1} + }, + pill/.style={phase in label left=##1}, + %%% Was supposed to automatically find the good style depending on content... Can't find how to do. + % Styles zxLong{X/Z} zxNoPhase{X/Z} are automatically selected by \zxZ2{...} and \zxX2{...} commands + % and zxShort is selected for fractions only like in \zxFracZ-{\pi}{4} + % zxZ/.style={zxChoose={##1},fill=colorZxZ}, + % zxX/.style={zxChoose={##1},fill=colorZxX}, + %%% First argument is additional style. Second argument is content of node. + zxZ2/.style 2 args={ + add@Phase@Spider={zxNoPhaseZ}{zxLongZ}{stylePhaseInLabelZ}{##2}, + /zx/post preparation labels, + /zx/user post preparation labels, + %/zx/user overlay nodes, + ##1, + zx@Execute@Very@End={zxNoPhaseZ}{zxLongZ}{stylePhaseInLabelZ}{##2}, + }, + %% ##1: other styles, ##2: content + zxX2/.style 2 args={ + add@Phase@Spider={zxNoPhaseX}{zxLongX}{stylePhaseInLabelX}{##2}, + /zx/post preparation labels, + /zx/user post preparation labels, + ##1, + zx@Execute@Very@End={zxNoPhaseX}{zxLongX}{stylePhaseInLabelX}{##2}, + }, + %% These take 6 arguments: additional style, sign (string "-" for minus, nothing for "+", + %% otherwise inserted directly), above fraction (no parens), below fraction (no parens), above fraction (parens), below fraction (parens). + zxFracZ6/.style n args={6}{ + add@Phase@Spider@Frac={zxNoPhaseZ}{zxShortZ}{stylePhaseInLabelZ}{##2}{##3}{##4}{##5}{##6}, + /zx/post preparation labels, + /zx/user post preparation labels, + ##1, + zx@Execute@Very@End@Frac={zxNoPhaseZ}{zxShortZ}{stylePhaseInLabelZ}{##2}{##3}{##4}{##5}{##6}, + }, + zxFracX6/.style n args={6}{ + add@Phase@Spider@Frac={zxNoPhaseX}{zxShortX}{stylePhaseInLabelX}{##2}{##3}{##4}{##5}{##6}, + /zx/post preparation labels, + /zx/user post preparation labels, + ##1, + zx@Execute@Very@End@Frac={zxNoPhaseX}{zxShortX}{stylePhaseInLabelX}{##2}{##3}{##4}{##5}{##6}, + }, + % For Hadamard + zxH/.style={ + zxAllNodes, + outer sep=0pt, + fill=colorZxH, + draw, + inner sep=0.6mm, + minimum height=1.5mm, + minimum width=1.5mm, + shape=rectangle}, + zxHSmall/.style={zxH}, + }, + % Default style. Can be changed by user + /zx/default style nodes/.style={ + /zx/styles/rounded style + }, + % User can put here any additional property + /zx/user overlay nodes/.style={ + }, + % Any additional property that needs to be loaded after add@Phase@Spider (by script, not by user). + /zx/post preparation labels/.style={ + }, + % User can put here any additional property that needs to be loaded after add@Phase@Spider + /zx/user post preparation labels/.style={ + }, + % Default wire style. Can be changed by user. + /zx/default style wires/.style={ + }, + % User can add stuff in this style to improve wire styles + /zx/user overlay wires/.style={ + }, + /zx/defaultEnv/.style={ + column sep=tiny, + row sep=tiny, + % center on the math axis + baseline={([yshift=-axis_height]current bounding box.center)}, + % Fix 1-row diagram baseline + 1-row diagram/.style={% + /tikz/baseline={([yshift=-axis_height]current bounding box.center)}% + }, + % Load (thanks ".search also") our own style + /tikz/every node/.style={% + % For quickly adding alias, and displaying this alias in debug mode. + a/.code={% + \pgfkeysalso{% + alias=####1,% + }% + \ifdefined\zxDebugMode% + \pgfkeysalso{% + label={[inner sep=0pt,overlay,red,font={\fontsize{5}{6}}]-45:\scalebox{.5}{####1}} + }% + \fi% + }, + /zx/default style nodes, + /zx/user overlay nodes, + }, + every arrow/.style={% + /zx/wires definition, + /zx/default style wires, + /zx/user overlay wires, + }, + %%% To be used only in \zx{...} environment. + %%% Exemple: + phase in content/.style={ + /zx/post preparation labels/.append style={ + phase in content, + } + }, + phase in label/.style={ + /zx/post preparation labels/.append style={ + phase in label=##1, + } + }, + phase in label above/.style={ + /zx/post preparation labels/.append style={ + phase in label above=##1, + } + }, + phase in label below/.style={ + /zx/post preparation labels/.append style={ + phase in label below=##1, + } + }, + phase in label right/.style={ + /zx/post preparation labels/.append style={ + phase in label right=##1, + } + }, + phase in label left/.style={ + /zx/post preparation labels/.append style={ + phase in label left=##1, + } + }, + % for "Phase In Label" + pil/.style={phase in label=##1}, + pilb/.style={phase in label below=##1}, + pila/.style={phase in label above=##1}, + pilr/.style={phase in label right=##1}, + pill/.style={phase in label left=##1}, + }, +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Helper functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +% Defines a "on layer=nameoflayer" style. TODO: check if better to move it in /zx/ +% https://tex.stackexchange.com/questions/20425/z-level-in-tikz/20426#20426 +% For path: on layer=namelayer, for nodes "node on layer=..." +% /!\ node on layer fails in tikzcd: https://tex.stackexchange.com/questions/618823/node-on-layer-style-in-tikz-matrix-tikzcd +\pgfkeys{% + /tikz/on layer/.code={ + \pgfonlayer{#1}\begingroup + \aftergroup\endpgfonlayer + \aftergroup\endgroup + }, + /tikz/node on layer/.code={ + \gdef\node@@on@layer{% + \setbox\tikz@tempbox=\hbox\bgroup\pgfonlayer{#1}\unhbox\tikz@tempbox\endpgfonlayer\egroup} + \aftergroup\node@on@layer + }, + /tikz/end node on layer/.code={ + \endpgfonlayer\endgroup\endgroup + } +} +\def\node@on@layer{\aftergroup\node@@on@layer} + +%%% Declare a symbol for a short minus (useful in fractions) +\DeclareMathSymbol{\zxMinus}{\mathbin}{AMSa}{"39} % Requires amssymb + +%%% Checks if a function is a point or a node. +%%% Not sure if best solution (needed to dig into source of TeX), but can't find anything better in manual +%%% https://tex.stackexchange.com/questions/6189553 +\def\ifPgfpointOrNode#1#2#3{% + \pgfutil@ifundefined{pgf@sh@ns@#1}{% + #2% + }{% + #3% + }% +} + + +%%% Create different kinds of dots... +%% https://tex.stackexchange.com/questions/617959 +%% https://tex.stackexchange.com/questions/528774/excess-vertical-space-in-vdots/528775#528775 +\DeclareRobustCommand\cvdotsAboveBaseline{% + \vbox{\baselineskip4\p@ \lineskiplimit\z@% + \hbox{.}\hbox{.}\hbox{.}} +} + +\DeclareRobustCommand{\cvdotsCenterMathline}{% + % vcenter is used to center the argument on the 'math axis', which is at half the height of an 'x', or about the position of a minus sign. + \vcenter{\cvdotsAboveBaseline}% +} + +\DeclareRobustCommand{\cvdotsCenterBaseline}{% + \raisebox{-.5\height}{% + $\cvdotsAboveBaseline$% + }% +} + +\DeclareRobustCommand{\chdots}{% + \raisebox{-.5\height}{% + \rotatebox{90}{% Maybe better options than rotatebox... + $\cvdotsAboveBaseline$% + }% + }% +} + +\DeclareRobustCommand{\cvdots}{\cvdotsCenterMathline} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Practical macros to automatically choose appropriate style and arrows +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% /!\ Warning: you should add {} at the end of all macros (except arrows)! +% Not using that may work for now, but it may break later... +% TODO: define them only in \zx environment. + +% % Example: \leftManyDots{n} +% Useful to put on the left of a node like "n \vdots", linked to the next node. Example: \leftManyDots{n}. +% First optional argument is scale of text, second is scale of =. +\NewExpandableDocumentCommand{\leftManyDots}{O{1}O{\zxScaleDots}m}{% + |[zxNone+,inner xsep=0pt]| \scalebox{#1}{$#3$\,}\makebox[0pt][l]{\scalebox{#2}{$\cvdots$}} \ar[r,-s.,start anchor=north east] \ar[r,-s',start anchor=south east] \pgfmatrixnextcell% +} + +% Useful to link two nodes and put a vdots in between. +\NewExpandableDocumentCommand{\middleManyDots}{}{% + \ar[r,3 vdots] \ar[o',r] \ar[o.,r]% +} + +% Like \leftManyDots but on the right. Do *not* create a new node, like in |[zxShortZ]| \alpha \rightManyDots{m} +\NewExpandableDocumentCommand{\rightManyDots}{O{1}O{\zxScaleDots}m}{% + \ar[r,s'-,end anchor=north west] \ar[r,s.-,end anchor=south west] \pgfmatrixnextcell |[zxNone+,inner xsep=0pt]| \makebox[0pt][r]{\scalebox{#2}{$\cvdots$}}\scalebox{#1}{\,$#3$} +} + +% A swap on one line... Practical mostly to gain space. Must be used with large nodes tough... +% \NewExpandableDocumentCommand{\OneLineSwap}{}{% +% \ar[r,s,start anchor=south,end anchor=north] \ar[r,s,start anchor=north,end anchor=south] +% } + + +\NewExpandableDocumentCommand{\zxLoop}{O{90}O{20}O{}m}{% + \ar[loop,in=#1-#2,out=#1+#2,looseness=8,min distance=3mm,#3] +} + +\NewExpandableDocumentCommand{\zxLoopAboveDots}{O{20}O{}m}{% + \ar[loop,in=90-#1,out=90+#1,looseness=8,min distance=3mm,"\cvdots" {scale=.6,anchor=north,yshift=-0.4mm},#2] +} + +% Usage: node without any style, but may have space. Default is no space, \zxNone+{} is both horizontal +% and vertical, \zxNone-{} is only horizontal space, \zxNone|{} is only vertical space. +\NewExpandableDocumentCommand{\zxNone}{t+t-t|O{}m}{ + \IfBooleanTF{#1}{ % \zxNone+ + |[zxNone+,#4]| #5% + }{ + \IfBooleanTF{#2}{ % \zxNone- + |[zxNone-,#4]| #5% + }{ + \IfBooleanTF{#3}{ % \zxNone + |[zxNoneI,#4]| #5% + }{% \zxNone + |[zxNone,#4]| #5% + } + } + } +} + +% Usage: alias of \zxNone... To bad token can't be easily forwarded to another function. +\NewExpandableDocumentCommand{\zxN}{t+t-t|O{}m}{ + \IfBooleanTF{#1}{ % \zxNone+ + |[zxNone+,#4]| #5% + }{ + \IfBooleanTF{#2}{ % \zxNone- + |[zxNone-,#4]| #5% + }{ + \IfBooleanTF{#3}{ % \zxNone + |[zxNoneI,#4]| #5% + }{% \zxNone + |[zxNone,#4]| #5% + } + } + } +} + +% Cf \zxNone, but with larger space. +\NewExpandableDocumentCommand{\zxNoneDouble}{t+t-t|O{}m}{ + \IfBooleanTF{#1}{ % \zxNoneDouble+ + |[zxNoneDouble+,#4]| #5% + }{ + \IfBooleanTF{#2}{ % \zxNoneDouble- + |[zxNoneDouble-,#4]| #5% + }{ + \IfBooleanTF{#3}{ % \zxNoneDouble + |[zxNoneDoubleI,#4]| #5% + }{% \zxNoneDouble + |[zxNoneDouble,#4]| #5% + } + } + } +} + +%% For maximum styling liberty, the content is given directly to the style. +% It allows the style to put the phase in a label. +\NewExpandableDocumentCommand{\zxZ}{O{}m}{ + |[zxZ2={#1}{#2}]| % +} + +%% For maximum styling liberty, the content is given directly to the style. +%% It allows the style to put the phase in a label. +\NewExpandableDocumentCommand{\zxX}{O{}m}{ + |[zxX2={#1}{#2}]| % +} + +\NewExpandableDocumentCommand{\zxH}{O{}m}{ + |[zxH,#1]| {}% +} + +% Use like: \zxFracX{\pi}{4} for positive values or for negative \zxFracX-{\pi}{4} +\NewExpandableDocumentCommand{\zxFracZ}{O{}t-moom}{% + \IfNoValueTF{#5}{% 2 arguments like: \zxFracZ{\pi}{2} + |[zxFracZ6={#1}{\IfBooleanTF{#2}{\zxMinus}{}}{#3}{#6}{#3}{#6}]| % + }{% 4 arguments like \zxFracZ{a+b}[(a+b)][(c+d)]{c+d} + |[zxFracZ6={#1}{\IfBooleanTF{#2}{\zxMinus}{}}{#3}{#6}{#4}{#5}]| % + }% +} + +% Use like: \zxFracX{\pi}{4} for positive values or for negative \zxFracX-{\pi}{4} +\NewExpandableDocumentCommand{\zxFracX}{O{}t-moom}{% + \IfNoValueTF{#5}{% 2 arguments like: \zxFracZ{\pi}{2} + |[zxFracX6={#1}{\IfBooleanTF{#2}{\zxMinus}{}}{#3}{#6}{#3}{#6}]| % + }{% 4 arguments like \zxFracZ{a+b}[(a+b)][(c+d)]{c+d} + |[zxFracX6={#1}{\IfBooleanTF{#2}{\zxMinus}{}}{#3}{#6}{#4}{#5}]| % + }% +} + +\NewExpandableDocumentCommand{\zxEmptyDiagram}{}{ + |[zxEmptyDiagram]| {}% +} + +% Quantikz has a bug which adds space automatically. +% https://tex.stackexchange.com/questions/618330 +% Fixing that by copying the original (unpatched) functions, and reusing them later. +% Warning: you must load this package **before** quantikz otherwise the fix will not work. +\let\tikzcd@@originalCopyZx\tikzcd@ +\let\endtikzcd@originalCopyZx\endtikzcd + +%%%%% Main environment \begin{ZX}...\end{ZX} +\NewDocumentEnvironment{ZX}{O{}}{% + \bgroup% + % Add a switch in case someone really wants the current tikzcd version: + \ifdefined\doNotPatchQuantikz% Do not patch tikzcd. + \else% Restore locally original tikzcd. + \let\tikzcd@\tikzcd@@originalCopyZx% + \let\endtikzcd\endtikzcd@originalCopyZx% + \fi% + \pgfsetlayers{background,edgelayer,nodelayer,main,box,labellayer,foreground} % Layers are defined locally to avoid to disturb other drawings + \begin{tikzcd}[% + /zx/defaultEnv,% + #1]% + }{\end{tikzcd}\egroup} + +%%%%% Shortcut macro \zx{...} equivalent to \begin{ZX}...\end{ZX} +\newcommand\zx{% + \begingroup% To avoid ampersand issues https://tex.stackexchange.com/a/611535/116348 + \NewDocumentCommand{\tmpZX}{O{}+m}{% + \endgroup% + \begin{ZX}[##1]% + ##2% + \end{ZX}% + }% + \catcode`&=13% + \tmpZX% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% Old code that tried to automatically find if zxShort or zxLong should be used... +%%% Now using a special command for fractions (easier to code, and more customizable) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\newsavebox\zx@box % Temporary box to compute height/width/depth + +\newlength{\zxMaxDepthPlusHeight}\setlength{\zxMaxDepthPlusHeight}{2em} +\def\zxMaxRatio{1.3} % Ratio width/(height+depth) + +\NewExpandableDocumentCommand{\zxChooseStyle}{mmmm}{% + % #1=text,#2=empty style,#3=short style,#4=long style + \savebox\zx@box{#1}% + % Check if width is 0pt: + \ifdimcomp{\wd\zx@box}{=}{0pt}{% Return empty style if box is empty + #2% + }{% Else compute size of thext + % Check if height+depth < zxMaxDepthPlusHeight to see if short style applies + \ifdimcomp{\dimexpr\dp\zx@box+\ht\zx@box\relax}{<}{\zxMaxDepthPlusHeight}{% + % Check if width < ratio*(height+depth) to see if short style applies + \ifdimcomp{\wd\zx@box}{<}{\dimexpr \zxMaxRatio\ht\zx@box + \zxMaxRatio\dp\zx@box\relax}{% + #3% Short style is used + }{ % Else + #4% Long style is used + } % + }{ + #4% Long style is used + } + }% +} diff --git a/Master/texmf-dist/tex/latex/zx-calculus/zx-calculus.sty b/Master/texmf-dist/tex/latex/zx-calculus/zx-calculus.sty new file mode 100644 index 00000000000..d3ce3beea87 --- /dev/null +++ b/Master/texmf-dist/tex/latex/zx-calculus/zx-calculus.sty @@ -0,0 +1,9 @@ +% This is a zx library to typeset ZX calculus directly in LaTeX. +% Written by Léo Colisson. Report bugs on https://github.com/leo-colisson/zx-calculus/issues +% Published under the MIT license. +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{zx-calculus}[2021/10/15 A package to typeset ZX calculus in directly in LaTeX, based on tikz/tikzcd.] + +\RequirePackage{tikz} + +\usetikzlibrary{zx-calculus} % See library in "tikzlibraryzx.code.tex". |