Gforth random generator has no seed - random

The following program in gforth prints out 10 random numbers between 0 and 2:
require random.fs
: main 10 0 do i cr . 3 random . loop ;
main
The problem is, that after each start, the numbers are the same. That means no time(0) seed was used. How can i get random numbers which are different on each start?

In the GPL-licensed source file random.fs:
Variable seed
$10450405 Constant generator
: rnd ( -- n ) seed # generator um* drop 1+ dup seed ! ;
: random ( n -- 0..n-1 ) rnd um* nip ;
To grab a random number you can seed the variable seed with a line, perhaps like this:
utime drop seed !
However I'm no cryptographer, but I'm under the impression seeding with the current time isn't cryptographically secure. I wouldn't use this in any production code.

Related

Random Generator in OpenCL?

Since there is no built-in random function in OpenCL (not that I know of, please correct me if this is not true). To generate a random list that put into kernel will not work for the purpose of my work. It has to be a random generator running on GPU (kernel). I intended to write my own function that generate random number in the range from 0 to 1. The code below is what i have run on CPU, and it seem to work well.
array_of_random_numbers = [0.0] * N
seed = 19073486328125
multiplier = 19073486328125
adder = 0
random_number = 19073486328125
modulus = 2**48.0
RAND_MAX = 2**48.0
for i in range( 0 , (N-1) ):
random_number = (multiplier * random_number + adder ) % (modulus)
print(multiplier * random_number)
array_of_random_numbers[i] = (random_number / RAND_MAX)
However, I have hard time migrate the code to kernel since I cannot set the random_number in a loop and let it change over iterations.
kernel = """__kernel void get_new_rand(__global float* c)
{
random_number = (19073486328125 * 19073486328125 + 0) % (281474976710656);
c[thread_id] = (random_number / 281474976710656.0);
}"""
Is there a way I can write the random generator on kernel?
Thank you in advance!
I intended to write my own function that generate random number in the range from 0 to 1. The code below is what i have run on CPU, and it seem to work well. However, I have hard time migrate the code to kernel since I cannot set the random_number in a loop and let it change over iterations.
The simplest approach is to use a linear congruence generator function (like you already have), that takes in a seed value and outputs a pseudo-random number that can be normalized to the range [0,1[. The remaining problem is how to get the seed.
Solution: you can pass a seed value as a global parameter from the host side, and change the seed value for every call of the kernel on the host side. This does not have any performance impact. Finally, to get different seeds for the different GPU threads, add the global ID to the seed passed over from the host before calling the LCG function.
This way you don't need any array of numbers stored. Also you have full control over the seed value on the host side, and it all remains fully deterministic.

Random numbers generated show periodicity

I am trying to generate a sequence of random numbers $\xi_i$ uniformly distributed in [0,1] using the built-in functions in Fortran. The sequence has to be reproducible so I want to seed the random number generator by the index $i$ (that is the position of $\xi_i$ in the sequence) rather than using the system clock for the seed. Below is my code:
module rand
contains
function generate_random(iseed) result(xi1)
!!
implicit none
integer, intent(in) :: iseed
integer, dimension(:), allocatable :: seed
integer :: i, j, n
real :: xi1
!!-generate a seed first
call random_seed(size = n)
allocate(seed(n))
seed = iseed * (/(i, i=1,n,1)/)
call random_seed(PUT = seed)
deallocate(seed)
call random_number(xi1)
!!
end function generate_random
end module rand
program test
use rand
implicit none
integer :: i, imax
imax=100
do i=1,imax
print *, generate_random(i)
enddo
end program test
However the result of this shown in the plot where $\xi_i$ is plotted vs. the index $i$ clearly has some pattern, so it is not so random after all. How to improve this, i.e., to make it "more random"?
I see you are seeding the generator before every call to random_number. This is a clear abuse and you are not supposed to do that!
You should seed the generator just once using some repeatable, but not too simple, number. Even when the clock is used as a seed it is used only once.
Often there is an additional step to increase the entropy of your time or your selected repeatable seed value. Notice how lcg() is used to increase entropy of the clock value in https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gfortran/RANDOM_005fSEED.html#RANDOM_005fSEED

How do I use Random generators in elm 0.17 with a user-specified seed?

In Elm 0.17, I'd like to run a program that relies on random numbers, but I'd like to have a user-specified seed. This is to have reproducible results across multiple user sessions: users who enter the same seed should see the same results.
But I can't figure out how to affect the behavior of built-in functions like:
Random.list 10 (Random.int 0 100)
With a call like the one above, I want to get the same list of 10 random numbers each time I feed in the same seed. But I can't figure out how to feed in a seed at all. I'd appreciate any help!
Overview
Generating a random value with Random, using user-specified seed is possible with Random.step
You need to specify a Generator and a Seed, where Generator a is a function to produce random values of a type, using integer Seed
To create a Seed from integer, you need to use Random.initialSeed function, since Seed is not a plain integer, it's a data-structure containing meta-information for the the next steps of the Generator
Random.step
Generator a -> Seed -> (a, Seed)
Calling Random.step will return a new state (a, Seed), where a is your random value, and Seed is the seed, required for generating the next random value.
Example
I have made a comprehensive example, which shows how to use generator for producing random values: Random value with user-specified seed
The example might be too big for the answer so I will highlight the most important parts:
Create a generator
generator : Int -> Generator (List Int)
generator length =
Random.list length (Random.int 0 100)
Step through generator
The seed might be specified through user input, or you can pass it as flags upon start-up.
Random.step (generator 10) seed
The expression that you specified returns a Generator. The function that generates random values is step which takes as arguments a Generator and a Seed. A Seed can be created with the function initialSeed which takes an Int that can be specified by the user as argument.
The same argument to initialSeed will result in the same Seed as output which will result in the same List of random Int values each time. The function below illustrates this.
randomSequence : Int -> List Int
randomSequence int =
let gen = Random.list 10 (Random.int 0 100)
s = initialSeed int
(res, ns) = step gen s
in res

Reading and Printing a random number

I have the following program and below the program an input data file, which contains 10 lines of different data. I want to read this data randomly not sequentially, for example, it will maybe read line 3 then maybe line 5, not like number 1 2 3 4... Then these numbers I want to print randomly.
program rand
implicit none
integer::i, ok
real(kind=8) , allocatable , dimension(:):: s
integer, parameter:: nstep = 1, natom = 10
integer:: seed, rand
open(unit=2,file="fort.2",status="old",action="read")
allocate(s(natom),stat=ok)
if(ok/=0)then
print*,"problem allocating position array"
end if
do i=1,natom
read(2,*)s(i)
print*,i=(rand(seed))
end do
end program rand
Input file:
1.004624
1.008447
1.028897
1.001287
0.9994195
1.036111
0.9829285
1.029622
1.005867
0.9372157
As suggested by #IanBush in a comment, and also by #Sazzad in his answer, a reasonable approach is to read the whole file into an array as your program is already doing. However, simply shuffing does not seem to me to lead to a random printing. It is just a new order. That is the reason while I am proposing this solution.
Random means that the same number can be printed many times while other are not printed at all, if the number of print is limited. And as I can see your problem is how to select randomly. Since you show some effort, here is a modified version of your program
program rand
implicit none
integer::i, ok, idx
real(kind=8) , allocatable , dimension(:):: s
integer, parameter:: nstep = 1, natom = 10
integer:: seed!, rand
real(kind = 8) :: randNum
!
!
open(unit=2,file="fort.2",status="old",action="read")
!
!
allocate(s(natom),stat=ok)
if(ok/=0)then
print*,"problem allocating position array"
end if
!
do i=1,natom
read(2,*)s(i)
!print*,i=(rand(seed))
end do
!
CALL random_seed() ! Initialize a pseudo-random number sequence
! to the default state. For serious program, do not use the default
! use for example the program on the website of gnu fortran
! https://gcc.gnu.org/onlinedocs/gfortran/RANDOM_005fSEED.html
!
do i=1,natom !you can and should change natom here to something else
CALL random_number(randNum)
idx = int(randNum*natom) + 1
print*,'element at ',idx,': ', s(idx)
end do
end program rand
This difference is that the printing is commented in your original program and there is a new loop to print randomly. You will see that some numbers will be printed more than once. To give each number a chance to be printed, you should set a large number of iteration inf the printing loop.
In this answer, I used the default seed for the random number which is not a good idea. On the web site of gnu fortran ( link ) you can find a good approach of initializing the random seed. It is a good programming habit if the reproducibility is not a concern.
General algorithm looks like,
Read all or N lines from file in lines[N]
Create an array index[N] = {1, 2, ... N}
Shuffle index array with simple shuffle algorithms
Traverse index[i] for each i up to size and output line[i]
You have to convert it in your language yourself

working of rand in perl

How does the value produced by rand function depends on it seed value.When we do not define any seed then how does its values differ.
Below is a code that i found for generating numbers for an integer array can any one please explain :
#!/usr/bin/perl -w
# Linear search of an array
# Note that if you later on want to search for something from a
# list of values, you shouldn’t have used an array in the first
# place.
# Generating 10 integers
$NUM = 10;
$MAXINT = 100; # 1 + the maximum integer generated
srand(); # initialize the randomize seed
print "Numbers Generated:\n(";
for $i (1 .. $NUM) {
push #array, sprintf("%d", rand(1) * $MAXINT);
print $array[$i-1];
print ", " unless ($i == $NUM);
}
print ")\n\n";
You don't need to explicitly call srand; it will be implicitly done for you the first time you call rand if you haven't previously called srand.
srand with no parameters will try to initialize the random number generator to a, err, random state. It uses /dev/urandom or the like if available and otherwise falls back on a value calculated from the current time and pid.
rand() with no parameters returns a floating point value between 0 (inclusive) and 1 (exclusive). Multiplying that by some integer number gives a floating point value from >= 0 and < that integer. Using that in integer context (such as a '%d' format value) gives you an integer from 0 to one less than your multiplier. rand(x), for x other than 0, returns the same range of random numbers that x * rand() would have. So rand(1) is equivalent to just rand(), and rand(1) * $MAXINT could have just been rand($MAXINT).
As far as I know perl uses the pseudo-random number generation functions of the standard C library.
It may depend on the implementation but it usually is a Linear Congruential Generator. This kind of PRNG uses its previous value to generate the next, therefore it will need a start value aka the seed.
The value of initializing with a selected seed is, that you get the same pseudo-random numbers. In that way you can keep some random based calculations repeatable, eg. how different alogrithms performs on a fixed set.

Resources