1
$\begingroup$

I want to create a list length l with the function $f(x_n)=x_{n-1}+r$ where $r$ is a random real number between -1 and 1 and $x_0=1$. It got it working like this:

l = 50; a = Range[l]; a[[1]] = 0;
For[i = 2, i <= l, i++, a[[i]] = a[[i - 1]] + RandomReal[{-1, 1}]];
a

But I have a feeling I'm doing it "wrong" and this can be heavily optimized and written shorter.

Any ideas ?

For example the fact that I use Range to create a list with elements that I never use seems wrong...

$\endgroup$
  • 3
    $\begingroup$ Take a look at FoldList/Accumulate and related functions. $\endgroup$ – Kuba Jan 31 '18 at 18:14
  • 1
    $\begingroup$ One easy to follow method, x = 0;Table[x = x + RandomReal[{-1, 1}], i], where i is the length of the list you desire. $\endgroup$ – user6014 Jan 31 '18 at 18:15
  • 1
    $\begingroup$ Prepend[ RandomReal[{-1, 1}, 50], 1] $\endgroup$ – Artes Jan 31 '18 at 18:16
  • $\begingroup$ Or even NestList[# + RandomReal[{-1, 1}] &, 0, 20] $\endgroup$ – user6014 Jan 31 '18 at 19:17
  • $\begingroup$ To expand on Kuba's suggestion: {0}~Join~Accumulate[RandomReal[{-1, 1}, l]]. $\endgroup$ – anderstood Jan 31 '18 at 20:00
2
$\begingroup$

It's not clear if the first entry should be zero or one (the body of the question uses $x_0=1$ but in the code there is a[[1]]=0) and if it's RandomReal or RandomInteger the relevant function to use; here, the first entry in the list is set to zero (see xo below) and RandomReal is used to generate the random numbers.

(* init *)
With[{l = 50, xo = 0},

 (* make everything reproducible *)
 BlockRandom[

  (* localize the generation of random numbers *)
  Block[{r = RandomReal[{-1, 1}, l - 1]},

   (* perform the actual iteration *)
   FoldList[#1 + #2 &, xo, r]

   ], RandomSeeding -> 123]
 ]

edit #1

Let $X_l=\{x_t\}_{t=0}^{l-1}$ denote a series of $l$ numbers, namely $X_l=\{x_0,x_1,...,x_{l-1}\}$. Please note that when using zero-based indexing for a list of $l$ numbers, the indexes themselves run from $0$ to $l-1$.

Consider the following example: for $l=3$, the list of numbers is going to be $X_3=\{x_0,x_1,x_2\}$.

Writing something like $x_s = x_{s-1} + c$, where $c$ is a scalar and $s$ is an index, running from $1$ to $l-1$, allows one to impose structure on list $X_l$.

A recursion like this, in the case of our example with $X_3$ above, would imply that, instead of $\{x_0,x_1,x_2\}$, list $X_3$ should-effectively-be transformed into $\{x_0,x_0+c,x_0+2c\}$ (example 1).

A further extension of the recursion model would allow $c$ to be dependent on the recursion step, $s$, too. In that case, the recursion would be written as $x_s = x_{s-1} + c_s$; in which case, the $X_3$ example should be modified to read $\{x_0,x_0+c_1,x_0+c_1+c_2\}$ (example 2).

Now, in the body of the question, function $f$, defines a recursion that is seemingly (that's my interpretation of the question in conjunction with the code provided) similar to the first example above ($x_s = x_{s-1} + c$, where $c$ a scalar); furthermore, it is explicitly stated in the question that $x_0=1$ (the first number in the sequence should be equal to one).

When ones inspects the code segment, however, one can't help but notice that the sequence a=Range[l]; a[[1]]=0; effectively imposes $x_0=0$ (the a[[1]]=0 part), contrary to what was originally stated.

Additionally, calling RandomReal in a[[i]] = a[[i - 1]] + RandomReal[{-1, 1}] will produce a new random real number for every iteration step; this behavior implies that the relevant recursion model is that of example 2 (see above). This, however, contrasts with what was initially adhered to (see quote "[...] $f(x_n)=x_{n-1}+r$ where r is a random real number between -1 and 1" from the question; here, $r$ is not dependent on the recursion step).

Having said that, if the relevant recursion model for the original question is the one exemplified in example 1, then a straightforward way to generate a list $X_l$ is

xo + Range[0, l-1] RandomReal[{-1, 1}]

On the other hand, if what's relevant for the question, is the recursion model of example 2, then a straightforward way to generate list $X_l$ is

FoldList[#1 + #2 &, xo, RandomReal[{-1, 1}, l - 1]]

edit #2

The use of BlockRandom is intended to assist in producing reproducible results.

For the function definition f[x___] := RandomReal[], evaluating f[] two consecutive times will produce two different random numbers. On the contrary, evaluating BlockRandom[f[]] two or more consecutive times will always produce the same random number.

The same effect can be gotten with BlockRandom[f[],RandomSeeding->123456789] where RandomSeeding provides the seed for the random number generators (see the documentation for BlockRandom).

The same effect as BlockRandom can be practically achieved by, using instead SeedRandom before the evaluation of f in the example above (although there are caveats, please refer to the documentation).

What this means for this answer is that you can practically have a functioning solution without using BlockRandom if you choose to not use it.

According to the documentation, BlockRandom was introduced in 2007 (v.6.0) and was updated in 2017 (v.11.2)

$\endgroup$
  • $\begingroup$ I want $x_0$ as the element 1 of the list, but call it $x_0$ instead because it's the value where +r has been executed 0 times. It's a bit confusing, true. Should I edit my question ? $\endgroup$ – Garo Jan 31 '18 at 19:25
  • 1
    $\begingroup$ It is not moderators' job to review details of answers if they are more or less on topic. Please talk to Garo if you have doubts. $\endgroup$ – Kuba Jan 31 '18 at 20:33
1
$\begingroup$

I am understanding you want to generate a sequence of real numbers recursively (with some randomness) starting with $x_0=1$, Maybe this is a solution:

RandomSeed[2];
f[0] = 1;
f[n_Integer /; n > 0] := f[n] = f[n - 1] + RandomReal[{-1, 1}];
l = 50; 
f[#] & /@ Range[0, l]

(*  
 {1, 1.44448, 0.663377, 0.604782, 0.675946, 0.842301, 0.430186,
  -0.239505, -0.0369893, 0.471446, 1.01369, 1.57084, 0.618061, 1.46357,
  2.44848, 2.1493, 1.23931, 1.24203, 1.50954, 1.79396, 1.57371,
  1.90365, 2.59141, 2.72949, 2.52592, 2.00322, 2.35025, 2.18926,
  2.36406, 1.38073, 2.26561, 2.80813, 2.10314, 3.03269, 3.83018, 
  3.4961, 2.9052, 3.58327, 3.08405, 2.56132, 2.79456, 3.55316, 3.36217, 
  3.1672, 3.19959, 2.78361, 2.48201, 1.85312, 2.05956, 1.12755, 1.67286}
 *)

The use of SeedRandomis for obtaining always the same sequence. I f you do not want this, and generate a different sequence every time, just comment or remove the line.

$\endgroup$

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.