2

TL;DR: I have a series of variables $x_1, x_2, x_3, \dots$ which to which I assign values inside a loop. However, when I use ValueQ to determine which values I've already assigned, the results don't appear to make much sense.

Minimal example: Code:

Clear[x];
For[i = 1, i < 4, i = i + 1,
x[i] = i;
Print[i, ": ", ValueQ[x[i]], " ", ValueQ [x[i + 1]], " ", ValueQ [x[i + 10]] , " ", ValueQ[x[2]]]]

Output:

1: True True True False
2: True True True True
3: True True True True

Explanation: In $i$-th iteration of the loop, I assign the value to x[i]. Hence, in $i$-th iteration the values x[1], x[2], ..., x[i] are defined, but x[i+1], x[i+2], ... are not. However, when I try to check if x[j] are defined, Mathematica tells me that: 1) x[i] is defined, as expected; 2) x[i+1] is defined, although it is not yet defined; 3) x[i+10] is defined, although it is never defined at all; 4) x[2] is defined if and only if $i \geq 2$, as expected.

Motivation: In the application I have in mind, I'm computing values $x_i$ in a somewhat haphazard order. It so happens that to compute $x_i$ it is useful to know $x_j$ where $j$ is a function of $i$ (a non-trivial one). At the time $x_i$ is computed, I would like to check if $x_j$ has already been computed, and use its value if it has (if it has not, then I need to compute $x_i$ in a more time-consuming way). However, when I try to implement this using ValueQ, I get the unexpected behaviour described above.

Question: How does this behaviour arise, and how can I change the above code to make it work?

Jakub Konieczny
  • 463
  • 2
  • 8

1 Answers1

4

since x[1+1] evaluates (at least) to x[2], ValueQ returns True as it is already different than the input.

You don't have to check if you already calculated x for e.g. 2. You can use memoization:

  x[n_]:=x[n] = ...

So once e.g. x[5] is called, each subsequent x[5] will not require recomputation.

Kuba
  • 136,707
  • 13
  • 279
  • 740
  • Thank you for explaining where the issue comes from. However, in this particular case, momoization is not the solution: I specifically need to check if x[i] (say) is defined, and do one of two different things depending on the outcome (i.e. if I learn that I could speed up computing x[1] by knowing the value of x[101] but I haven't yet computed x[101], I don't want to compute x[101] but rather I want to run a completely different routine). – Jakub Konieczny Feb 06 '18 at 16:54
  • 1
    @JakubKonieczny I see, without details I can only suggest to check MatchQ[x[i], _x]. – Kuba Feb 06 '18 at 17:35
  • @JakubKonieczny or ValueQ[x[#]]&[1+1] – Kuba Feb 12 '18 at 12:58