El método de Bairstow es un algoritmo iterativo diseñado para encontrar las raíces (reales e imaginarias) de un polinomio. Fue introducido por Leonard Bairstow en 1920 en su libro Aerodinámica Aplicada. Este método está basado en los métodos de Müller y Newton-Raphson, y utiliza divisiones sintéticas para encontrar factores cuadráticos del polinomio original, lo que permite ir reduciendo su grado progresivamente.
Una de sus mayores ventajas es que puede encontrar raíces complejas sin necesidad de trabajar con números complejos directamente.
¿Para qué sirve?
Este método matemático sirve para:
- Encontrar todas las raíces de un polinomio, sean reales o complejas.
- Resolver polinomios de grado mayor a 2, donde otros métodos pueden fallar o ser ineficientes.
- Superar limitaciones de otros métodos como Newton-Raphson o bisección, especialmente en casos donde hay raíces complejas o el método oscila o diverge.
- Automatizar el proceso de solución de polinomios de grados altos, sin cambiar de método entre raíces reales e imaginarias.
¿Cómo se utiliza?
Este método se aplica en múltiples áreas de la ingeniería y las ciencias computacionales, tales como:
- Análisis de estabilidad en sistemas de control.
- Estudio de vibraciones mecánicas.
- Resolución de ecuaciones características en circuitos eléctricos.
- Diseño de algoritmos de procesamiento digital de señales.
Algoritmo:
- Paso 1: Inicializar los valores r₀ y s₀ (estimaciones iniciales).
-
Paso 2: Determinar los valores bi usando las siguientes ecuaciones:
- bn = an
- bn-1 = an-1 + r · bn
- bi = ai + r · bi+1 + s · bi+2, para i = n - 2 hasta 0
-
Paso 3: Determinar los valores ci:
- cn = bn
- cn-1 = bn-1 + r · cn
- ci = bi + r · ci+1 + s · ci+2, para i = n - 2 hasta 0
-
Paso 4: Determinar los incrementos Δr y Δs resolviendo el sistema:
c2 · Δr + c3 · Δs = -b1
c1 · Δr + c2 · Δs = -b0 -
Paso 5: Actualizar los valores de r y s:
- r = r₀ + Δr
- s = s₀ + Δs
-
Paso 6: Evaluar el error relativo:
-
|EΔr| = |Δr| |r| × 100
-
|EΔs| = |Δs| |s| × 100
-
-
Paso 7: Verificar convergencia:
- Si |EΔr| < tolerancia y |EΔs| < tolerancia, se procede a encontrar las raíces.
- Si no se cumple la condición de convergencia, se regresa al paso 1 con r₀ = r y s₀ = s.
-
Las raíces del factor cuadrático x² + r·x + s se calculan como:x = -r ± √(r² + 4s) 2
-
Paso 8: Si se determinó una raíz, se realiza la división sintética del polinomio original:
P(x) = (x - x₁)(x - x₂) · Q(x)
-
Paso 9: Evaluar el nuevo polinomio Q(x):
- a) Si Q(x) es de grado ≥ 3: volver al paso 1 con nuevas estimaciones r y s.
-
b) Si Q(x) es de grado 2: usar la fórmula cuadrática:
x = -r ± √(r² + 4s) 2
-
c) Si Q(x) es de grado 1: resolver directamente:
x = -s r
Este método solo permite buscar las raíces de cada función.
En este ejemplo tenemos tres raíces reales diferentes y dos imaginarias.
Este método solo permite buscar las raíces de cada función.
En este ejemplo tenemos cuatro raíces reales diferentes.
Este método solo permite buscar las raíces de cada función.
En este ejemplo tenemos una raiz real y dos imaginarias iguales.
Método de Bairstow en Python
import sympy as sp
import math
x = sp.Symbol('x')
def f(x):
return x**4 + x**3 - 7*x**2 - x + 6
tolerancia = 0.05
R0, S0 = 1.5, 1.5
coeficientes = sp.Poly(f(x), x).all_coeffs()
funcionLimpia = f(x)
numeroDeRaices = []
for iteracion in range(20):
n = len(coeficientes)
for _ in range(20):
b = []
for i in range(n):
if i == 0:
b.append(coeficientes[i])
elif i == 1:
b.append(coeficientes[i] + R0 * b[0])
else:
b.append(coeficientes[i] + R0 * b[i - 1] + S0 * b[i - 2])
c = []
for i in range(n):
if i == 0:
c.append(b[i])
elif i == 1:
c.append(b[i] + R0 * c[0])
else:
c.append(b[i] + R0 * c[i - 1] + S0 * c[i - 2])
absDelta = c[n - 3] * c[n - 3] - c[n - 4] * c[n - 2]
absDeltaR = (-b[n - 2]) * c[n - 3] - (-b[n - 1]) * c[n - 4]
absDeltaS = c[n - 3] * (-b[n - 1]) - (-b[n - 2]) * c[n - 2]
deltaR = absDeltaR / absDelta
deltaS = absDeltaS / absDelta
r = R0 + deltaR
s = S0 + deltaS
errorDeltaR = sp.Abs(deltaR / r) * 100
errorDeltaS = sp.Abs(deltaS / s) * 100
print(f"Iteración interna #{_}")
print(f"Error en ΔR: {errorDeltaR:.5f}%")
print(f"Error en ΔS: {errorDeltaS:.5f}%")
if errorDeltaR < tolerancia and errorDeltaS < tolerancia:
X1 = (r + sp.sqrt(r**2 + 4 * s)) / 2
X2 = (r - sp.sqrt(r**2 + 4 * s)) / 2
print("\n======= Raíces encontradas =======")
numeroDeRaices.append(X1)
print(f"Raíz #{len(numeroDeRaices)}: {X1}")
numeroDeRaices.append(X2)
print(f"Raíz #{len(numeroDeRaices)}: {X2}")
break
else:
R0 = r
S0 = s
dividendo = funcionLimpia
divisor = x**2 - r*x - s
cociente, residuo = sp.div(dividendo, divisor, domain='RR')
print("\nCociente:", cociente)
print("Residuo:", residuo)
funcionLimpia = sp.sympify(cociente + residuo)
coeficientes = sp.Poly(funcionLimpia, x).all_coeffs()
if len(coeficientes) <= 2:
if len(coeficientes) == 2:
raiz_final = -coeficientes[1] / coeficientes[0]
numeroDeRaices.append(raiz_final)
print(f"Raíz lineal restante: {raiz_final}")
break
print("\n======= Todas las raíces encontradas =======")
for i, raiz in enumerate(numeroDeRaices, 1):
print(f"Raíz #{i}: {raiz.evalf()}")