1

So I am trying to draw the figure from this question in tikz. I have two "lists" of mathematical expressions, say x and y which have same number of elements, and I want this line to be repeated for so multiple times, once for each element.

Consider this pseudocode:
x = list of n mathematical expressions y = another list of n mathematical expressions for i = 1 to n \node [on chain, myNode] (Li) at (0, -3-(i-1)) {$x[i]$\$y[i]$}; ```

Here, x[i], y[i] are actually the elements of lists x and y, and not to be evaluated as strings x[i], y[i].

But I don't see how I can do this using tikz's foreach syntax. I don't want to combine the two arrays into one and use slash because I already have the arrays in two text files, and manually combining them into one would be a pain.

Edit:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{chains,positioning,scopes,shapes}
\begin{document}
    \tikzstyle{myNode}=[on chain, align=center,shape=ellipse,draw, minimum width=3cm, minimum height=1cm,inner ysep=0pt]
    \begin{tikzpicture}
    \def\firstlist{$(1 - x_a) (1 - x_b) $, $ (1 - x_1) (1 - x_b) $, $ x_a (1 - x_b) $, $ x_1 (1 - x_2) $, $ x_1 x_b $, $ (1 - x_1)(1 - x_2) $, $ (x_1)(x_2) $, $ (1 - x_1) (x_b) $, $ x_a x_b $, $ x_1(1 - x_b)$}
    \def\secondlist{$(k + 4)v_1 + (-2k + -5)v_2 + (k + 2)v_3 \ge 1$, $(k + 3)v_1 + (-2k + -3)v_2 + (k + 1)v_3 \ge 1$, $-v_1 + (k + 3)v_2 + (-k + -2)v_3 \ge 0$, $kv_2 + (-k + 0)v_3 \ge 0$, $(k + 1) v_3 \ge 0$, $(k + 2)v_1 + (-2k + -1)v_2 + (k + 0)v_3 \ge 1$, $(1)v_2 + (k)v_3 \ge 0$, $-v_1 + (k + 2)v_2 + (-k + -1)v_3 \ge 0$, $-v_2 + (k + 2)v_3 \ge 0$, $(k + 1)v_2 + (-k + -1)v_3 \ge 0$}
   \begin{scope}
   [start chain=going below, node distance=2cm]
   \foreach \x [count=\c, var=\y in \secondlist{\c-1}] in \firstlist
   {
      \node (L\c) [on chain, myNode]  at (0, -3-\c) {\x\\\y};
    }
  \end{scope}
\end{tikzpicture}
\end{document}

But this only repeats elements of first list twice in a node. I want first line to be an element from first list, and second line to be an element from second list.

  • Check the answer here – Jonas Nyrup Dec 11 '15 at 20:31
  • @JonasNyrup That somehow doesn't work. My guess is, first answer only works if the each element in the second list is one character long. Not sure. – taninamdar Dec 11 '15 at 20:53
  • Please provide us with a minimal example showing your set up such that if we solve the problem for that example, it will satisfactorily answer your question. This should include lists representative of the list you've got and should begin \documentclass and end \end{document}. – cfr Dec 11 '15 at 22:06
  • @cfr Added a minimal example. – taninamdar Dec 11 '15 at 22:11
  • I don't understand why array(<list>,\c) is not what you want. You say in comments that it is 'not a simple index' but you have 1 dimensional arrays, so how can it be anything but a simple index? – cfr Dec 11 '15 at 23:00
2

Do you want something like this?

arrays in nodes

\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{chains}
\begin{document}
\tikzset{
  myNode/.style={align=center},
}
\begin{tikzpicture}[start chain=chain]
  \foreach \i in {0,1}
  \node [on chain, myNode] (Li) at (0,\i)  {\pgfmathparse{array({"$f_1(x)$", "$f_2(x)$"},\i)}\pgfmathresult\\\pgfmathparse{array({"$g_1(x)$", "$g_2(x)$"},\i)}\pgfmathresult};
\end{tikzpicture}
\end{document}

EDIT

Note that this does exactly the same thing but with your code and without array because the latter introduces complications (but would presumably be more efficient).

It is still using the ith element from one list and combining it with the ith element from another list. Although you say that is not what you mean, it is rather hard to see what else could be intended here. Of course, you could manipulate the variables to take, say, the ith element from list one and the *i+3*th element from list two, and then use the first elements in list two to match the final elements in list one. Those are still 'simple indices', though.

\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{chains,shapes.geometric}
\begin{document}
\tikzset{
  myNode/.style={on chain, align=center,shape=ellipse, draw, minimum width=3cm, minimum height=1cm, inner ysep=0pt},
}
\begin{tikzpicture}
  \def\firstlist{$(1 - x_a) (1 - x_b) $, $ (1 - x_1) (1 - x_b) $, $ x_a (1 - x_b) $, $ x_1 (1 - x_2) $, $ x_1 x_b $, $ (1 - x_1)(1 - x_2) $, $ (x_1)(x_2) $, $ (1 - x_1) (x_b) $, $ x_a x_b $, $ x_1(1 - x_b)$}
  \def\secondlist{$(k + 4)v_1 + (-2k + -5)v_2 + (k + 2)v_3 \ge 1$, $(k + 3)v_1 + (-2k + -3)v_2 + (k + 1)v_3 \ge 1$, $-v_1 + (k + 3)v_2 + (-k + -2)v_3 \ge 0$, $kv_2 + (-k + 0)v_3 \ge 0$, $(k + 1) v_3 \ge 0$, $(k + 2)v_1 + (-2k + -1)v_2 + (k + 0)v_3 \ge 1$, $(1)v_2 + (k)v_3 \ge 0$, $-v_1 + (k + 2)v_2 + (-k + -1)v_3 \ge 0$, $-v_2 + (k + 2)v_3 \ge 0$, $(k + 1)v_2 + (-k + -1)v_3 \ge 0$}
  \begin{scope}
    [start chain=going below, node distance=2cm]
    \foreach \i [count=\c] in \firstlist
    \foreach \j [count=\d] in \secondlist
    {
      \ifnum\c=\d \node (L\c) [on chain, myNode]  at (0, -3-\c) {\i\\\j};\fi
    };;
  \end{scope}
\end{tikzpicture}
\end{document}

list elements pairwise in nodes without <code>array</code>

But probably something like this would be better?

rearrangement

\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{chains,shapes.geometric}
\begin{document}
\tikzset{
  myNode/.style={align=center,shape=ellipse, draw, minimum width=3cm, minimum height=1cm, inner ysep=0pt},
}
\begin{tikzpicture}
  \def\firstlist{$(1 - x_a) (1 - x_b) $, $ (1 - x_1) (1 - x_b) $, $ x_a (1 - x_b) $, $ x_1 (1 - x_2) $, $ x_1 x_b $, $ (1 - x_1)(1 - x_2) $, $ (x_1)(x_2) $, $ (1 - x_1) (x_b) $, $ x_a x_b $, $ x_1(1 - x_b)$}
  \def\secondlist{$(k + 4)v_1 + (-2k + -5)v_2 + (k + 2)v_3 \ge 1$, $(k + 3)v_1 + (-2k + -3)v_2 + (k + 1)v_3 \ge 1$, $-v_1 + (k + 3)v_2 + (-k + -2)v_3 \ge 0$, $kv_2 + (-k + 0)v_3 \ge 0$, $(k + 1) v_3 \ge 0$, $(k + 2)v_1 + (-2k + -1)v_2 + (k + 0)v_3 \ge 1$, $(1)v_2 + (k)v_3 \ge 0$, $-v_1 + (k + 2)v_2 + (-k + -1)v_3 \ge 0$, $-v_2 + (k + 2)v_3 \ge 0$, $(k + 1)v_2 + (-k + -1)v_3 \ge 0$}
  \begin{scope}
    [start chain=going below, node distance=2cm]
    \foreach \i [count=\c] in \firstlist
    \foreach \j [count=\d] in \secondlist
    {
      \pgfmathsetmacro\cbelow{-3-2*\c}
      \ifnum\c=\d
        \node (L\c) [myNode]  at (0,\cbelow) {\i\\\j};
        \chainin (L\c);
      \fi
    };;
  \end{scope}
\end{tikzpicture}
\end{document}

EDIT EDIT

Note that if you can use lists with quoted values, you can use my original answer, thus running only n rather than n^2 iterations. For example:

\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{chains,shapes.geometric}
\begin{document}
\tikzset{
  myNode/.style={align=center,shape=ellipse, draw, minimum width=3cm, minimum height=1cm, inner ysep=0pt},
}
\begin{tikzpicture}
  \def\firstlist{"$(1 - x_a) (1 - x_b) $", "$ (1 - x_1) (1 - x_b) $", "$ x_a (1 - x_b) $", "$ x_1 (1 - x_2) $", "$ x_1 x_b $", "$ (1 - x_1)(1 - x_2) $", "$ (x_1)(x_2) $", "$ (1 - x_1) (x_b) $", "$ x_a x_b $", "$ x_1(1 - x_b)$"}
  \def\secondlist{"$(k + 4)v_1 + (-2k + -5)v_2 + (k + 2)v_3 \ge 1$", "$(k + 3)v_1 + (-2k + -3)v_2 + (k + 1)v_3 \ge 1$", "$-v_1 + (k + 3)v_2 + (-k + -2)v_3 \ge 0$", "$kv_2 + (-k + 0)v_3 \ge 0$", "$(k + 1) v_3 \ge 0$", "$(k + 2)v_1 + (-2k + -1)v_2 + (k + 0)v_3 \ge 1$", "$(1)v_2 + (k)v_3 \ge 0$", "$-v_1 + (k + 2)v_2 + (-k + -1)v_3 \ge 0$", "$-v_2 + (k + 2)v_3 \ge 0$", "$(k + 1)v_2 + (-k + -1)v_3 \ge 0$"}
  \begin{scope}
    [start chain=going below, node distance=2cm]
    \foreach \i [evaluate=\i as \c using {array({\firstlist},\i)},evaluate=\i as \d using {array({\secondlist},\i)}]    in {0,1,2,...,9}
    {
      \pgfmathsetmacro\ibelow{-3-2*\i}
        \node (L\i) [myNode]  at (0,\ibelow) {\c\\\d};
        \chainin (L\i);
    };
  \end{scope}
\end{tikzpicture}
\end{document}

also produces

first solution with full lists, values quoted

Note that I'm assuming you are chaining the nodes for further use. The chaining isn't handling the placement here at all.

  • Again, no. i is not just the index of functions. It stands for ith element of array, and it's not directly related to i. You can check my updated question to see examples of first and second lists. – taninamdar Dec 11 '15 at 22:32
  • Well that is picking out the ith element in the first list and the ith element in the second list. If that's not what you mean, I guess I just don't understand your use of array. That's what the array function in PGF/TikZ does: it accesses the array x at the index y (page 937). If you are using array in some other sense, I guess you should explain for those of us not in the know. (I realise that an array can have more than 1 dimension, but you gave simple lists in your earlier comment and those are each 1 dimensional.) – cfr Dec 11 '15 at 22:56
  • Yes this is exactly what I wanted. I know this is not the place to worry about efficiency, but there's no "linear" solution, is there? – taninamdar Dec 12 '15 at 0:50
  • My original solution using array is linear, yes. Structurally, it does the same thing but it does it by finding the ith element in the second list directly rather than looping through the entire second list for each i and only using the one which is in the ith position. Hence, only one loop is needed rather than two. In effect, that means that the array solution runs through n iterations, whereas the other solution runs through n^2 iterations, so obviously the former is likely to be more efficient, depending on how efficiently array is implemented. – cfr Dec 12 '15 at 1:02
  • 1
    @taninamdar Please see second edit above for an example which uses array with your lists, modified to quote the values. (I used a simple regex in my editor to transform the lists. Presumably this would be pretty easy to do for your files, too.) – cfr Dec 12 '15 at 1:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.