diff --git a/mathics/builtin/numbers/randomnumbers.py b/mathics/builtin/numbers/randomnumbers.py index d49405d7a..100da9b1e 100644 --- a/mathics/builtin/numbers/randomnumbers.py +++ b/mathics/builtin/numbers/randomnumbers.py @@ -101,43 +101,6 @@ def randchoice(self, n, size, replace, p): return numpy.random.choice(n, size=size, replace=replace, p=p) -class RandomState(Builtin): - """ - :WMA: https://reference.wolfram.com/language/ref/RandomState.html -
-
'$RandomState' -
is a long number representing the internal state of the \ - pseudo-random number generator. -
- - >> Mod[$RandomState, 10^100] - = ... - >> IntegerLength[$RandomState] - = ... - - So far, it is not possible to assign values to '$RandomState'. - >> $RandomState = 42 - : It is not possible to change the random state. - = 42 - Not even to its own value: - >> $RandomState = $RandomState; - : It is not possible to change the random state. - """ - - name = "$RandomState" - messages = { - "rndst": "It is not possible to change the random state.", - # "`1` is not a valid random state.", - } - summary_text = "internal state of the (pseudo)random number generator" - - def eval(self, evaluation): - "$RandomState" - - with RandomEnv(evaluation): - return Integer(get_random_state()) - - class _RandomBase(Builtin): messages = { "array": ( @@ -168,16 +131,22 @@ def _size_to_python(self, domain, size, evaluation): class _RandomSelection(_RandomBase): - # implementation note: weights are clipped to numpy floats. this might be different from MMA - # where weights might be handled with full dynamic precision support through the whole computation. - # we try to limit the error by normalizing weights with full precision, and then clipping to float. - # since weights are probabilities into a finite set, this should not make a difference. + # Implementation note: weights are clipped to numpy floats. this + # might be different from MMA where weights might be handled with + # full dynamic precision support through the whole computation. + # we try to limit the error by normalizing weights with full + # precision, and then clipping to float. since weights are + # probabilities into a finite set, this should not make a + # difference. messages = { - "wghtv": "The weights on the left-hand side of `1` has to be a list of non-negative numbers " - + "with the same length as the list of items on the right-hand side.", - "lrwl": "`1` has to be a list of items or a rule of the form weights -> choices.", - "smplen": "RandomSample cannot choose `1` samples, as this are more samples than there are in `2`. " + "wghtv": "The weights on the left-hand side of `1` has to be a list of " + "non-negative numbers with the same length as the list of items " + "on the right-hand side.", + "lrwl": "`1` has to be a list of items or a rule of the form " + "weights -> choices.", + "smplen": "RandomSample cannot choose `1` samples, as this are more samples " + "than there are in `2`. " + "Use RandomChoice to choose items from a set with replacing.", } @@ -249,7 +218,7 @@ def _weights_to_python(self, weights, evaluation): class Random(Builtin): """ - :WMA: + :WMA link: https://reference.wolfram.com/language/ref/Random.html
'Random[]' @@ -280,18 +249,81 @@ class Random(Builtin): summary_text = "pick a random number" +class RandomChoice(_RandomSelection): + """ + + :WMA link: + https://reference.wolfram.com/language/ref/RandomChoice.html + +
+ +
'RandomChoice[$items$]' +
randomly picks one item from $items$. + +
'RandomChoice[$items$, $n$]' +
randomly picks $n$ items from $items$. Each pick in the $n$ picks happens \ + from the given set of $items$, so each item can be picked any number of times. + +
'RandomChoice[$items$, {$n1$, $n2$, ...}]' +
randomly picks items from $items$ and arranges the picked items in the \ + nested list structure described by {$n1$, $n2$, ...}. + +
'RandomChoice[$weights$ -> $items$, $n$]' +
randomly picks $n$ items from $items$ and uses the corresponding numeric \ + values in $weights$ to determine how probable it is for each item in $items$ \ + to get picked (in the long run, items with higher weights will get picked \ + more often than ones with lower weight). + +
'RandomChoice[$weights$ -> $items$]' +
randomly picks one items from $items$ using weights $weights$. + +
'RandomChoice[$weights$ -> $items$, {$n1$, $n2$, ...}]' +
randomly picks a structured list of items from $items$ using weights \ + $weights$. +
+ + Note: 'SeedRandom' is used below so we get repeatable "random" numbers that we \ + can test. + + >> SeedRandom[42] + >> RandomChoice[{a, b, c}] + = {c} + >> SeedRandom[42] (* Set for repeatable randomness *) + >> RandomChoice[{a, b, c}, 20] + = {c, a, c, c, a, a, c, b, c, c, c, c, a, c, b, a, b, b, b, b} + >> SeedRandom[42] + >> RandomChoice[{"a", {1, 2}, x, {}}, 10] + = {x, {}, a, x, x, {}, a, a, x, {1, 2}} + >> SeedRandom[42] + >> RandomChoice[{a, b, c}, {5, 2}] + = {{c, a}, {c, c}, {a, a}, {c, b}, {c, c}} + >> SeedRandom[42] + >> RandomChoice[{1, 100, 5} -> {a, b, c}, 20] + = {b, b, b, b, b, b, b, b, b, b, b, c, b, b, b, b, b, b, b, b} + """ + + _replace = True + summary_text = "pick items randomly from a given list" + + class RandomComplex(Builtin): """ - :WMA: https://reference.wolfram.com/language/ref/RandomComplex.html) + + :WMA link: + https://reference.wolfram.com/language/ref/RandomComplex.html +
'RandomComplex[{$z_min$, $z_max$}]' -
yields a pseudorandom complex number in the rectangle with complex corners $z_min$ and $z_max$. +
yields a pseudorandom complex number in the rectangle with complex corners \ + $z_min$ and $z_max$.
'RandomComplex[$z_max$]' -
yields a pseudorandom complex number in the rectangle with corners at the origin and at $z_max$. +
yields a pseudorandom complex number in the rectangle with corners at the \ + origin and at $z_max$.
'RandomComplex[]' -
yields a pseudorandom complex number with real and imaginary parts from 0 to 1. +
yields a pseudorandom complex number with real and imaginary parts from 0 \ + to 1.
'RandomComplex[$range$, $n$]'
gives a list of $n$ pseudorandom complex numbers. @@ -407,7 +439,9 @@ def eval_list(self, zmin, zmax, ns, evaluation): class RandomInteger(Builtin): """ - :WMA: https://reference.wolfram.com/language/ref/RandomInteger.html) + + :WMA link: + https://reference.wolfram.com/language/ref/RandomInteger.html
'RandomInteger[{$min$, $max$}]'
yields a pseudorandom integer in the range from $min$ to \ @@ -485,7 +519,10 @@ def eval_list(self, rmin, rmax, ns, evaluation): class RandomReal(Builtin): """ - :WMA: https://reference.wolfram.com/language/ref/RandomReal.html) + + :WMA link: + https://reference.wolfram.com/language/ref/RandomReal.html +
'RandomReal[{$min$, $max$}]'
yields a pseudorandom real number in the range from $min$ to $max$. @@ -581,9 +618,49 @@ def eval_list(self, xmin, xmax, ns, evaluation): ) +class RandomState(Builtin): + """ + :WMA link: + https://reference.wolfram.com/language/ref/RandomState.html +
+
'$RandomState' +
is a long number representing the internal state of the \ + pseudo-random number generator. +
+ + >> Mod[$RandomState, 10^100] + = ... + >> IntegerLength[$RandomState] + = ... + + So far, it is not possible to assign values to '$RandomState'. + >> $RandomState = 42 + : It is not possible to change the random state. + = 42 + Not even to its own value: + >> $RandomState = $RandomState; + : It is not possible to change the random state. + """ + + name = "$RandomState" + messages = { + "rndst": "It is not possible to change the random state.", + # "`1` is not a valid random state.", + } + summary_text = "internal state of the (pseudo)random number generator" + + def eval(self, evaluation): + "$RandomState" + + with RandomEnv(evaluation): + return Integer(get_random_state()) + + class SeedRandom(Builtin): """ - :WMA: https://reference.wolfram.com/language/ref/SeedRandom.html) + + :WMA link: + https://reference.wolfram.com/language/ref/SeedRandom.html
'SeedRandom[$n$]'
resets the pseudorandom generator with seed $n$. @@ -651,94 +728,39 @@ def eval_empty(self, evaluation): return SymbolNull -# If numpy is not in the system, the following classes are going to be redefined as None. flake8 complains about this. -# What should happen here is that, or the classes be defined just if numpy is there, or to use a fallback native -# implementation. - - -class RandomChoice(_RandomSelection): - """ - :WMA: https://reference.wolfram.com/language/ref/RandomChoice.html - -
- -
'RandomChoice[$items$]' -
randomly picks one item from $items$. - -
'RandomChoice[$items$, $n$]' -
randomly picks $n$ items from $items$. Each pick in the $n$ picks happens from the \ - given set of $items$, so each item can be picked any number of times. - -
'RandomChoice[$items$, {$n1$, $n2$, ...}]' -
randomly picks items from $items$ and arranges the picked items in the nested list \ - structure described by {$n1$, $n2$, ...}. - -
'RandomChoice[$weights$ -> $items$, $n$]' -
randomly picks $n$ items from $items$ and uses the corresponding numeric values in \ - $weights$ to determine how probable it is for each item in $items$ to get picked (in the \ - long run, items with higher weights will get picked more often than ones with lower weight). - -
'RandomChoice[$weights$ -> $items$]' -
randomly picks one items from $items$ using weights $weights$. - -
'RandomChoice[$weights$ -> $items$, {$n1$, $n2$, ...}]' -
randomly picks a structured list of items from $items$ using weights $weights$. -
- - Note: 'SeedRandom' is used below so we get repeatable "random" numbers that we can test. - - >> SeedRandom[42] - >> RandomChoice[{a, b, c}] - = {c} - >> SeedRandom[42] (* Set for repeatable randomness *) - >> RandomChoice[{a, b, c}, 20] - = {c, a, c, c, a, a, c, b, c, c, c, c, a, c, b, a, b, b, b, b} - >> SeedRandom[42] - >> RandomChoice[{"a", {1, 2}, x, {}}, 10] - = {x, {}, a, x, x, {}, a, a, x, {1, 2}} - >> SeedRandom[42] - >> RandomChoice[{a, b, c}, {5, 2}] - = {{c, a}, {c, c}, {a, a}, {c, b}, {c, c}} - >> SeedRandom[42] - >> RandomChoice[{1, 100, 5} -> {a, b, c}, 20] - = {b, b, b, b, b, b, b, b, b, b, b, c, b, b, b, b, b, b, b, b} - """ - - _replace = True - summary_text = "pick items randomly from a given list" - - class RandomSample(_RandomSelection): """ - :WMA: https://reference.wolfram.com/language/ref/RandomSample.html + :WMA link: + https://reference.wolfram.com/language/ref/RandomSample.html
'RandomSample[$items$]'
randomly picks one item from $items$.
'RandomSample[$items$, $n$]' -
randomly picks $n$ items from $items$. Each pick in the $n$ picks happens after the \ - previous items picked have been removed from $items$, so each item can be picked at most \ - once. +
randomly picks $n$ items from $items$. Each pick in the $n$ picks happens \ + after the previous items picked have been removed from $items$, so each item \ + can be picked at most once.
'RandomSample[$items$, {$n1$, $n2$, ...}]' -
randomly picks items from $items$ and arranges the picked items in the nested list \ - structure described by {$n1$, $n2$, ...}. \ +
randomly picks items from $items$ and arranges the picked items in the \ + nested list structure described by {$n1$, $n2$, ...}. \ Each item gets picked at most once.
'RandomSample[$weights$ -> $items$, $n$]' -
randomly picks $n$ items from $items$ and uses the corresponding numeric values in \ - $weights$ to determine how probable it is for each item in $items$ to get picked (in the \ - long run, items with higher weights will get picked more often than ones with lower weight). \ - Each item gets picked at most once. +
randomly picks $n$ items from $items$ and uses the corresponding numeric \ + values in $weights$ to determine how probable it is for each item in $items$ \ + to get picked (in the long run, items with higher weights will get \ + picked more often than ones with lower weight). Each item gets picked at\ + most once.
'RandomSample[$weights$ -> $items$]'
randomly picks one items from $items$ using weights $weights$. \ Each item gets picked at most once.
'RandomSample[$weights$ -> $items$, {$n1$, $n2$, ...}]' -
randomly picks a structured list of items from $items$ using weights $weights$. Each \ - item gets picked at most once. +
randomly picks a structured list of items from $items$ using weights $weights$. + Each item gets picked at most once.
>> SeedRandom[42]