/**
* Bracketing.java
* @author Fabio G. Cozman
* Copyright 1996 - 1999, Fabio G. Cozman,
* Carnergie Mellon University, Universidade de Sao Paulo
* fgcozman@usp.br, http://www.cs.cmu.edu/~fgcozman/home.html
*
* The JavaBayes distribution is free software; you can
* redistribute it and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation (either
* version 2 of the License or, at your option, any later version),
* provided that this notice and the name of the author appear in all
* copies. Upon request to the author, some of the packages in the
* JavaBayes distribution can be licensed under the GNU Lesser General
* Public License as published by the Free Software Foundation (either
* version 2 of the License, or (at your option) any later version).
* If you're using the software, please notify fgcozman@usp.br so
* that you can receive updates and patches. JavaBayes is distributed
* "as is", in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with the JavaBayes distribution. If not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package CredalSets;
/**
* Perform bisection to find the root of a function (described
* by an object that implements the MappingDouble interface),
* which must lie between x1 and x2.
* The root is refined until its accuracy is +/- x_accuracy.
*/
class Bracketing {
int status;
private final static int MAXIMUM_ITERATIONS = 40;
private final static int ERROR = -1;
private final static int TOO_MANY_BISECTIONS = 0;
private final static int EXACT_ROOT_FOUND = 1;
private final static int APPROXIMATE_ROOT_FOUND = 2;
/**
* Perform bisection.
*/
double
perform(MappingDouble function,
double x1, double x2, double x_accuracy) {
return( perform(function, 0, x1, x2, x_accuracy) );
}
/**
* Perform bisection.
*/
double
perform(MappingDouble function, int function_type,
double x1, double x2, double x_accuracy) {
int j;
double f1, f2;
double dx, x_middle, current_solution_point;
// Initialize variables with the function values at endpoints
f1 = function.map(function_type, x1);
f2 = function.map(function_type, x2);
// Check whether endpoints are solution
if (f1 == 0.0) {
status = EXACT_ROOT_FOUND;
return(x1);
}
if (f2 == 0.0) {
status = EXACT_ROOT_FOUND;
return(x2);
}
// Error: both endpoints have same sign
if ( (f1 * f2) > 0.0) {
status = ERROR;
return(0.0);
}
// Bisection goes from x (where f(x)<=0) to x + dx
if (f1 < 0.0) {
dx = x2 - x1;
current_solution_point = x1;
}
else {
dx = x1 - x2;
current_solution_point = x2;
}
// Bisection loop
for (j=1; j<=MAXIMUM_ITERATIONS; j++) {
dx *= 0.5;
x_middle = current_solution_point + dx;
f2 = function.map(function_type, x_middle);
if (f2 <= 0.0) current_solution_point = x_middle;
// Check whether stop conditions are met
if (f2 == 0.0) {
status = EXACT_ROOT_FOUND;
return(current_solution_point);
}
if (Math.abs(dx) < x_accuracy) {
status = APPROXIMATE_ROOT_FOUND;
return(current_solution_point);
}
}
status = TOO_MANY_BISECTIONS;
return(0.0);
}
}