3

I have recently attempted to concisely draw several graphs in a plot using gnuplot and the plot for ... syntax. In this case, I needed nested loops because I wanted to pass something like the following index combinations (simplified here) to the plot expression:

  • i = 0, j = 0
  • i = 1, j = 0
  • i = 1, j = 1
  • i = 2, j = 0
  • i = 2, j = 1
  • i = 2, j = 2
  • and so on.

So i loops from 0 to some upper limit N and for each iteration of i, j loops from 0 to i (so i <= j). I tried doing this with the following:

# f(i, j, x) = ...
N = 5
plot for [i=0:N] for [j=0:i] f(i, j, x) title sprintf('j = %d', j)

but this only gives five iterations with j = 0 every time (as shown by the title). So it seems that gnuplot only evaluates the for expressions once, fixing i = 0 at the beginning and not re-evaluating to keep up with changing i values. Something like this has already been hinted at in this answer (“in the plot for ... structure the second index cannot depend on the first one.”).

Is there a simple way to do what I want in gnuplot (i.e. use the combinations of indices given above with some kind of loop)? There is the do for { ... } structure since gnuplot 4.6, but that requires individual statements in its body, so it can’t be used to assemble a single plot statement. I suppose one could use multiplot to get around this, but I’d like to avoid multiplot if possible because it makes things more complicated than seems necessary.

3
  • No, there is no simple way. That's why I proposed that ugly workaround in the answer you linked to ;) Commented Dec 16, 2015 at 18:45
  • @Christoph For this specific case there is nice workaround I worked out in my answer below. Commented Dec 16, 2015 at 22:27
  • @Miguel Indeed, :) +1 Commented Dec 17, 2015 at 8:14

1 Answer 1

1

I took your problem personally. For your specific problem you can use a mathematical trick. Remap your indices (i,j) to a single index k, such that

(0,0) -> (0)
(1,0) -> (1)
(1,1) -> (2)
(2,0) -> (3)
...

It can be shown that the relation between i and j and k is

k = i*(i+1)/2 + j

which can be inverted with a bit of algebra

i(k)=floor((sqrt(1+8.*k)-1.)/2.)
j(k)=k-i(k)*(i(k)+1)/2

Now, you can use a single index k in your loop

N = 5
kmax = N*(N+1)/2 + N
plot for [k=0:kmax] f(i(k), j(k), x) title sprintf('j = %d', j(k))
Sign up to request clarification or add additional context in comments.

2 Comments

Of course, this is not really a “simple” solution from a mathematical point of view, but it does allow one to use the simple plot for ... syntax without having to deal with multiplot or other gnuplot complications. Also, it’s not easily extensible to other cases where the indices depend on each other in different ways. But I’m sure you know that ;-) So I guess the answer is “No, not without transforming the indices or other workarounds.”
It is simple in the sense that the expressions are short and transparent. Arriving at the expressions requires a bit more work, so yes you're right. This is just a case-specific solution that relies on the fact that analytic expressions can be obtained for the mapping inversion. For the general case, I would use a variant of the solution given in Christoph's answer (the one you linked in your question).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.