Метод наименьших квадратов аппроксимации функций
Прежде чем запускать основной код, нужно сформировать код для метода Гаусса и проинициализировать его.
Вспомогательный код для решения СЛАУ методом Гаусса (подробнее в этой статье):
import numpy
def Metod_Gaussa(arr, brr):
for k in range(arr.shape[0] - 1):
#поиск строки с максимальным элементом
max_elem = 0
str = 0
for i in range (k, arr.shape[0]):
if abs(arr[i,k]) > abs(max_elem):
max_elem = arr[i,k]
str = i
#меняем местами строки квадратной матрицы
change = numpy.repeat(arr[k], 1)
arr[k], arr[str] = arr[str], change
#меняем местами элементы вектора-столбца
change = numpy.repeat(brr[k], 1)
brr[k], brr[str] = brr[str], change
#делим полученную строку на max_elem
arr[k] = arr[k] / max_elem
brr[k] = brr[k] / max_elem
#домножаем строку на коэффициенты и вычитаем ее из остальных строк
for i in range (k + 1, arr.shape[0]):
factor = arr[i,k]
arr[i] = arr[i] - arr[k] * factor
brr[i] = brr[i] - brr[k] * factor
#находим неизвестные
arg = [brr[brr.shape[0] - 1] / (arr[arr.shape[0] - 1, arr.shape[0] - 1])]
for i in range(arr.shape[0] - 2, -1, -1):
n = brr[i]
for j in range(len(arg)):
n = n - arg[j] * arr[i, arr.shape[0] - 1 - j]
arg.append(n)
#переворачиваем значения в списке
otv = []
for i in reversed(arg): otv.append(i)
return otv
Этот код следует добавить в отдельный файл в ту же папку PyCharm
, что и основной код:
Основной код:
#библиотека для параметризации функции и построения графиков
from sympy import *
#для построения набора точек на графике
import matplotlib.pyplot as plt
#для решения СЛАУ
from Project1 import Gaussa
import numpy
x = symbols('x')
K = 3 #степень многочлена
#опорные точки
xi = [1, 1.25, 1.25, 1.5, 1.75, 2]
yi = [5.47863093565943e-837, 0.000244140625000000, 1, 0.0156250000000000, 0.177978515625000, 1]
def approksim(xi, yi, K):
#поиск констант
A = numpy.zeros([K + 1, K + 1])
for i in range(K + 1):
for j in range(K + 1):
for t in xi: A[i, j] += t ** (2 * K - i - j)
a = numpy.zeros([K + 1])
for i in range(K + 1):
for j in range(len(xi)): a[i] += yi[j] * xi[j] ** (K - i)
const = []
for j in Gaussa.Metod_Gaussa(A, a): const.append(float(j))
#составление уравнения
f = 0
for i in range(len(const)):
f += const[i] * x ** (len(const) - 1 - i)
return f
#значения линейной функции, полученной МНК, в тех же точках
f1 = []
for i in xi: f1.append(approksim(xi, yi, 1).evalf(subs={'x': i}))
#отклонения (невязки в точках)
e1 = []
for i in range(len(xi)): e1.append(abs(f1[i] - yi[i]))
#значения квадратичной функции, полученной МНК, в тех же точках
f2 = []
for i in xi: f2.append(approksim(xi, yi, 2).evalf(subs={'x': i}))
#отклонения (невязки в точках)
e2 = []
for i in range(len(xi)): e2.append(abs(f2[i] - yi[i]))
#значения кубической функции, полученной МНК, в тех же точках
f3 = []
for i in xi: f3.append(approksim(xi, yi, 3).evalf(subs={'x': i}))
#отклонения (невязки в точках)
e3 = []
for i in range(len(xi)): e3.append(abs(f3[i] - yi[i]))
#все функции на одном графике
xfi = numpy.linspace(xi[0], xi[len(xi) - 1], 100)
f1i = [approksim(xi, yi, 1).subs(x, a) for a in xfi]
f2i = [approksim(xi, yi, 2).subs(x, a) for a in xfi]
f3i = [approksim(xi, yi, 3).subs(x, a) for a in xfi]
plt.plot(xfi, f1i, 'b')
plt.plot(xfi, f2i, 'r')
plt.plot(xfi, f3i, 'g')
plt.plot(xi, yi, 'k*')
plt.grid()
plt.show()
Результат (линейная, квадратичная и кубическая аппроксимации на одном графике):