I am unable to generate a histogram in Matlab using array
% initialising the five arrays to hold the averages of five probabilities of interests
ar1=zeros(1,100);
ar2=zeros(1,100);
ar3=zeros(1,100);
ar4=zeros(1,100);
ar5=zeros(1,100);
%initialising the variable to count the number of experiments
k=1;
while k<=100,
%generating the required random numbers for the proble
%pi is the probablity in winning the ith game
p1=rand(1);
p2=rand(1)*p1;
p3=rand(1)*p2;
p4=rand(1)*p3;
%initialising variable to count the number of tournaments
count_tour=1;
%initialising the variables in order to get the sum of all probabilties of interests and then we can get our respective averages
t1=0; t2=0; t3=0; t4=0; t5=0;
%starting the loop for 50 tournaments
while count_tour<=50,
%Total probabilties of winning the ith game
W1=p1;
W2=p1*(1+p2-p1);
W3=(p1*p2*p3)+((p1*p1)*(2-p1-p2))+((p4)*(1-p1)*(1-p1));
%probabilty that player had won the first game given that he won the second game
W4=(p1*p2)/W2;
%probabilty of winning all three games
W5=p1*p2*p3;
%getting the sum of all probabilies in 50 tournaments
t1=t1+W1;
t2=t2+W2;
t3=t3+W3;
t4=t4+W4;
t5=t5+W5;
count_tour=count_tour+1;
end
%getting the averages of probabilties of interest in 50 tournaments
av1=t1/50;
av2=t2/50;
av3=t3/50;
av4=t4/50;
av5=t5/50;
ar1(k)=ar1(k)+av1;
ar2(k)=ar2(k)+av2;
ar3(k)=ar3(k)+av3;
ar4(k)=ar4(k)+av4;
ar5(k)=ar5(k)+av5;
k=k+1;
end
figure();
h1=histogram(ar1);
h2=histogram(ar2);
h3=histogram(ar3);
h4=histogram(ar4);
h5=histogram(ar5);
Assuming that the section calculating the arrays ar1, ar2, ar3, ar4, ar5 is correct, and also considering the update proposed in the answer from #EBH, the problem could be in the way you plot the histograms:
you first open a figure
the you call, in sequence, 5 time the functin histogram
This might work for the first histogram, nevertheless, the second one will be plot on the same figure and it will replace the first one; same for the others.
Possible solutions could be:
to have each histogram on a deedicated figure
all the histogram on one figure
In the first case it is sufficient to call figure before each call to histogram.
In the second case you can use the function subplot to create 5 axes in one figure on which to plot the histograms.
In the following, you can find a possible implementation of the proposed approach.
Two flags are used to control the drawing:
same_xy_lim: 1 => set the same xlim, ylim for all the axes
0 => do not modify the xlim, ylim
multi_fig: 1 => plot each histogram in a separate figure
0 => plot all the histograms in a single figure using
subplot
The plotting section of the the script could be updated as follows:
% Define and set the flags to control the drawing mode:
% same_xy_lim: 1 => set the same xlim, ylim for all the axes
% 0 => do not modify the xlim, ylim
% multi_fig: 1 => plot each histogram in a separate figure
% 0 => plot all the histograms in a single figure using
% subplot
same_xy_lim=1;
multi_fig=1;
% figure();
if(multi_fig)
figure
else
subplot(3,2,1)
end
h1=histogram(ar1);
if(same_xy_lim)
xlim([0 1])
ylim([0 100])
end
if(multi_fig)
figure
else
subplot(3,2,2)
end
h2=histogram(ar2);
if(same_xy_lim)
xlim([0 1])
ylim([0 100])
end
if(multi_fig)
figure
else
subplot(3,2,3)
end
h3=histogram(ar3);
if(same_xy_lim)
xlim([0 1])
ylim([0 100])
end
if(multi_fig)
figure
else
subplot(3,2,4)
end
h4=histogram(ar4);
if(same_xy_lim)
xlim([0 1])
ylim([0 100])
end
if(multi_fig)
figure
else
subplot(3,2,5)
end
h5=histogram(ar5);
if(same_xy_lim)
xlim([0 1])
ylim([0 100])
end
This generate, depending on the setting of the above mentioned flags:
All in one figure
One histogram per figure
Hope this helps,
Qapla'
Here is a more correct, simple, readable and working version of your code:
% initialising the five arrays to hold the averages of five probabilities
% of interests
ar = zeros(100,5);
for k = 1:100
% generating the required random numbers for the proble
% pi is the probablity in winning the ith game
p = cumprod(rand(4,1));
% initialising the variables in order to get the sum of all probabilties of interests and then we can get our respective averages
t = zeros(1,5);
% starting the loop for 50 tournaments
for count_tour = 1:50,
% Total probabilties of winning the ith game
W(1) = p(1);
W(2) = p(1)*(1+p(2)-p(1));
W(3) = p(1)*p(2)*p(3)+((p(1)*p(1))*(2-p(1)-p(2)))+((p(4))*(1-p(1))*(1-p(1)));
% probabilty that player had won the first game given that he won the second game
W(4) = (p(1)*p(2))/W(2);
% probabilty of winning all three games
W(5) = p(1)*p(2)*p(3);
% getting the sum of all probabilies in 50 tournaments
t = t+W;
end
% getting the averages of probabilties of interest in 50 tournaments
av = t./50;
ar(k,:)=ar(k,:)+av;
end
figure();
hold on
for k = 1:size(ar,2)
h(k) = histogram(ar(k,:));
end
hold off
Which result in (for example):
In fact, your inner loop is not needed at all, it does nothing, and the outer loop could be eliminated using the element-wise arithmetic, so this code can be shortened to a more efficient and compact version:
% generating the required random numbers for the proble
% pi is the probablity in winning the ith game
p = cumprod(rand(100,4));
% Total probabilties of winning the ith game
W(:,1) = p(:,1);
W(:,2) = p(:,1).*(1+p(:,2)-p(:,1));
W(:,3) = p(:,1).*p(:,2).*p(:,3)+((p(:,1).*p(:,1)).*(2-p(:,1)-p(:,2)))+...
((p(:,4)).*(1-p(:,1)).*(1-p(:,1)));
% probabilty that player had won the first game given that he won the second game
W(:,4) = (p(:,1).*p(:,2))./W(:,2);
% probabilty of winning all three games
W(:,5) = p(:,1).*p(:,2).*p(:,3);
figure();
hold on
for k = 1:size(W,2)
h(k) = histogram(W(k,:));
end
hold off
without changing any computation in your code, just eliminating unnecessary loops and variables.
Related
I am trying to take numbers from two intervals in Julia. The problem is the following,
I am trying to create concentric spheres and I need to generate vectors of dimension equal to 15 filled with numbers taken from each circle. The code is:
rmax = 5
ra = fill(0.0,1,rmax)
for i=1:rmax-1
ra[:,i].=rad/i
ra[:,rmax].= 0
end
for i=1:3
ptset = Any[]
for j=1:200
yt= 0
yt= rand(Truncated(Normal(0, 1), -ra[i], ra[i] ))
if -ra[(i+1)] < yt <= -ra[i] || ra[(i+1)] <= yt < ra[i]
push!(ptset,yt)
if length(ptset) == 15
break
end
end
end
end
Here, I am trying to generate spheres with uniform random numbers inside of each one; In this case, yt is only part of the construction of the numbers inside the sphere.
I would like to generate points in a sphere with radius r0 (ra[:,4] for this case), then points distributed from the edge of the first sphere to the second one wit radius r1 (here ra[:,3]) and so on.
In order to do that, I try to take elements that fulfill one of the two conditions -ra[(i+1)] < yt <= -ra[i]
or ra[(i+1)] <= yt < ra[i], i.e. I would like to generate a vector with positive and negative numbers. I used the operator || but it seems to take only the positive part. I am new in Julia and I am not sure how to take the elements from both parts of the interval. Does anyone has a hit on how to do it?. Thanks in advance
I hope I understood you correctly. First, we need to be able to sample uniformly from an N-dimensional shell with radii r0 and r1:
using Random
using LinearAlgebra: normalize
struct Shell{N}
r0::Float64
r1::Float64
end
Base.eltype(::Type{<:Shell}) = Vector{Float64}
function Random.rand(rng::Random.AbstractRNG, d::Random.SamplerTrivial{Shell{N}}) where {N}
shell = d[]
Δ = shell.r1 - shell.r0
θ = normalize(randn(N)) # uniformly distributed N-dimensional direction of length 1
r = shell.r0 .* θ # scale to a point on the interior of the shell
return r .+ Δ .* θ .* .√rand(N) # add a uniformly random segment between r0 and r1
end
(See here for more info about hooking into Random. You could equally implement a new Distribution, but that's not really necessary.)
Most importantly, a truncated normal will not result in a uniform distribution, but neither will adding a uniform scaling into the right direction: see here for why the square root is necessary (and I hope I got it right; you should check the math once more).
Then we can just create a sequence of shell samples with nested radii:
rmax = 5
rad = 10.0
ra = range(0, rad, length=rmax)
ptset = [rand(Shell{2}(ra[i], ra[i+1]), 15) for i = 1:(rmax - 1)]
(This part I wasn't really sure about, but the point should be clear.)
I want to create an array that has incremental random steps, I've used this simple code.
t_inici=(0:10*rand:100);
The problem is that the random number keeps unchangable between steps. Is there any simple way to change the seed of the random number within each step?
If you have a set number of points, say nPts, then you could do the following
nPts = 10; % Could use 'randi' here for random number of points
lims = [0, 10] % Start and end points
x = rand(1, nPts); % Create random numbers
% Sort and scale x to fit your limits and be ordered
x = diff(lims) * ( sort(x) - min(x) ) / diff(minmax(x)) + lims(1)
This approach always includes your end point, which a 0:dx:10 approach would not necessarily.
If you had some maximum number of points, say nPtsMax, then you could do the following
nPtsMax = 1000; % Max number of points
lims = [0,10]; % Start and end points
% Could do 10* or any other multiplier as in your example in front of 'rand'
x = lims(1) + [0 cumsum(rand(1, nPtsMax))];
x(x > lims(2)) = []; % remove values above maximum limit
This approach may be slower, but is still fairly quick and better represents the behaviour in your question.
My first approach to this would be to generate N-2 samples, where N is the desired amount of samples randomly, sort them, and add the extrema:
N=50;
endpoint=100;
initpoint=0;
randsamples=sort(rand(1, N-2)*(endpoint-initpoint)+initpoint);
t_inici=[initpoint randsamples endpoint];
However not sure how "uniformly random" this is, as you are "faking" the last 2 data, to have the extrema included. This will somehow distort pure randomness (I think). If you are not necessarily interested on including the extrema, then just remove the last line and generate N points. That will make sure that they are indeed random (or as random as MATLAB can create them).
Here is an alternative solution with "uniformly random"
[initpoint,endpoint,coef]=deal(0,100,10);
t_inici(1)=initpoint;
while(t_inici(end)<endpoint)
t_inici(end+1)=t_inici(end)+rand()*coef;
end
t_inici(end)=[];
In my point of view, it fits your attempts well with unknown steps, start from 0, but not necessarily end at 100.
From your code it seems you want a uniformly random step that varies between each two entries. This implies that the number of entries that the vector will have is unknown in advance.
A way to do that is as follows. This is similar to Hunter Jiang's answer but adds entries in batches instead of one by one, in order to reduce the number of loop iterations.
Guess a number of required entries, n. Any value will do, but a large value will result in fewer iterations and will probably be more efficient.
Initiallize result to the first value.
Generate n entries and concatenate them to the (temporary) result.
See if the current entries are already too many.
If they are, cut as needed and output (final) result. Else go back to step 3.
Code:
lower_value = 0;
upper_value = 100;
step_scale = 10;
n = 5*(upper_value-lower_value)/step_scale*2; % STEP 1. The number 5 here is arbitrary.
% It's probably more efficient to err with too many than with too few
result = lower_value; % STEP 2
done = false;
while ~done
result = [result result(end)+cumsum(step_scale*rand(1,n))]; % STEP 3. Include
% n new entries
ind_final = find(result>upper_value,1)-1; % STEP 4. Index of first entry exceeding
% upper_value, if any
if ind_final % STEP 5. If non-empty, we're done
result = result(1:ind_final-1);
done = true;
end
end
I'm trying to generate coordinates in a mulidimensional array.
the range for each digit in the coords is -1 to 1. <=> seems like the way to go comparing two random numbers. I'm having trouble because randomizing it takes forever, coords duplicate and sometimes don't fill all the way through. I've tried uniq! which only causes the initialization to run forever while it tries to come up with the different iterations.
the coords look something like this. (-1, 0, 1, 0, 0)
5 digits give position. I could write them out but I'd like to generate the coords each time the program is initiated. The coords would then be assigned to a hash tied to a key. 1 - 242.
I could really use some advice.
edited to add code. It does start to iterate but it doesn't fill out properly. Short of just writing out an array with all possible combos and randomizing before merging it with the key. I can't figure out how.
room_range = (1..241)
room_num = [*room_range]
p room_num
$rand_loc_cords = []
def Randy(x)
srand(x)
y = (rand(100) + 1) * 1500
z = (rand(200) + 1) * 1000
return z <=> y
end
def rand_loc
until $rand_loc_cords.length == 243 do
x = Time.new.to_i
$rand_loc_cords.push([Randy(x), Randy(x), Randy(x), Randy(x), Randy(x)])
$rand_loc_cords.uniq!
p $rand_loc_cords
end
#p $rand_loc_cords
end
rand_loc
You are trying to get all possible permutations of -1, 0 and 1 with a length of 5 by sheer luck, which can take forever. There are 243 of them (3**5) indeed:
coords = [-1,0,1].repeated_permutation(5).to_a
Shuffle the array if the order should be randomized.
I want to create a 3D plot of the final fraction of grass covered on the Earth (=in 2 billion years from now) (=A) as a function of a varying death rate of grass (=D) and the growth rate of grass (=G).
The final value of A (at 2 billion years away from now) can be calculated using a loop with the following discritised equation:
A(t+dt) = A(t)*((1-A(t))*G-D)*dt + A(t)
%Define variables and arrays
D=0.1; %constant value
G=0.4; %constant value
A=0.001; %initial value of A at t=0
t=0;
dt=10E6;
startloop=1; %define number of iterations
endloop=200;
timevector=zeros(1,endloop); %create vector with 0
grassvector=zeros(1,endloop);
%Define the loop
for t=startloop:endloop
A=A.*((((1-A).*G)-D)) + A;
grassvector(t)=A;
timevector(t)=t*dt;
end
Now i'm stuck on how to create a 3D plot of this final value of A as a function of a varying G and D. I got this but after a few trials, it keeps giving errors:
%(1) Create array of values for G and D varying between 0 and 1
A=0.001;
G=[0.005:0.005:1]; %Vary from 0.005 to 1 in steps of 0.005
D=[0.005:0.005:1]; %Vary from 0.005 to 1 in steps of 0.005
%(2) Meshgrid both variables = all possible combinations in a matrix
[Ggrid,Dgrid]=meshgrid(G,D);
%(3) Calculate the final grass fraction with varying G and D
D=0.1;
G=0.4;
A=0.001;
t=0;
dt=10E6;
startloop=1; %define number of iterations
endloop=200;
timevector=zeros(1,endloop); %create vector with 0
grassvector=zeros(1,endloop);
%Define the loop
for t=startloop:endloop
A=A.*((((1-A).*Ggrid)-Dgrid)) + A;
grassvector(t)=A;
timevector(t)=t*dt;
end
%(4) mesh together with D and G
...??
Can someone help? Thanks!
Your code is wrong, as grassvector(t)=A; can not be executed, as the sizes are not consistent. However, I think you may want to do:
grassvector=zeros([size(Ggrid),endloop]);
and in the loop:
grassvector(:,:,t)=A;
Also, while completely unnecesary computationally, you may want to initialize A to A=0.001*ones(size(Dgrid)), as it makes more sense logically.
Anyways: this is how you can plot it in the end:
surf(Ggrid,Dgrid,A,'LineStyle','none');
xlabel('growth rate ')
ylabel('death rate ')
zlabel('grass')
colorbar
gives:
But, as I was actually interested in your research, I decided to make a couple of plots to see how fast the grass will grow and stuff. Here is some nice plotting code. You can modify different stuff here to be able to change the appearance of it. I use custom colormaps, so if it doesn't work, delete the colormap(viridis()) line. If you like the colormap, visit this.
fh=figure();
filename='grass.gif';
for t=startloop:endloop
clf
hold on
surf(Ggrid,Dgrid,grassvector(:,:,t),'LineStyle','none');
[c,h]=contour3(Ggrid,Dgrid,grassvector(:,:,t)+0.05,[0:0.1:1],'LineColor',[153,0,18]/255,'LineWidth',2);
clabel(c,h);
xlabel('growth rate ')
ylabel('death rate ')
zlabel('grass')
title(['Years passed: ' num2str(t*dt/1000000) ' million'])
colormap(viridis())
axis([0 1 0 1 0 1])
grid on
view(-120,40);
frame = getframe(fh);
im = frame2im(frame);
[imind,cm] = rgb2ind(im,256);
if t == 1;
imwrite(imind,cm,filename,'gif', 'Loopcount',inf);
else
imwrite(imind,cm,filename,'gif','WriteMode','append','DelayTime',0.1);
end
end
Results:
How can i Plot an array in a graph against its order in array in matlab ??
Example : x= [6,10,12,20] point 1 become 6:1 and point 3= 12:3 for example even after i remove some elemets from this array i want to preserve same order
example of what am trying to do here is to remove all values bellow mean while keep order cause it represent the time in sec's (this is from video processing code):
m=mean(amp);
for i=totalframes
if (amp(i) >= m)
time(i)=i/framerate;
end
end
amp(amp >= m) = [];
time(time > 0) = [];
figure, plot(time,amp) %% plot my curve
P.s: time and amp array was created by Zeros earlier in my code..
Thanks
If you want to remove all values below the mean m you should do:
inds=(amp<m) %% find where amp is lower than m
amp(inds) = []; %% remove corresponding amp
time(inds) = []; %% remove corresponding time
figure, plot(time,amp)
Change design of x from [6; 10; 12; 20] to [1 6; 2 10; 3 12; 4 20] and traverse this array deleting rows that you dont want then you will have result array with indexes.