How to find Big-O notation of FFT multiplication under a loop - c++

The Big-O notation of FFT Multiplication is O(nlogn). What is Big-O notation of a FFT multiplication under a loop as given in algorithm below? The code is given in matlab and FFTmulti is a function for FFT Multiplication of two polynomials
rG=1;
rN=1;
AreaFunc=[1 2 5 2 3 6 7 2 4 5 6];
N=length(AreaFunc);
for i=1:(N-1)
ref_coeff(i) = (AreaFunc(i+1) - AreaFunc(i)) / (AreaFunc(i+1) + AreaFunc(i));
end
ref_coeff=[ref_coeff rN];
G = (1 + rG) / 2;
A0 = [1]; B0 = [-rG];
for i = 1 : length(ref_coeff)
G = G * (1 + ref_coeff(i));
A1 = [-ref_coeff(i) 0]; B1 = [1 0];
An = [0 A0] + FFTmulti(A1,B0);
Bn = [0 -ref_coeff(i)*A0] + FFTmulti(B1,B0);
A0=An;
B0=Bn;
end
A0 =fliplr(A0);
num = zeros(1, (floor(N/2)));
num = [num G];

FFT complexity -for the best known optimization algorithms - is N*log2(N).
If you call it inside a loop of N, will be N^2 log2(N).

Related

Working with large integer data type, possibly larger than 10^18

What data type or what ways can I store large integers possibly greater than 10^18 and How can I efficiently improve my approach to the problem?
I am currently working on a problem that asks to find the sum of all divisors d(k) given that:
N N
S(N) = ∑ ∑ d(j*i)
i=1 j=1
with the largest value of N = 10^9 and largest divisor (10^9 * 10^9). Stored in:
long long int
The program solves and slows down at N = 10^3 and anything higher takes up to much memory and crashes.
I used a for loop for the values of i and j that calculates the values of d(k) > d(i * j) and store it in a vector:
{d(1 * 1), d(1 * 2), ... , d(i>N * j>N)}
Then a separate function that finds all divisors of d(k) then adds them up:
d(1) = 1
d(2) = 1 + 2 = 3
d(3) = 1 + 3 = 4
d(4) = 1 + 2 + 4 = 7
...
d(i>N * j>N)
S(N) = d(1) + d(2) + d(3) + d(4) + ... + d(i>N * j>N)
Any values of N greater than 10^5 gets displayed as S(N) mod 10^9.

What will be the complexity of this algorithm in the terms of n?

In the following algorithm the loop is increasing by the square of previous value of i,
what will be the complexity of this algorithm?
#include<iostream>
using namespace std;
int main(){
int i=2;
while(i<=n){
cout<<"Something"<<endl;
i=(i*i);
}
return 0;
}
The answer is log(log n)
It goes like this:
a0 = 2
a1 = 2 * 2 = 4
a2 = 4 * 4 = 16
a3 = 16 * 16 = 256
...
In general terms this is:
ai = 2 ^ (2 ^ i) where ^ is the power function
Now we solve
n = 2 ^ (2 ^ i)
for i which gives
i = log(log(n)/log(2))/log(2)
then replace the constants with 1 (i.e. log(2) -> 1) as we do with big O notation.
i ~ log(log(n))
So we need approx. log(log(n)) loops so we have
O(n) = log(log(n))

Extended polynomials in library NTL

There is code is written using NTL library:
int main()
{
ZZ_p::init(ZZ(5)); // define GF(5)
ZZ_pX P;
BuildIrred(P, 4); // generate an irreducible polynomial P
// of degree 4 over GF(5)
ZZ_pE::init(P); // define GF(5^4)
ZZ_pEX f, g, h; // declare polynomials over GF(5^4)
random(f, 3); // f is a random, monic polynomial of degree 3
SetCoeff(f, 3);
cout << f << endl<< endl;
}
The output is:
[[3 1 1 4] [2 1 3 2] [1 0 3 1] [1]]
For example, [1 2 3] is mean 3x² + 2x + 1.
What the form of notation polynomial over GF in this case?
Your question is a little bit difficult to understand. If I understand you right, the question is how to interpret the NTL representation [[3 1 1 4] [2 1 3 2] [1 0 3 1] [1]] of a polynomial over the finite field with 5⁴ elements.
First: The elements in the finite field with 5⁴ elements (called GF(5⁴)) are represented as the polynomials GF(5)[X] mod f, where f is an irreducible polynomial of degree 4.
This means a polynomial over GF(5⁴) is a Polynomial where the coefficients are polynomials in GF(5)[X] mod f.
So [[3 1 1 4] [2 1 3 2] [1 0 3 1] [1]] can be interpreted as
Y³ + (X³ + 3X² + 1)⋅Y² + (2X³ + 3X² + X + 2)⋅Y + (4X³ + X² + X + 3)
Notice: The comment in
random(f, 3); // f is a random, monic polynomial of degree 3
SetCoeff(f, 3);
is a little bit misleading. random(f,3) sets f to a random polynomial of degree less than 3. SetCoeff(f, 3) sets the coefficient of Y³ to 1 and after that it is a polynomial of degree 3.

How should I go about solving this recursion without trial and error

int sum_down(int x)
{
if (x >= 0)
{
x = x - 1;
int y = x + sum_down(x);
return y + sum_down(x);
}
else
{
return 1;
}
}
What is this smallest integer value of the parameter x, so that the returned value is greater than 1.000.000 ?
Right now I am just doing it by trial and error and since this question is asked via a paper format. I don't think I will have enough time to do trial and error. Question is, how do you guys visualise this quickly such that it can be solved easily. Thanks guys and I am new to programming so thanks in advance!
The recursion logic:
x = x - 1;
int y = x + sum_down(x);
return y + sum_down(x);
can be simplified to:
x = x - 1;
int y = x + sum_down(x) + sum_down(x);
return y;
which can be simplified to:
int y = (x-1) + sum_down(x-1) + sum_down(x-1);
return y;
which can be simplified to:
return (x-1) + 2*sum_down(x-1);
Put in mathematical form,
f(N) = (N-1) + 2*f(N-1)
with the recursion terminating when N is -1. f(-1) = 1.
Hence,
f(0) = -1 + 2*1 = 1
f(1) = 0 + 2*1 = 2
f(2) = 1 + 2*2 = 5
...
f(18) = 17 + 2*f(17) = 524269
f(19) = 18 + 2*524269 = 1048556
Your program can be written this way (sorry about c#):
public static void Main()
{
int i = 0;
int j = 0;
do
{
i++;
j = sum_down(i);
Console.Out.WriteLine("j:" + j);
} while (j < 1000000);
Console.Out.WriteLine("i:" + i);
}
static int sum_down(int x)
{
if (x >= 0)
{
return x - 1 + 2 * sum_down(x - 1);
}
else
{
return 1;
}
}
So at first iteration you'll get 2, then 5, then 12... So you can neglect the x-1 part since it'll stay little compared to the multiplication.
So we have:
i = 1 => sum_down ~= 4 (real is 2)
i = 2 => sum_down ~= 8 (real is 5)
i = 3 => sum_down ~= 16 (real is 12)
i = 4 => sum_down ~= 32 (real is 27)
i = 5 => sum_down ~= 64 (real is 58)
So we can say that sum_down(x) ~= 2^x+1. Then it's just basic math with 2^x+1 < 1 000 000 which is 19.
A bit late, but it's not that hard to get an exact non-recursive formula.
Write it up mathematically, as explained in other answers already:
f(-1) = 1
f(x) = 2*f(x-1) + x-1
This is the same as
f(-1) = 1
f(x+1) = 2*f(x) + x
(just switched from x and x-1 to x+1 and x, difference 1 in both cases)
The first few x and f(x) are:
x: -1 0 1 2 3 4
f(x): 1 1 2 5 12 27
And while there are many arbitrary complicated ways to transform this into a non-recursive formula, with easy ones it often helps to write up what the difference is between each two elements:
x: -1 0 1 2 3 4
f(x): 1 1 2 5 12 27
0 1 3 7 15
So, for some x
f(x+1) - f(x) = 2^(x+1) - 1
f(x+2) - f(x) = (f(x+2) - f(x+1)) + (f(x+1) - f(x)) = 2^(x+2) + 2^(x+1) - 2
f(x+n) - f(x) = sum[0<=i<n](2^(x+1+i)) - n
With eg. a x=0 inserted, to make f(x+n) to f(n):
f(x+n) - f(x) = sum[0<=i<n](2^(x+1+i)) - n
f(0+n) - f(0) = sum[0<=i<n](2^(0+1+i)) - n
f(n) - 1 = sum[0<=i<n](2^(i+1)) - n
f(n) = sum[0<=i<n](2^(i+1)) - n + 1
f(n) = sum[0<i<=n](2^i) - n + 1
f(n) = (2^(n+1) - 2) - n + 1
f(n) = 2^(n+1) - n - 1
No recursion anymore.
How about this :
int x = 0;
while (sum_down(x) <= 1000000)
{
x++;
}
The loop increments x until the result of sum_down(x) is superior to 1.000.000.
Edit : The result would be 19.
While trying to understand and simplify the recursion logic behind the sum_down() function is enlightening and informative, this snippet tend to be logical and pragmatic in that it does not try and solve the problem in terms of context, but in terms of results.
Two lines of Python code to answer your question:
>>> from itertools import * # no code but needed for dropwhile() and count()
Define the recursive function (See R Sahu's answer)
>>> f = lambda x: 1 if x<0 else (x-1) + 2*f(x-1)
Then use the dropwhile() function to remove elements from the list [0, 1, 2, 3, ....] for which f(x)<=1000000, resulting in a list of integers for which f(x) > 1000000. Note: count() returns an infinite "list" of [0, 1, 2, ....]
The dropwhile() function returns a Python generator so we use next() to get the first value of the list:
>>> next(dropwhile(lambda x: f(x)<=1000000, count()))
19

Complexity of an algorithm with two recursive calls

I have a strange algorithm than is being called recursively 2 times. It's
int alg(int n)
loop body = Θ(3n+1)
alg(n-1);
alg(n-2)
Somehow i need to find this algorithm's complexity. I've tried to find it with using characteristic polynomial of the above equation but the result system is too hard to solve so i was wondering if there was any other straight way..
Complexity: alg(n) = Θ(φ^n) where φ = Golden ratio = (1 + sqrt(5)) / 2
I can't formally prove it at first, but with a night's work, I find my missing part - The substitution method with subtracting a lower-order term. Sorry for my bad expression of provement (∵ poor English).
Let loop body = Θ(3n+1) ≦ tn
Assume (guess) that cφ^n ≦ alg(n) ≦ dφ^n - 2tn for an n (n ≧ 4)
Consider alg(n+1):
Θ(n) + alg(n) + alg(n-1) ≦ alg(n+1) ≦ Θ(n) + alg(n) + alg(n-1)
c * φ^n + c * φ^(n-1) ≦ alg(n+1) ≦ tn + dφ^n - 2tn + dφ^(n-1) - 2t(n-1)
c * φ^(n+1) ≦ alg(n+1) ≦ tn + d * φ^(n+1) - 4tn + 2
c * φ^(n+1) ≦ alg(n+1) ≦ d * φ^(n+1) - 3tn + 2
c * φ^(n+1) ≦ alg(n+1) ≦ d * φ^(n+1) - 2t(n+1) (∵ n ≧ 4)
So it is correct for n + 1. By mathematical induction, we can know that it's correct for all n.
So cφ^n ≦ alg(n) ≦ dφ^n - 2tn and then alg(n) = Θ(φ^n).
johnchen902 is correct:
alg(n)=Θ(φ^n) where φ = Golden ratio = (1 + sqrt(5)) / 2
but his argument is a bit too hand-waving, so let's make it strict. His original argument was incomplete, therefore I added mine, but now he has completed the argument.
loop body = Θ(3n+1)
Let us denote the cost of the loop body for the argument n with g(n). Then g(n) ∈ Θ(n) since Θ(n) = Θ(3n+1).
Further, let T(n) be the total cost of alg(n) for n >= 0. Then, for n >= 2 we have the recurrence
T(n) = T(n-1) + T(n-2) + g(n)
For n >= 3, we can insert the recurrence applied to T(n-1) into that,
T(n) = 2*T(n-2) + T(n-3) + g(n) + g(n-1)
and for n > 3, we can continue, applying the recurrence to T(n-2). For sufficiently large n, we therefore have
T(n) = 3*T(n-3) + 2*T(n-4) + g(n) + g(n-1) + 2*g(n-2)
= 5*T(n-4) + 3*T(n-5) + g(n) + g(n-1) + 2*g(n-2) + 3*g(n-3)
...
k-1
= F(k)*T(n+1-k) + F(k-1)*T(n-k) + ∑ F(j)*g(n+1-j)
j=1
n-1
= F(n)*T(1) + F(n-1)*T(0) + ∑ F(j)*g(n+1-j)
j=1
with the Fibonacci numbers F(n) [F(0) = 0, F(1) = F(2) = 1].
T(0) and T(1) are some constants, so the first part is obviously Θ(F(n)). It remains to investigate the sum.
Since g(n) ∈ Θ(n), we only need to investigate
n-1
A(n) = ∑ F(j)*(n+1-j)
j=1
Now,
n-1
A(n+1) - A(n) = ∑ F(j) + (((n+1)+1) - ((n+1)-1))*F((n+1)-1)
j=1
n-1
= ∑ F(j) + 2*F(n)
j=1
= F(n+1) - 1 + 2*F(n)
= F(n+2) + F(n) - 1
Summing that, starting with A(2) = 2 = F(5) + F(3) - 5, we obtain
A(n) = F(n+3) + F(n+1) - (n+3)
and therefore, with
c*n <= g(n) <= d*n
the estimate
F(n)*T(1) + F(n-1)*T(0) + c*A(n) <= T(n) <= F(n)*T(1) + F(n-1)*T(0) + d*A(n)
for n >= 2. Since F(n+1) <= A(n) < F(n+4), all terms depending on n in the left and right parts of the inequality are Θ(φ^n), q.e.d.
Assumptions:
1: n >= 0
2: Θ(3n+1) = 3n + 1
Complexity:
O(2 ^ n * (3n - 2));
Reasoning:
int alg(int n)
loop body = Θ(3n+1)// for every n you have O(3n+1)
alg(n-1);
alg(n-2)
Assuming the alg does not execute for n < 1, you have the following repetitions:
Step n:
3 * n + 1
alg(n - 1) => 3 * (n - 1) + 1
alg(n - 2) => 3 * (n - 2) + 1
Now you basically have a division. You have to imagine a number tree with N as parent and n-1 and n-2 as children.
n
n-1 n-2
n - 2 n - 3 n - 3 n - 4
n - 3 n - 4 n - 4 n - 5 n - 4 n - 5 n - 5 n - 6
n-4 n-5 | n-5 n-6 |n-5 n-6 |n-6 n-7 n-5 n-6 n-6 n-7 n-6 n-6| n-6 n-8
It's obvious that there is a repetition pattern here. For every pair (n - k, n - k - 1) in A = {k, with k from 0 to n) except the first two and the last two, (n - 1, n - 2) and (n-2, n-3) there is a 3k + 1 * (2 ^ (k - 1)) complexity.
I am looking at the number of repetitions of the pair (n - k, n - k - 1). So now for each k from 0 to n I have:
(3k + 1) * (2 ^ (k - 1)) iterations.
If you sum this up from 1 to n you should get the desired result. I will expand the expression:
(3k + 1) * (2 ^ (k - 1)) = 3k * 2 ^ (k - 1) + 2 ^ (k - 1)
Update
1 + 2 + 2^2 + 2^3 + ... + 2^n = 2 ^ (n + 1) - 1
In your case, this winds up being:
2^n - 1
Based on the summation formula and k = 0, n . Now the first one:
3k * 2 ^ (k - 1)
This is equal to 3 sum from k = 0, n of k * 2 ^ (k - 1).
That sum can be determined by switching to polinomial functions, integrating, contracting using the 1 + a ^ 2 + a ^ 3 + ... + a ^ n formula, and then differentiated again to obtain the result, which is (n - 1) * 2 ^ n + 1.
So you have:
2 ^ n - 1 + 3 * (n - 1) * 2 ^ n + 1
Which contracted is:
2 ^ n * (3n - 2);
The body of the function takes Θ(n) time.
The function is called twice recursively.
For the given function the complexity is,
T(n) = T(n-1) + T(n-2) + cn ----- 1
T(n-1) = T(n-2) + T(n-3) + c(n-1) ----- 2
1-2 -> T(n) = 2T(n-1) - T(n-3) + c ----- 3
3 --> T(n-1) = 2T(n-2) + T(n-4) + c ----- 4
3-4 -> T(n) = 3T(n-1) - 2T(n-2) - T(n-3) - T(n-4) ----- 5
Let g(n) = 3g(n-1)
There for, we can approximate T(n) = O(g(n))
g(n) is Θ(3n)
There for T(n) = O(3n)