How can we create random numbers without using any function rand in matlab? - matlab

b=round(rand(1,20));
Instead of using the function rand, I would like to know how to create such series.

This is a very interesting question. Actually, the easiest way to go, in my opinion is to use a Linear-feedback Shift Register. You can find plenty of examples and implementations googling around (here is one coming from another SO question).
Here is a quick Matlab demo based on this code:
b = lfsr(20)
function r = lfsr(size)
persistent state;
if (isempty(state))
state = uint32(1);
end
if (nargin < 1)
size = 1;
end
r = zeros(size,1);
for i = 1:size
r(i) = bitand(state,uint32(1));
if (bitand(state,uint32(1)))
state = bitxor(bitshift(state,-1),uint32(142));
else
state = bitshift(state,-1);
end
end
end

Related

matlab random number generation in parfor loop

I want to generate same normal random numbers for loop and parfor loop. Following MATLAB documentation I tried three different method:
Method 1: Using rng(seed, 'twister')
N = 1;
for ind = 1:10
rng(ind, 'twister')
samps(ind) = normrnd(0,1,N,1);
end
plot(samps); hold on
parfor ind = 1:10
rng(ind, 'twister')
samps(ind) = normrnd(0,1,N,1);
end
scatter(1:length(samps), samps)
legend({'using for loop', 'using parfor loop'})
Method 2: Using RandStream Method
N = 1;
sc = parallel.pool.Constant(RandStream('Threefry'));
for ind = 1:10
stream = sc.Value;
stream.Substream = ind;
samps(ind) = normrnd(0,1,N,1);
end
plot(samps); hold on
sc = parallel.pool.Constant(RandStream('Threefry'));
parfor ind = 1:10
stream = sc.Value;
stream.Substream = ind;
samps(ind) = normrnd(0,1,N,1);
end
scatter(1:length(samps), samps)
legend({'using for loop', 'using parfor loop'})
Method 3: Using another RandStream method
N = 1;
stream = RandStream('mrg32k3a');
for ind = 1:10
stream.Substream = ind;
samps(ind) = normrnd(0,1,N,1);
end
plot(samps); hold on
stream = RandStream('mrg32k3a');
parfor ind = 1:10
set(stream,'Substream',ind);
samps(ind) = normrnd(0,1,N,1);
end
scatter(1:length(samps), samps)
legend({'using for loop', 'using parfor loop'})
My question is why the last two methods are not working. If I understood MATLAB documentation correctly, they should have worked. Also, is there anything wrong with using rng(seed, 'twister') method with different seeds to produce statistically independent samples?
Edit:
Here is the link to the MATLAB documentation that I used.
As #Cris points out, normrnd uses the current global stream. Here's how to make your 3rd case match between client and workers - you need to set the global stream explicitly. (Note that I'm reverting the global stream immediately after using it too).
N = 1;
stream = RandStream('mrg32k3a');
for ind = 1:10
stream.Substream = ind;
prev = RandStream.setGlobalStream(stream);
samps(ind) = normrnd(0,1,N,1);
RandStream.setGlobalStream(prev);
end
stream = RandStream('mrg32k3a');
parfor ind = 1:10
set(stream,'Substream',ind);
prev = RandStream.setGlobalStream(stream);
pf_samps(ind) = normrnd(0,1,N,1);
RandStream.setGlobalStream(prev);
end
With this code, samps and pf_samps are identical.
Also, you should not use "twister" in parallel, since the random samples you obtain by setting the seed in this way will not have as good qualities as if you use a "parallel" generator like mrg32k3a. (I'm no expert, but my understanding is that the twister "seed" values are not able to select statistically-independent sequences of samples in the way that streams/substreams can)
In recent versions of MATLAB, faster generators that support multiple streams are available. See the doc https://www.mathworks.com/help/matlab/math/creating-and-controlling-a-random-number-stream.html#brvku_2 . Philox and Threefry in particular are good parallel generators.
I'm inferring that your concern is that the pseudorandomly generated numbers for your for and parfor loops did not match. This is however expected behavior. You used a MRG32K3A pseudorandom algorithm, which "does not make a guarantee that a fixed seed and a fixed series of calls to mrg32k3a.RandomState methods using the same parameters will always produce the same results." Source.
So it appears that everything is working correctly.
When you do normrnd(0,1,N,1), you are not using stream to generate a random number, but rather the default RNG. Instead, use randn(stream,N,1), see the documentation.
As far as I can tell, normrnd and other generators from the Statistics and a Machine Learning toolbox always use the default RNG, and cannot use a custom RandStream object.

Generate random matrix with eigenvalues

I am doing the following to generate random matrices with eigenvalues in a specific range:
function mat = randEig(dim, rReal)
D=diff(rReal).*rand(dim,1)+rReal(1);
P=rand(dim);
mat=P*diag(D)/P;
end
But I also want to be able to generate random real matrices with complex (conjugate) eigenvalues. How would one do that? The similarity transformation trick would return complex matrices.
EDIT: Okay I managed to do it by piggybacking on MATLAB's cdf2rdf function (which is basically the second function below).
function mat = randEig(dim, rangeEig, nComplex)
if 2*nComplex > dim
error('Cannot happen');
end
if nComplex
cMat=diff(rangeEig).*rand(dim-2*nComplex,1)+rangeEig(1);
for k=1:nComplex
rpart=(diff(rangeEig).*rand(1,1)+rangeEig(1))*ones(2,1);
ipart=(diff(rangeEig).*rand(1,1)+rangeEig(1))*i;
ipart=[ipart; -ipart];
cMat=[cMat; rpart+ipart];
end
else
cMat=diff(rangeEig).*rand(dim,1)+rangeEig(1);
end
D=cMat;
realDform = comp2rdf(diag(D));
P=rand(dim);
mat=P*realDform/P;
end
function dd = comp2rdf(d)
i = find(imag(diag(d))');
index = i(1:2:length(i));
if isempty(index)
dd=d;
else
if (max(index)==size(d,1)) | any(conj(d(index,index))~=d(index+1,index+1))
error(message('Complex conjugacy not satisfied'));
end
j = sqrt(-1);
t = eye(length(d));
twobytwo = [1 1;j -j];
for i=index
t(i:i+1,i:i+1) = twobytwo;
end
dd=t*d/t;
end
end
But the code is ugly, mainly the way rand is called multiple times is annoying). If someone wants to post an answer that calls rand once and manages to do the trick I will surely accept and upvote.
I made it either a single call or two calls with this:
function mat = randEig(dim, rangeEig, nComplex)
if 2*nComplex > dim
error('Cannot happen');
end
if nComplex
cMat=diff(rangeEig).*rand(2*nComplex,1)+rangeEig(1);
cPart=cMat(1:nComplex)*i;
cMat(1:nComplex)=[];
cPart=upsample(cPart,2);
cPart=cPart+circshift(-cPart,1);
cMat=upsample(cMat,2);
cMat=cMat+circshift(cMat,1);
cMat=cMat+cPart;
cMat=[diff(rangeEig).*rand(dim-2*nComplex,1)+rangeEig(1); cMat];
else
cMat=diff(rangeEig).*rand(dim,1)+rangeEig(1);
end
D=cMat;
realDform = comp2rdf(diag(D));
P=rand(dim);
mat=P*realDform/P;
end
function dd = comp2rdf(d)
i = find(imag(diag(d))');
index = i(1:2:length(i));
if isempty(index)
dd=d;
else
if (max(index)==size(d,1)) | any(conj(d(index,index))~=d(index+1,index+1))
error(message('Complex conjugacy not satisfied'));
end
j = sqrt(-1);
t = eye(length(d));
twobytwo = [1 1;j -j];
for i=index
t(i:i+1,i:i+1) = twobytwo;
end
dd=t*d/t;
end
end
If someone can make it a single call or shorter/more elegant code they are welcome to post an answer.

How to update a uitable after creation from other functions?

I created a matfile in which I store data that are constantly overwritten by user behavior. This occurs in a function "test()".
n=1
while n < 5
myVal = double(Test704(1, 780, -1)) %Returns the user's behavior
if myVal == 1
n = n + 1 %"n" is the overwritten variable in the matfile
end
save('testSave1.mat') %The matfile
m = matfile('testSave1.mat')
end
Then, I want to display these data in another function (it is essential to have two separated functions) called "storageTest()". More particularly, storageTest() is a GUI function where I developped an uitable "t". So, I first call the function "test()" and give its output values as data of "t". Here is the code of the interesting part of "storageTest":
m = test()
d = [m.n]
t = uitable('Data',d, ...
'ColumnWidth',{50}, ...
'Position',[100 100 461 146]);
t.Position(3) = t.Extent(3);
t.Position(4) = t.Extent(4);
drawnow
This code executes only when "m = test()" running is over and displays me a tab in which I can see the final value of "n". However, I want my table to be displayed before and to see my value incrementing according to user's behavior.
I have searched on the web to solve my issue, but I cannot find any answer, is it possible to do such a thing?
Assuming I'm interpreting the question correctly, it should be fairly trivial to accomplish this if you initialize your table prior to calling test and then pass the handle to your table for test to update in the while loop:
For example:
function testGUI
% Initialize table
t = uitable('ColumnWidth',{50}, 'Position',[100 100 461 146]);
test(t)
function test(t)
n = 1;
while n < 5
n = n + 1;
t.Data = n;
pause(0.25); % Since we're just incrementing a number, a slight so we can actually see the change
end
When you run the above, you'll notice the data in your table iterating as expected.
excaza was a little faster in writing basically the same answer like me. As it looks a slightly different, I'll post it anyway.
function storagetest()
close all
f = figure;
data = [1];
t = uitable(f,'Data',data,'ColumnWidth',{50});
test()
end
function test()
% handle uitable
t = evalin('caller','t')
n = 1;
while n < 5
newVal = input('Enter a number:');
data = get(t,'Data');
set(t,'Data', [data; newVal]);
n = n + 1;
end
end
The "user behaviour" I imitated with the input function. The basic idea is to update your table from within test(). evalin you can use, if you don't want to pass parameters to test(), though passing the handle of the uitable directly is certainly the better option.
If you are working on a serious GUI project I highly recommend you reading this answer.

Get the iteration number inside a MATLAB for loop

Say I have a for loop in MATLAB:
scales = 5:5:95;
for scale = scales
do stuff
end
How can I get the iteration number inside a MATLAB for loop as concisely as possible?
In Python for example I would use:
for idx, item in enumerate(scales):
where idx is the iteration number.
I know that in MATLAB (like in any other language) I could create a count variable:
scales = 5:5:95;
scale_count = 0;
for scale = scales
scale_count = scale_count + 1;
do stuff
end
I could otherwise use find:
scales = 5:5:95;
for scale = scales
scale_count = find(scales == scale);
do stuff
end
But I'm curious to know whether there exists a more concise way to do it, e.g. like in the Python example.
Maybe you can use the following:
scales = 5:5:95;
for iter = 1:length(scales)
scale=scales(iter); % "iter" is the iteration number.
do stuff
end
Since for iterates over the columns of whatever you give it, another way of approximating multiple loop variables would be to use an appropriately constructed matrix:
for scale=[5:5:95; 1:19]
% do stuff with scale(1) or scale(2) as appropriate
end
(my personal preference is to loop over the indices as per Parag's answer and just refer to data(index) directly within the loop, without an intermediate. Matlab's syntax isn't very concise at the best of times - you just get used to it)
The MATLAB way is probably doing it with vectors.
For example suppose you want to find in a vector if there is a value that is equal to its position. You would generally do this:
a = [10 20 1 3 5];
found = 0;
for index = 1:length(a)
if a(index) == index
found = 1;
break;
end
end
Instead you can do:
found = any(a == 1:length(a));
In general
for i=1:length(a)
dostuff(a(i), i);
end
can be replaced with:
dostuff(a(i), 1:length(a))
it dostuff can be vectorized or
arrayfun(#dostuff, a, 1:length(a))
otherwise.

Whats wrong with my function code (MATLAB/OCTAVE)

I am trying to make my program work. It is for prime numbers.
Below is my function then my main program
I believe this is the right formatting, (obviously I'm probably wrong cause its not working) and I have been trying to fix it to no avail. Any help will be most appreciated and an explanation of what I am doing wrong (I am pretty sure it has to do with subtle formatting) would be great too.
function [answer,primefactors ] = primey1 (N)
for i=2:(N-1)
A(i-1)=rem(N,i);
end
A;
if(all(A)==1)
answer=['Yes']
primefactors=[1,N]
elseif(all(A)==0)
answer=['No']
fac=[]
for i=2:N
q=0;
while N/i==floor(N/i)
N=N/i;
q=q+1;
end
if q>0
fac=[fac,i]
if N==1
break
primefactors=[fac]
end
end
end
end
endfunction
As noted by Magla, MATLAB comes with the primes and factor functions, which you can at least use to compare your implementation with and/or check your outcomes.
Anyway, as for your code, try this:
function [answer, primefactors] = primey1(N)
% Use vectorization for simple cases such as these:
A = rem(N,2:N-1);
if all(A)
answer = 'Yes';
primefactors = [1,N];
% Re-wrote this entire section. There were a bunch of things wrong with it:
% the order of commands was wrong, variables were not assigned for some N,
% etc. Just compare the two implementations
else
answer = 'No';
primefactors = [];
for ii = 2:N
q = 0;
while N/ii == floor(N/ii)
N = N/ii;
q = q+1;
end
if q > 0
primefactors = [primefactors,ii]; %#ok<AGROW>
if N==1
break;
end
end
end
end
end
Matlab has a factor function that does what your code is trying to do
p = factor(10)
returns 2, 5
and
p = factor(11)
returns 11.
All you have is to test for length
if length(p) == 1
is true for prime numbers.
The solution as offered by #Rody should do the job, in theory even more efficient than this, however to illustrate the concept of initialization, I would recommend you to initialize the output variables of your function right after the function start. In your case this would mean that I recommend starting the code like this:
function [answer, primefactors] = primey1(N)
% Function to determine whether a number is prime and which prime factors it has
% Assign default values
answer = 'No';
primefactors = [];