`graph` command doesn't accept nodes named with `-`

Except that one can modify codes related to matrix or graph, here is an alternative.

The idea is that we usually protect sensitive characters by adding additional braces, for example (\x,sin(\x)) does not work and (\x,{sin(\x)}) does.

In case of graphs, braces have another meaning and we should protect node names by quotation marks. The ideal code should be like this

\begin{tikzpicture}
    \node[draw] (A-1) {A};
    \node[draw] (B-1) at (1,0) {B};
    \graph [use existing nodes] {"A-1"->"B-1";};
\end{tikzpicture}

However, anything putting inside quotation marks is processed for security reason: special characters are replaced by something else, for example - becomes @HYPHEN MINUS@ and > becomes @GREATER THAN SIGN@. Therefore the following code actually works.

\begin{tikzpicture}
    \node[draw] (A@HYPHEN MINUS@1) {A};
    \node[draw] (B@GREATER THAN SIGN@2) at (1,0) {B};
    \graph [use existing nodes] {"A-1"->"B>2";};
\end{tikzpicture}

The Next step is that whenever we (or TikZ) create and name a node, we would like to replace - in the name by the same string above. Thus we hack the name= scheme

\makeatletter
\tikzset{
    name/.code={
        {
            \catcode`\-=13\relax
            \scantokens{
                \def-{@HYPHEN MINUS@}
                \xdef\hypenminusname{#1}
            }
        }
        \edef\tikz@fig@name{\tikz@pp@name{\hypenminusname}}
    }
}
\makeatother

You can expand the list by yourself if there are other special characters involved.

Now The code at the beginning works. Also the following code works

\tikz{
    \matrix(magic)[matrix of nodes]{
        8 & 1 & 6 \\
        3 & 5 & 7 \\
        4 & 9 & 2 \\
    };
    \graph[use existing nodes]{
        "magic-2-1"->{"magic-1-3","magic-2-3","magic-3-3"};
    };
}


Full code

\documentclass[tikz,border=2mm]{standalone} 
\usetikzlibrary{graphs,matrix}
\begin{document}

\begin{tikzpicture}
    \node[draw] (A@HYPHEN MINUS@1) {A};
    \node[draw] (B@GREATER THAN SIGN@2) at (1,0) {B};
    \graph [use existing nodes] {"A-1"->"B>2";};
\end{tikzpicture}

\makeatletter
\tikzset{
    name/.code={
        {
            \catcode`\-=13\relax
            \scantokens{
                \def-{@HYPHEN MINUS@}
                \xdef\hypenminusname{#1}
            }
        }
        \edef\tikz@fig@name{\tikz@pp@name{\hypenminusname}}
    }
}
\makeatother

\begin{tikzpicture}
    \node[draw] (A-1) {A};
    \node[draw] (B-1) at (1,0) {B};
    \graph [use existing nodes] {"A-1"->"B-1";};
\end{tikzpicture}

\tikz{
    \matrix(magic)[matrix of nodes]{
        8 & 1 & 6 \\
        3 & 5 & 7 \\
        4 & 9 & 2 \\
    };
    \graph[use existing nodes]{
        "magic-2-1"->{"magic-1-3","magic-2-3","magic-3-3"};
    };
}

\end{document}

Instead of hacking graph library or parsing, you can change the relevant parts of the matrix of nodes code. You can also make this a local behavior etc.

\documentclass[tikz]{standalone}
\usetikzlibrary{graphs,matrix}
\makeatletter
\def\tikz@lib@matrix@empty@cell{\iftikz@lib@matrix@empty\node[name=\tikzmatrixname!\the\pgfmatrixcurrentrow!\the\pgfmatrixcurrentcolumn]{};\fi}
\def\tikz@lib@matrix@with@options|#1|{\tikz@lib@matrix@plainfalse\node%
  [name=\tikzmatrixname!\the\pgfmatrixcurrentrow!\the\pgfmatrixcurrentcolumn]#1\bgroup\tikz@lib@matrix@startup}
\def\tikz@lib@matrix@normal@start@cell{\pgfutil@ifnextchar\let{\tikz@lib@matrix@check}{\tikz@lib@matrix@plainfalse\node
  [name=\tikzmatrixname!\the\pgfmatrixcurrentrow!\the\pgfmatrixcurrentcolumn]\bgroup\tikz@lib@matrix@startup}}%
\def\tikz@lib@matrix@check#1{% evil hackery to find out about start of path
  \pgfutil@ifnextchar\tikz@signal@path{\tikz@lib@matrix@plaintrue\let}{\tikz@lib@matrix@plainfalse\node
  [name=\tikzmatrixname!\the\pgfmatrixcurrentrow!\the\pgfmatrixcurrentcolumn]\bgroup\tikz@lib@matrix@startup\let}%
}
\makeatother

\begin{document}
\begin{tikzpicture}
\matrix[matrix of nodes] (a) {
A\\[4mm]
B\\
};
    \graph [use existing nodes] {a!1!1 -> a!2!1;};
\end{tikzpicture}
\end{document}

Tags:

Tikz Pgf