How to estimate the number of recursive calls
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 24

Thread: How to estimate the number of recursive calls

Hybrid View

  1. #1
    Join Date
    Dec 2012
    Posts
    7

    Question How to estimate the number of recursive calls

    How to estimate the number of recursive calls that would be used by the code
    Code:
    public static double binomial(int N, int k, double p)
    {
    if ((N == 0) || (k < 0)) return 1.0;
    return (1.0 - p)*binomial(N-1, k) + p*binomial(N-1, k-1);
    }
    to compute binomial(100, 50)???

    I am looking for the formula that gives me the exact number of calls
    I sent an email to writer of the book that I found this problem in it and he answered me:

    Hint: calculate the number of calls for some small values of N and k and consider functions that involve N! (N factorial) and k! (k factorial).
    but still nothing and I am confused

  2. #2
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,011

    Re: How to estimate the number of recursive calls

    So, which small values for N and k did you try?
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  3. #3
    Join Date
    Dec 2012
    Posts
    7

    Re: How to estimate the number of recursive calls

    Quote Originally Posted by D_Drmmr View Post
    So, which small values for N and k did you try?
    I wrote a program that gives me the numbes but for (100,50) it takes too long
    I am sure that there is a formul

    Code:
    (1,0)=3
    (2,0)=5
    (2,1)=7
    (3,0)=7
    (3,1)=13
    (3,2)=15
    (4,0)=9
    (4,1)=21
    (4,2)=29
    (4,3)=31
    (5,0)=11
    (5,1)=31
    (5,2)=51
    (5,3)=61
    (5,4)=63
    (6,0)=13
    (6,1)=43
    (6,2)=83
    (6,3)=113
    (6,4)=125
    (6,5)=127
    (7,0)=15
    (7,1)=57
    (7,2)=127
    (7,3)=197
    (7,4)=239
    (7,5)=253
    (7,6)=255
    (8,0)=17
    (8,1)=73
    (8,2)=185
    (8,3)=325
    (8,4)=437
    (8,5)=493
    (8,6)=509
    (8,7)=511

  4. #4
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,011

    Re: How to estimate the number of recursive calls

    Quote Originally Posted by arira View Post
    I wrote a program that gives me the numbes but for (100,50) it takes too long
    I am sure that there is a formul
    Of course, and the question is about finding that formula, rather than the specific answer.

    Let's take the following approach: write a function f that expresses the number of recursive calls in terms of n and k.
    Forgetting the check on the value of n and k for a minute, it should be obvious that f(n, k) = f(n - 1, k) + f(n - 1, k - 1).
    You can expand this further in steps by substituting this formula for the elements on the right hand side. I.e. the second step yields f(n, k) = f(n - 2, k) + 2 * f(n - 2, k - 1) + f(n - 2, k - 2).
    Repeat this for a few steps and then have a look at this: http://en.wikipedia.org/wiki/Pascal's_triangle
    That should help you to find a more general formula for f(n, k). Once you have that, you can consider how to introduce the if condition in the function.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  5. #5
    Join Date
    Dec 2012
    Posts
    7

    Re: How to estimate the number of recursive calls

    I tried before all of this and I think no one knows the answer in the world and wanna give up because it takes my time too much and spent enough time for this problem.

    number of recursive calls :

    Code:
    f(n, k) = f(n - 1, k) + f(n - 1, k - 1) + 1
    thanks

  6. #6
    Join Date
    May 2009
    Posts
    2,413

    Re: How to estimate the number of recursive calls

    Quote Originally Posted by arira View Post
    I tried before all of this and I think no one knows the answer in the world and wanna give up because it takes my time too much and spent enough time for this problem.
    I think I have a solution.

    Each call to f gives rise to two new calls to f recursively. One can think of the call pattern as an imaginary binary tree. Each call to f represents a node and the first f call in f goes to the left child node and the second to the right child node.

    If k is equal to n or bigger then the recursion will be limited by n only. The imaginary binary tree will be complete and have a depth of n. The number of nodes, or rather f calls, will be 2^(n+1) - 1. Say n=1 for example that will give 3 f calls and if n=2 there are 7.

    Now if k is made smaller than n it will start limiting the recursion. The imaginary binary tree will no longer be complete. Certain branches will be ignored because k becomes negative in some call paths and that will stop the recursion before it reaches the maximum depth determined by n. This happens each time the second call to f in f has been called k+1 times along a call path (the first call to f in f leaves k unchanged).

    The question becomes: How many nodes, that is f calls, in the imaginary binary tree won't be visited because of k? If those are subtracted from the total number of nodes of the complete binary tree we have the number of actual f calls. An analysis is somewhat involved. If a node (f call) in the complete binary tree is on a path below more than k+1 right side child nodes (calls to the second f in f) then it will never be reached (because of the k limit) and should be subtracted from the total.

    The result is simple and somewhat surprising. The number of never performed f calls can be found in Pascal's triangle! They're in a subtriangle defined by n and k. One simply add up all binominal coefficients of that subtriangle and double the sum.

    Code:
    Pascal's triangle
    -----------------
    1:        1 1
    2:       1 2 1
    3:      1 3 3 1
    4:     1 4 6 4 1
    5:    1 5 10 10 5 1
    6:   1 6 15 20 15 6 1
    7:    ...
    The subtriangle for f(n,k) is from k+1 to n-1. To show how the subtriangle is extracted is easiest with an example.

    If n=4 and k=1 the subtriangle is from 2 to 3 and looks like this:

    Code:
    Subtriangle (from k+1=2 to n-1=3)
    ---------------------------------
    2:       1
    3:      1 3
    All coefficients are added and the sum is doubled. That's the number of f calls that should be removed from the maximum total (which is 2^(n+1) - 1 according to the formula above). So we have f(4,1) = (2^(4+1) - 1) - 2*(1 + 1+3) = (32 - 1) - 2*5 = 21.

    If instead n=6 and k=2 one gets a subtriangle from 3 to 5 like:

    Code:
    Subtriangle (from k+1=3 to n-1=5)
    ---------------------------------
    3:      1
    4:     1 4
    5:    1 5 10
    And f(6,2) = (2^(6+1) - 1) - 2*(1 + 1+4 + 1+5+10) = (128-1) - 2*22 = 83.

    Since Pascal's triangle can be calculated in quadratic time an f(n,k) algorithm based on that will be O(N^2). On the other hand binominal coefficients quickly become very large so f(100, 50) is hardly tractable with standard hardware supported arithmetics.
    Last edited by nuzzle; December 13th, 2012 at 06:54 AM.

  7. #7
    Join Date
    Dec 2012
    Posts
    7

    Question Re: How to estimate the number of recursive calls

    Quote Originally Posted by nuzzle View Post
    I think I have a solution.

    Each call to f gives rise to two new calls to f recursively. One can think of it as a binary tree. Each call to f represents a node and the first f call in f goes to the left and the second to the right.

    If k is equal to n or bigger then the recursion will be limited by n only. The imaginary binary tree will be complete and have a depth of n. The number of nodes, or rather f calls, will be 2^(n+1) - 1. Say n=1 for example that will give 3 f calls.

    Now if k is made smaller than n it will start limiting the recursion. The imaginary binary tree will no longer be complete. Certain branches will be ignore because k has become smaller than 0 for certain paths and the recursion will stop until it reaches the maximum depth sey by n. This happens each time the second call to f in f has been called k+1 times because then k becomes negative (the first call to f in f leaves k unchanged)

    The question now becomes: How many nodes, that is f calls, in the imaginary binary tree won't be visited because of k? If those are subtracted from the total number of nodes of the complete binary tree we have the number of actual f calls.

    An analysis is somewhat involved. If a node is reached after more than k+1 "right child" calls to f then it should be subtracted from the total. But the result is simple and somewhat surprising. The number of not performed f calls can found in Pascal's triangle. One simply cuts out a subtriangle and add up all coefficients.

    Code:
    Pascal's triangle
    ---------------
    1:        1 1
    2:       1 2 1
    3:      1 3 3 1
    4:     1 4 6 4 1
    5:    1 5 10 10 5 1
    6:   1 6 15 20 15 6 1
    Now if n=4 and k=1 you cut out this subtriangle from k+1 to n-1.

    Code:
    Subtriangle (cut from k+1=2 to n-1=3)
    ---------------------------------------------
    2:       1
    3:      1 3
    You add up the numbers and double the sum. That's the number of nodes (f calls) that should be removed from the total which is 2^(n+1) - 1 according to the formula above. So we have f(4,1) = (2^(4+1) - 1) - 2*(1 + 1+3) = (32 - 1) - 2*5 = 21.

    If instead n=6 and k=2 you get,

    Code:
    Subtriangle (cut from  k+1=3 to n-1=5)
    ---------------------------------------------
    3:      1
    4:     1 4
    5:    1 5 10
    And f(6,2) = (2^(6+1) - 1) - 2*(1 + 1+4 + 1+5+10) = (128-1) - 2*22 = 83.

    Since Pascal's triangle can be calculated in quadratic time the algorithm is O(N^2). On the other hand binominal coefficients quickly become very large so f(100, 50) is hardly tractable with standard arithmetic.
    thank for your answer
    but there is only one thing remains
    I sent an mail to the writer of the book that I found this problem and he answered me
    Code:
    Hint: calculate the number of calls for some small values of N and k and consider functions that involve N! (N factorial) and k! (k factorial).
    where is the factorial in this formula?

  8. #8
    Join Date
    May 2009
    Posts
    2,413

    Re: How to estimate the number of recursive calls

    Quote Originally Posted by arira View Post
    where is the factorial in this formula?
    Pascal's triangle consists of binominal coefficients (n|k) defined as n! / (k! * (n-k)!) so there are lots of factorials in the solution. I wouldn't say that hinting at factorials is such a great help really but maybe the author has some other solution approach in mind where they play a more prominent role.

    In my solution binominals appear because they have a combinatorial interpretation. (n|k) tells how many ways there are to order k of n elements. There may be a deeper reason why they appear as a subtriangle of Pascal's triangle or maybe it's just coincidental. I couldn't say but it's interesting.
    Last edited by nuzzle; December 12th, 2012 at 06:05 AM.

  9. #9
    Join Date
    Feb 2011
    Location
    United States
    Posts
    1,005

    Re: How to estimate the number of recursive calls

    The entries in Pascal's triangle can be expressed in terms of factorials ( https://en.wikipedia.org/wiki/Pascal...e#Combinations ). By nuzzle's analysis, you are summing over entries in the triangle. Presumably there is some analytical solution.
    Best Regards,

    BioPhysEngr
    http://blog.biophysengr.net
    --
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  10. #10
    Join Date
    Feb 2011
    Location
    United States
    Posts
    1,005

    Re: How to estimate the number of recursive calls

    To follow up: possibly of interest, though perhaps at an excessive level of detail: http://mathworld.wolfram.com/BinomialSums.html
    Best Regards,

    BioPhysEngr
    http://blog.biophysengr.net
    --
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  11. #11
    Join Date
    May 2009
    Posts
    2,413

    Re: How to estimate the number of recursive calls

    Quote Originally Posted by BioPhysEngr View Post
    Presumably there is some analytical solution.
    Maybe the sum of binominals I have in my solution can be reduced to factorials but computationally it may be better to keep the binominals. It's because of the relationship with Pascal's triangle in this case. Factorials becomes awfully big very quickly and require lots of multiplications to compute. Binominals on the other hand stay smaller and if the recurrent Pascal's triangle algorithm is used only additions are needed. For example the factorial 20! is 2432902008176640000 while the binominal (20|10) is just 184756.

    I looks like the OP is using Java and it sports a standard class for arbitrary-precision integers called BigInteger. Using BigInteger in combination with the very efficient recurrent Pascal's triangle algorithm would make it possible I think to find the exact solution to even something as big as f(100,50) in reasonable time.
    Last edited by nuzzle; December 13th, 2012 at 06:56 AM.

  12. #12
    Join Date
    Dec 2012
    Posts
    7

    Re: How to estimate the number of recursive calls

    Quote Originally Posted by nuzzle View Post
    Maybe the sum of binominals I have in my solution can be reduced to factorials but computationally it may be better to keep the binominals. It's because of the relationship with Pascal's triangle in this case. Factorials becomes awfully big very quickly and require lots of multiplications to compute. Binominals on the other hand stay smaller and if the recurrent Pascal's triangle algorithm is used only additions are needed. For example the factorial 20! is 2432902008176640000 while the binominal (20|10) is just 184756.

    I looks like the OP is using Java and it sports a standard class for arbitrary-precision integers called BigInteger. Using BigInteger in combination with the very efficient recurrent Pascal's triangle algorithm would make it possible I think to find the exact solution to even something as big as f(100,50) in reasonable time.
    I know what you mean but our purpose is to find a formula not a better way to calculate binomial
    we can say in formula 50! and don't need to calculate it because it is formula

  13. #13
    Join Date
    May 2009
    Posts
    2,413

    Re: How to estimate the number of recursive calls

    Quote Originally Posted by arira View Post
    I know what you mean but our purpose is to find a formula not a better way to calculate binomial
    we can say in formula 50! and don't need to calculate it because it is formula
    Well, in the outset you were desperate for even a solution to this problem and now you've been presented with both an analytical formula and an algorithm for its efficient calculation.

    I'm sure you can take it from here, can't you?

  14. #14
    Join Date
    Dec 2012
    Posts
    7

    Resolved Re: How to estimate the number of recursive calls

    Quote Originally Posted by nuzzle View Post
    Well, in the outset you were desperate for even a solution to this problem and now you've been presented with both an analytical formula and an algorithm for its efficient calculation.

    I'm sure you can take it from here, can't you?
    yeah I think I can do
    many thank to you

  15. #15
    Join Date
    May 2009
    Posts
    2,413

    Re: How to estimate the number of recursive calls

    This is the biggest integer I've ever calculated,

    f(2000, 1000) =
    1209534321 9735098552 2903522586 7446778809 8668638152
    9033033273 7325193927 2634582289 8869424817 6781461447
    0294409273 1357601491 2317637051 5305036720 9372516932
    2073305244 1230852872 8460082699 4515592105 7639325243
    8822463388 1260473484 3111276259 8987157639 2918042559
    8529937335 7198161486 1757772413 3263187077 6197841476
    0695661597 2817042973 3181299132 5620020547 1522883226
    1828324145 3410507555 2256126444 3935238098 3367645450
    2592255180 5298299119 7437362408 6333913348 2328527571
    0095093958 9645321675 9311085561 7293560592 5007747916
    5565749079 7322221063 3340124528 3282046444 6579215765
    1962457506 7927119801 7132820676 0505220292 2739198418
    495

    I took just a second on an ordinary desktop. Quite amazing.

    The code is written in Java using BigInteger and the recurrent Pascal's triangle algorithm.

    Code:
    import java.math.BigInteger;
    import java.util.ArrayList;
    
    public class Main {
    
    		// the rows of Pascal's triangle one by one
    	static class PascalRows extends ArrayList<BigInteger> {
    		{	add(BigInteger.ONE);}
    		public void nextRow() {
    			BigInteger f = get(0);
    			for (int i=1,N=size(); i<N; i++) {
    				final BigInteger s = get(i);
    				set(i, f.add(s));
    				f = s;
    			}
    			add(BigInteger.ONE);
    		}
    	}
    		// sum of all binominals of a subtriangle of Pascal's triangle
    	static BigInteger subTriangle(int n, int k) {
    		BigInteger sum = BigInteger.ZERO;
    		final PascalRows pascal = new PascalRows();
    		for (int i=0; i<k; i++) pascal.nextRow();
    		for (int i=0,N=n-k-1; i<N; i++) {
    			pascal.nextRow();
    			for (int j=0; j<=i; j++) sum = sum.add(pascal.get(j));
    		}
    		return sum;
    	}
    		// f(n,k) = 2 * (2^n - subTriangle(n,k)) - 1
    	static BigInteger f(int n, int k) {
    		return BigInteger.ONE.shiftLeft(n).subtract(subTriangle(n,k)).shiftLeft(1).subtract(BigInteger.ONE);
    	}
    	
    	public static void main(String[] args) {
    		System.out.println("Hello World!");
    		System.out.println(f(2000,1000));
    	}
    }
    This was a nostalgic trip down memory lane. I haven't used Java or Eclipse for years.

    BigInteger is something of a fossil. It's the only surviving reminder of a proud initiative called Java Grande. It was active at the peak of the Java hype age when there still was no limit to what Java could and should be used for. So much effort and now it's just a faint memory in the senile minds of a few elders who still remember Java in its hayday. So sad.

    http://www.javagrande.org/

    But BigInteger still is nice and handy. I wish Boost offered an arbitrary precision arithmetics package (at least I haven't seen any).
    Last edited by nuzzle; December 18th, 2012 at 03:46 AM.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center