How to make this algorithm stable - algorithm

I have to compute the iterative version of this formula:
f(i)=integral ( x^i/(4x+1) ) from 0 to 1
Using these formulas:
f(0)=ln(5)/4;
f(i)=1/(i+1) - 4*f(i+1);
I have tried tried the following: I calculate integral ( x^100/(4x+1) ) from 0 to 1, and store the result.Then I calculate f(i) starting from this result, using the iterative version.
But I get wrong result because the error is too big.
The error is acceptable only for i<=25.
I would like to know, why this algorithm is not stable and if there's a solution to compute the result starting from i=100 or higher.
This is the code:
function y=Integral(i,max)
if i==0
y=1/4*log(5);
elseif i==max
y=0.0;
else
y=1/(i+1)-4*Integral(i+1,max);
end
end
With this function I never get an exact value because the error accumulated is too high.I get a close value (but even 3 or 4 times higher, so not acceptable) if I use i=15 and max=18.I need the stable version of this formula.

This recursive function should do the job without the need to store partial results on the way to 100:
function y = Integral(i)
if i==0
y=log(5)/4;
else
y = (-Integral(i-1) + 1/i)/4;
end
end
For recursion to work you need to start from i=100 and then call the function with i-1 until it reaches i=0.
Integral(100) will give the final answer without the need to store partial results.

Related

linear probability from non-linear one

here is my problem.
Imagine you've got a function like that : (here in C )
int strangeRand() {
if ( rand() % 100 <= 70 ) return 0;
else return 1;
}
This one return 0 a probability of 0.7
and 1 with a probability of 0.3
Here is what i want to do, create a function that return 0 with a probability of 0.5 and 1 with a probability of 0.5 too.
I need to only use strangeRand() function [Can't modify it] (and loop, and if etc but no rand() function )
Is someone got an idea, how to do this ?
Thanks.
This is actually a solved problem! It's usually known as getting a fair result from an unfair coin.
The algorithm works as follows:
Call the function twice.
If the results match, start over, forgetting both results.
If the results differ, use the first result, forgetting the second.
The provided link contains an explanation of why the algorithm works.

Find a math algorithm for an equation

I just post a mathematic question at math.stackexchange, but I'll ask people here for a programmatically recursive algorithm.
The problem: fill in the blank number from 1 to 9 (once and only once each blank) to finish the equation.
Additional conditions:
1. Mathematic priority DOES matter.
2. All numbers (include evaluation result) should be integers.
Which mean the divide should be divisible (E.g. 9 mod 3 = 0 is OK, 8 mod 3 != 0 is not OK).
3. For those who don't know (as one in the original question), the operations in the diagram are:
+ = plus; : = divide; X = multiple; - = minus.
There should be more than 1 answer. I'd like to have a recursive algorithm to find out all the solutions.
Original question
PS: I'd like to learn about the recursive algorithm, performance improval. I was trying to solve the problem using brute force. My PC freeze for quite a while.
You have to find the right permuations
9! = 362880
This is not a big number and you can do your calculations the following way:
isValid(elements)
//return true if and only if the permutation of elements yields the expected result
end isValid
isValid is the validator, which checks whether a given permutation is correct.
calculate(elements, depth)
//End sign
if (depth >= 9) then
//if valid, then store
if (isValid(elements)) then
store(elements)
end if
return
end if
//iterate elements
for element = 1 to 9
//exclude elements already in the set
if (not contains(elements, element)) then
calculate(union(elements, element), depth + 1)
end if
end for
end calculate
Call calculate as follows:
calculate(emptySet, 1)
Here's a solution using PARI/GP:
div(a,b)=if(b&&a%b==0,a/b,error())
f(v)=
{
iferr(
v[1]+div(13*v[2],v[3])+v[4]+12*v[5]-v[6]-11+div(v[7]*v[8],v[9])-10==66
, E, 0)
}
for(i=0,9!-1,if(f(t=numtoperm(9,i)),print(t)))
The function f defines the particular function here. I used a helper function div which throws an error if the division fails (producing a non-integer or dividing by 0).
The program could be made more efficient by splitting out the blocks which involve division and aborting early if they fail. But since this takes only milliseconds to run through all 9! permutations I didn't think it was worth it.

Finding the exp

Hi I have a question on the result of the following function
The input is the row vector of x and we are outputing the calculated exp value using the ∑_(n=0)^(n=50)▒(x^n)/n! (i.e. Summation from n=0 to n=50 using x^n)/n!)
The loop will terminate either when n reaches 50 or (x^n)/n! < 0.01
function [summ] = ExpFunction(x)
// there is a loop to iterate.
There are two versions
1) We write an if to see if the value (x^n)/n! is >= 0.01. if it is then add it the the summ.
2) Add it to the summ first and then check if (x^n)/n! is >= 0.01. if not then terminates the program.
My question is that why do the two versions produce different results and the second version appears to produce better results(i.e. closer the exp(x) )
Thank you
version 1:
function [result] = Exp(x)
result = 0;
a = 0;
n = 0;
while(n <= 50)
{
a = (x.^n)/factorial(n) %% The factorial function is self written have have been checked.
if(abs(a) >= 0.01)
result = result + a;
else
break;
n = n + 1;
}
Second version is to do result = result + a; before checking abs(a) >=0.01
The question seems simple. The series is increasing (i.e. each addition results in a larger sum) and the limit value is being approached from below. This means that every new term added to the sum is getting closer to the final value = the limit. This results in each addition being a better approximation to the result.
It is also clear that the first method, not adding the term, will result in a slightly less accurate result than the second method, which does add the term.
It is clear that the accuracy of the result is improved by adding more terms. The only cost is the extra computing time. Is your termination criterion (x^n/factorial(n) < 0.01) giving good enough values for all values of x? I would have expected you to use a formula more like (x^n/factorial(n) < g(x)) where g(x) is a formula involving x. I suggest that you go back to the text on series and determine whether a better g(x) is required for your accuracy requirements.

a faster way of implementing the nested loop with gamma function

I am trying to evaluate the following integral:
I can find the area for the following polynomial as follows:
pn =
-0.0250 0.0667 0.2500 -0.6000 0
First using the integration by Simpson's rule
fn=#(x) exp(polyval(pn,x));
area=quad(fn,-10,10);
fprintf('area evaluated by Simpsons rule : %f \n',area)
and the result is area evaluated by Simpsons rule : 11.483072
Then with the following code that evaluates the summation in the above formula with gamma function
a=pn(1);b=pn(2);c=pn(3);d=pn(4);f=pn(5);
area=0;
result=0;
for n=0:40;
for m=0:40;
for p=0:40;
if(rem(n+p,2)==0)
result=result+ (b^n * c^m * d^p) / ( factorial(n)*factorial(m)*factorial(p) ) *...
gamma( (3*n+2*m+p+1)/4 ) / (-a)^( (3*n+2*m+p+1)/4 );
end
end
end
end
result=result*1/2*exp(f)
and this returns 11.4831. More or less the same result with the quad function. Now my question is whether or not it is possible for me to get rid of this nested loop as I will construct the cumulative distribution function so that I can get samples from this distribution using the inverse CDF transform. (for constructing the cdf I will use gammainc i.e. the incomplete gamma function instead of gamma)
I will need to sample from such densities that may have different polynomial coefficients and speed is of concern to me. I can already sample from such densities using Monte Carlo methods but I would like to see whether or not it is possible for me to use exact sampling from the density in order to speed up.
Thank you very much in advance.
There are several things one might do. The simplest is to avoid calling factorial. Instead one can use the relation that
factorial(n) = gamma(n+1)
Since gamma seems to be actually faster than a call to factorial, you can save a bit there. Even better, you can
>> timeit(#() factorial(40))
ans =
4.28681157826087e-05
>> timeit(#() gamma(41))
ans =
2.06671024634146e-05
>> timeit(#() gammaln(41))
ans =
2.17632543333333e-05
Even better, one can do all 4 calls in a single call to gammaln. For example, think about what this does:
gammaln([(3*n+2*m+p+1)/4,n+1,m+1,p+1])*[1 -1 -1 -1]'
Note that this call has no problem with overflows either in case your numbers get large enough. And since gammln is vectorized, that one call is fast. It costs little more time to compute 4 values than it does to compute one.
>> timeit(#() gammaln([15 20 40 30]))
ans =
2.73937416896552e-05
>> timeit(#() gammaln(40))
ans =
2.46521943333333e-05
Admittedly, if you use gammaln, you will need a call to exp at the end to recover the final result. You could do it with a single call to gamma however too. Perhaps like this:
g = gamma([(3*n+2*m+p+1)/4,n+1,m+1,p+1]);
g = g(1)/(g(2)*g(3)*g(4));
Next, you can be more creative in the inner loop on p. Rather than a full loop, coupled with a test to ignore the combinations you don't need, why not just do this?
for p=mod(n,2):2:40
That statement will select only those values of p that would have been used anyway, so now you can drop the if statement completely.
All of the above will give you what I'll guess is about a 5x speed increase in your loops. But it still has a set of nested loops. With some effort, you might be able to improve that too.
For example, rather than computing all of those factorials (or gamma functions) many times, do it ONCE. This should work:
a=pn(1);b=pn(2);c=pn(3);d=pn(4);f=pn(5);
area=0;
result=0;
nlim = 40;
facts = factorial(0:nlim);
gammas = gamma((0:(6*nlim+1))/4);
for n=0:nlim
for m=0:nlim
for p=mod(n,2):2:nlim
result = result + (b.^n * c.^m * d.^p) ...
.*gammas(3*n+2*m+p+1 + 1) ...
./ (facts(n+1).*facts(m+1).*facts(p+1)) ...
./ (-a)^( (3*n+2*m+p+1)/4 );
end
end
end
result=result*1/2*exp(f)
In my test on my machine, I find that your triply nested loops required 4.3 seconds to run. My version above produces the same result, yet required only 0.028418 seconds, a speedup of roughly 150 to 1, despite the triply nested loops.
Well, without even making changes to your code you could install an excellent package from Tom Minka at Microsoft called lightspeed which replaces some built-in matlab functions with much faster versions. I know there's a replacement for gammaln().
You'll get nontrivial speed improvements, though I'm not sure how much, and it's straight-forward to install.

Why does Math.Log crash only inside my for loop?

I have the below code
A = 1.0
B = 0.20
N = 8.0
for i in 1..Total
t = Maxt * rand
x = A * Math.cos(t) / (Math.log(B*Math.tan(t/(2*N))))
y = A * Math.sin(t) / (Math.log(B*Math.tan(t/(2*N))))
end
If I comment out the For loop it executes fine and produces 1 of the results I want. If I don't comment out the for loop, it generates the below. I am a newbie with Ruby and am mainly curious why it only breaks when the for loop is present.
rubyfile.rb:22:in `log': Numerical argument out of domain - log (Errno::EDOM)
from rubyfile.rb:22
from rubyfile.rb:20:in `each'
from rubyfile.rb:20
Math.log represents the logarithm function, which is undefined for negative numbers. Math.tan, however, represents the tangent function, which can return negative numbers. So, if Math.tan comes out to a negative number, the Math.log will tell you that its argument is "out of domain", meaning that there is no logarithm for that number.
I'm betting the fact that your input is random means that, when you loop, you are far more likely to get that error than if you just run the script once. If you were the remove the loop then run the script multiple times, I bet you'd get that error eventually.
Find out why your math involves negative numbers when it shouldn't, and you're good to go :)
B*Math.tan(t/(2*N))) will take negative values and log is undefined for x < 0. As the error states, you're out of domain.

Resources