3

I want to represent a graph where the labels for each node are obtained computing a modulo computation. The first and easy way to do it is as follow :

\documentclass[tikz]{standalone}
\usetikzlibrary{graphs,graphs.standard}

\begin{document}
\begin{tikzpicture}
    \def \n {3}
    \graph[clockwise=\n,radius=3cm] {
        \foreach \x [evaluate=\x as \xn using {int(mod(\x+1,\n))}] in {0,...,\the\numexpr\n-1} {
            \foreach \y [evaluate=\y as \yn using {int(mod(\y+1,\n))}] in {\x,...,\the\numexpr\n-1} {
                \x / {$a_\x, a_\xn$} --
                \y / {$a_\y, a_\yn$};
            };
        };
    };
\end{tikzpicture}

\end{document}

enter image description here

Then I found out about pgfmathtruncatemacro and wrote

\documentclass[tikz]{standalone}
\usetikzlibrary{graphs,graphs.standard}

\begin{document}
\begin{tikzpicture}
    \def \n {3}
    \graph[clockwise=\n,radius=3cm] {
        \foreach \x in {0,...,\the\numexpr\n-1} {
            \pgfmathtruncatemacro{\xn}{mod(\x+1,\n)}%
            \foreach \y in {\x,...,\the\numexpr\n-1} {
                \pgfmathtruncatemacro{\yn}{mod(\y+1,\n)}%
                \x / {$a_\x, a_\xn$} --
                \y / {$a_\y, a_\yn$};
            };
        };
    };
\end{tikzpicture}

\end{document}

And strangely it gives me these errors :

! Undefined control sequence. \pgfmathsetcount ... \pgfmath@onquick #2\pgfmath@ {\afterassignment \pgfmath... l.16 } ; The control sequence at the end of the top line of your error message was never \def'ed. If you have misspelled it (e.g., \hobx'), typeI' and the correct spelling (e.g., `I\hbox'). Otherwise just continue, and I'll forget about whatever was undefined.

! Undefined control sequence. \tikz@lib@graph@handle@node@cont ...kzgraphnodeas \tikzgraphnodeas@default ... l.16 } ; The control sequence at the end of the top line of your error message was never \def'ed. If you have misspelled it (e.g., \hobx'), typeI' and the correct spelling (e.g., `I\hbox'). Otherwise just continue, and I'll forget about whatever was undefined.

! Undefined control sequence. \tikz@lib@graph@typesetter ->\tikzgraphnodetext l.16 } ; The control sequence at the end of the top line of your error message was never \def'ed. If you have misspelled it (e.g., \hobx'), typeI' and the correct spelling (e.g., `I\hbox'). Otherwise just continue, and I'll forget about whatever was undefined.

) ! Incomplete \iffalse; all text was ignored after line 16. \fi

And I really can't understand why it wouldn't work.

[EDIT] I wrote my second code based on this answer. The part where I write \n - 1 without \the\numexpr is not needed when working in Overleaf so it's NOT the problem here. And I don't want to have \pgfmathtruncatemacro in the labelling of the node since the answer I linked works perfectly for me too without needing it. My problem is that it looks buggy when using it in the \graph environment.

[EDIT 2] Added \the\numexpr since it would not compile on every installation of TL and since it was not this that made the program not work.

Lhooq
  • 332
  • The issue is not the \pgfmathtruncatemacro but the \n-1 in the \foreach loop, and can be solved e.g. with \the\numexpr\n-1. However, even your first example does not compile. –  Oct 14 '19 at 13:52
  • @Schrödinger'scat Good point ! Another solution: add the new (?) parse=true option to the \foreach... – Paul Gaborit Oct 14 '19 at 13:59
  • @PaulGaborit This is a nice option but I did experience issues, in particular with integers when trying to use it so I do not use it myself. –  Oct 14 '19 at 14:01
  • The \graph macro changes the syntax : you can't use TeX code directly. Here, you must use [/utils/exec={\pgfmathtruncatemacro{\xn}{mod(\x+1,\n)}}] instead of \pgfmathtruncatemacro{\xn}{mod(\x+1,\n)}... – Paul Gaborit Oct 15 '19 at 06:07
  • @JosephWright It's not just about suppressing error messages since Overleaf actually compiles it (and if I had [parse=true] it tells me it doesn't know this command. The image I put was obtained with the first code on Overleaf. – Lhooq Oct 15 '19 at 09:13
  • 1
    @JosephWright Here, with the latest TL2018 (updated in april 2019), the first code compiles... And the same code with Overleaf distribution (TL 2018 by default) compiles also. – Paul Gaborit Oct 15 '19 at 09:32
  • I note that the original version of part 1 did not compile cleanly, and that the edit which allows it to work is the same as a suggestion in one of the answers. That is a little odd: could you clarify whether your edit was based on the answer or simply that this is coincidental? – Joseph Wright Oct 17 '19 at 06:48
  • The thing is I based my edit on the comment made immediately under my question since it didn't change my problem. When I noticed the author of the comment put his comment as an answer I considered it not to be the proper answer since of the two codes, the first one had no problem on my side (in Overleaf) when the second one wouldn't be compiled. I hope I answered your question. – Lhooq Oct 17 '19 at 12:32

2 Answers2

4

The \graph macro changes the syntax: you can't use TeX code directly. You can use the /utils/exec key to execute some arbitrary TeX code.

Here is a solution with the final version of TeXLive 2018 (used by Overleaf, cf. TeX Live upgrade Sep.2019):

\documentclass[tikz]{standalone}
\usetikzlibrary{graphs,graphs.standard}
\begin{document}
\begin{tikzpicture}
    \def \n {3}
    \graph[clockwise=\n,radius=3cm] {
        \foreach \x in {0,...,\n-1} {
            [/utils/exec={\pgfmathtruncatemacro{\xn}{mod(\x+1,\n)}}]%
            \foreach \y in {\x,...,\n-1} {
                [/utils/exec={\pgfmathtruncatemacro{\yn}{mod(\y+1,\n)}}]%
                \x / {$a_\x, a_\xn$} --
                \y / {$a_\y, a_\yn$};
            };
        };
    };
\end{tikzpicture}
\end{document}

And, here is a solution with TeXLive 2019:

\documentclass[tikz]{standalone}
\usetikzlibrary{graphs,graphs.standard}
\begin{document}
\begin{tikzpicture}
  \def\n{3}
  \graph[clockwise=\n,radius=3cm] {
    \foreach[parse=true] \x in {0,...,\n-1} {
      [/utils/exec={\pgfmathtruncatemacro{\xn}{mod(\x+1,\n)}}]
      \foreach[parse=true] \y in {\x,...,\n-1} {
        [/utils/exec={\pgfmathtruncatemacro{\yn}{mod(\y+1,\n)}}]
        \x / {$a_\x, a_\xn$} --
        \y / {$a_\y, a_\yn$};
      }
    }
  };
\end{tikzpicture}
\end{document}

Here is a solution with TeXLive 2019 using \pgfmathsetmacro to compute \xmax (without the parse option that still does not work very well):

\documentclass[tikz]{standalone}
\usetikzlibrary{graphs,graphs.standard}
\begin{document}
\begin{tikzpicture}
  \def\n{3}
  \graph[clockwise=\n,radius=3cm] {
    [/utils/exec={\pgfmathsetmacro\xmax{int(\n-1)}}]
    \foreach \x in {0,...,\xmax} {
      [/utils/exec={\pgfmathtruncatemacro{\xn}{mod(\x+1,\n)}}]
      \foreach \y in {\x,...,\xmax} {
        [/utils/exec={\pgfmathtruncatemacro{\yn}{mod(\y+1,\n)}}]
        \x / {$a_\x, a_\xn$} --
        \y / {$a_\y, a_\yn$};
      }
    }
  };
\end{tikzpicture}
\end{document}
Paul Gaborit
  • 70,770
  • 10
  • 176
  • 283
  • I see. Overleaf does compile this. +1. (My problem with parse is that some things do not work, e.g. \foreach[parse=true] \x in {0,...,{int(\n-1)}} gives an error. –  Oct 15 '19 at 06:38
  • @Schrödinger'scat I see the same problem. The parse option is probably not fully developed. – Paul Gaborit Oct 15 '19 at 07:36
  • Yes. There are also some hidden gems like a function dim that returns the length of an array but does not always work. There are problems when the last item of the list is "non-atomic". (I do not know whether parse has been a hidden gem for a while, but I am pretty positive that it only made it to the manual very recently.) –  Oct 15 '19 at 07:40
  • Funny how the tone changes when talking to someone with a big score and a simple user asking a question. Thanks for your answer, I didn't know Overleaf was hiding error messages and I tried it on my distro this morning noticing the error messages. @Schrödinger'scat That's how you answer to someone. You may tell them they have some errors in their code asserting the fact that on their side the code may have compiled and thus answering their question. Or at least don't post a comment as an answer when it doesn't answer the question asked. Thanks for the remark about \n - 1 though. – Lhooq Oct 15 '19 at 08:50
  • @Lhooq Well, your code did and does not compile, and I pointed that out and fixed it. All you did was to charge into me and to downvote me. And now this remark. Well, you have presumably a way of interpreting this in your own way, and I have my way of rating this behavior. My tone did not change, I am just allergic to wrong statements and undeserved downvotes. –  Oct 15 '19 at 09:05
2

This is a compilable version of your first example. I do not see any benefit in using \pgfmathtruncatemacro since you'd also have to wrap it into \pgfextra and so on if you want to use it in a path.

\documentclass[tikz]{standalone}
\usetikzlibrary{graphs,graphs.standard}

\begin{document}
\begin{tikzpicture}
    \def \n {3}
    \graph[clockwise=\n,radius=3cm] {
        \foreach \x [evaluate=\x as \xn using {int(mod(\x+1,\n))}] in
        {0,...,\the\numexpr\n-1} {
            \foreach \y [evaluate=\y as \yn using {int(mod(\y+1,\n))}] in
            {\x,...,\the\numexpr\n-1} {
                \x / {$a_\x, a_\xn$} --
                \y / {$a_\y, a_\yn$}
            }
        }
    };
\end{tikzpicture}

\end{document}

And here is a version where \pgfmathtruncatemacro gets used. Luckily in this application the result is not needed for the path but only for typesetting. So you can add \pgfmathtruncatemacro just to the stuff you want to typeset.

\documentclass[tikz]{standalone}
\usetikzlibrary{graphs,graphs.standard}

\begin{document}
\begin{tikzpicture}
    \def \n {3}
    \graph[clockwise=\n,radius=3cm] {
        \foreach \x  in {0,...,\the\numexpr\n-1} {
            \foreach \y in {\x,...,\the\numexpr\n-1} {               
                \x / {$\pgfmathtruncatemacro{\xn}{int(mod(\x+1,\n))}a_\x, a_\xn$} --
                \y / {$\pgfmathtruncatemacro{\yn}{int(mod(\y+1,\n))}a_\y, a_\yn$}
            }
        }
    };
\end{tikzpicture}

\end{document}

enter image description here