3

I'm having issues with my adaptive trapezoidal rule algorithm in C++ -- basically, regardless of the tolerance specified, I get the same exact approximation. The recursion is supposed to stop very early for large tolerances (since abs(coarse-fine) is going to be smaller than 3.0*large tolerance and minLevel of recursion is about 5).

However, what this function does is run the maximum number of times regardless of choice of tolerance. Where did I mess up? EDIT: Perhaps there are issues in my helper functions?

double trap_rule(double a, double b, double (*f)(double),double tolerance, int count)
{
    double coarse = coarse_helper(a,b, f); //getting the coarse and fine approximations from the helper functions
    double fine = fine_helper(a,b,f);

    if ((abs(coarse - fine) <= 3.0*tolerance) && (count >= minLevel))
        //return fine if |c-f| <3*tol, (fine is "good") and if count above
        //required minimum level
    {
        return fine;
    }
    else if (count >= maxLevel)
        //maxLevel is the maximum number of recursion we can go through
    {
        return fine;

    }
    else
    {
        //if none of these conditions are satisfied, split [a,b] into [a,c] and [c,b] performing trap_rule
        //on these intervals -- using recursion to adaptively approach a tolerable |coarse-fine| level
        //here, (a+b)/2 = c
        ++count;
        return  (trap_rule(a, (a+b)/2.0, f, tolerance/2.0, count) + trap_rule((a+b)/2.0, b, f, tolerance/2.0, count));
    }
}


EDIT: Helper and test functions:

//test function
double function_1(double a)
{
    return pow(a,2);
}

//"true" integral for comparison and tolerances




//helper functions

double coarse_helper(double a, double b, double (*f)(double))
{
    return 0.5*(b - a)*(f(a) + f(b)); //by definition of coarse approx
}


double fine_helper(double a, double b, double (*f)(double))
{
    double c = (a+b)/2.0;
    return 0.25*(b - a)*(f(a) + 2*f(c) + f(b)); //by definition of fine approx
}

double helper(double a, double b, double (*f)(double x), double tol)
{
    return trap_rule(a, b, f, tol, 1);
}

And here's what's in main():

std::cout << "First we approximate the integral of f(x) = x^2 on [0,2]" << std::endl;

    std::cout << "Enter a: ";
    std::cin >> a;

    std::cout << "Enter b: ";
    std::cin >> b;

    true_value1 = analytic_first(a,b);

    for (int i = 0; i<=8; i++)
    {
        result1 [i] = helper(a, b, function_1, tolerance[i]);
        error1 [i] = fabs(true_value1 - result1 [i]);
    }

    std::cout << "(Approximate integral of x^2, tolerance, error )" << std::endl;
    for (int i = 0; i<=8; i++)
    {
        std::cout << "(" << result1 [i] << "," << tolerance[i] << "," << error1[i] << ")" << std::endl;
    }
Nico Schlömer
  • 53,797
  • 27
  • 201
  • 249
Emir
  • 481
  • 1
  • 5
  • 15
  • 2
    On first glance, I don't see any problems. Have you verified the course and fine values at each step? If one of them is bad, you would experience this problem. Can you provide the helper and test functions and initial values so that we can try it? – walrii Oct 16 '12 at 02:54
  • Any ideas? I still can't figure it out :/ – Emir Oct 16 '12 at 03:30
  • What are minLevel and maxLevel set to? (So that we can run your main). – Michael Anderson Oct 16 '12 at 03:50

1 Answers1

4

I find that exactly the opposite of what you suggest is happening --- the algorithm is terminating after only minLevel steps --- and the reason is due to your usage of abs, rather than fabs in the tolerance test. The abs is converting its argument to an int and thus any error less than 1 is getting rounded to zero.

With the abs in place I get this output from a very similar program:

(0.333496,0.001,0.00016276)
(0.333496,0.0001,0.00016276)
(0.333496,1e-05,0.00016276)
(0.333496,1e-06,0.00016276)
(0.333496,1e-07,0.00016276)
(0.333496,1e-08,0.00016276)
(0.333496,1e-09,0.00016276)
(0.333496,1e-10,0.00016276)
(0.333496,1e-11,0.00016276)

Replacing with fabs I get this:

(0.333496,0.001,0.00016276)
(0.333374,0.0001,4.06901e-05)
(0.333336,1e-05,2.54313e-06)
(0.333334,1e-06,6.35783e-07)
(0.333333,1e-07,3.97364e-08)
(0.333333,1e-08,9.93411e-09)
(0.333333,1e-09,6.20882e-10)
(0.333333,1e-10,3.88051e-11)
(0.333333,1e-11,9.7013e-12)
Michael Anderson
  • 70,661
  • 7
  • 134
  • 187