2

This one is somewhat hard to explain, but I'll try my best to.
I'm trying to generate a list of numbers (containing only pi/10, 0, -pi/10). Numbers are randomly selected from these 3, where the probability of getting 0 is always 70%. But the probability of getting pi/10 and -pi/10 depend on the previous outcomes.

Here's I'm going to explain it how it depends:

Initially, the probability of getting pi/10 is 25%, and of getting -pi/10 is 5%. But once I get -pi/10 as an outcome, probabilities will be switched. (i.e., the probability of getting pi/10 will be 5%, and of getting -pi/10 will be 25%.)
Similarly, when pi/10 comes next comes as an outcome, probabilities will again get switched and so on...

So, here's what I've tried, but didn't get the desired result.

rr := RandomReal[{0, 1}]
x1 = \[Piecewise]{{0, # < 0.7}, {-\[Pi]/10, 0.7 <= # < 0.75}, {\ [Pi]/10,True}} &@rr
x2 = \[Piecewise]{{0, # < 0.7}, {\[Pi]/10, 0.7 <= # < 0.75}, {-\[Pi]/10, True}} &@rr

And then I run a for-loop:
(Here, where I have used which function, my 3rd condition is when I get 0, and in that case, probabilites don't get switched, so it remains the previous "a". If you have a better way to that also, then that'll be great.)

list{}
For[i = 1 ; a = 1, i <= 100, i++;
If[a == 0, x = x1, x = x2];
a = Which[x == \[Pi]/10, 0, x == -\[Pi]/10, 1, True, a];
AppendTo[list, x]]
list

Your help will be really appreciated!!

P.S.: There might be some syntax errors, if you could point that out too, I'll be thankful to you (as I'm new to Mathematica).

Rishabh
  • 35
  • 6

4 Answers4

4

Here's a way using NestList:

probabilities = {0.25, 0.05};
f[{result_, pList_}] := With[{x = RandomReal[]},
  Which[x < 0.7, {0, pList},
   (x > 0.7) && (x < 0.7 + pList[[1]]), {Pi/10, Reverse@pList},
  True, {-Pi/10, Reverse@pList}]];

Then run it, for example 10 times:

#[[1]] & /@ NestList[f, {0, probabilities}, 10]

(* {0, 0, \[Pi]/10, 0, -(\[Pi]/10), -(\[Pi]/10), -(\[Pi]/
10), 0, 0, \[Pi]/10, 0}*)

Edit: After reading your comment, I wrote a small update. Here's a new code.

probabilities = {0.25, 0.05};
f2[{result_, pList_}] := With[{x = RandomReal[]},
Which[x < 0.7, {0, pList},
(x > 0.7) && (x < 0.7 + pList[[1]]), {Pi/10, 
If[pList[[1]] == probabilities[[2]], pList, Reverse@pList]},
True, {-Pi/10, 
If[pList[[1]] == probabilities[[1]], pList, Reverse@pList]}]]
Whelp
  • 1,715
  • 10
  • 21
  • Thanks a lot, Whelp!! – Rishabh May 31 '18 at 11:32
  • 1
    @Rishabh If you're new to Mathematica, you might want to read up a little bit about the principles and basics of the language. In general, procedural programming is discouraged, and you can often find simpler solutions using functions. – Whelp May 31 '18 at 11:37
  • Can you please tell me the source from where I could learn these things. Because whenever I search for Mathematica tutorials, it shows very elementary stuff. – Rishabh May 31 '18 at 12:15
  • 1
    I suggest starting here: https://www.wolfram.com/language/elementary-introduction/2nd-ed/ – Whelp May 31 '18 at 12:20
  • 1
    And see also https://mathematica.stackexchange.com/questions/18/where-can-i-find-examples-of-good-mathematica-programming-practice – Whelp May 31 '18 at 12:22
  • Thanks for these references.. Also, I have a query regarding the question that I asked. What you answered, is that it flips the probability, whenever I get pi/10 or -pi/10. What I did ask was: suppose the probability of getting pi/10 is 0.25 and that of -pi/10 is 0.05. Now, For eg.: I got this sequence: 0, 0, 0, pi/10, 0, pi/10, pi/10, 0, 0, 0, -pi/10. Now the moment I get -pi/10. The probs. will be switched. i.e. the prob. of getting -pi/10 is more. Similarly when the next time I'll get pi/10, the prob. will get switched, and so on – Rishabh May 31 '18 at 14:32
  • This also doesn't serve my purpose. But great help anyway. I can use these codes (By you and Okkes) to write the code that I want to. – Rishabh Jun 01 '18 at 11:04
  • Hey @Whelp! I had one more doubt. you used variable "result" in f, but I couldn't figure out where it was used. Also, you used capital 'L' in pList but I thought of it just as a variable, or is it something more! P.S.:I know that these are very silly doubts. – Rishabh Jun 04 '18 at 12:53
  • 1
    @Rishabh The variable "result" is defined because the function is passed to NestList. The function "f" doesn't need "result", but having it as an argument allows it to be displayed in the list created by NestList. – Whelp Jun 05 '18 at 07:49
2

Here is different approach.

weight = {0.25, 0.7, 0.05};
list = Table[       
   Which[val = First@RandomSample[weight -> {π/10, 0, -π/10},1]; 
(val == -(π/10)) || (val == π/10), 
        weight = Reverse@weight; val, True, val], 10000];

Count[list, #] & /@ {0, Pi/10, -Pi/10}

{7061, 1467, 1472}

Edit: Please double check if this is what you want.

ClearAll["Global`*"]
weight = {0.25, 0.7, 0.05};
list = {};
sign = {};
list = Last@Table[

    Which[
     val = First@
       RandomSample[weight -> {π/10, 0, -(π/10)}, 1]; 
     If[Last@list != 0, AppendTo[sign, Last@list], True, Nothing]; 
     sign = SplitBy[sign, Sign]; Length@sign == 2, 
     weight = Reverse@weight; sign = Rest@sign; AppendTo[list, val]; 
     list, True, AppendTo[list, val]; list]
    , 100] // Quiet

$\left\{\frac{\pi }{10},\frac{\pi }{10},0,0,0,-\frac{\pi }{10},0,0,\frac{\pi }{10},0,0,0,-\frac{\pi }{10},0,0,\frac{\pi }{10}, \frac{\pi }{10},0,\frac{\pi }{10},0,0,0,0,0,\frac{\pi }{10},-\frac{\pi }{10},\frac{\pi }{10},0,\frac{\pi }{10},0,0,0,0,0,0,-\frac{\pi }{10},-\frac{\pi }{10},0,-\frac{\pi }{10},-\frac{\pi }{10},0,0,0, -\frac{\pi }{10},0,0,-\frac{\pi }{10},\frac{\pi }{10},0,0,0,0,\frac{\pi }{10},\frac{\pi }{10},0,\frac{\pi }{10},\frac{\pi }{10},0,\frac{\pi }{10}, \frac{\pi }{10},0,0,0,\frac{\pi }{10},0,-\frac{\pi }{10},\frac{\pi }{10},\frac{\pi }{10},-\frac{\pi }{10},-\frac{\pi }{10},0,0,0,0,0,\frac{\pi }{10},0,-\frac{\pi }{10},-\frac{\pi }{10},0,-\frac{\pi }{10}, -\frac{\pi }{10},0,0,\frac{\pi }{10},0,0,0,0,0,0,0,0,0,0,0,0,\frac{\pi }{10},0,-\frac{\pi }{10}\right\}$

OkkesDulgerci
  • 10,716
  • 1
  • 19
  • 38
  • Thanks for the answer. But what you answered, is that it flips the probability, whenever I get pi/10 or -pi/10. What I did ask was: suppose the probability of getting pi/10 is 0.25 and that of -pi/10 is 0.05. Now, For eg.: I got this sequence: 0, 0, 0, pi/10, 0, pi/10, pi/10, 0, 0, 0, -pi/10. Now the moment I get -pi/10. The probs. will be switched. i.e. the prob. of getting -pi/10 is more. Similarly when the next time I'll get pi/10, the prob. will get switched, and so on.. – Rishabh May 31 '18 at 20:13
  • Yes, I noticed your last comment after I posted my solution which does not answer your question. You should unselect your acceptance so that other people comes and try different solution. – OkkesDulgerci May 31 '18 at 20:21
  • Not exactly but I'll try to work it out from here on my own. Anyway, thanks a lot, man! It's a great help. – Rishabh Jun 01 '18 at 08:38
2

This answer relies on the built-in function $\texttt{DiscreteMarkovProcess}$. In order to use it, the states of the world must be specified. A state is composed of two items: the current value and the most recent nonzero value. (Again I use {-1, 0, 1} for the values instead of {-Pi/10, 0, Pi/10}.)

There are four possible states

State: {current, most recent nonzero}
1       {-1,      -1}
2       { 0,      -1}
3       { 0,       1}
4       { 1,       1}

Note that third state cannot be reached directly from either of the first two states. Similarly, the second state cannot be reached from either of the last two states.

Let us construct the transition matrix and setup the Markov process object:

row = {.25, .7, 0., .05};
mat = {row, row, Reverse[row], Reverse[row]};

(* start in the first state *)
process = DiscreteMarkovProcess[{1, 0, 0, 0}, mat];

In order to convert the state numbers 1 through 4 into the current values, it is convenient to define a helper function:

fun = Function @@ {x, Piecewise[{{-1, x == 1}, {1, x == 4}}]}

We are now set to simulate from this process:

ran = fun /@ RandomFunction[process, {1, 10^6}]["ValueList"][[1]];

On my MacBook this takes about 0.33 seconds. (This is faster than my other answer, which see for additional post processing.)

mef
  • 1,629
  • 11
  • 15
1

If I have understood correctly, then I think the following code does what you want. (To keep things simple, I have used {-1, 0, 1} instead of {-Pi/10, 0, Pi/10}. One can easily modify the output as shown at the end.) I have compiled the function for speed.

cf = Compile[{{n, _Integer}},
  Module[{
    probs = {.25, .7, .05},
    state = -1,
    current
    },
  Table[
   current =
     RandomChoice[
      If[
        state == -1,
        probs,
        Reverse[probs]
        ] -> {-1, 0, 1}
      ];
    If[
     current == 0,
     current,
     state = current
     ],
    n]
   ]
  ]

Here is the usage (this takes about 0.4 seconds on my MacBook):

ran = cf[10^6];

We can examine the output:

KeySort[Counts[Partition[ran, 2, 1]]] -->

<|{-1, -1} -> 37211, {-1, 0} -> 104798, {-1, 1} -> 7324, 
  {0, -1} -> 104713, {0, 0} -> 491009,  {0, 1} -> 105168, 
  {1, -1} -> 7410,   {1, 0} -> 105082,  {1, 1} -> 37284|>

Making the substitution takes about 0.23 seconds:

ran1 = ran /. {-1 -> -Pi/10, 1 -> Pi/10};

Let me know if I have misunderstood.

mef
  • 1,629
  • 11
  • 15