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

1 Answers1

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.

cfr
  • 198,882
  • 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 00: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 01:02
  • The problem with using array (aside from the fact that you insisted that isn't what you meant) is that the values in your lists are not quoted and they include $ signs so you get errors. So you could use array (if you changed your mind about that not being what you wanted) if you manipulated the list to quote each value and then you'd avoid the additional iterations. – cfr Dec 12 '15 at 01:07
  • It was my earlier impression that the first solution gave index i inside subscripts of hardcoded f and g. I'll try to wrap my head around the solutions, but the last one definitely meets my requirements. – taninamdar Dec 12 '15 at 01:11
  • No. It is picking out the ith element in the list. That is array(<list>,i) picks the ith element of <list> whatever that happens to be. So array({"sardines","oranges","go-carts"},2) will produce oranges. (It may work without quotes for text - I'm not sure.) – cfr Dec 12 '15 at 01:29
  • 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 01:52
  • Thank you! I'll try it once I have access to my laptop which has TeX installation. – taninamdar Dec 12 '15 at 02:01
  • You're welcome! You do need to quote the values, though. Otherwise, the $ are a problem. – cfr Dec 12 '15 at 02:02