First index is not integer using foreach loop from 0

You could just tell TikZ explicitly that you want an integer.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}
    \tikzset{mynode/.style={circle, fill=blue!25, minimum size=0.1 cm}}
    \foreach \ilayer in {0,...,3} {
        \tikzmath {\nnodes = 3 ^ \ilayer; }
        \tikzmath {\leftnum = int(1 - floor(\nnodes / 2) - 1); }
        \tikzmath {\rightnum = \nnodes - floor(\nnodes / 2) - 1; }
        \foreach \isibling in {\leftnum,...,\rightnum} {                
            \tikzmath {\d = 3 ^ (- \ilayer) * 15; }
            \tikzmath {\x = \isibling * \d; }
            \tikzmath {\y = - \ilayer * 2; }
            \node[mynode] (node_\ilayer_\isibling) at (\x cm, \y cm) {\isibling};
        }
    }
\end{tikzpicture}
\end{document}

enter image description here

Or

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}
    \tikzset{mynode/.style={circle, fill=blue!25, minimum size=0.1 cm}}
    \foreach \ilayer in {0,...,3} {
        \tikzmath {int \nnodes,\leftnum,\rightnum;
            \nnodes = 3 ^ \ilayer;
            \leftnum = 1 - floor(\nnodes / 2) - 1; 
        \rightnum = \nnodes - floor(\nnodes / 2) - 1; }
        \foreach \isibling in {\leftnum,...,\rightnum} {                
            \tikzmath {\d = 3 ^ (- \ilayer) * 15; 
            \x = \isibling * \d; 
            \y = - \ilayer * 2; }
            \node[mynode] (node_\ilayer_\isibling) at (\x cm, \y cm) {\isibling};
        }
    }
\end{tikzpicture}
\end{document}

In principle you do not need the math library here.

\documentclass[tikz,border=3.14mm]{standalone}
\begin{document}
\begin{tikzpicture}
    \tikzset{mynode/.style={circle, fill=blue!25, minimum size=0.1 cm}}
    \foreach \ilayer [evaluate=\ilayer as \nnodes using {int(3 ^ \ilayer)},
    evaluate=\nnodes as \leftnum using {int(1 - floor(\nnodes / 2) - 1)},
    evaluate=\nnodes as \rightnum using {int(\nnodes - floor(\nnodes / 2) - 1)}]
    in {0,...,3} {
        \foreach \isibling 
        [evaluate=\ilayer as \d using {3 ^ (- \ilayer) * 15},
        evaluate=\isibling as \x using {\isibling * \d},
        evaluate=\ilayer as \y using {- \ilayer * 2}]
        in {\leftnum,...,\rightnum} {                
            \node[mynode] (node_\ilayer_\isibling) at (\x cm, \y cm) 
            {\isibling};
        }
    }
\end{tikzpicture}
\end{document}

enter image description here


As @marmot said you do not need tikzmath here, but if you use it you can do it in more efficient way :

  • You can have a single \tikzmath command with loops inside it.
  • You can declare your integer variables as int so you do not need to do int() afterward.
  • As \nnodes is odd you do not need separate \rightnum and \leftnum as \rightnum = - \leftnum;
  • Why you use 1-floor(\nnodes/2)-1 in place of -floor(\nnodes/2) ?
  • The value \d can be calculated in the outer loop.
  • Instead of using \x=\isibling*\d you can say [x=\d cm] and then use \isibling as\x. And in the same way \y can be replaced by \ilayer using [y=-2cm].

So here is my proposal :

\documentclass[tikz,border=7pt]{standalone}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}
  \tikzstyle{node}=[circle, fill=blue!25, minimum size=0.1 cm];
  \tikzmath{
    int \ilayer,\nnodes,\rightnum,\isibling;
    \nnodes = 1;
    for \ilayer in {0,...,3}{
      \rightnum = (\nnodes-1)/2;
      \d = 15/\nnodes;
      for \isibling in {-\rightnum,...,\rightnum}{
        {
          \path[x=\d cm,y=-2cm]
            node[node] (node_\ilayer_\isibling) at (\isibling, \ilayer) {\isibling};
        };
      };
      \nnodes = 3*\nnodes;
    };
  }
\end{tikzpicture}
\end{document}

enter image description here