Mutual recursion analysis - algorithm

I'm trying to analyze these functions but i am getting a bit lost. So for function f when t(n) = c if n < 1^-5
so if n >= 1^5 i get t(n) = c2 + t( n / 2 ) + t2( n / 2) where t2 is the time analysis of function h, but i'm confused on expanding it should it be something like
t(n) = ( t(n / 2) + t2( n / 2) ) * c2 + c
or should i be expanding t2 in side of that?
here is the code i am trying to analyze.
float f( float x) {
if ( abs( x ) < 1e-5 ) {
return x + ( ( x * x * x ) / 2 );
}
float y = f( x / 2 );
float z = g( x / 2 );
return 2 * y * z;
}
float g( float x ) {
if ( abs( x ) < 1e-5 ) {
return 1 + ( ( x * x ) / 2 );
}
float y = f( x / 2 );
float z = g( x / 2 );
return ( z * z ) + ( y * y );
}

T1(n) = T1(n / 2) + T2(n / 2) + c1
T2(n) = T1(n / 2)+T2(n / 2) + c2
so we have
T1(n) = O(T2(n))
T1(n) = 2T1(n / 2) + c1
since c1 = O(nlog22) master theorem implies that
T(n) = O(n)

Even though we are calling two different functions in this code, there is a thing about them that makes finding the complexity of this recursion easy.
What's happening is that at the top level, if you are entering f(), you are evaluating x and then calling two different functions - itself and g(). Even if you enter the function g() first, same thing happens, i.e. g() calls itself and f().
Since, every level down the tree the value of x halves, the number of levels on this tree would be Log2(n). Also, every node has 2 children viz. f(x/2) and g(x/2).
This is a complete binary tree of length Log2(n).
Work done on each node is constant - If the node represents the call to f(), you do 2 * y * z, which is constant. If the node represents the call to g(), you do y*y + z*z, which is also constant.
Hence, all we need to do is, find the total number of nodes in a compete binary tree of length Log2(n) and we have our complexity.
A perfect binary tree of height h has total 2h + 1 - 1 nodes.
In this case it would be 2Log2(n) + 1 - 1 nodes.
Also, aLogab = b (By property of logarithms)1
Hence, the complexity is O(2Log2(n)) = O(n).
1 See first property in "Cancelling Exponentials" section.

Related

Finite difference method for solving the Klein-Gordon equation in Matlab

I am trying to numerically solve the Klein-Gordon equation that can be found here. To make sure I solved it correctly, I am comparing it with an analytical solution that can be found on the same link. I am using the finite difference method and Matlab. The initial spatial conditions are known, not the initial time conditions.
I start off by initializing the constants and the space-time coordinate system:
close all
clear
clc
%% Constant parameters
A = 2;
B = 3;
lambda = 2;
mu = 3;
a = 4;
b = - (lambda^2 / a^2) + mu^2;
%% Coordinate system
number_of_discrete_time_steps = 300;
t = linspace(0, 2, number_of_discrete_time_steps);
dt = t(2) - t(1);
number_of_discrete_space_steps = 100;
x = transpose( linspace(0, 1, number_of_discrete_space_steps) );
dx = x(2) - x(1);
Next, I define and plot the analitical solution:
%% Analitical solution
Wa = cos(lambda * x) * ( A * cos(mu * t) + B * sin(mu * t) );
figure('Name', 'Analitical solution');
surface(t, x, Wa, 'edgecolor', 'none');
colormap(jet(256));
colorbar;
xlabel('t');
ylabel('x');
title('Wa(x, t) - analitical solution');
The plot of the analytical solution is shown here.
In the end, I define the initial spatial conditions, execute the finite difference method algorithm and plot the solution:
%% Numerical solution
Wn = zeros(number_of_discrete_space_steps, number_of_discrete_time_steps);
Wn(1, :) = Wa(1, :);
Wn(2, :) = Wa(2, :);
for j = 2 : (number_of_discrete_time_steps - 1)
for i = 2 : (number_of_discrete_space_steps - 1)
Wn(i + 1, j) = dx^2 / a^2 ...
* ( ( Wn(i, j + 1) - 2 * Wn(i, j) + Wn(i, j - 1) ) / dt^2 + b * Wn(i - 1, j - 1) ) ...
+ 2 * Wn(i, j) - Wn(i - 1, j);
end
end
figure('Name', 'Numerical solution');
surface(t, x, Wn, 'edgecolor', 'none');
colormap(jet(256));
colorbar;
xlabel('t');
ylabel('x');
title('Wn(x, t) - numerical solution');
The plot of the numerical solution is shown here.
The two plotted graphs are not the same, which is proof that I did something wrong in the algorithm. The problem is, I can't find the errors. Please help me find them.
To summarize, please help me change the code so that the two plotted graphs become approximately the same. Thank you for your time.
The finite difference discretization of w_tt = a^2 * w_xx - b*w is
( w(i,j+1) - 2*w(i,j) + w(i,j-1) ) / dt^2
= a^2 * ( w(i+1,j) - 2*w(i,j) + w(i-1,j) ) / dx^2 - b*w(i,j)
In your order this gives the recursion equation
w(i,j+1) = dt^2 * ( (a/dx)^2 * ( w(i+1,j) - 2*w(i,j) + w(i-1,j) ) - b*w(i,j) )
+2*w(i,j) - w(i,j-1)
The stability condition is that at least a*dt/dx < 1. For the present parameters this is not satisfied, they give this ratio as 2.6. Increasing the time discretization to 1000 points is sufficient.
Next up is the boundary conditions. Besides the two leading columns for times 0 and dt one also needs to set the values at the boundaries for x=0 and x=1. Copy also them from the exact solution.
Wn(:,1:2) = Wa(:,1:2);
Wn(1,:)=Wa(1,:);
Wn(end,:)=Wa(end,:);
Then also correct the definition (and use) of b to that in the source
b = - (lambda^2 * a^2) + mu^2;
and the resulting numerical image looks identical to the analytical image in the color plot. The difference plot confirms the closeness

Optimized point on line finding algorithm

I'm looking for an optimized integer-based point-on-line algorithm, where you can define the line using begin and end coordinates, and the point to find based on either an x or y input.
I know how to do this using dy/dx division but I'm looking for an algorithm that eliminates all divisions.
This is what I'm currently doing:
int mult = ((px - v0.x)<<16) / (v1.x - v0.x);
vec2 result{px, v0.y + (lerpmult*(v1.y - v0.y))>>16};
The division in the first line is the problem I'm trying to eliminate.
One trick to solve this would be using the scalar product to determine the cosine of the angle between two vectors:
def line_test(a, b, p):
v_ap = tuple(m - n for n, m in zip(a, p))
v_ab = tuple(m - n for n, m in zip(a, b))
scp = sum(m * n for m, n in zip(v_ap, v_ab))
return scp > 0 and scp * scp == sum(n * n for n in v_ap) * sum(n * n for n in v_ab) and all(m <= n for m, n in zip(v_ap, v_ab))
The parameters of the above function are the end-points of the line (a and b) and the point p (c in the image), which we want to test.
Step by step the following happens in each line:
v_ap = tuple(m - n for n, m in zip(a, p))
We calculate the vector from a to p (v_ap)
v_ab = tuple(m - n for n, m in zip(a, b))
The vector from a to b (v_ab)
scp = sum(m * n for m, n in zip(v_ap, v_ab))
In this line the scalar product of v_ap and v_ab is calculated. The result is scp = cos(v_ab, v_ap) * euclidean_length(v_ab) * euclidean_length(v_ap), where the euclidean length of a vector is defined as sqrt(sum(n * n for n in vector)) (the standard definition of the geometric length of a vector).
return scp > 0 and scp * scp == sum(n * n for n in v_ap) * sum(n * n for n in v_ab) and all(m <= n for m, n in zip(v_ap, v_ab)
This line is pretty complex, so I'll break it down into a few parts:
scp * scp == sum(n * n for n in v_ap) * sum(n * n for n in v_ab)
Since division isn't allowed, we shouldn't use the square-root either, since it's calculation usually involves divisions. So instead of calculating the square-root, we take the square of both the euclidean length of both vectors and the scalar product, thus eliminating the square-root calculation:
scp = cos(v_ab, v_ap) * euclidean_length(v_ab) * euclidean_length(v_ap) =
= cos(v_ab, v_ap) * sqrt(sum(n ^ 2 for n in v_ab)) * sqrt(sum(n ^ 2 for n in v_ap))
scp ^ 2 = cos(v_ab, v_ap) ^ 2 * sum(n ^ 2 for n in v_ab) * sum(n ^ 2 for n in v_ap)
The cosine of the angle between the two vectors should be 1, if they point in the same direction. So the square of the scalar product if the vectors share the same direction would be
euclidean_length(v_ap) ^ 2 * euclidean_length(v_ab) ^ 2
which we then compare to the actual scalar product scp.
This however leaves one problem: taking the square eliminates the sign, which we check separately with the comparison scp > 0. Since the euclidean length is always positive, only the sign of the cosine determines the value of scp. A negative value of scp means that the angle of between v_ap and v_ab is at least pi / 4 and at most pi * 3/4. However the sign of scp get's lost when squaring, which means that we can only check whether the two vectors are parallel, not if they point into the same direction. This problem is solved by checking scp > 0 in addition.
Last but not least we have to check whether the distance from a to p is shorter than the distance from a to b. This can be done by checking whether v_ap has a smaller length than v_ab. Since we already checked that the two vectors point into exactly the same direction, it is sufficient check whether all elements in v_ap are at most as large as the corresponding element in v_ab, which is done by
all(m <= n for m, n in zip(v_ap, v_ab))
The answer what you are finding is as follows:
Lets say our line equation is Ax + By + C = 0. Then we just need
this three coefficients (A, B and C).
Say this line goes through point P(P_x, P_y) and Q(Q_x, Q_y). Then
it is easy to calculate the above three coefficients.
A = P_y - Q_y,
B = Q_x - P_x,
C = - A P_x - B P_y
Once we have our line equation, we can easily calculate x or y
coordinate for given y or x respectfully.
Here is my c++ template:
#include <iostream>
using namespace std;
// point struct
struct pt {
int x, y;
};
// line struct
struct line {
int a, b, c;
// create line object
line() {}
line (pt p, pt q) {
a = p.y - q.y;
b = q.x - p.x;
c = - a * p.x - b * p.y;
}
// a > 0; is must be true otherwise runtime error will occure
int getX(int y) {
return (-b * y - c) / a;
}
// b > 0; is must be true otherwise runtime error will occure
int getY(int x) {
return (-a * x - c) / b;
}
};
int main() {
pt p, q;
p.x = 1, p.y = 2;
q.x = 3, q.y = 6;
line m = line(p, q);
cout << "for y = 4, x = " << m.getX(4) << endl;
cout << "for x = 2, y = " << m.getY(2) << endl;
return 0;
}
Output:
for y = 4, x = 2
for x = 2, y = 4
Ref: http://e-maxx.ru/algo/segments_intersection

How to find the n-th term in a sequence with following recurrence relation for a given n?

How to find the n-th term in a sequence with following recurrence relation for a given n?
F(n) = 2 * b * F(n – 1) – F(n – 2), F(0) = a, F(1) = b
where a and b are constants.
The value of N is quite large (1 ≤ n ≤ 1012) and so matrix exponentiation is required.
Here is my code for it; ll is a typedef for long long int, and value is to be taken modulo r.
void multiply(ll F[2][2], ll M[2][2])
{
ll x = ((F[0][0] * M[0][0]) % r + (F[0][1] * M[1][0]) % r) % r;
ll y = ((F[0][0] * M[0][1]) % r + (F[0][1] * M[1][1]) % r) % r;
ll z = ((F[1][0] * M[0][0]) % r + (F[1][1] * M[1][0]) % r) % r;
ll w = ((F[1][0] * M[0][1]) % r + (F[1][1] * M[1][1]) % r) % r;
F[0][0] = x;
F[0][1] = y;
F[1][0] = z;
F[1][1] = w;
}
void power(ll F[2][2], ll n, ll b)
{
if (n == 0 || n == 1)
return;
ll M[2][2] = {{2 * b, -1}, {1, 0}};
power(F, n / 2,b);
multiply(F, F);
if (n % 2 != 0)
multiply(F, M);
}
ll rec(ll n, ll b, ll a)
{
ll F[2][2] = {{2 * b, -1}, {1, 0}};
if (n == 0)
return a;
if (n == 1)
return b;
power(F, n - 1,b);
return F[0][0] % r;
}
However I am facing problems getting required value in all cases, that is I am getting Wrong Answer (WA) verdict for some cases.
Could anyone help me with this question and point out the mistake in this code so I can tackle these kind of problems myself afterward?
P.S. First timer here. Apologies if I did something incorrectly and missed out on anything.
Technical:
Perhaps you are asked to find the value res modulo r so that 0 <= res < r.
However, by using -1 in the matrix, you can actually get negative intermediate and final values. The reason is that, in most programming languages, the modulo operation actually uses division rounded towards zero, and so produces a result in the range -r < res < r (example link).
Try either of the following:
Change that -1 to r - 1, so that all intermediate values remain non-negative.
Fix the final result by returning (F[0][0] + r) % r instead of just F[0][0] % r.
Formula:
Your formula looks wrong. Logically, your rec function says that nothing except F(0) depends on a, which is obviously wrong.
Recall why and how we use the matrix in the first place:
( F(n) ) = ( 2b -1 ) * ( F(n-1) )
( F(n-1) ) ( 1 0 ) ( F(n-2) )
Here, we get a 2x1 vector by multiplying a 2x2 matrix and a 2x1 vector. We then look at its top element and have, by multiplication rules,
F(n) = 2b * F(n-1) + (-1) * F(n-2)
The point is, we can take the power of the matrix to get the following:
( F(n) ) = ( 2b -1 ) ^{n-1} * ( F(1) )
( F(n-1) ) ( 1 0 ) ( F(0) )
By the same argument, we have
F(n) = X * F(1) + Y * F(0)
where X and Y are the top row of the matrix:
( 2b -1 ) ^{n-1} = ( X Y )
( 1 0 ) ( Z T )
So F[0][0] % r is not the answer, really.
The real answer looks like
(F[0][0] * b + F[0][1] * a) % r
If we can have negative intermediate values (see point 1 above), the result is still from -r to r instead of from 0 to r. To fix it, we can add one more r and take the modulo once again:
((F[0][0] * b + F[0][1] * a) % r + r) % r
Possible reason for WA is, you return a or b without doing any mod.
Try it.
if (n == 0)
return a%r;
if (n == 1)
return b%r;
If you are still getting WA, please give some test cases or problem link.

For integers A>0, B>0, N>0, find integers x>0,y>0 such that N-(Ax+By) is smallest non-negative

Example :
A=5, B=2, N=12
Then let x=2, y=1, so 12 - (5(2) + 2(1)) = 0.
Another example:
A=5, B=4, N=12
Here x=1, y=1 is the best possible. Note x=2, y=0 would be better except that x=0 is not allowed.
I'm looking for something fast.
Note it's sufficient to find the value of Ax+By. It's not necessary to give x or y explicitly.
If gcd(A,B)|N, then N is your maximal value. Otherwise, it's the greatest multiple of gcd(A,B) that's smaller than N. Using 4x+2y=13 as an example, that value is gcd(4,2)*6=12 realized by 4(2)+2(2)=12 (among many solutions).
As a formula, your maximal value is Floor(N/gcd(A,B))*gcd(A,B).
Edit: If both x and y must be positive, this may not work. However, won't even be a solution if A+B>N. Here's an algorithm for you...
from math import floor, ceil
def euclid_wallis(m, n):
col1 = [1, 0, m]
col2 = [0, 1, n]
while col2[-1] != 0:
f = -1 * (col1[-1] // col2[-1])
col2, col1 = [x2 * f + x1 for x1, x2 in zip(col1, col2)], col2
return col1, col2
def positive_solutions(A, B, N):
(x, y, gcf), (cx, cy, _) = euclid_wallis(A, B)
f = N // gcf
while f > 0:
fx, fy, n = f*x, f*y, f*gcf
k_min = (-fx + 0.) / cx
k_max = (-fy + 0.) / cy
if cx < 0:
k_min, k_max = k_max, k_min
if floor(k_min) + 1 <= ceil(k_max) - 1:
example_k = int(floor(k_min) + 1)
return fx + cx * example_k, fy + cy * example_k, n
if k_max <= 1:
raise Exception('No solution - A: {}, B: {}, N: {}'.format(A, B, N))
f -= 1
print positive_solutions(5, 4, 12) # (1, 1, 9)
print positive_solutions(2, 3, 6) # (1, 1, 5)
print positive_solutions(23, 37, 238) # (7, 2, 235)
A brute-force O(N^2 / A / B) algorithm, implemented in plain Python3:
import math
def axby(A, B, N):
return [A * x + B * y
for x in range(1, 1 + math.ceil(N / A))
for y in range(1, 1 + math.ceil(N / B))
if (N - A * x - B * y) >= 0]
def bestAxBy(A, B, N):
return min(axby(A, B, N), key=lambda x: N - x)
This matched your examples:
In [2]: bestAxBy(5, 2, 12)
Out[2]: 12 # 5 * (2) + 2 * (1)
In [3]: bestAxBy(5, 4, 12)
Out[3]: 9 # 5 * (1) + 4 * (1)
Have no idea what algorithm that might be, but I think you need something like that (C#)
static class Program
{
static int solve( int a, int b, int N )
{
if( a <= 0 || b <= 0 || N <= 0 )
throw new ArgumentOutOfRangeException();
if( a + b > N )
return -1; // Even x=1, y=1 still more then N
int x = 1;
int y = ( N - ( x * a ) ) / b;
int zInitial = a * x + b * y;
int zMax = zInitial;
while( true )
{
x++;
y = ( N - ( x * a ) ) / b;
if( y <= 0 )
return zMax; // With that x, no positive y possible
int z = a * x + b * y;
if( z > zMax )
zMax = z; // Nice, found better
if( z == zInitial )
return zMax; // x/y/z are periodical, returned where started, meaning no new values are expected
}
}
static void Main( string[] args )
{
int r = solve( 5, 4, 12 );
Console.WriteLine( "{0}", r );
}
}

How to pick a number based on probability?

I want to select a random number from 0,1,2,3...n, however I want to make it that the chance of selecting k|0<k<n will be lower by multiplication of x from selecting k - 1 so x = (k - 1) / k. As bigger the number as smaller the chances to pick it up.
As an answer I want to see the implementation of the next method:
int pickANumber(n,x)
This is for a game that I am developing, I saw those questions as related but not exactly that same:
How to pick an item by its probability
C Function for picking from a list where each element has a distinct probabili
p1 + p2 + ... + pn = 1
p1 = p2 * x
p2 = p3 * x
...
p_n-1 = pn * x
Solving this gives you:
p1 + p2 + ... + pn = 1
(p2 * x) + (p3 * x) + ... + (pn * x) + pn = 1
((p3*x) * x) + ((p4*x) * x) + ... + ((p_n-1*x) * x) + pn = 1
....
pn* (x^(n-1) + x^(n-2) + ... +x^1 + x^0) = 1
pn*(1-x^n)/(1-x) = 1
pn = (1-x)/(1-x^n)
This gives you the probability you need to set to pn, and from it you can calculate the probabilities for all other p1,p2,...p_n-1
Now, you can use a "black box" RNG that chooses a number with a distribution, like those in the threads you mentioned.
A simple approach to do it is to set an auxillary array:
aux[i] = p1 + p2 + ... + pi
Now, draw a random number with uniform distribution between 0 to aux[n], and using binary search (aux array is sorted), get the first value, which matching value in aux is greater than the random uniform number you got
Original answer, for substraction (before question was editted):
For n items, you need to solve the equation:
p1 + p2 + ... + pn = 1
p1 = p2 + x
p2 = p3 + x
...
p_n-1 = pn + x
Solving this gives you:
p1 + p2 + ... + pn = 1
(p2 + x) + (p3 + x) + ... + (pn + x) + pn = 1
((p3+x) + x) + ((p4+x) + x) + ... + ((p_n-1+x) + x) + pn = 1
....
pn* ((n-1)x + (n-2)x + ... +x + 0) = 1
pn* x = n(n-1)/2
pn = n(n-1)/(2x)
This gives you the probability you need to set to pn, and from it you can calculate the probabilities for all other p1,p2,...p_n-1
Now, you can use a "black box" RNG that chooses a number with a distribution, like those in the threads you mentioned.
Be advised, this is not guaranteed you will have a solution such that 0<p_i<1 for all i, but you cannot guarantee one given from your requirements, and it is going to depend on values of n and x to fit.
Edit This answer was for the OPs original question, which was different in that each probability was supposed to be lower by a fixed amount than the previous one.
Well, let's see what the constraints say. You want to have P(k) = P(k - 1) - x. So we have:
P(0)
P(1) = P(0) - x
P(2) = P(0) - 2x
...
In addition, Sumk P(k) = 1. Summing, we get:
1 = (n + 1)P(0) -x * n / 2 (n + 1),
This gives you an easy constraint between x and P(0). Solve for one in terms of the other.
For this I would use the Mersenne Twister algorithm for a uniform distribution which Boost provides, then have a mapping function to map the results of that random distribution to the actual number select.
Here's a quick example of a potential implementation, although I left out the quadtratic equation implementation since it is well known:
int f_of_xib(int x, int i, int b)
{
return x * i * i / 2 + b * i;
}
int b_of_x(int i, int x)
{
return (r - ( r ) / 2 );
}
int pickANumber(mt19937 gen, int n, int x)
{
// First, determine the range r required where the probability equals i * x
// since probability of each increasing integer is x higher of occuring.
// Let f(i) = r and given f'(i) = x * i then r = ( x * i ^2 ) / 2 + b * i
// where b = ( r - ( x * i ^ 2 ) / 2 ) / i . Since r = x when i = 1 from problem
// definition, this reduces down to b = r - r / 2. therefore to find r_max simply
// plugin x to find b, then plugin n for i, x, and b to get r_max since r_max occurs
// when n == i.
// Find b when
int b = b_of_x(x);
int r_max = f_of_xib(x, n, b);
boost::uniform_int<> range(0, r_max);
boost::variate_generator<boost::mt19937&, boost::uniform_int<> > next(gen, range);
// Now to map random number to desired number, just find the positive value for i
// when r is the return random number which boils down to finding the non-zero root
// when 0 = ( x * i ^ 2 ) / 2 + b * i - r
int random_number = next();
return quadtratic_equation_for_positive_value(1, b, r);
}
int main(int argc, char** argv)
{
mt19937 gen;
gen.seed(time(0));
pickANumber(gen, 10, 1);
system("pause");
}

Resources