Polinomio De Bernstein Con Python 3

Hola
Siguiendo con el tema de aproximar funciones con polinomios veamos el Polinomio de Bernstein. El pol. de Bernstein es otra forma de aproximar funciones como es el pol. de Taylor. Con el pol. de Taylor hacemos una aproximación puntual (o en un entorno pequeño alrededor de un punto), con el de Bernstein podemos hacer una aproximación en un intervalo de tamaño más o menos grande, que dependerá de las características de nuestra función y del grado del pol. Bernstein; se supone que a mayor grado mejor aproximación.
Lo he programado con Python 3 utilizando de nuevo las librerías de cálculo simbólico Sympy, que aunque no tienen una función o procedimiento para hallarlo directamente, lo podemos formular fácilmente utilizando funciones de Sympy como: subs(), binomial(), summation() y expand().
La fórmula del polinomio de Bernstein y sus propiedades podéis consultarlas en la Wikipedia:


A parte de calcularlo he realizado una comparación gráfica entre la función y el polinomio utilizando Matplotlib. El código:

  1. __author__ = 'tobal'
  2.  
  3. #/usr/bin/env python3
  4. # -*- coding: utf-8 -*-
  5.  
  6. from sympy import *
  7. import matplotlib.pyplot as plt
  8. from matplotlib import rcParams
  9. import numpy as np
  10.  
  11. rcParams['text.latex.unicode'] = True
  12. rcParams['text.usetex'] = True
  13. rcParams['text.latex.preamble'] = '\\usepackage{amsthm}', '\\usepackage{amsmath}', '\\usepackage{amssymb}',
  14. '\\usepackage{amsfonts}', '\\usepackage[T1]{fontenc}', '\\usepackage[utf8]{inputenc}'
  15.  
  16. x = symbols('x')
  17. n = symbols('n', integer=True)
  18. i = symbols('i', integer=True)
  19.  
  20. init_printing(use_unicode=True)
  21.  
  22. pprint('Introduce la función para calcular su polinomio de Bernstein: ')
  23. fun = eval(input())
  24. pprint('La función es: ')
  25. pprint(fun)
  26. pprint('Introduce el grado del polinomio: ')
  27. n = int(input())
  28. pprint('Introduce el extremo izqdo. del intervalo: ')
  29. a = float(input())
  30. pprint('Introduce el extremo dcho. del intervalo: ')
  31. b = float(input())
  32. f = lambdify(x, fun, 'numpy')
  33.  
  34. ci = fun.subs(x, i*((b - a) / n) + a)
  35. binom = binomial(n, i)
  36. Bin = binom * ((x - a) ** i * (b - x)**(n-i)) / (b - a) ** n
  37. pprint('El polinomio de Bernstein de grado {0} en el intervalo [{1}, {2}] es: '.format(n, a, b))
  38. bernstein = expand(summation(ci * Bin, (i,0,n)))
  39. pprint(bernstein)
  40. g = lambdify(x, bernstein, 'numpy')
  41.  
  42. fig, ax = plt.subplots()
  43. title = r'$Polinomio \; De \; Bernstein \; ([{0}, {1}] \; n={2})$'.format(a, b, n)
  44. ax.set_title(title)
  45. t = np.linspace(a, b, 1000)
  46. ax.axis([a, b, a, b + 5])
  47.      
  48. ax.set_xlabel('x', color='blue')
  49. ax.set_ylabel('y', color='blue')
  50.      
  51. ax.grid('on')
  52.      
  53. ax.plot(t, f(t), 'b-', lw=1.5)
  54. ax.plot(t, g(t), 'r-', lw=1.5)
  55.      
  56. # Drawing Our Legend
  57. text1 = r'$f(x)={}$'.format(latex(fun))
  58. text2 = r'$Pol.\; Bernstein$'
  59.      
  60. plt.legend([text1, text2])
  61.      
  62. plt.show()

Por la Shell obtenemos lo siguiente:

usuario@nombrepc:~$
Introduce la función para calcular su polinomio de Bernstein:
exp(sin(x))
La función es:
e^{sin(x)}
Introduce el grado del polinomio:
5
Introduce el extremo izqdo. del intervalo:
-1
Introduce el extremo dcho. del intervalo:
1
El polinomio de Bernstein de grado 5 en el intervalo [-1.0, 1.0] es:
- 0.00196875751579639\cdot x^5  - 0.0237648335485573\cdot x^4  - 0.0317093189458472\cdot x^3  + 0.3                                            12198756243064\cdot x^2  + 0.978028513496774\cdot x + 1.08699246498622

En éste caso obtenemos las siguientes gráficas:
polbernstein

Aunque Taylor y Bernstein no sean ideales por su alto costo computacional, sí son muchas veces buenas alternativas, además de tener un alto valor en cuanto a aprendizaje de conceptos matemáticos fundamentales.
Si queremos disminuir el costo computacional cuando el grado de nuestros polinomios es grande podemos utilizar en Sympy la función horner() para aplicar el método polinomial de Horner. El método de Horner también disminuye el costo computacional si tenemos que calcular una gran cantidad de puntos en nuestro polinomio. En nuestro código basta con modificar la línea:

  1. bernstein = expand(summation(ci * Bin, (i,0,n)))

por el siguiente código:

  1. bernstein = horner(expand(summation(ci * Bin, (i,0,n))))

En la Shell obtenemos:

usuario@nombrepc:~$
Introduce la función para calcular su polinomio de Bernstein:
exp(sin(x))
La función es:
sin(x)

Introduce el grado del polinomio:
5
Introduce el extremo izqdo. del intervalo:
-1
Introduce el extremo dcho. del intervalo:
1
El polinomio de Bernstein de grado 5 en el intervalo [-1.0, 1.0] es:
x⋅(x⋅(x⋅(x⋅(-0.00196875751579634⋅x – 0.0237648335485573) – 0.0317093189458473)
+ 0.312198756243064) + 0.978028513496774) + 1.08699246498622

Perfecto

En fin, Sympy es impresionante, tenemos una alternativa totalmente libre para realizar matemáticas.
Saludos

Pingbacks/Trackbacks

  1. Bitacoras.com - 13 abril, 2014

    Información Bitacoras.com

    Valora en Bitacoras.com: Hola Siguiendo con el tema de aproximar funciones con polinomios veamos el Polinomio de Bernstein. El pol. de Bernstein es otra forma de aproximar funciones como es el pol. de Taylor. Con el pol. de Taylor hacemos una aproxim..…

Comments are closed.

Proudly powered by WordPress   Premium Style Theme by www.gopiplus.com
A %d blogueros les gusta esto: