2

I need to define a function which generates a random real number between 0 and $2\pi$, as a random phase constant for a wave superposition. The output should be different each time I re-run the code, with possibly an optional "fixing" parameter (so the random numbers are kept the same at each re-run of the code). The wave is defined as a linear superposition of functions like this one, where $n$ is an integer :

Phi[t_, x_, n_] := Sin[n Pi x] Sin[n Pi t + PhaseCste[n]]

The function "PhaseCste[n]" is the random phase number which I need. It should output a different random value for each $n = 1, 2, 3, \ldots, \infty$. Using the following doesn't work :

PhaseCste[n] = RandomReal[{0, 2Pi}]

because the function "Phi[t_, x_, n_]" should be called with the same values of the "PhaseCste" in the rest of the code (I'm using the same function "Phi[t, x, n]" several times elsewhere in the code).

I hope the question is clear. Any idea how to achieve this ?

Please, take note that the code should be compatible with Mathematica 7.0.

Dr. belisarius
  • 115,881
  • 13
  • 203
  • 453
Cham
  • 4,093
  • 21
  • 36
  • I tried this function from another question : PhaseCste[n] := (SeedRandom[n]; RandomReal[{0, 2 Pi}]). It is almost working. The problem is that the values are fixed, i.e. they don't change at each re-run of the code. – Cham Jan 12 '16 at 15:14
  • how about PhaseCste[n_]:=PhaseCste[n]=2Pi RandomReal[]? – AccidentalFourierTransform Jan 12 '16 at 15:18
  • That last suggestion doesn't work, as stated in my question. The same Phi function is used several times in the code, and should use the same random phase values or else the code outputs only random numbers everywhere (so it gives nothing interesting). – Cham Jan 12 '16 at 15:21
  • 3
    thats what PhaseCste[n_]:=PhaseCste[n] does: it remembers the output for later. If you use the same n, you get the same random number. Try this simplified code: f[n_]:=f[n]=RandomReal[]; {f/@Range[10] ,f/@Range[10]} – AccidentalFourierTransform Jan 12 '16 at 15:24
  • This one is almost working (like the semi-solution I gave in my first comment) : the problem is the output is exactly the same each time I re-run the code. – Cham Jan 12 '16 at 15:26
  • 2
    try including Clear[PhaseCste] at the beginning of your code. – AccidentalFourierTransform Jan 12 '16 at 15:29
  • This is a good step in the right direction ! :-) it's almost working great ! Strangely, there's a part of my code which don't do what it should, I don't know why yet. Where should I place the Clear directive ? At the end ? – Cham Jan 12 '16 at 15:30
  • at the very beginning of your code – AccidentalFourierTransform Jan 12 '16 at 15:34
  • That may be it ! 8-) So if I want to fix the output, I just have to comment out that directive, right ? – Cham Jan 12 '16 at 15:36
  • What if I want to turn off that Clear directive using a simple parameter, instead of placing it between the comments symbols (* ... *) ? It is a bit tedious to add and remove the (*...*) each times. – Cham Jan 12 '16 at 15:39
  • Can you see if this works for you? list = {}; Table[(While[MemberQ[list, r = RandomReal[{2, 2 \[Pi]}]], list = Join[list, {r}];]; r), {i, 1, 1000}]; – Basheer Algohi Jan 12 '16 at 15:55
  • @Algohi Your suggestion is way too complex and "unnatural", compared to the previous solution (which works perfectly). I just need to polish the Clear directive to make the code easier (i.e. simpler) to use. – Cham Jan 12 '16 at 16:02
  • How to turn off the Clear directive using a simple parameter ? – Cham Jan 12 '16 at 16:03
  • @Cham, it is just accumulating the current RandomReal in list and then generate new one and if it is not in the accumulated list then it uses it. It can be used like this: PhaseCste := (While[MemberQ[list, r = RandomReal[{0, 2 \[Pi]}]], list = Join[list, {r}];]; r) – Basheer Algohi Jan 12 '16 at 16:17
  • 1
    @AccidentalFourierTransform, I think you could write your solution as an answer for the benefit of future readers. – rhermans Feb 22 '16 at 10:16

1 Answers1

1

It seems we managed to find the solution in the comment section, but I was asked to post a self-contained answer for future readers, so here it goes.

The task: to generate random numbers that change from session to session, but are memorised in the current session so that they can be reused.

The solution is easy if we use memoization:

PhaseCste[n_]:=PhaseCste[n]=2Pi RandomReal[]

This will generate a random number between $(0,2\pi)$ for every n, and if we call PhaseCste with the same n later on, we get the same random number. Example:

First call:

PhaseCste /@ Range[5]
{3.72868, 4.78289, 0.948487, 4.66522, 5.74172}

Second call:

PhaseCste /@ Range[5]
{3.72868, 4.78289, 0.948487, 4.66522, 5.74172}

If we close the Mathematica session, the list of numbers will be deleted. If at some point we want to start over without closing the session, we can use Clear:

Clear[PhaseCste]

Note that if we do this, we have to define PhaseCste again, i.e., we have to execute

    PhaseCste[n_]:=PhaseCste[n]=2Pi RandomReal[]

again, because by Clearing PhaseCste, we delete its "memory" and its definition.

Upon a third call:

PhaseCste /@ Range[5]
{1.48909, 0.369098, 5.01689, 0.680512, 4.80392}

A better approach is to use DownValues:

DownValues[PhaseCste] = Last@DownValues[PhaseCste];

which deletes the "memory" of the function, but not its definition.

Upon a fourth call:

PhaseCste /@ Range[5]
{3.05886, 2.17051, 1.83634, 2.54535, 4.30857}

Finally, in the comment section OP asked an quick/easy way to toggle on and off this deletion process. A simple possibility is to write something like

OnOff=False;
If[OnOff,Clear[PhaseCste]]
PhaseCste[n_]:=PhaseCste[n]=2Pi RandomReal[]

By changing False to True, the DownValues of PhaseCste will get automatically deleted.