Figures were positioned by hand-written offsets. Every gap was a magic number tuned against the content that happened to be there, so a label that grew two characters landed on the next tensor, and two stages started from two different x shared no rail. Both failures compile cleanly. Replace it with a cursor. Objects placed with an empty coordinate argument reserve their own width -- including a stack's offset sheets and a bracket's overhang -- and gaps are declared once (\stgutter, \strowgap, \stblockgap). The gap belongs to the object that follows it and the first object in a band gets none, so every band starts flush on a shared rail and gap=0pt states that two shards tile exactly. \stlink makes a connector's label a flow object, which is what removes the label-wider-than-its-arrow failure entirely. \stcol is a vertical sub-flow for a split along the contracted axis. \strow declares its height, so an object that does not fit -- or a column that does not add up to what it declared, and is therefore drawn off-center -- becomes a package warning, which build.sh fails on. Absolute placement is unchanged: passing a coordinate takes the original code path, and \sttrack folds a hand-placed node back into the cursor. All three golden examples and the new tests/flow.tex are converted and build clean.
72 lines
2.3 KiB
TeX
72 lines
2.3 KiB
TeX
% Regression test for the flow layout: stage headings on a shared left rail,
|
|
% bands whose objects reserve their own width, connectors whose labels are flow
|
|
% objects. No absolute coordinate appears anywhere in this figure.
|
|
% ../scripts/build.sh flow.tex
|
|
\documentclass[border=10pt]{standalone}
|
|
\usepackage[cjk]{supertensor}
|
|
|
|
\stsetrole{act}{stTeal}
|
|
\stsetrole{w}{stOrange}
|
|
\stsetrole{o}{stViolet}
|
|
|
|
\stdim{T}{7}
|
|
\stdim{d}{5}
|
|
\stdim{r}{3}
|
|
|
|
\begin{document}
|
|
\begin{tikzpicture}
|
|
|
|
\ststage{S1}{一、面、算子、带标签的连接线都由游标排布}
|
|
\strow{R1}{T}
|
|
\stface[role=act, bracket=true]{X}{}{T}{d}
|
|
\stglyph{m1}{$\times$}
|
|
\stface[role=w, bracket=true]{W}{}{d}{r}
|
|
\stlink{l1}{一个很长的标签也不会压到下一个张量}
|
|
\stface[role=o, bracket=true]{Y}{}{T}{r}
|
|
\strowend
|
|
\stcaption{X}{$\mathbf X$}{$T\times d$}
|
|
\stcaption{W}{$\mathbf W$}{$d\times r$}
|
|
\stcaption{Y}{$\mathbf Y$}{$T\times r$}
|
|
|
|
\ststage{S2}{二、堆叠的偏移页也计入宽度,行首自动回到同一条左轨}
|
|
\strow{R2}{T}
|
|
\ststack[role=act]{Q}{}{T}{r}{3}
|
|
\stlink{l2}{}
|
|
\stcomm{c1}{All-Reduce}
|
|
\stlink{l3}{sum}
|
|
\stface[role=o, pattern=causal]{A}{}{T}{T}
|
|
\stgap{4mm}
|
|
\stface[role=w, pattern=diag]{D}{}{r}{r}
|
|
\strowend
|
|
\stcaption{Q}{$\mathbf Q$}{$3\times T\times r$}
|
|
\stcaption{A}{$\mathbf A$}{$T\times T$}
|
|
\stcaption{D}{$\mathbf D$}{$r\times r$}
|
|
|
|
\ststage{S3}{三、列子流:两片沿收缩维叠放,恰好铺满一格}
|
|
\strow{R3}{T}
|
|
\stface[role=act]{H}{}{T}{d}
|
|
\stglyph{m3}{$\times$}
|
|
\stcol{Wc}{d}
|
|
% d = 2 * (d/2)... here r=3 and d=5, so the two shards are 3 and 2 units.
|
|
\stface[role=w]{Wa}{}{r}{T}
|
|
\stface[role=o, gap=0pt]{Wb}{}{2}{T}
|
|
\stcolend
|
|
\stglyph{e3}{$=$}
|
|
\stface[role=o, bracket=true]{Z}{}{T}{T}
|
|
\strowend
|
|
\stcaption{H}{$\mathbf H$}{$T\times d$}
|
|
\stcaption{Wc}{$\mathbf W^{(r)}$}{$d\times T$}
|
|
\stcaption{Z}{$\mathbf Z$}{$T\times T$}
|
|
|
|
\stbbox{all}
|
|
\stmeaningbox{mb}{15cm}{all}
|
|
{$T$ 序列长,$d$ 模型维,$r$ 低秩维}
|
|
{}
|
|
{三行的左端都落在同一条左轨上,行内间距由 \texttt{\string\stgutter} 声明一次,
|
|
标签自己占位,所以任何一处变宽都只会把后面的东西推开,不会盖住它们;
|
|
第三行的列子流用 \texttt{gap=0pt} 声明两片相邻,声明高度与实际不符会直接报警}
|
|
\stsignature{流式排版自测}{mb}
|
|
|
|
\end{tikzpicture}
|
|
\end{document}
|