trying to do a series sum in matlab - matlab

I want to calculate the sum of a series in MATLAB
The assignment is on the last page question 3 on this webpage
The series's sum should be pi but when I used MATLAB to prove that it just does not converge to pi
What am I doing wrong in my code?
function f = equation(n)
for i=1:n;
f=4*sum(((-1)^i)/(2*i+1))
if f >= pi
break;
else
continue;
end
end
end
EDIT :
function f = equation(n)
i=0:n;
f=4*sum((-1).^i ./(2*i+1));
plot(f,'x')
end
It does not work to plot(f) , what am I doing wrong ?

There are a few things you are doing wrong. First, you aren't keeping track of the running sum, you are just defining each term inside the loop. You should instead have something like
function total = equation(n)
total = 0;
for i = 1:n
total = total + (-1)^i / (2 * i + 1);
if total > pi
break;
end
end
total = 4 * total;
end
Second, you don't want the break statement there. If you plot the partial sums of this series, you can see that it oscillates either side of pi -
If you break as soon as you have exceeded pi, then you will break too early (after the first term, in fact!)
So your code should look like
function total = equation(n)
total = 0;
for i = 1:n
total = total + (-1)^i / (2*i+1);
end
total = 4 * total;
end
Additionally, this series will only converge to pi if you start it at zero, rather than one -
function total = equation(n)
total = 0;
for i = 0:n
total = total + (-1)^i / (2*i+1);
end
total = 4 * total;
end
Finally, you can simplify dramatically by vectorizing your code -
function total = equation(n)
indices = 0:n;
total = 4 * sum((-1).^indices ./ (2 * indices + 1));
end

To add to the rest of the answers. This code will compute all the approximations of pi from n=1 to n=100.
n=100;
f=[];
for jj=1:n
ii=0:jj;
f=[f 4*sum( ((-1).^ii)./(2.*ii+1) )];
end;
hold on
plot(f)
plot(1:size(f,2),ones(size(f))*pi)

Your code does not make sense: why would you sum a single element, then discard the result the next cycle? Your purpose would be better served by:
function f = no_kitty_is_my_pi_you_cant_have_it(n)
%'Sorry for the South Park reference/pun'
k = 0:n;
f = 4 * sum((-1).^k ./ (2*k+1));
end
And, as side note on MATLAB programming practices: choosing i and j as names for variables is not a good idea, because these two are built-in functions that give you the imaginary unit (the square root of -1).

Related

Matlab Xcorr function returns NaNs for a large block of the return array

I have some synthetic signal data to cross correlate before moving on with real data but the xcorr function is returning an odd result.
I have added a delay onto either the start (delay =100) or end of the respective data sets which are the same size (2101 x 1 double) and put them through xcorr which has returned an array (4201 x 1 double).
The result has NaNs between rows 101 and 2205 and then a ring down effect after that start at an order of x10^5. I have now attached pictures of the result
Can anyone please offer some suggestions on how to correct what I am attempting to do? I am expecting to be able to plot the result and see a spike at the delay that I have set.
Thanks
EDIT:
Short example code
X = [-4.99 -0.298 4.95 12.06 15.76 18.86 19.00 17.82 14.35 11.77 6.71 0.80 -5.07 -11.79 -15.34 -18.60 -18.56 -19.31 -14.37 -11.51 -5.04];
Y = [14.13 18.48 7.53 -3.41 -8.41 -13.40 -15.37 -17.34 -16.83 -16.33 -12.21 -8.09 -8.80 -9.52 3.90 17.31 17.52 17.72 17.73 17.75 16.90];
N = length(X);
delay = 2;
% set up two new arrays which will have random noise at ends
Xx = zeros(N+delay,1);
Yx = zeros(N+delay,1);
for i=1:N+delay
if i<=delay
Xx(i) = rand;
elseif i>delay
Xx(i) = X(i-delay);
end
end
for i=1:N+delay
if i<=N
Yx(i) = Y(i);
elseif i>N
Yx(i) = rand;
end
end
C = xcorr(Xx,Yx);

how to modify the program to find how long till the population doubled

p=malt(p0,r,n)
p=zeros(n+1,1);
p(1)=p0;
for i=1:n
p(i+1)=(1+r)*p(i);
end
I wrote this program (in matlab) to find the population where,
p0=initial population, r=annual growth rate, n=years. I want to modify the code using while loop to be able to find how long till the population doubled.
If you want a while-loop:
p0 = 10000;
r = 0.02; % 0.02 --> 2%
p = cell(2,1);
p{1}=p0;
i = 1;
while (p{i}<p0*2)
i = i + 1;
p{i}=(1+r)*p{i-1};
end
years = i - 1;
But do you know that you don't need a loop for this but just a simple formula?
Pn = P0*(1+r/100)^n with n in years and r the growth rate in percentage
If Pn needs to be 2*P0
--> n_doubling = log(2)/log(1+r/100)

Matlab: Is there a quicker way to count the number of occurrences of a value in a vector?

Thanks in advance for the help
I am using the following to count the number of occurrences of the value x in a vector v
count = sum(v == x);
Is there anyway that I can decrease the time to count these occurrences? Notice that v tends to be small; usually no more than 100 elements. However, this operation occurs tens of thousands of times in my code and seems to be by far the most time consuming operation when analyzing my code using the profiler. I've looked at the accumarray function but it appears that the approach I give above tends to be faster (at least the way I tried to use it).
Depending on the rest of your code and the type of data, one possible way to approach this is to subtract x from v and count zeros instead. E.g.,
v = rand(200,1);
v(121) = v(3); % add some duplicates of v(3)
v(189) = v(3); % add some duplicates of v(3)
x = v(3);
count = numlel(v)-nnz(v-x);
Subtracting costs CPU-time but you might benefit from it in the end. Since I don't have your data I've just made a small test. You can test on your actual data to see whether it's something for you or not.
N = 100000;
for k = 1:1
v = randn(200,1);
vy = zeros(size(v));
v(121) = v(3);
v(189) = v(3);
x = v(3);
t1=tic;
for j = 1:N
count1 = sum(v(:)==x);
end
t1s=toc(t1)/N;
t2=tic;
for j = 1:N % time the cost of subtraction prior to nnz()
vy=v-x;
count2 = numel(v)-nnz(vy);
end
t2s=toc(t2)/N;
t3=tic;
for j = 1:N % time the cost of subtraction within nnz()
count3 = numel(v)-nnz(v-x);
end
t3s=toc(t3)/N;
[count1 count2 count3]
[t1s t2s t3s]
end
ans =
3 3 3
ans =
1.0e-05 *
0.1496 0.1048 0.1222
You can see John D'Errico's answer here about counting zeros.

How to implement parallel-for in a 4 level nested for loop block

I have to calculate the std and mean of a large data set with respect to quite a few models. The final loop block is nested to four levels.
This is what it looks like:
count = 1;
alpha = 0.5;
%%%Below if each individual block is to be posterior'd and then average taken
c = 1;
for i = 1:numel(writers) %no. of writers
for j = 1: numel(test_feats{i}) %no. of images
for k = 1: numel(gmm) %no. of models
for n = 1: size(test_feats{i}{j},1)
[~, scores(c)] = posterior(gmm{k}, test_feats{i}{j}(n,:));
c = c + 1;
end
c = 1;
index_kek=find(abs(scores-mean(scores))>alpha*std(scores));
avg = mean(scores(index_kek)); %using std instead of mean... beacause of ..reasons
NLL(count) = avg;
count = count + 1;
end
count = 1; %reset count
NLL_scores{i}(j,:) = NLL;
end
fprintf('***score for model_%d done***\n', i)
end
It works and gives the desired result but it takes 3 days to give me the final calculation, even on my i7 processor. During processing the task manager tells me that only 20% of the cpu is being used, so I would rather put more load on the cpu to get the result faster.
Going by the official help here if I suppose want to make the outer most loop a parfor while keeping the rest normal for all I have to do is to insert integer limits rather than function calls such as size or numel.
So making these changes the above code will become:
count = 1;
alpha = 0.5;
%%%Below if each individual block is to be posterior'd and then average taken
c = 1;
num_writers = numel(writers);
num_images = numel(test_feats{1});
num_models = numel(gmm);
num_feats = size(test_feats{1}{1},1);
parfor i = 1:num_writers %no. of writers
for j = 1: num_images %no. of images
for k = 1: num_models %no. of models
for n = 1: num_feats
[~, scores(c)] = posterior(gmm{k}, test_feats{i}{j}(n,:));
c = c + 1;
end
c = 1;
index_kek=find(abs(scores-mean(scores))>alpha*std(scores));
avg = mean(scores(index_kek)); %using std instead of mean... beacause of ..reasons
NLL(count) = avg;
count = count + 1;
end
count = 1; %reset count
NLL_scores{i}(j,:) = NLL;
end
fprintf('***score for model_%d done***\n', i)
end
Is this the most optimum way to implement parfor in my case? Can it be improved or optimized further?
I couldn't test in Matlab for now but it should be close to a working solution. It has a reduced number of loops and changes a few implementation details but overall it might perform just as fast (or even slower) as your earlier code.
If gmm and test_feats take lots of memory then it is important that parfor is able to determine which peaces of data need to be delivered to which workers. The IDE should warn you if inefficient memory access is detected. This modification is especially useful if num_writers is much less than the number of cores in your CPU, or if it is only slightly larger (like 5 writers for 4 cores would take about as long as 8 writers).
[i_writer i_image i_model] = ndgrid(1:num_writers, 1:num_images, 1:num_models);
idx_combined = [i_writer(:) i_image(:) i_model(:)];
n_combined = size(idx_combined, 1);
NLL_scores = zeros(n_combined, 1);
parfor i_for = 1:n_combined
i = idx_combined(i_for, 1)
j = idx_combined(i_for, 2)
k = idx_combined(i_for, 3)
% pre-allocate
scores = zeros(num_feats, 1)
for i_feat = 1:num_feats
[~, scores(i_feat)] = posterior(gmm{k}, test_feats{i}{j}(i_feat,:));
end
% "find" is redundant here and performs a bit slower, might be insignificant though
index_kek = abs(scores - mean(scores)) > alpha * std(scores);
NLL_scores(i_for) = mean(scores(index_kek));
end

How can I make this MATLAB code fast (m-file script)?

I want to make the code below fast. It takes so long time to run, and I got this error:
Warning: FOR loop index is too large. Truncating to 2147483647.
I need to calculate over 3^100 so... is it impossible?
function sodiv = divisorSum(n)
sodiv = 0;
for i=1:n
if (mod(n,i) == 0)
sodiv = sodiv + i;
end
end
end
function finalSum1 = formular1(N,n)
finalSum1 = 0;
for k = 1:N
finalSum1 = finalSum1 + (divisorSum(k) * divisorSum(3^n*(N-k)));
end
end
Nv=100;
nv=[1:20];
for i=1:length(nv)
tic;
nfunc1(i)=formular1(Nv,nv(i));
nt1(i)=toc;
sprintf('nt1 : %d finished, %f', i,nt1(i))
end
The purpose of this code is to check the algorithm's calculation time.
The algorithm is too general and inefficient for this particular problem.
I understand you want to sum the divisors of 3^100. But these divisors are easily determined.
S = 1 + 3 + 3^2 + 3^3 + ... + 3^100, a geometric series.
3*S = 3 + 3^2 + ... + 3^101
subtract
2*S = 3^101 - 1
S = (3^101 - 1)/2
This code will never finish, because it is so inefficient.
For instance, there is a function that counts number of all divisors and is going through all numbers from 1 to N and count. But using an efficient formula would make it run much master.
Let's say that one need to sum divisors of number a^b where a is prime number.
Instead of calculating a^b and going form 1 to a^b, one can see that it is better going
a^1, a^2, a^3, ..., a^n, because only these numbers are divisors. But you can go even further and observe that the sum of these numbers are the sum of geometric progression so the number of divisors become:
sum divisors, a^b = (a^(b+1)-1) / (a-1)