Advertisement
qberik

Untitled

Apr 7th, 2023
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.89 KB | None | 0 0
  1. import math
  2.  
  3.  
  4. # Структура, описывающая сплайн на каждом сегменте сетки
  5. class MySpline:
  6. def __init__(self, a, b, c, d, x):
  7. self.a = a
  8. self.b = b
  9. self.c = c
  10. self.d = d
  11. self.x = x
  12.  
  13. def __str__(self):
  14. return "a = {0}, b = {1}, c = {2}, d = {3}".format(self.a,
  15. self.b,
  16. self.c,
  17. self.d)
  18.  
  19.  
  20. # Построение сплайна
  21. # x - узлы сетки, должны быть упорядочены по возрастанию,
  22. # кратные узлы запрещены
  23. # y - значения функции в узлах сетки
  24. # n - количество узлов сетки
  25. def BuildSpline(x, y, n, my_h, my_n):
  26. # Инициализация массива сплайнов
  27. splines = [MySpline(0, 0, 0, 0, 0) for _ in range(0, n)]
  28. for i in range(0, n):
  29. splines[i].x = x[i]
  30. splines[i].a = y[i]
  31.  
  32. splines[0].c = splines[n - 1].c = 0.0
  33.  
  34. # Решение СЛАУ относительно коэффициентов сплайнов c[i] методом прогонки
  35. # для трехдиагональных матриц
  36. # Вычисление прогоночных коэффициентов - прямой ход метода прогонки
  37. alpha = [0.0 for _ in range(0, n - 1)]
  38. beta = [0.0 for _ in range(0, n - 1)]
  39.  
  40. for i in range(1, n - 1):
  41. hi = x[i] - x[i - 1]
  42. hi1 = x[i + 1] - x[i]
  43. A = hi
  44. C = 2.0 * (hi + hi1)
  45. B = hi1
  46. F = 6.0 * ((y[i + 1] - y[i]) / hi1 - (y[i] - y[i - 1]) / hi)
  47. z = (A * alpha[i - 1] + C)
  48. alpha[i] = -B / z
  49. beta[i] = (F - A * beta[i - 1]) / z
  50.  
  51. # Нахождение решения - обратный ход метода прогонки
  52. for i in range(n - 2, 0, -1):
  53. splines[i].c = alpha[i] * splines[i + 1].c + beta[i]
  54.  
  55. # По известным коэффициентам c[i] находим значения b[i] и d[i]
  56. for i in range(n - 1, 0, -1):
  57. hi = x[i] - x[i - 1]
  58. splines[i].d = (splines[i].c - splines[i - 1].c) / hi
  59. splines[i].b = hi * (2.0 * splines[i].c +
  60. splines[i - 1].c) / 6.0 + (y[i] - y[i - 1]) / hi
  61.  
  62. print("Таблица коэффициентов сплайнов:")
  63. for i in range(0, n):
  64. print("i = {0}, {1}".format(i, splines[i]))
  65.  
  66. print()
  67.  
  68. print("Таблица значений сплайнов:")
  69. if my_n == 5:
  70. for i in range(0, n):
  71. print("i = {0}, {1}".format(i, get_spline_value(splines[i], my_h)))
  72. elif my_n == 25:
  73. for i in range(0, 5):
  74. i = 3 + 5 * i
  75. print("i = {0}, {1}".format(i, get_spline_value(splines[i], my_h)))
  76. else:
  77. for i in range(0, 5):
  78. i = 13 + 5 * i
  79. print("i = {0}, {1}".format(i, get_spline_value(splines[i], my_h)))
  80.  
  81. return splines
  82.  
  83.  
  84. def get_spline_value(spline, h):
  85. return spline.a + spline.b * h / 4 + spline.c * h ** 2 / 4 + spline.d * h ** 3 / 8
  86.  
  87.  
  88. # Вычисление значения интерполированной функции в произвольной точке
  89. def Interpolate(splines, x):
  90. if not splines:
  91. return None # Если сплайны ещё не построены - возвращаем NaN
  92.  
  93. n = len(splines)
  94. s = MySpline(0, 0, 0, 0, 0)
  95.  
  96. # Если x меньше точки сетки x[0] - пользуемся первым эл-тов массива
  97. if x <= splines[0].x:
  98. s = splines[0]
  99. # Если x больше точки сетки x[n - 1] - пользуемся последним эл-том массива
  100. elif x >= splines[n - 1].x:
  101. s = splines[n - 1]
  102. # Иначе x лежит между граничными точками сетки - производим
  103. # бинарный поиск нужного эл-та массива
  104. else:
  105. i = 0
  106. j = n - 1
  107. while i + 1 < j:
  108. k = i + (j - i) // 2
  109. if x <= splines[k].x:
  110. j = k
  111. else:
  112. i = k
  113. s = splines[j]
  114.  
  115. dx = x - s.x
  116. # Вычисляем значение сплайна в заданной точке по схеме Горнера
  117. return s.a + (s.b + (s.c / 2.0 + s.d * dx / 6.0) * dx) * dx
  118.  
  119.  
  120. def frange(start, stop, step):
  121. i = start
  122. while i <= stop:
  123. yield i
  124. i += step
  125.  
  126.  
  127. def f(x):
  128. return math.log(2 * x - 1) - math.sin(pow(x, 2))
  129.  
  130.  
  131. a = 1
  132. b = 3
  133. # n = 5
  134. # n = 25
  135. n = 5
  136. h = (b - a) / n
  137. x = [i for i in frange(a, b, h)]
  138. y = [f(i) for i in x]
  139. x2 = [i for i in frange(a+1, b+1, h)]
  140. z = [f(i-0.5) for i in x2]
  141. new_x = 2
  142.  
  143. func = "f(x) = ln(2x − 1) − sin x^2"
  144.  
  145. print("Интерполяция функции {0} на отрезке [{1}, {2}] с шагом {3}".format(
  146. func, a, b, h))
  147. print("Количество узлов сетки: {0}".format(n))
  148. print()
  149. print("Узлы сетки:")
  150. print("x = {0}".format(x))
  151. print("Таблица значений функции f(a + ih):")
  152. print("y = {0}".format(y))
  153. print('Xci = {0}'.format(x2))
  154. print("Таблица значений функции f(a + (i-0.5)*h):")
  155. print("y = {0}".format(z))
  156. print()
  157. print("Интерполяция в точке x = {0}".format(new_x))
  158. print()
  159.  
  160. spline = BuildSpline(x, y, len(x), h, n)
  161.  
  162. answer = Interpolate(spline, new_x)
  163.  
  164. print()
  165. print("Значение функции {0} в точке x = {1} равно {2}".format(
  166. func, new_x, answer))
  167. print("Табличное значение функции = {0}".format(f(new_x)))
  168. print("Погрешность = {0}".format(abs(answer - f(new_x))))
  169.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement