Clear Filters
Clear Filters

Generate normal distribution with LGC random issue

3 views (last 30 days)
hi as you can see im trying to compere values btween my function randi and built in function rand but i can't find a way to make myrandi plot normal distribution plot
clc
%N=input('sequence_length')
N=5000
N = 5000
la=65539
la = 65539
MinSec = fix(clock);
seed = 100*(MinSec(5) + MinSec(6));
Urand = myrandi(seed,N);
subplot(3,2,1)
hist(Urand)
%% Task 1: : the Linear Congruential Generator (LCG)
v = rand(1,N);
%u=u./max(u);
subplot(3,2,2);
hist(v,100);
title(subplot(3,2,2),'Uniform random: rand()');
%% Task 2: Generate exponential distribution with LGC random
u=myrandi(seed,N);
e=-log(1-u)./la;
subplot(3,2,3);
hist(e,100);
title(subplot(3,2,3),'Exponential random: myrand()');
%% Task 2: Generate exponential distribution with rand() random
u=rand(1,N);
f=-log(1-u)./la;
subplot(3,2,4);
hist(f,100);
title(subplot(3,2,4),'Exponential random: rand()');
%% Task 2: Generate normal distribution with LGC random
u1 = myrandi(seed,N);
u2 = myrandi(seed,N);
a = (-2*log(u1));
b = 2*pi*u2;
n = sqrt(a.*sin(b));
m = real(sqrt(a).*cos(b));
M = mean(m,'all'); %mean
s = std(m); %standard deaviation
T = normrnd(M, s);
subplot(3,2,5);
hist(T);
title(subplot(3,2,5),'Normal random: myrand()');
%% Task 2: Generate normal distribution with rand() function
u1 = rand(1,N);
u2 = rand(1,N);
a = (-2*log(u1)).^.5;
b = 2*pi*u2;
p = real(a.*sin(b));%p and q are both
q = real(a.*cos(b));%normal random variables
subplot(3,2,6);
hist(q,100);
title(subplot(3,2,6),'Normal random: rand()');
%Function that produce an uniform random numbers
%Using the technic of LCG r(k) = [lambda*r(k-1)]modulo(P)
function Urand = myrandi(seed,sequence_length)
la=65539;
N=sequence_length;
P=2^31;
%change N accordingly
%part a
Urand=zeros(1,N);
seed(1)=seed;
for i=2:N
Urand(i)= mod((la*seed*(i-1)),P);
end
Urand = Urand./(P-1);
end

Accepted Answer

John D'Errico
John D'Errico on 14 Oct 2022
Edited: John D'Errico on 14 Oct 2022
I might check that you REALLY are using the same expressions for both of the transformations to Normal. Have you done so? (STRONG HINT!) Just take a scan through that part of your codes. It popped out at me. I think you should see what you did wrong. (Sorry that I'm only giving you a hint here, but to be honest, it looks like your coding skills should be strong enough that you just missed something obvious. Once you look carefully, comparing the two code segments...)
  9 Comments
Faisal Al-Wazir
Faisal Al-Wazir on 14 Oct 2022
thanks for the cretique, but i'm still not clear on what to do for the 5th plot
John D'Errico
John D'Errico on 14 Oct 2022
That was merely an observation, as to why people stopped using simple LCRNGs like that many, many years ago. They are terrible for multiple reasons. I suppose, possibly, this may be why you are having a problem. But let me now look carefully at the algorithm, making sure you are doing the correct thing in that code.
A quick check shows you are using the Box-Muller method to generate normal deviates.
So if u1 and u2 are uniform deviartes on (0,1), then we expect that
sqrt(-2*log(u1))*cos(2*pi*u2)
is a normally distributed random variable, as is also
sqrt(-2*log(u1))*sin(2*pi*u2)
We can test that...
N = 1000000;
u1 = rand(1,N);
u2 = rand(1,N);
r = sqrt(-2*log(u1)).*cos(2*pi*u2);
hist(r,1000,'norm','pdf')
It looks reasonable to me.
Now we can try your RNG.
MinSec = fix(clock);
seed = 100*(MinSec(5) + MinSec(6))
seed = 5600
U1 = myrandi(seed,N);
U2 = myrandi(seed,N);
r = sqrt(-2*log(U1)).*cos(2*pi*U2);
hist(r,1000,'norm','pdf')
And it looks like warmed up crapola on a shingle. ;-)
So what did you do? I see you used the same starting seed for BOTH CASES, so both U1 and U2!!!! This means U1 and U2 will be the same sequence of numbers. For example,
U1 = myrandi(seed,10)
U1 = 1×10
0 0.1709 0.3418 0.5127 0.6836 0.8545 0.0254 0.1963 0.3673 0.5382
U2 = myrandi(seed,10)
U2 = 1×10
0 0.1709 0.3418 0.5127 0.6836 0.8545 0.0254 0.1963 0.3673 0.5382
So what you wrote has U1 and U2 as completely correlated sequences. Even if they really were even poorly generated pseudo-random numbers, they don't qualify for the Box-Muller transformation to Normal.
At the very least, you need to use DIFFERENT starting seeds for each sequence. So now let me try it with at least ifferent seeds. I'm too lazy to use anything intelligent to come up with two distinct seeds, so I'll just try one sequence, then split it into two sequences.
U1 = myrandi(seed,2*N);
U2 = U1(1:2:end);
U1 = U1(2:2:end);
r = sqrt(-2*log(U1)).*cos(2*pi*U2);
hist(r,1000,'norm','pdf')
And yet worse crapola, but do you see the pattern developing? This may be getting into the issue of the poorness of that RNG, as not truly very random. So, next, let me look at the RNG code you wrote. I'll do this in another comment.
function Urand = myrandi(seed,sequence_length)
la=65539;
N=sequence_length;
P=2^31;
%change N accordingly
%part a
Urand=zeros(1,N);
seed(1)=seed;
for i=2:N
Urand(i)= mod((la*seed*(i-1)),P);
end
Urand = Urand./(P-1);
end

Sign in to comment.

More Answers (1)

John D'Errico
John D'Errico on 14 Oct 2022
After looking at your code in my other answer, the problem clearly reduces to your RNG. Is that even a valid linear congruential RNG? GOD NO! For example, I'll use a simple starting seed to show what is happening.
seed = 1000;
myrandi(seed,10)
ans = 1×10
0 0.0305 0.0610 0.0916 0.1221 0.1526 0.1831 0.2136 0.2442 0.2747
Do you see that each such random number is just a multiple of the first one, and that it starts out at 0? We could have gotten the same result from linspace. You had this:
Urand(i)= mod((la*seed*(i-1)),P);
Effectively, you have not much more than a call to linspace, at least for the first few thousand random numbers you generated. And even after that, it is not much different.
Was that really your plan? Were you directed to write the RNG like that?
Try out this generator.
myslightlybetterrand(seed,10)
ans = 1×10
0.0305 0.1831 0.8240 0.2959 0.3597 0.4950 0.7322 0.9386 0.0416 0.8024
Do you see these already look now more random?
histogram(myslightlybetterrand(seed,100000),1000,'norm','pdf')
And again, this is starting to look more random. Still a completely crappy RNG, as I could surely show with some effort.
N = 1000000;
seed1 = 56554;
seed2 = 343453;
u1 = myslightlybetterrand(seed1,N);
u2 = myslightlybetterrand(seed2,N);
r = sqrt(-2*log(u1)).*cos(2*pi*u2);
hist(r,1000,'norm','pdf')
And that works. Your problem was in the basic RNG.
function Seq = myslightlybetterrand(seed,N)
Seq = zeros(1,N);
% don't use the seed as the first element of your sequence.
% make it effectively the 0'th element instead.
Seq0 = seed;
la = 65539;
P = 2^31;
for n = 1:N
Seq0 = mod(Seq0*la,P);
Seq(n) = Seq0;
end
Seq = Seq/(P-1);
end
function Urand = myrandi(seed,sequence_length)
la=65539;
N=sequence_length;
P=2^31;
%change N accordingly
%part a
Urand=zeros(1,N);
seed(1)=seed;
for i=2:N
Urand(i)= mod((la*seed*(i-1)),P);
end
Urand = Urand./(P-1);
end
  2 Comments
Faisal Al-Wazir
Faisal Al-Wazir on 14 Oct 2022
Were you directed to write the RNG like that?
the answer is yes there are a lot of things that the dr instructs us to not change in this code.
thank you so much john I learned a lot from you today I hope you have a wonderful day
John D'Errico
John D'Errico on 14 Oct 2022
Ok then. I was wondering just a wee bit about that. What you cannot control... :)

Sign in to comment.

Categories

Find more on Random Number Generation in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!