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

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)

Related

Matlab AR digital fiter computation w/o loops

I'm given the a(k) matrix and e(n) and I need to compute y(n) from the following eq:
y(n) = sum(k = 1 to 10 )( a(k)*y(n-k) ) + e(n).
I have the a matrix(filter coefficients) and the e matrix (the residual), therefore there is only 1 unknown: y, which is built by the previous 10 samples of y.
An example to this equation:
say e(0) (my first residual sample) = 3
and y(-10) to y(-1) = 0
then y(0), my first sample in the signal y, would just be e(0) = 3:
y(0) = a(1)*y(-1) + a(2)*y(-2) + .... + a(10)*y(-10) + e(0) = e(0) = 3
and if e(1) = 4, and a(1) = 5, then
y(1) = a(1)*y(0) + a(2)*y(-1) + a(3)&y(-2) + ... + a(10)*y(-9) + e(1) = 19
The problem is
I don't know how to do this without loops because, say, y(n) needs y(n-1), so I need to immediately append y(n-1) into my matrix in order to get y(n).
If n (the number of samples) = say, 10,000,000, then using a loop is not ideal.
What I've done so far
I have not implemented anything. The only thing I've done for this particular problem is research on what kind of Matlab functions I could use.
What I need
A Matlab function that, given an equation and or input matrix, computes the next y(n) and automatically appends that to the input matrix, and then computes the next y(n+1), and automatically append that to the input matrix and so on.
If there is anything regarding my approach
That seems like it's on the wrong track, or my question isn't clear enough, of if there is no such matlab function that exists, then I apologize in advance. Thank you for your time.

Approximate pi using finitie series

Given the equation to approximate pi
I need to the number of terms (n) that are needed to obtain an approximation that is within 10^(-12) of the actual value of pi. The code I have to find the n looks like this:
The while loop statement I have seems to never end, so I feel like my code must be wrong.
Try something along these lines (transcribed from your image), incrementing the number of approximation terms n inside your infinite while loop:
s = 1
n = 1
while true
s = abs(pi - approximate_pi(n))
if s <= 0.001
break
end
n = n + 1
end
On a related note, this calculation is a little bit pointless if you know the value of pi beforehand. Termination condition should be on the absolute magnitude of the n-th term.
The way you're doing it makes sense only if you're trying to find out minimum n for which your approximation series produces the result within some margin of error.
Edit. So, normally you would do it like this:
n = 1;
sum_running = 0
sum_target = (pi^2 - 8) / 16;
while true
sum_running += 1 / ((2*n-1)^2 * (2*n+1)^2);
if abs(sum_target - sum_running) <= 10e-12
break
end
n += 1;
end
pi_approx = sqrt(16*sum_running + 8)
There's no need to keep recalculating pi approximation up to n terms, for each new n. This is has O(n) complexity, while your initial solution had O(n^2), so it's much faster for large n.

trying to do a series sum in 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).

What's the difference between these two codes to get the sum of infinite series in MATLAB?

1 + 1/(2^4) + 1/(3^4) + 1/(4^4) + ...
This is the infinite series that I'd like to get the sum value. So I wrote this code in MATLAB.
n = 1;
numToAdd = 1;
sum = 0;
while numToAdd > 0
numToAdd = n^(-4);
sum = sum + numToAdd;
n = n + 1;
end
disp(sum);
But I couldn't get the result because this code occurred an infinite loop. However, the code I write underneath -- it worked well. It took only a second.
n = 1;
oldsum = -1;
newsum = 0;
while newsum > oldsum
oldsum = newsum;
newsum = newsum + n^(-4);
n = n+1;
end
disp(newsum);
I read these codes again and googled for a while, but coudln't find out the critical point. What makes the difference between these two codes? Is it a matter of precision of double in MATLAB?
The first version would have to go down to the minimum value for a double ~10^-308, while the second will only need to go down to the machine epsilon ~10^-16. The epsilon value is the largest value x such that 1+x = 1.
This means the first version will need approximately 10^77 iterations, while the second only needs 10^4.
The problem boils down to this:
x = 1.23456789; % Some random number
xEqualsXPlusEps = (x == x + 1e-20)
ZeroEqualsEps = (0 == 1e-20)
xEqualsXPlusEps will be true, while ZeroEqualsEps is false. This is due to the way floating point arithmetic works. The value 1e-20 is smaller than the least significant bit of x, so x+1e-20 won't be larger than x. However 1e-20 is not considered equal to 0. In comparison to x, 1e-20 is relatively small, whereas in comparison to 0, 1e-20 is not small at all.
To fix this problem you would have to use:
while numToAdd > tolerance %// Instead of > 0
where tolerance is some small number greater than zero.

matlab brute force indexing

Hi I am working with the brute force method to examine possible combinations of "panels" and "turbines"
My code is
for number_panels = 0:5
for number_turbines = 0:10
for n = 1:24 % number of hours per day
deficit(n) = Demand(n) - (PV_supply(n)*number_panels) -...
(WT_supply(n)*number_turbines);% hourly power deficit
if deficit(n)<0
deficit(n) = 0;
end
The problem I have above is that I haven't yet figured the correct indexing of this code.
What I am trying to do is find the "deficit" for the "number_panels" , "number_turbines" and "n". As it stands I can only find the "deficit" for the last for loop.
How can I code so that I can have the option to access the nth row (or sets of "n" i.e 1-24) and also for the "number_panels" "number_turbines" option?
thanks - in order to find the sum of each deficit(n) value and thus have the respective total deficit of the 24 hour period I have done the following which seems to me to be able to do what I am asking but I am getting incorrect answers:
daily_deficit(number_panels + 1, number_turbines + 1) =...
sum(deficit(number_panels + 1, number_turbines + 1,n)) –
function calcDeficit.m:
File Edit Options Buffers Tools ObjC Help
function deficit = calcDeficit (Demand, PV_supply, WT_supply)
% initialize the size (good practice)
deficit = zeros(6,11,24);
for number_panels = 0:5
for number_turbines = 0:10
for n = 1:24 % number of hours per day
deficit(number_panels+1,number_turbines+1,:) = Demand(n) - (PV_supply(n)*number_panels) -...
(WT_supply(n)*number_turbines);% hourly power deficit
if deficit(n)<0
deficit(n) = 0;
end
end
end
end
return
example call:
Demand=randn(24,1); PV_supply=randn(24,1); WT_supply=randn(24,1); test(Demand,PV_supply,WT_supply)
You access Demand by
Demand(panels+1,number_turbines+1,hour)
Your problem is that you're storing the deficit result as a function only of the value n, the number of hours per day. In your inner loop around n, you keep replacing the values each time through your outer loops, so at the end of the run, you only have the value for n = 1:24 at number_panels = 5 and number_turbines = 10.
Try this:
deficit(number_panels+1, number_turbines+1, n) = ...
That way at the end, you can check any combination given the three indices. I've added a value of 1 to number_panels and number_turbines because MATLAB uses 1-based indexes. To get your results for a specific number of panels or turbines, make sure to add 1 when checking.
Specifically, for 3 panels and 4 turbines at hour 5 in the day:
disp(deficit(3+1, 4+1, 5))
EDIT: Added 1 to the values of number_panels and number_turbines to avoid 0-indexing.