1.
00
Cl
ase 19
Métodos numéricos:
Cálculo de raíces
Empaquetado de funciones en objetos
•
Observe
e
l mé
todo de escr
it
ura que
calcula
la ra
íz de
una
f
unción o evalú
a
una función,
por ejemplo
:
–
f(x
)=
0
en alg
ún in
terv
alo [a,
b]
o
cálculo de
f(c)
•
El método general que realiza esto
debe t
ener
f(
x)
como argument
o
:
–
En java no se pueden pasar funciones a un método como argumento
–
Por ello, es necesario empaquetar primero la función en un objeto
• Luego, se pasa el objeto como argumento al método de evaluacióno al del cálculo de la raíz
–
De
fin
a
una interfaz que describ
a
el objeto
que se pasará al método numérico
Ejemplo de “paso de funciones”
// El archivo MathFunction.java define el
// paquete de la interfaz Clase 19;
// El ámbito es público, por lo que debe estar en su propio archivo
public interface MathFunction {
public double f(double x); }
// Coloque esta clase en Evaluator.java o en su propio archivo // FuncA implementa la interfaz
class funcA implements MathFunction {
Ejercicio: paso de funciones
•
Escriba la interfaz MathFunction2 en su propio archivo
public interface MathFunction2 {public double f(double x1, double x2); }
•
En un segundo archivo, escriba una clase que
implemente la interfaz para la función 5x
12+ 2x
23 class FuncB implements MathFunction2 { }
•
Escriba un método para evaluar funciones que
t
ome un objet
o
Mat
hFunction2
y dos dobles
como argumentos
:
–
EvalFunc devuelve verdadero si f >= 0; si no, falso
–
Se recomienda
definir
E
valFunc
como e
s
táti
co
class Evaluator {boolean EvalFunc(MathFunction2 func, double d1,double d2){ }
•
Escriba un main(), dentro o fuera de Evaluator, que:
–
Invoque a Evaluator,
le p
ase
a éste
u
n o
bjeto FuncB
y
–
Ofrezca una salida con el valor de la función en x
1=2 y
x
2=
-3
public double f(double x) {
return x*x - 2;
}
}
Cálculo de raíces
•
Dos casos:
–
Una función dimensional: f(x)= 0
–
Sistemas d
e ecuacio
nes
(
F(X)=
0
)
,
donde
• X y 0 son vectores y
• Fes una función vectorial de dimensión N
•
Sólo tr
ataremos la f
unción
1D
:
–
En 1D, es posible encerrar la raíz entre valores
limítrofes
–
En el ca
so mu
ltidimen
sio
nal
,
no es pos
ible
hacerlo
•
(
Casi)
tod
os lo
s mé
tod
os d
e cálcu
lo d
e raíces so
n iterativo
s
–
Parten de un
sup
uesto
inicial
–
Afinan la solución hasta alcanzar el límite
de c
onve
rgencia
–
Para funciones 1D suaves, la convergencia está
asegurada, pero no para las demás
Métodos de cálculo de raíces
•
Elemental (sólo para uso pedagógico):
–
Bisección
–
Secante, posición falsa (
regula falsi
)
•
“Práctico” (usar el término con cautela):
–
Algoritmo de Brent (derivada desconocida)
–
Newton-Raphson (derivada conocida)
–
Método de Laguerre (polinomios)
–
Newton-Raphson (para problemas N-dimensionales)
• Sólo si se puede ofrecer una primera suposición muy buena
•
Ver
referencia de fórmulas e
n C
para mét
odos
–
Biblioteca disponible en Athena. Traducible a Java
Preparación para cálculo de raíces
•
Antes de usar métodos de cálculo de raíces:
–
Representar
gráficamente
las ecuaciones:
Matlab,
etc.
• ¿Son continuas, suaves, diferenciables?
–
Usar Matlab, etc. para analizar soluciones
–
Alinear las ecuaciones y usar métodos de
matrices para obtener soluciones aproximadas
–
Aproximar las ecuaciones de otra forma y
resolver analíticamente
–
Acotar los rangos en que se esperan las raíces
•
Cur
iosidad: ver
f
(
x
)
=
3
x
2−
(1
/
π
4)
ln
[(
π
−
x
)
2]
+
1
–
Repre
sentarla en 3.13,
3.14,
3.15,
3.16;
f(x)
aprox.
30
–
Buen comportamiento excepto en x=
–
Mín
imos por deb
ajo d
e 0
en el in
tervalo x=
+/-
10
-667–
Este intervalo es men
or que la precisión de dobles
• Nunca se encpodrán calcular estas dos raíces numéricamente
Acotación
f(x)=x2-2
-8 -6 -4 -2 0 2 4 6 8
No hay ceros en la acotación (aunque no se
puede asegurar).Desplazar en la dirección
del valor de f(x) más pequeño.
Múltiplo empírico de 1.6 para ampliar acotación
L U
Acotación
f(x)= x2- 2
-8 -6 -4 -2 0 2 4 6 8
Sigue sin haber ceros en la acotación (aunque
no se puede asegurar).Desplazar de nuevo en la
dirección del valor de f(x) más pequeño.
Acotación
f(x)= x2- 2
-8 -6 -4 -2 0 2 4 6 8
Conseguido:se ha encontrado un intervalo que contiene un cero
L U
L U
Programa de acotación
public class Bracket {
public static boolean zbrac(MathFunction func, double[] x){ // Versión Java de zbrac, pág.352, Fórmulas
if (x[0] == x[1]) {
System.out.println("Rango inicial de zbrac erróneo"); return false; }
double f0= func.f(x[0]); double f1= func.f(x[1]);
for (int j= 0; j < NTRY; j++) { if (f0*f1 < 0.0) return true; if (Math.abs(f0) < Math.abs(f1)) { x[0] += FACTOR*(x[0]-x[1]); f0= func.f(x[0]); } else { x[1] += FACTOR*(x[1]-x[0]); f1= func.f(x[1]); } } return false; }
// No hay garantías de que este método funcione
Programa de acotación
// Clase Bracket (continuación) public static double FACTOR= 1.6; public static int NTRY= 50;
public static void main(String[] args) {
double[]bound={5.0,6.0}; //Suposición de acotación inicial guess boolean intervalFound= zbrac(new FuncA(), bound); System.out.println("¿Acotación encontrada? " +
intervalFound); if (intervalFound)
System.out.println( L:"+bound[0]+" U: "+bound[1]); System.exit(0);
} }
// La ref. de fórmulas contiene segundo prog. de acot. en p.352 que
Ej
ercicio:
límites
•
Calcule los
int
e
rval
os en los que
las
siguientes funciones tengan ceros o
singularidades:
–
3 sen(x)
–
0.1x
2–
1/x
–
5 sen(x) / x
–
sen (1/x)
•
Represéntelos de forma aproximada
•
Est
udiaremos estas
5
funciones c
on dist
int
os
métodos de cálculo de raíces en breve
Ejercicio:
Rep. gráfica de funciones
3 sen x
0.1 x
21/x
5 sen (x)/x
•
Bisección
:
Bisección
–
El intervalo del método debe contener al menos
una raíz
–
Co
n e
llo,
la bisección “
nunca”
fall
a
:
• Si el intervalo contiene 2 o más raíces, la bisección encontrará una de ellas
• Si el intervalo no contiene raíces, sino singularidades a ambos lados, la bisección las encontrará
–
Robusta, pero de convergencia lenta
–
La tolerancia debe ser casi exacta para los
d
obles (aprox. 10
-15)
:
• Si la raíz está cerca de 0, esto es factible
• Si la raíz está cerca de, por ejemplo, 1010, esto es difícil
–
Re
f. de fórmulas
,
p.354
ofrece un buen méto
do
:
• Comprueba si existe una raíz en la acotación definidapor los argumentos
• Verifica si f(puntomedio) == 0.0
• Limita el número de iteraciones, etc.
Bisección
2 x 1 x m f(x)= x2- 2 -8 -6 -4 -2 0 2 4 6 8f(x1)*f(m) > 0, por lo que no hay raíz en [x1, m] f(m)*f(x2) < 0, sí hay raíz en [m, x2]. Definir x1=m Suponer una raíz única en el intervalo (p.ej.,[-4.0,0.0])
x2 x1
Bisección
x1 m x2
f(x)= x2- 2
-8 -6 -4 -2 0 2 4 6 8
f(m)*f(x2) > 0, no hay raíz en [m, x2] f(x1)*f(m) < 0, sí hay raíz en [x1, m]. Definir x2= m Seguir hasta que (x2-x1)sea lo suficientemente pequeño
Bisección
m x1 x2
f(x)= x2- 2
Bisección
:
V
ersión simple
// Archivo RootFinder1.java
package Lecture19; // O importar el paquete con intfc
class FuncA implements MathFunction { public double f(double x) {
return x*x - 2; } }
public class RootFinder1 {
public static double bisect(MathFunction func, double x1, double x2, double epsilon) { double m;
for (m= (x1+x2)/2.0; Math.abs(x1-x2)> epsilon; m= (x1+x2)/2.0)
if (func.f(x1)*func.f(m) <= 0.0)
x2= m; // Usa subintervalo izquierdo else
x1= m; // Usa subintervalo derecho return m; }
B
isecc
ión
s
imple,
2
// método main() en clase RootFinder1
public static void main(String[] args) {
double root= RootFinder1.bisect(
new FuncA(),-8.0,8.0,0.0001); System.out.println("Raíz: " + root); System.exit(0); } }
Bisección
:
v
ersión
RefForm
public class RootFinder { // RefForm, p. 354 public static final int JMAX= 40; // Nº máx de bisecciones public static final double ERR_VAL= -10E10;
public static double rtbis(MathFunction func, double x1, double x2, double xacc) { double dx, xmid, rtb;
double f= func.f(x1); double fmid= func.f(x2); if (f*fmid >= 0.0) {
System.out.println("Es preciso acotar la raíz"); return ERR_VAL; } if (f < 0.0) { // Búsq. orientada: f>0 queda en x+dx dx= x2 - x1; rtb= x1; } else { dx= x1 - x2; rtb= x2; }
// Todo esto: preprocesado ; el bucle en la pág. siguiente
Bisección
:
v
ersión
RefForm
,
2
for (int j=0; j < JMAX; j++) {
dx *= 0.5; // Corta intervalo a la mitad xmid= rtb + dx; // Busca nueva x
fmid= func.f(xmid);
if (fmid <= 0.0) // Si f aún < 0, mueve rtb= xmid; // límite izq a la mitad if (Math.abs(dx) < xacc || fmid == 0.0)
return rtb; }
System.out.println("Demasiadas bisecciones"); return ERR_VAL;
}
// Invoca con mismo main() pero acotación correcta
// Esta es mucho más rápida que la versión simple, y
// requiere menos evaluaciones de la función. También es // más robusta, comprueba las acotaciones, limita las // iteraciones y usa mejores criterios de terminación. La
Ejercicio: Bisección
•
Descargar Roots.java del sitio Web
•
Usar la aplicación de bisección para
analizar
su
compor
tamient
o con las 5
f
unciones
:
–
Elegir valores iniciales distintos (acotaciones)
–
La aplicación no comprueba si hay un cero en
la acotación, por lo que es posible ver qué va
mal...
–
Registre los resultados;
anote
comportamientos
extraño
s o interesan
tes
Secante,
m
étodos de falsa posición
•
Para funciones suaves:
– Aproxima la función a una línea recta
– Calcula la raíz en la intersección de la línea con el eje
•
Método secante:
– Usa los 2 puntos más recientes para la siguiente línea de aprox.
– Más rápido que la falsa posición, pero no acota la raíz y puede divergir
•
Método de falsa posición:
– Usa los puntos más recientes con valores de función opuestos
•
El método de Brent es mejor que el resto y es el único
que debe utilizar:
– Combina bisección, acotación de raíces y aproximación cuadrática, no lineal
Método secante
Ejercicio
•
Usar la aplicación de método
secante para experimentar con
las 5
funciones
:
–
Elegir distintos valores iniciales
(acotaciones)
–
La aplicación no comprueba si hay un
cero en la acotación, por lo que es
posible ver qué va mal…
–
Registrar los resultados; anotar
cualquier comportamiento extraño o
interesante
Método de Newton
•
Basado e
n la amp
liaci
ón de la serie de T
aylor:
f
(
x
+
δ
)
≈
f
(
x
)
+
f
' (
x
)
δ
+
f
'
'
(
x
)
δ
2
/ 2
+
...
–
Pa
ra pequeños incrementos y fu
nciones suaves,
las derivadas de orden superior son pequeñas y
f
(
x
+ δ
)
=
0
implica
δ = −
f
(
x
) /
f
' (
x
)
–
Si las derivadas de alto orden son grandes o la
primera derivada es pequeña, Newton puede fallar
–
Conver
ge rápid
amente s
i
se cumplen las premisas
–
Generalización a N dimensiones si es una de
las pocas disponibles
–
Consultar
ref. de fórmulas
para el método
‘seguro’
de Newto
n-
Raphson,
que utiliza
Método de Newton
f’(x)
f(x)
Suposición inicial de la raíz
Patología del método de Newton
f’(x)
f(x)
Método de Newton
public class Newton { // RefForm, pág. 365 public static double newt(MathFunction2 func, double a,
double b, double epsilon) { double guess= 0.5*(a + b);
for (int j= 0; j < JMAX; j++) { double fval= func.fn(guess); double fder= func.fd(guess); double dx= fval/fder;
guess -= dx;
System.out.println(guess);
if ((a - guess)*(guess - b) < 0.0) {
System.out.println("Error: fuera de acotación"); return ERR_VAL; // Experimente con esto
} // Es conservador
if (Math.abs(dx) < epsilon) return guess; }
System.out.println("Superado el máximo de iteraciones"); return guess; }
Método de Ne
wton,
2
public static int JMAX= 50;
public static double ERR_VAL= -10E10;
public static void main(String[] args) {
double root= Newton.newt(new FuncB(), -0.0, 8.0, 0.0001); System.out.println("Raíz: " + root);
System.exit(0); } }
class FuncB implements MathFunction2 { public double fn(double x) {
return x*x - 2; }
public double fd(double x) { return 2*x; } }
public interface MathFunction2 {
public double fn(double x); // Valor de la función
Ejemplos
•
f(x)= x
2+ 1
–
Sin raíces reales, Newton genera suposiciones
“aleatorias”
•
f(x)= sen(5x) + x
2– 3
Raíz= -0.36667
–
Acotación entre –1 y 2, por ejemplo
–
La acotación entre 0 y 2
fallar
á con Newton
(conservador): fuera de la acotación
•
f(x)= ln(x
2–0.8x + 1)
Raíces= 0, 0.8
–
Aco
t. entre 0
y 1.2:
correcto
–
Ac
ot. entre 0.0
y 8.0:
erróneo
8