# How can I generate monotonic random real numbers

My question is simple, and therefore I made a search of an answer to it using the Repository of this forum. There are relevant questions, however, none of them answers to the following question.

My first question is how to generate a list of lists (matrix) of RandomReal numbers, but the repetitively generated lists should be monotonic (increasing or decreasing).

SeedRandom[213];
RandomReal[{0.3, 0.8}, 4];
(*output={0.5318, 0.412309, 0.571831, 0.673618}*)


In the next round of RealRandom generation, every element in the list output should be increased (or decreased) randomly within a small range, call the new output as output1. In still another round, RandomReal should generate another list output2, every element of which should be greater than every corresponding element of output1 and so on.

My second question is more difficult (for me) since I also want some of the elements in the randomly generated list to remain unchanged, while others monotonically change. Namely, I like to control some elements during the process of random number generation.

Eventually, I like to combine the answers to these questions in a Mathematica function, such as rng[...]:= to automate the random number generations in the range of my interest.

EDIT 1

The type of Mathematica function I have in mind has the following form:

f[inc_List, rngi_Range, rti_Real, dec_List, rngd_Range, rtd_Real,
fix_List, lrv_Integer, ni_Integer]


where

• inc_List = list of elements to be increased;
• rngi_Range = a range for the increment of inc_List;
• rti_Real = rate of increase (real number in the interval [0,1]);
• dec_List = list of elements to be decreased;
• rngd_Range = a range for the decrease of dec_List;
• rtd_Real = rate of decrease (real number in the interval [0,1]);
• fix = list of elements to be fixed;
• ni_Integer = number of times for Random # generation/number of iterations;
• lrv_Integer = length of the random vector;
• when generating output2 in round 2 do you use rti and rngi to increase all elements of output1 or only the elements in in inc?
– kglr
Nov 30, 2019 at 19:16
• @kglr: In round 2, I want to use rti and rngi to increase the elements in inc only. Similarly, I like to use rtd and rngd to decrease the elements in dec only. Nov 30, 2019 at 20:20
• Why not just generate a list of random numbers and then sort them from low to high?
– JimB
Dec 5, 2019 at 22:07
• @JimB: I have a list of elements {a,b,c,d,e,f,g,h}, some of which should increase like {a,b,c}, some decrease like {d,e,f}, while still others like {g,h} are fixed. A new value for each element in each group should be randomly selected but in the desired direction such as increase, decrease and fix. Dec 5, 2019 at 22:15

ClearAll[step, iterate]
step[initialvector_, indicesdecay_, rangedecay_, indicesgrow_,  rangegrow_] :=
Module[{ca = Normal[
Length@initialvector]]},
initialvector (1 + (ca /. {1 :> RandomReal[rangegrow],
-1 :> RandomReal[rangedecay]}))]

iterate[initialvector_, indicesdecay_, rangedecay_, indicesgrow_,
rangegrow_, iterations_] :=
NestList[step[#, indicesdecay, rangedecay, indicesgrow, rangegrow] &,
initialvector, iterations]


Example:

Given an initial vector ({1,2,3,4,5}), column 4 stays constant, columns 1 and 3 decay at a random rate in range {-.3, -.2} at each step, and columns 2 and 5 grow at a random rate in range {.1,.5}, iterated 7 steps:

SeedRandom[1]
ListLinePlot[Transpose@ iterate[Range[5], {1, 3}, {-.3, -.2}, {2, 5}, {.1, .5}, 7],
PlotLegends -> Automatic]


For arithmetic progression (columns in indicesdecay decrease by a random amount and columns in indicesgrow increase by a random amount at every step) ypu can use:

ClearAll[step2, iterate2]
step2[initialvector_, indicesdecay_, rangedecay_, indicesgrow_, rangegrow_] :=
Module[{ca = Normal[SparseArray[
Length@initialvector]]},
initialvector + (ca /. {1 :> RandomReal[rangegrow], -1 :>
RandomReal[rangedecay]})]

iterate2[initialvector_, indicesdecay_, rangedecay_, indicesgrow_,
rangegrow_, iterations_] :=
NestList[step2[#, indicesdecay, rangedecay, indicesgrow,
rangegrow] &, initialvector, iterations]


Example:

SeedRandom[1]
ListLinePlot[Transpose@iterate2[Range[5], {1, 3}, {-.3, -.2}, {2, 5}, {.1, .5}, 7],
PlotLegends -> Automatic]


Making parameter selections interactive:

DynamicModule[{m = ConstantArray[0, 20], iv0, iv, dv, sim},
Manipulate[dv = m[[;; vl[[1]]]];
SeedRandom[seed];
iv0 = RandomReal[ir, {1, vl[[2]]}];
iv = iv0[[{1}, ;; vl[[1]]]];
sim = NestList[# (1 + (dv /. {1 :> RandomReal[gr], -1 ->
RandomReal[dr]})) &, iv[[1]], iter[[1]]];
Column[{Style["initial vector", 16],
ListLinePlot[iv, Frame -> True,
FrameTicks -> {{Automatic, None}, { Range[vl[[1]]], None}},
AspectRatio -> All, ImageSize -> 1 -> 50,
PlotRange -> {{.5, vl[[1]] + .5}, {0, All}}],
MatrixPlot[iv, Mesh -> All, PlotRangePadding -> 0,
FrameTicks -> {{{{1, Invisible[0.5]}}, None}, {Range[vl[[1]]],
None}}, ImageSize -> 1 -> 50], Style["directions", 16],
EventHandler[Dynamic@MatrixPlot[{dv}, Mesh -> All, PlotRangePadding -> 0,
FrameTicks -> {{{{1, Invisible[0.5]}}, None}, {
Range[vl[[1]]], None}}, ImageSize -> 1 -> 50,
Epilog -> Dynamic[MapIndexed[
Text[Style[#, Large], Reverse@#2 - .5] &, {dv}, {2}]]],
{"MouseClicked" :> With[{p = First@Ceiling@MousePosition["Graphics"]},
m[[p]] = Mod[m[[p]] + 1, 3, -1]]}], Style["simulation", 16],
Row[{ListLinePlot[Transpose@sim, Frame -> True,
FrameTicks -> {{Automatic, None}, { Range[iter[[1]]], None}},
AspectRatio -> Full, ImageSize -> (iter[[1]]/vl[[1]]) -> 50,
PlotRange -> {{.5, iter[[1]] + 1}, All}],
TableForm[sim, TableHeadings -> {Range[iter[[1]]], Range[vl[[1]]]}]}, Spacer[10]]}],
{{seed, 1, "seed"}, 1, 100, 1, Manipulator, Appearance -> {"Labeled"}},
{{vl, {5, 10}, "vector Length"}, 1, 20, 1, IntervalSlider[##, Method -> "Stop"] &,
Appearance -> {"Paired", "Labeled"}},
{{iter, {10, 15}, "iterations"}, 1, 50, 1, IntervalSlider[##, Method -> "Stop"] &,
Appearance -> {"Paired", "Labeled"}},
{{ir, {.3, .9}, "inital range"}, 0, 1, IntervalSlider[##, Method -> "Stop"] &,
Appearance -> {"Paired", "Labeled"}},
{{gr, {.1, .3}, "growth range"}, 0, 1, IntervalSlider[##, Method -> "Stop"] &,
Appearance -> {"Paired", "Labeled"}},
{{dr, {-.3, -.05}, "decay range"}, -1, 0, IntervalSlider[##, Method -> "Stop"] &,
Appearance -> {"Paired", "Labeled"}}]]


• Your answer is more than excellent. I do not know how to thank you for this very very useful code. Thank you again. Dec 6, 2019 at 12:12
• When I run DynamicModule, the colored row above showing {-1, 1, 0, -1, 1} becomes {0,0,0,0,0}. Do you think my Mathematica version 11 is the cause or something else? Dec 6, 2019 at 13:12
• I got it! When I click on the colored vector, I get the results. Sorry for this. Dec 6, 2019 at 13:22
• @Tugrul, thank you for the accept.
– kglr
Dec 6, 2019 at 13:45

Starting as you do, let's write:

SeedRandom[123];
list1 = RandomReal[{0.3, 0.8}, 4]


which produces

{0.52786, 0.788913, 0.771607, 0.781108}


Next, we want to increase each of these a small amount. You could do this:

smallRange = {0.05, 0.1};
list2 = list1 + RandomReal[smallRange, 4]


My session produces

{0.592977, 0.862248, 0.824689, 0.85039}


Next, only increase some of the numbers in the list by a small amount

list3 = list2 + RandomInteger[{0, 1}, 4]*RandomReal[smallRange, 4]


which results in

{0.644909, 0.930171, 0.896649, 0.85039}


If you need help turning these fragments into a neat function then

• clarify your requirements, as I expect I have missed some of the fine detail (eg which elements are not to increase - selected ones or random as I have assumed); and

Here's a few pieces of the puzzle. To generate monotonic sequences of "random" numbers:

Accumulate[RandomReal[{0, 0.1}, 10]
{0.0669849, 0.0935961, 0.141986, 0.216063, 0.238291,
0.255048, 0.269631, 0.276363, 0.284295, 0.329844}


Now let's say you have a vector x and you want the first few to go up a tiny bit and the rest to go down. Specify the direction using the vector dir

x = RandomInteger[{0, 10}, 10];
dir = Flatten@{ConstantArray[1, 4], ConstantArray[-1, 6]};

ran = dir RandomReal[{0, 0.1}, 10];
x+ran
`

Now x+ran is a perturbed vector of the same kind as x, but with the first four perturbed up and the rest perturbed down. To have some remain unchanged, set the corresponding elements of dir to zero.

• Thanks for useful few pieces of the puzzle. The function described in the question requires the representation of all the pieces together in a functional form. The problem lies in the "repeated" generation of a ready-to-use set random numbers in a system of equations to assess the slope change in some variables. Dec 5, 2019 at 23:46