Following up [this answer](https://topanswers.xyz/tex?q=1563#a1815), I would like to get the desired output with a rule that chooses the plane (top or bottom) the edges/arrows are drawn in such a way that they are drawn in the **top half** if the connections/edges involve the nodes of either the input `R(s)` or the output `Y(s)`. Otherwise, the edges are drawn in the **bottom half**. Specifically speaking, for the following, the edge between `X3(s)` and `sX1(s)` should accordingly be **automatically** drawn in the bottom half. ![image.jpg](/image?hash=8f4d0e9312405efae69d3967c15b3ee8efc3cbb53e199c9672bc663cb5ac06dd) ``` % define the matrix \edef\mmat{% {2,-5,3,2},% <= a missing edge of label "3" should be drawn from X3 to sX1 {-6,-2,2,5},% {1,-3,-4,7},% {-4,6,9,0}% } \documentclass[tikz,border=5mm]{standalone} \usetikzlibrary{calc,decorations.markings,positioning,arrows.meta} \newif\iflabrev \begin{document} \begin{tikzpicture}[node distance = 15 mm, label revd/.is if=labrev, label revd/.default=true, amark/.style = { decoration={ markings, mark=at position {0.5} with { \arrow{stealth}, \iflabrev \node[below] {#1};\else \node[above] {#1};\fi } }, postaction={decorate} }, % make the mark an entry of the \mmat matrix pmark/.code n args={2}{% \pgfmathtruncatemacro{\myi}{int({\mmat}[\numexpr#1][\numexpr#2])}% \tikzset{suppress if 0=\myi, amark={$\myi$}}% <- changed }, terminal/.style 2 args={draw,alias=ln,circle,inner sep=2pt,label={#1:#2}}, % semicircle path semicircle/.style={to path={let \p1=($(\tikztotarget)-(\tikztostart)$) in \ifdim\x1>0pt (\tikztostart.north) arc[start angle=180,end angle=0,radius=0.5*\x1] \else (\tikztostart.south) arc[start angle=0,end angle=-180,radius=-0.5*\x1] \fi}}, add key if/.code n args={3}{\pgfmathtruncatemacro{\itest}{(#1?0:1)}% \ifcase\itest \tikzset{#2}% \else \tikzset{#3}% \fi },suppress if 0/.style={add key if={#1==0}{opacity=0}{}}, switch if/.style 2 args={} ] \pgfmathtruncatemacro{\dimy}{dim({\mmat})} % number of rows \pgfmathtruncatemacro{\dimx}{dim({\mmat}[0])} % number of columns % create the graph \path % R node node[terminal={left}{$R(S)$},alias={X-\dimy}] (R) {} % loop over matrix entries foreach \Y [evaluate=\Y as \X using {int(\dimy-\Y)}] in {1,...,\numexpr\dimy-1} {node[right=of ln,terminal={below right}{% sX_i node $sX_{\X}(s)$}](sX-\X){} node[right=of ln,terminal={below right}{% X_i node $X_{\X}(s)$}](X-\X){} % ege from sX_i to X_i (sX-\X) edge[amark={$\frac{1}{s}$}] (X-\X) % edge from X_{i+1} to X_i (R had an alias) (X-\the\numexpr\X+1) edge[pmark={\X-1}{\X},swap] (sX-\X) % semicircle edge from X_i to sX_i (X-\X) edge[semicircle,label revd,pmark={\X-1}{\X-1}] (sX-\X) } node[right=of ln,terminal={right}{$Y(s)$},alias=sX-\dimy](Y){} (X-1) edge[pmark={\dimy-1}{0}] (Y) % we are now done with the horizontal part, % and have also dealt with the entries on the diagonal and % the {i-1},i entries % now we deal with the matrix entries foreach \X in {1,...,\the\numexpr\dimx-1} { foreach \Y in {\the\numexpr\X+1,...,\dimy} { \unless\ifnum\X\Y=1\dimy (X-\X) edge[semicircle,pmark={\Y-1}{\X-1},add key if={\Y==\dimy}{}{label revd}] (sX-\Y) \fi \unless\ifnum\numexpr\Y-\X=\numexpr1\relax (X-\Y) edge[semicircle,pmark={\X-1}{\Y-1}] (sX-\X) \fi }}; \end{tikzpicture} \end{document} ```

This is an attempt to disentangle the cases more clearly, and make it easier to customize the code. In particular, there are various comments in the code. * These comments may or may not use intuitive wording, so an alternative way to see what different pieces do is to just add a key like `red` to a given edge, then one sees which edges are controlled by this piece of code. * Something freaky is going on (I meant to report it already in my previous answer). Sometimes the `\ifnum`s go berserk. I thought I had already some intuition when one could use them without problems, and would have thought that this was such a case. However, for some reason now some of them only work when one adds a `\numexpr` after the `=`, `>` or `<` operator. *Maybe* a kernel change is responsible for that. So if on TeX.SE some complaints surface that some old codes by some deleted users seem not to work, please let me know, this may give further credit to the suggestion that some kernel change is to blame. It may also be that I was too optimistic when using the `\ifnum`s here (but in this case why would adding `\numexpr` "repair" them?). Anyway, if you are wondering why there are all these useless `\numexpr`, on my LaTeX installation they seem to be necessary. * I did away with the `label revd` stuff. IMHO there is no reason to prefer it to a good old `edge` label, which one could swap. * I also added a `semicircle'` which is drawn on the opposite site of a `semicircle`. So this is the result of the exercise. ``` \edef\mmat{% {2,-5,3,2},% {-6,-2,2,5},% {1,-3,-4,7},% {-4,6,9,0}% } \documentclass[tikz,border=5mm]{standalone} \usetikzlibrary{calc,decorations.markings,positioning,arrows.meta} \begin{document} \begin{tikzpicture}[node distance = 15 mm, amark/.style={ decoration={ markings, mark=at position {0.5} with { \arrow{stealth}, } }, postaction={decorate,edge label={#1}} }, % make the mark an entry of the \mmat matrix pmark/.code n args={2}{% \pgfmathtruncatemacro{\myi}{int({\mmat}[\numexpr#1][\numexpr#2])}% \tikzset{suppress if 0=\myi,edge label={$\myi$}, amark}% <- changed }, terminal/.style 2 args={draw,alias=ln,circle,inner sep=2pt,label={#1:#2}}, % semicircle path semicircle/.style={to path={let \p1=($(\tikztotarget)-(\tikztostart)$) in \ifdim\x1>0pt (\tikztostart.north) arc[start angle=180,end angle=0,radius=0.5*\x1] \else (\tikztostart.south) arc[start angle=0,end angle=-180,radius=-0.5*\x1] \fi \tikztonodes}}, semicircle'/.style={to path={let \p1=($(\tikztotarget)-(\tikztostart)$) in \ifdim\x1>0pt (\tikztostart.south) arc[start angle=-180,end angle=0,radius=0.5*\x1] \else (\tikztostart.north) arc[start angle=0,end angle=180,radius=-0.5*\x1] \fi \tikztonodes}}, add key if/.code n args={3}{\pgfmathtruncatemacro{\itest}{(#1?0:1)}% \ifcase\itest \tikzset{#2}% \else \tikzset{#3}% \fi },suppress if 0/.style={add key if={#1==0}{opacity=0}{}} ] \pgfmathtruncatemacro{\dimy}{dim({\mmat})} % number of rows \pgfmathtruncatemacro{\dimx}{dim({\mmat}[0])} % number of columns % create the graph \path % R node node[terminal={left}{$R(S)$},alias={X-\dimy}] (R) {} % loop over matrix entries foreach \Y [evaluate=\Y as \X using {int(\dimy-\Y)}] in {1,...,\numexpr\dimy-1} {node[right=of ln,terminal={below right}{% sX_i node $sX_{\X}(s)$}](sX-\X){} node[right=of ln,terminal={below right}{% X_i node $X_{\X}(s)$}](X-\X){} % ege from sX_i to X_i (sX-\X) edge[amark,edge label={$\frac{1}{s}$}] (X-\X) % edge from X_{i+1} to X_i (R had an alias) (X-\the\numexpr\X+1) edge[pmark={\X-1}{\X}] (sX-\X) % semicircle edge from X_i to sX_i (X-\X) edge[semicircle,pmark={\X-1}{\X-1}] (sX-\X) } node[right=of ln,terminal={right}{$Y(s)$},alias=sX-\dimy](Y){} (X-1) edge[pmark={\dimy-1}{0}] (Y) % we are now done with the horizontal part, % and have also dealt with the entries on the diagonal and % the {i-1},i entries % now we deal with the matrix entries foreach \X in {1,...,\the\numexpr\dimx-1} {% all edges that end in Y (excluding the horizontal one) \ifnum\X>\numexpr1\relax (X-\X) edge[pmark={\dimx-1}{\X-1},semicircle] (Y) \fi % all edges that start at R (excluding the horizontal one) \ifnum\X<\numexpr\dimx-1\relax (R) edge[pmark={\X-1}{\dimx-1},semicircle] (sX-\X) \fi % remaining semicircles foreach \Y in {\the\numexpr\X+1,...,\dimy} {% backwards pointing semicircles \unless\ifnum\X\Y=1\dimy (X-\X) edge[pmark={\Y-1}{\X-1},semicircle] (sX-\Y) \fi % forward pointing semicircles \pgfextra{\pgfmathtruncatemacro{\itest}{(\Y<\dimy&&\Y-\X>1?1:0)}} \ifnum\itest=\numexpr1\relax (X-\Y) edge[swap,pmark={\X-1}{\Y-1},semicircle'] (sX-\X) \fi } }; \end{tikzpicture} \end{document} ``` ![Screen Shot 2020-12-20 at 5.34.00 PM.png](/image?hash=8433ef7dc868cb73b90b16933096b3020579e6742908920f581cf7f7604947e9)