diff --git "a/\320\2403265-69/furzikova_368979/lab1/2.txt" "b/\320\2403265-69/furzikova_368979/lab1/2.txt" new file mode 100644 index 0000000..833e909 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab1/2.txt" @@ -0,0 +1,2 @@ +1 5 | 7 +3 -2 | 4 diff --git "a/\320\2403265-69/furzikova_368979/lab1/3.txt" "b/\320\2403265-69/furzikova_368979/lab1/3.txt" new file mode 100644 index 0000000..8376d26 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab1/3.txt" @@ -0,0 +1,3 @@ +1 -1 3 | 5 +4 -1 5 | 4 +2 -2 4 | 6 diff --git "a/\320\2403265-69/furzikova_368979/lab1/5.txt" "b/\320\2403265-69/furzikova_368979/lab1/5.txt" new file mode 100644 index 0000000..d4d5d46 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab1/5.txt" @@ -0,0 +1,5 @@ +1 -1 3 1 3 | 5 +4 -1 5 4 -2 | 4 +2 -2 4 1 3 | 6 +1 -4 5 -1 -4 | 3 +2 -4 5 -1 5 | 3 diff --git "a/\320\2403265-69/furzikova_368979/lab1/main.py" "b/\320\2403265-69/furzikova_368979/lab1/main.py" new file mode 100644 index 0000000..7c2e800 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab1/main.py" @@ -0,0 +1,211 @@ +import numpy as np + +# Функция для округления чисел +def round_number(num, digits=3): + return f'{num:.{digits}f}' + +# Функция для чтения системы уравнений из файла +def read_from_file(file_path): + try: + n = 0 + equations = [] + with open(file_path, 'r', encoding='utf-8') as file: + for line in file: + if line.strip(): # Пропускаем пустые строки + n += 1 + if n > 20: + print('Файл содержит более 20 уравнений. Пожалуйста, уменьшите количество уравнений и попробуйте снова.') + return + with open(file_path, 'r', encoding='utf-8') as file: + for row in file: + if row.strip(): # Пропускаем пустые строки + parts = row.split() + if parts[-2] != '|' or len(parts) - 2 != n: + print('Ошибка формата файла. Пожалуйста, проверьте формат и попробуйте снова.') + return + equations.append(parts) + solver = EquationSolver(n, prepare_equations(equations, n)) + solver.solve() + except FileNotFoundError: + print('Файл не найден по указанному пути:', file_path) + +# Функция для ввода системы уравнений вручную +def input_manually(): + try: + n = int(input('Введите количество уравнений (не более 20): ')) + if 1 < n <= 20: + equations = [] + print('Введите коэффициенты уравнений в формате:') + print('\t', 'a1 a2 ... an | b') + for i in range(n): + while True: + line = input(f'{i + 1}: ').split() + if len(line) - 2 != n or line[-2] != '|': + print('Количество коэффициентов не соответствует количеству уравнений или неправильный формат.') + print('Пожалуйста, попробуйте снова.') + else: + equations.append(line) + break + solver = EquationSolver(n, prepare_equations(equations, n)) + solver.solve() + else: + print('Некорректный ввод! Количество уравнений должно быть от 2 до 20.') + except ValueError: + print('Некорректный ввод! Пожалуйста, введите целое число.') + +# Преобразуем строки в числа +def prepare_equations(arr, n): + for i in range(n): + for j in range(n): + arr[i][j] = float(arr[i][j]) + arr[i][-1] = float(arr[i][-1]) + return arr + +# Решение системы уравнений с использованием numpy +def solve_with_numpy(equations, n): + # Преобразуем уравнения в матрицу коэффициентов и вектор свободных членов + A = np.array([equations[i][:n] for i in range(n)], dtype=float) + B = np.array([equations[i][-1] for i in range(n)], dtype=float) + + # Решаем систему уравнений + solutions = np.linalg.solve(A, B) + + # Вычисляем определитель матрицы + determinant = np.linalg.det(A) + + return solutions, determinant + +class EquationSolver: + def __init__(self, n, equations): + self.n = n + self.original_equations = [row.copy() for row in equations] # Сохраняем исходную матрицу + self.equations = equations # Матрица для преобразований + self.solutions = [] + self.swaps = 0 + + def solve(self): + try: + print('\nИсходная система уравнений:') + self.print_equations() + + self.convert_to_triangle() + print('\nТреугольная матрица:') + self.print_equations() + + print('\nКоличество перестановок:', self.swaps) + + self.calculate_determinant() + + self.find_solutions() + self.print_solutions() + + self.print_residuals() + + # Передаем исходную матрицу в numpy, а не модифицированную + numpy_solutions, numpy_determinant = solve_with_numpy(self.original_equations, self.n) + print('\nРешения системы через numpy:') + for i in range(self.n): + print(f'\tx[{i}] = {round_number(numpy_solutions[i])}') + print(f'\nОпределитель матрицы через numpy: {round_number(numpy_determinant)}') + + # Сравнение результатов + print('\nСравнение результатов:') + print(f'\tРазница в решениях: {np.linalg.norm(np.array(self.solutions) - numpy_solutions)}') + print(f'\tРазница в определителях: {abs(self.determinant - numpy_determinant)}') + + except ZeroDivisionError: + print('Ошибка: деление на ноль!') + except ArithmeticError: + print('Ошибка: система не имеет решений!') + except np.linalg.LinAlgError as e: + print(f'Ошибка при решении системы через numpy: {e}') + + def check_diagonal(self, i): + for j in range(i, self.n): + if self.equations[j][i] != 0: + self.equations[i], self.equations[j] = self.equations[j], self.equations[i] + self.swaps += 1 + return + print('Система не имеет решений!') + raise ArithmeticError + + def convert_to_triangle(self): + for i in range(self.n): + if self.equations[i][i] == 0: + self.check_diagonal(i) + for m in range(i + 1, self.n): + factor = -(self.equations[m][i] / self.equations[i][i]) + for j in range(i, self.n): + self.equations[m][j] += factor * self.equations[i][j] + self.equations[m][-1] += factor * self.equations[i][-1] + + def print_equations(self): + for i in range(self.n): + equation = ' '.join([f'{round_number(self.equations[i][j])} * x[{j}]' for j in range(self.n)]) + print(f'{equation} | {round_number(self.equations[i][-1])}') + + def calculate_determinant(self): + self.determinant = 1 + for i in range(self.n): + self.determinant *= self.equations[i][i] + if self.swaps % 2 == 1: + self.determinant *= -1 + print(f'\nОпределитель матрицы: {round_number(self.determinant)}\n') + if self.determinant == 0: + print('Система вырождена и не имеет решений.') + raise ArithmeticError + + def find_solutions(self): + self.solutions = [0] * self.n + for i in range(self.n - 1, -1, -1): + self.solutions[i] = self.equations[i][-1] / self.equations[i][i] + for j in range(i - 1, -1, -1): + self.equations[j][-1] -= self.equations[j][i] * self.solutions[i] + + def print_solutions(self): + print('Решения системы:') + for i in range(self.n): + print(f'\tx[{i}] = {round_number(self.solutions[i])}') + + def print_residuals(self): + print('\nВеличины невязок:') + for i in range(self.n): + residual = sum(self.equations[i][j] * self.solutions[j] for j in range(self.n)) - self.equations[i][-1] + print(f'\tНевязка для уравнения {i + 1}: {round_number(abs(residual))}') + +# Основное меню программы +def main(): + print('Решение систем линейных уравнений методом Гаусса') + + while True: + try: + print('\nДоступные действия:') + print('\t1: Загрузить систему уравнений из файла.') + print('\t2: Ввести систему уравнений вручную.') + print('\t3: Выйти из программы.') + choice = int(input('Выберите действие: ')) + + if choice == 1: + print('Загрузка системы уравнений из файла.') + print('Формат файла должен быть следующим (максимум 20 уравнений):') + print('\ta11 a12 ... a1n | b1') + print('\ta21 a22 ... a2n | b2') + print('\t... ... ... ... | ..') + print('\tan1 an2 ... ann | bn') + file_path = input('Введите путь к файлу: ').strip() + read_from_file(file_path) + elif choice == 2: + print('Ручной ввод системы уравнений.') + input_manually() + elif choice == 3: + print('Программа завершена. До свидания!') + break + else: + print('Некорректный выбор. Пожалуйста, выберите действие от 1 до 3.') + except KeyboardInterrupt: + print('\nПрограмма была прервана пользователем.') + except Exception as e: + print(f'Произошла ошибка: {e}') + +if __name__ == '__main__': + main() \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab1/\320\222\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\261\320\260 1.pdf" "b/\320\2403265-69/furzikova_368979/lab1/\320\222\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\261\320\260 1.pdf" new file mode 100644 index 0000000..80a5e0d Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab1/\320\222\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\261\320\260 1.pdf" differ diff --git "a/\320\2403265-69/furzikova_368979/lab2/graph.py" "b/\320\2403265-69/furzikova_368979/lab2/graph.py" new file mode 100644 index 0000000..0d065ca --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab2/graph.py" @@ -0,0 +1,29 @@ +from typing import Callable, List, Tuple + +import numpy as np +from matplotlib import pyplot as plt + + +def show_2d(y: Callable, points: List[Tuple]): + width = max(abs(points[0][0]), abs(points[len(points) - 1][0])) + 1 + height = abs(y(width)) + + vf = np.vectorize(y) + x = np.linspace(-width, width, 100) + + fig = plt.figure() + ax = fig.add_subplot(1, 1, 1) + + plt.grid(True) + plt.xlim((-width, width)) + plt.ylim((-height, height)) + + ax.spines['left'].set_position('center') + ax.spines['bottom'].set_position('center') + ax.spines['right'].set_color('none') + ax.spines['top'].set_color('none') + + ax.plot(x, vf(x), 'g', label='y=f(x)') + ax.plot(*list(zip(*points)), 'ro') + + plt.show() diff --git "a/\320\2403265-69/furzikova_368979/lab2/main.py" "b/\320\2403265-69/furzikova_368979/lab2/main.py" new file mode 100644 index 0000000..ce2affd --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab2/main.py" @@ -0,0 +1,169 @@ +# variant number: 15 + + +# 3 - Метод Ньютона +# 5 - Метод простой итерации +# 6 - Метод Ньютона + + +from math import sqrt + +import numpy as np + +from solvers import horde_method, newton_method, simple_iteration_method, system_newton_method +from graph import show_2d + +A, B, C, D = -2.40, 1.27, 8.63, 2.31 +f = lambda x: A * x ** 3 + B * x ** 2 + C * x + D +df = lambda x: 3 * A * x ** 2 + 2 * B * x + C +ddf = lambda x: 6 * A * x + 2 * B + + +def dphi(x): + return abs(sqrt(abs(1/A)) / 3 * (B * x**2 + C * x + D) ** (-2/3) * (2*B*x + C)) + + +def phi(x): + base = -(B * x ** 2 + C * x + D) / A + if base < 0: + return -(-base) ** (1 / 3) + return base ** (1 / 3) + + +def non_linear(output_file): + left, right = map(float, input('Границы левого корня через пробел (-2 -1): ').split()) + #c_x0 = float(input('Нулевое приближение центрального корня (0): ')) + + a, b = map(float, input('Границы для второго корня: (-1 0): ').split()) + if f(a) * ddf(a) > 0: + c_x0 = a + else: + c_x0 = b + + print(f'x0 для второго корня равен равен: {c_x0}') + + # r_x0 = float(input('Нулевое приближение правого корня (5): ')) + a1, b1 = map(float, input('Границы для правого корня: (2 3): ').split()) + if f(a1) * ddf(a1) > 0: + r_x0 = a1 + else: + r_x0 = b1 + + print(f'dpfi в a1 = {dphi(a1)}') + print(f'dpfi в b1 = {dphi(b1)}') + + epsilon = float(input('Погрешность (0.01): ')) + + left_x = horde_method(f, left=left, right=right, epsilon=epsilon) + center_x = newton_method(f, df, c_x0, epsilon=epsilon) + right_x = simple_iteration_method(f, phi, r_x0, epsilon=epsilon) + + show_2d(f, [(left_x.root, 0), (center_x.root, 0), (right_x.root, 0)]) + + print(f'Левый корень x_0={left_x.root:.7f}, знач-e: {left_x.znach_f:.7f}, n: {left_x.iter_count}') + # Значение функции + количество итераций + print(f'Центральный корень x_1={center_x.root:.7f}, знач-e: {center_x.znach_f:.7f}, n: {center_x.iter_count}') + # Значение функции + количество итераций + print(f'Правый корень x_2={right_x.root:.7f}, знач-e: {right_x.znach_f:.7f}, n: {right_x.iter_count}') + # Значение функции + количество итераций + + print(f'Таблица для метода хорд:') + print(left_x) + + print('Таблица для метода Ньютана:') + print(center_x) + + print('Таблица для метода простой итерации:') + print(right_x) + + if output_file != None: + with open(output_file, 'a') as fl: + fl.write(f'Таблица для метода хорд:') + fl.write(str(left_x)) + + fl.write('Таблица для метода Ньютана:') + fl.write(str(center_x)) + + fl.write('Таблица для метода простой итерации:') + fl.write(str(right_x)) + + +def function_1(x, y): + return [ + (-1)*(x+(2*y)-2), + (-1)*((x**2)+(4*(y**2))-4) + ] + + +def jacobian_1(x, y): + return [ + [1, 2], + [2*x, 8*y] + ] + + +def function_2(x, y, z): + return [ + (-1)*(x+y+z-3), + (-1)*((x**2)+(y**2)+(z**2)-5), + (-1)*((np.exp(x))+(x*y)-(x*z)-1) + ] + + +def jacobian_2(x, y, z): + return [[1, 1, 1], [2*x, 2*y, 2*z], [np.exp(x), x, -x]] + + +FUNCTIONS = [ + { + 'disp': 'f1(x1, x2) = x + 2*y - 2\nf2(x1, x2) = x^2 + 4*y^2 - 4)', + 'func': function_1, + 'jacob': jacobian_1, + 'init': [1, 1], + }, + { + 'disp': 'f1(x1, x2, x3) = x + y + z - 3\nf2(x1, x2, x3) = x^2 + y^2 + z^2 - 5\nf3(x1, x2, x3) = exp(x) + x*y - x*z -1', + 'func': function_2, + 'jacob': jacobian_2, + 'init': [100, 200, 3], + }, +] + + +def non_linear_system(output_file): + print(f'Выберите систему нелинейных уравнений:') + for i, group in enumerate(FUNCTIONS, 1): + print(f'Система №{i}') + print(group['disp']) + print() + n = int(input()) + f = FUNCTIONS[n - 1]['func'] + hint = FUNCTIONS[n-1]['init'] + jacob = FUNCTIONS[n - 1]['jacob'] + + x0 = list(map(float, input(f'Начальные приближения ({" ".join(str(num) for num in hint)}): ').split())) + eps = float(input('Погрешность (0.001): ')) + + res = system_newton_method(f, jacob, x0, eps) + + print(res) + if output_file != None: + with open(output_file, 'a') as fl: + fl.write(f'Решение системы нелинейных уравнений:') + fl.write(str(res)) + +def main(): + read_from_file = input('Нужно ли записать результат в файл (y/n): ') + output_file = None + if(read_from_file == 'y'): + output_file = input('Введите название файла (out.txt): ') + + + print('Решение нелейного уравнения: ') + non_linear(output_file) + print('Решение системы нелинейных уравнений: ') + non_linear_system(output_file) + + +if __name__ == '__main__': + main() diff --git "a/\320\2403265-69/furzikova_368979/lab2/out.txt" "b/\320\2403265-69/furzikova_368979/lab2/out.txt" new file mode 100644 index 0000000..afc473c --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab2/out.txt" @@ -0,0 +1,240 @@ + :+---+--------+--------+--------+--------+-------+-------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+--------+-------+-------+-------+ +| 1 | -2.000 | -1.000 | -1.295 | -7.963 | 3.327 | 1.828 | 1.000 | +| 2 | -2.000 | -1.295 | -1.426 | -7.963 | 1.828 | 0.697 | 0.705 | +| 3 | -2.000 | -1.426 | -1.473 | -7.963 | 0.697 | 0.229 | 0.574 | +| 4 | -2.000 | -1.473 | -1.487 | -7.963 | 0.229 | 0.071 | 0.527 | +| 5 | -2.000 | -1.487 | -1.492 | -7.963 | 0.071 | 0.022 | 0.513 | +| 6 | -2.000 | -1.492 | -1.493 | -7.963 | 0.022 | 0.007 | 0.508 | ++---+--------+--------+--------+--------+-------+-------+-------+ :+---+--------+---------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+---------+---------+---------+---------------+ +| 1 | 1.000 | -13.093 | -15.210 | 0.139 | 0.861 | +| 2 | 0.139 | -1.749 | -10.405 | -0.029 | 0.168 | +| 3 | -0.029 | -0.120 | -8.947 | -0.042 | 0.013 | ++---+--------+---------+---------+---------+---------------+ :+---+-------+--------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+--------+---------+----------+---------------+ +| 1 | 6.000 | -1.643 | 6.015 | 6.015 | 0.015 | +| 2 | 6.015 | -0.960 | 6.024 | 6.024 | 0.009 | +| 3 | 6.024 | -0.560 | 6.029 | 6.029 | 0.005 | +| 4 | 6.029 | -0.326 | 6.032 | 6.032 | 0.003 | +| 5 | 6.032 | -0.190 | 6.034 | 6.034 | 0.002 | ++---+-------+--------+---------+----------+---------------+ :+---+--------+--------+--------+--------+-------+-------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+--------+-------+-------+-------+ +| 1 | -2.000 | -1.000 | -1.295 | -7.963 | 3.327 | 1.828 | 1.000 | +| 2 | -2.000 | -1.295 | -1.426 | -7.963 | 1.828 | 0.697 | 0.705 | +| 3 | -2.000 | -1.426 | -1.473 | -7.963 | 0.697 | 0.229 | 0.574 | +| 4 | -2.000 | -1.473 | -1.487 | -7.963 | 0.229 | 0.071 | 0.527 | +| 5 | -2.000 | -1.487 | -1.492 | -7.963 | 0.071 | 0.022 | 0.513 | +| 6 | -2.000 | -1.492 | -1.493 | -7.963 | 0.022 | 0.007 | 0.508 | +| 7 | -2.000 | -1.493 | -1.494 | -7.963 | 0.007 | 0.002 | 0.507 | ++---+--------+--------+--------+--------+-------+-------+-------+ :+---+--------+---------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+---------+---------+---------+---------------+ +| 1 | 1.000 | -13.093 | -15.210 | 0.139 | 0.861 | +| 2 | 0.139 | -1.749 | -10.405 | -0.029 | 0.168 | +| 3 | -0.029 | -0.120 | -8.947 | -0.042 | 0.013 | ++---+--------+---------+---------+---------+---------------+ :+---+-------+--------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+--------+---------+----------+---------------+ +| 1 | 6.000 | -1.643 | 6.015 | 6.015 | 0.015 | +| 2 | 6.015 | -0.960 | 6.024 | 6.024 | 0.009 | +| 3 | 6.024 | -0.560 | 6.029 | 6.029 | 0.005 | +| 4 | 6.029 | -0.326 | 6.032 | 6.032 | 0.003 | +| 5 | 6.032 | -0.190 | 6.034 | 6.034 | 0.002 | +| 6 | 6.034 | -0.110 | 6.035 | 6.035 | 0.001 | +| 7 | 6.035 | -0.064 | 6.035 | 6.035 | 0.001 | ++---+-------+--------+---------+----------+---------------+ :+---+--------+--------+--------+--------+-------+-------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+--------+-------+-------+-------+ +| 1 | -2.000 | -1.000 | -1.295 | -7.963 | 3.327 | 1.828 | 1.000 | +| 2 | -2.000 | -1.295 | -1.426 | -7.963 | 1.828 | 0.697 | 0.705 | +| 3 | -2.000 | -1.426 | -1.473 | -7.963 | 0.697 | 0.229 | 0.574 | +| 4 | -2.000 | -1.473 | -1.487 | -7.963 | 0.229 | 0.071 | 0.527 | +| 5 | -2.000 | -1.487 | -1.492 | -7.963 | 0.071 | 0.022 | 0.513 | ++---+--------+--------+--------+--------+-------+-------+-------+ :+---+--------+---------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+---------+---------+---------+---------------+ +| 1 | 1.000 | -13.093 | -15.210 | 0.139 | 0.861 | +| 2 | 0.139 | -1.749 | -10.405 | -0.029 | 0.168 | +| 3 | -0.029 | -0.120 | -8.947 | -0.042 | 0.013 | ++---+--------+---------+---------+---------+---------------+ :+---+-------+--------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+--------+---------+----------+---------------+ +| 1 | 6.000 | -1.643 | 6.015 | 6.015 | 0.015 | +| 2 | 6.015 | -0.960 | 6.024 | 6.024 | 0.009 | ++---+-------+--------+---------+----------+---------------+ :: -0.000 1.000 +: + 5 + :+---+--------+--------+--------+-------+--------+--------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+-------+--------+--------+-------+ +| 1 | -2.000 | -1.000 | -1.221 | 9.330 | -2.650 | -1.964 | 1.000 | +| 2 | -2.000 | -1.221 | -1.357 | 9.330 | -1.964 | -1.068 | 0.779 | +| 3 | -2.000 | -1.357 | -1.423 | 9.330 | -1.068 | -0.486 | 0.643 | +| 4 | -2.000 | -1.423 | -1.451 | 9.330 | -0.486 | -0.203 | 0.577 | +| 5 | -2.000 | -1.451 | -1.463 | 9.330 | -0.203 | -0.082 | 0.549 | +| 6 | -2.000 | -1.463 | -1.468 | 9.330 | -0.082 | -0.033 | 0.537 | ++---+--------+--------+--------+-------+--------+--------+-------+ :+---+--------+--------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+--------+---------+---------+---------------+ +| 1 | 0.000 | 2.310 | 8.630 | -0.268 | 0.268 | +| 2 | -0.268 | 0.137 | 7.434 | -0.286 | 0.018 | ++---+--------+--------+---------+---------+---------------+ :+---+-------+---------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+---------+---------+----------+---------------+ +| 1 | 3.000 | -25.170 | 2.546 | 2.546 | 0.454 | +| 2 | 2.546 | -7.109 | 2.384 | 2.384 | 0.162 | +| 3 | 2.384 | -2.418 | 2.323 | 2.323 | 0.061 | +| 4 | 2.323 | -0.886 | 2.300 | 2.300 | 0.023 | +| 5 | 2.300 | -0.334 | 2.292 | 2.292 | 0.009 | ++---+-------+---------+---------+----------+---------------+ :+---+--------+--------+--------+-------+--------+--------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+-------+--------+--------+-------+ +| 1 | -2.000 | -1.000 | -1.221 | 9.330 | -2.650 | -1.964 | 1.000 | +| 2 | -2.000 | -1.221 | -1.357 | 9.330 | -1.964 | -1.068 | 0.779 | +| 3 | -2.000 | -1.357 | -1.423 | 9.330 | -1.068 | -0.486 | 0.643 | +| 4 | -2.000 | -1.423 | -1.451 | 9.330 | -0.486 | -0.203 | 0.577 | +| 5 | -2.000 | -1.451 | -1.463 | 9.330 | -0.203 | -0.082 | 0.549 | +| 6 | -2.000 | -1.463 | -1.468 | 9.330 | -0.082 | -0.033 | 0.537 | +| 7 | -2.000 | -1.468 | -1.470 | 9.330 | -0.033 | -0.013 | 0.532 | +| 8 | -2.000 | -1.470 | -1.470 | 9.330 | -0.013 | -0.005 | 0.530 | ++---+--------+--------+--------+-------+--------+--------+-------+ :+---+--------+--------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+--------+---------+---------+---------------+ +| 1 | 0.000 | 2.310 | 8.630 | -0.268 | 0.268 | +| 2 | -0.268 | 0.137 | 7.434 | -0.286 | 0.018 | ++---+--------+--------+---------+---------+---------------+ :+---+-------+---------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+---------+---------+----------+---------------+ +| 1 | 3.000 | -25.170 | 2.546 | 2.546 | 0.454 | +| 2 | 2.546 | -7.109 | 2.384 | 2.384 | 0.162 | +| 3 | 2.384 | -2.418 | 2.323 | 2.323 | 0.061 | +| 4 | 2.323 | -0.886 | 2.300 | 2.300 | 0.023 | +| 5 | 2.300 | -0.334 | 2.292 | 2.292 | 0.009 | +| 6 | 2.292 | -0.127 | 2.288 | 2.288 | 0.003 | +| 7 | 2.288 | -0.049 | 2.287 | 2.287 | 0.001 | +| 8 | 2.287 | -0.019 | 2.286 | 2.286 | 0.000 | ++---+-------+---------+---------+----------+---------------+ :: -0.004 1.008 1.996 +: + 197 + :+---+--------+--------+--------+-------+--------+--------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+-------+--------+--------+-------+ +| 1 | -2.000 | -1.000 | -1.221 | 9.330 | -2.650 | -1.964 | 1.000 | +| 2 | -2.000 | -1.221 | -1.357 | 9.330 | -1.964 | -1.068 | 0.779 | +| 3 | -2.000 | -1.357 | -1.423 | 9.330 | -1.068 | -0.486 | 0.643 | +| 4 | -2.000 | -1.423 | -1.451 | 9.330 | -0.486 | -0.203 | 0.577 | +| 5 | -2.000 | -1.451 | -1.463 | 9.330 | -0.203 | -0.082 | 0.549 | +| 6 | -2.000 | -1.463 | -1.468 | 9.330 | -0.082 | -0.033 | 0.537 | +| 7 | -2.000 | -1.468 | -1.470 | 9.330 | -0.033 | -0.013 | 0.532 | +| 8 | -2.000 | -1.470 | -1.470 | 9.330 | -0.013 | -0.005 | 0.530 | ++---+--------+--------+--------+-------+--------+--------+-------+ :+---+--------+--------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+--------+---------+---------+---------------+ +| 1 | 0.000 | 2.310 | 8.630 | -0.268 | 0.268 | +| 2 | -0.268 | 0.137 | 7.434 | -0.286 | 0.018 | ++---+--------+--------+---------+---------+---------------+ :+---+-------+---------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+---------+---------+----------+---------------+ +| 1 | 3.000 | -25.170 | 2.546 | 2.546 | 0.454 | +| 2 | 2.546 | -7.109 | 2.384 | 2.384 | 0.162 | +| 3 | 2.384 | -2.418 | 2.323 | 2.323 | 0.061 | +| 4 | 2.323 | -0.886 | 2.300 | 2.300 | 0.023 | +| 5 | 2.300 | -0.334 | 2.292 | 2.292 | 0.009 | +| 6 | 2.292 | -0.127 | 2.288 | 2.288 | 0.003 | +| 7 | 2.288 | -0.049 | 2.287 | 2.287 | 0.001 | +| 8 | 2.287 | -0.019 | 2.286 | 2.286 | 0.000 | ++---+-------+---------+---------+----------+---------------+ :+---+--------+--------+--------+-------+--------+--------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+-------+--------+--------+-------+ +| 1 | -2.000 | -1.000 | -1.221 | 9.330 | -2.650 | -1.964 | 1.000 | +| 2 | -2.000 | -1.221 | -1.357 | 9.330 | -1.964 | -1.068 | 0.779 | +| 3 | -2.000 | -1.357 | -1.423 | 9.330 | -1.068 | -0.486 | 0.643 | +| 4 | -2.000 | -1.423 | -1.451 | 9.330 | -0.486 | -0.203 | 0.577 | +| 5 | -2.000 | -1.451 | -1.463 | 9.330 | -0.203 | -0.082 | 0.549 | +| 6 | -2.000 | -1.463 | -1.468 | 9.330 | -0.082 | -0.033 | 0.537 | +| 7 | -2.000 | -1.468 | -1.470 | 9.330 | -0.033 | -0.013 | 0.532 | +| 8 | -2.000 | -1.470 | -1.470 | 9.330 | -0.013 | -0.005 | 0.530 | ++---+--------+--------+--------+-------+--------+--------+-------+ :+---+--------+--------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+--------+---------+---------+---------------+ +| 1 | 0.000 | 2.310 | 8.630 | -0.268 | 0.268 | +| 2 | -0.268 | 0.137 | 7.434 | -0.286 | 0.018 | ++---+--------+--------+---------+---------+---------------+ :+---+-------+---------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+---------+---------+----------+---------------+ +| 1 | 3.000 | -25.170 | 2.546 | 2.546 | 0.454 | +| 2 | 2.546 | -7.109 | 2.384 | 2.384 | 0.162 | +| 3 | 2.384 | -2.418 | 2.323 | 2.323 | 0.061 | +| 4 | 2.323 | -0.886 | 2.300 | 2.300 | 0.023 | +| 5 | 2.300 | -0.334 | 2.292 | 2.292 | 0.009 | +| 6 | 2.292 | -0.127 | 2.288 | 2.288 | 0.003 | +| 7 | 2.288 | -0.049 | 2.287 | 2.287 | 0.001 | +| 8 | 2.287 | -0.019 | 2.286 | 2.286 | 0.000 | ++---+-------+---------+---------+----------+---------------+ :+---+--------+--------+--------+-------+--------+--------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+-------+--------+--------+-------+ +| 1 | -2.000 | -1.000 | -1.221 | 9.330 | -2.650 | -1.964 | 1.000 | +| 2 | -2.000 | -1.221 | -1.357 | 9.330 | -1.964 | -1.068 | 0.779 | +| 3 | -2.000 | -1.357 | -1.423 | 9.330 | -1.068 | -0.486 | 0.643 | +| 4 | -2.000 | -1.423 | -1.451 | 9.330 | -0.486 | -0.203 | 0.577 | +| 5 | -2.000 | -1.451 | -1.463 | 9.330 | -0.203 | -0.082 | 0.549 | +| 6 | -2.000 | -1.463 | -1.468 | 9.330 | -0.082 | -0.033 | 0.537 | +| 7 | -2.000 | -1.468 | -1.470 | 9.330 | -0.033 | -0.013 | 0.532 | +| 8 | -2.000 | -1.470 | -1.470 | 9.330 | -0.013 | -0.005 | 0.530 | ++---+--------+--------+--------+-------+--------+--------+-------+ :+---+--------+--------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+--------+---------+---------+---------------+ +| 1 | 0.000 | 2.310 | 8.630 | -0.268 | 0.268 | +| 2 | -0.268 | 0.137 | 7.434 | -0.286 | 0.018 | ++---+--------+--------+---------+---------+---------------+ :+---+-------+---------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+---------+---------+----------+---------------+ +| 1 | 3.000 | -25.170 | 2.546 | 2.546 | 0.454 | +| 2 | 2.546 | -7.109 | 2.384 | 2.384 | 0.162 | +| 3 | 2.384 | -2.418 | 2.323 | 2.323 | 0.061 | +| 4 | 2.323 | -0.886 | 2.300 | 2.300 | 0.023 | +| 5 | 2.300 | -0.334 | 2.292 | 2.292 | 0.009 | +| 6 | 2.292 | -0.127 | 2.288 | 2.288 | 0.003 | +| 7 | 2.288 | -0.049 | 2.287 | 2.287 | 0.001 | +| 8 | 2.287 | -0.019 | 2.286 | 2.286 | 0.000 | ++---+-------+---------+---------+----------+---------------+ :+----+--------+--------+--------+-------+--------+--------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++----+--------+--------+--------+-------+--------+--------+-------+ +| 1 | -2.000 | -1.000 | -1.221 | 9.330 | -2.650 | -1.964 | 1.000 | +| 2 | -2.000 | -1.221 | -1.357 | 9.330 | -1.964 | -1.068 | 0.779 | +| 3 | -2.000 | -1.357 | -1.423 | 9.330 | -1.068 | -0.486 | 0.643 | +| 4 | -2.000 | -1.423 | -1.451 | 9.330 | -0.486 | -0.203 | 0.577 | +| 5 | -2.000 | -1.451 | -1.463 | 9.330 | -0.203 | -0.082 | 0.549 | +| 6 | -2.000 | -1.463 | -1.468 | 9.330 | -0.082 | -0.033 | 0.537 | +| 7 | -2.000 | -1.468 | -1.470 | 9.330 | -0.033 | -0.013 | 0.532 | +| 8 | -2.000 | -1.470 | -1.470 | 9.330 | -0.013 | -0.005 | 0.530 | +| 9 | -2.000 | -1.470 | -1.471 | 9.330 | -0.005 | -0.002 | 0.530 | +| 10 | -2.000 | -1.471 | -1.471 | 9.330 | -0.002 | -0.001 | 0.529 | +| 11 | -2.000 | -1.471 | -1.471 | 9.330 | -0.001 | -0.000 | 0.529 | ++----+--------+--------+--------+-------+--------+--------+-------+ :+---+--------+--------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+--------+---------+---------+---------------+ +| 1 | 0.000 | 2.310 | 8.630 | -0.268 | 0.268 | +| 2 | -0.268 | 0.137 | 7.434 | -0.286 | 0.018 | +| 3 | -0.286 | 0.001 | 7.314 | -0.286 | 0.000 | ++---+--------+--------+---------+---------+---------------+ :+----+-------+---------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++----+-------+---------+---------+----------+---------------+ +| 1 | 3.000 | -25.170 | 2.546 | 2.546 | 0.454 | +| 2 | 2.546 | -7.109 | 2.384 | 2.384 | 0.162 | +| 3 | 2.384 | -2.418 | 2.323 | 2.323 | 0.061 | +| 4 | 2.323 | -0.886 | 2.300 | 2.300 | 0.023 | +| 5 | 2.300 | -0.334 | 2.292 | 2.292 | 0.009 | +| 6 | 2.292 | -0.127 | 2.288 | 2.288 | 0.003 | +| 7 | 2.288 | -0.049 | 2.287 | 2.287 | 0.001 | +| 8 | 2.287 | -0.019 | 2.286 | 2.286 | 0.000 | +| 9 | 2.286 | -0.007 | 2.286 | 2.286 | 0.000 | +| 10 | 2.286 | -0.003 | 2.286 | 2.286 | 0.000 | ++----+-------+---------+---------+----------+---------------+ :: -0.001 1.003 1.999 +: + 409 diff --git "a/\320\2403265-69/furzikova_368979/lab2/solvers.py" "b/\320\2403265-69/furzikova_368979/lab2/solvers.py" new file mode 100644 index 0000000..57ce68c --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab2/solvers.py" @@ -0,0 +1,127 @@ +from typing import Callable, Optional, List + +import numpy as np +from attr import dataclass, field +from prettytable import PrettyTable + + +MAX_ITER_COUNT = 100 + + +@dataclass +class Result: + root: Optional[float] = None + error: Optional[float] = None + header: list = field(factory=list) + data: list = field(factory=list) + znach_f: float = field(default=0) + iter_count: int = field(default=0) + + def __str__(self): + tt = PrettyTable(self.header) + data = [(n, *map(lambda x: f'{x:.3f}', floats)) for n, *floats in self.data] + tt.add_rows(data) + return str(tt) + + +@dataclass +class SystemResult: + iteration: int = field(default=0) + solved: bool = field(default=False) + roots: list = field(factory=list) + errors: list = field(factory=list) + + def __str__(self): + if self.solved: + return 'Решение: ' + ' '.join(f'{x:.3f}' for x in self.roots) + '\n' + \ + 'Погрешности: ' + ' '.join(str(x) for x in self.errors) + '\n' + \ + f'Количество итераций {self.iteration}\n' + else: + return 'Решений не найдено!' + + +def horde_method(f: Callable, left: float, right: float, fix=-1, epsilon=10e-3): + # [left, right] - интервал изоляции корня + res = Result(header=['№', 'a', 'b', 'x', 'f(a)', 'f(b)', 'f(x)', '|a-b|']) + + x0 = left if fix == -1 else right + for i in range(1, MAX_ITER_COUNT + 1): + res.iter_count = i + x1 = (left * f(right) - right * f(left)) / (f(right) - f(left)) + res.data.append([i, left, right, x1, f(left), f(right), f(x1), abs(left - right)]) + if abs(x1 - x0) <= epsilon or abs(f(x1)) <= epsilon: + res.root = x1 + res.error = abs(x1 - x0) + break + if f(x1) * f(left) < 0: + right = x1 + else: + left = x1 + x0 = x1 + + res.znach_f = f(res.root) + return res + + +def newton_method(y: Callable, df: Callable, x0: float, epsilon=10e-3): + res = Result(header=['№', 'x_k', 'f(x_k)', "f'(x_k)", 'x_{k+1}', '|x_k-x_{k+1}|']) + + for i in range(1, MAX_ITER_COUNT + 1): + res.iter_count = i + x1 = x0 - y(x0) / df(x0) + res.data.append([i, x0, y(x0), df(x0), x1, abs(x1 - x0)]) + + if abs(x1 - x0) <= epsilon or abs(y(x1) / df(x1)) <= epsilon or abs(y(x1)) <= epsilon: + res.root = x1 + res.error = abs(x1 - x0) + break + x0 = x1 + res.znach_f = y(res.root) + return res + + +def simple_iteration_method(f: Callable, phi: Callable, x0=1, epsilon=10e-3): + res = Result(header=['№', 'x_k', 'f(x_k)', 'x_{k+1}', 'phi(x_k)', '|x_k-x_{k+1}|']) + + for i in range(1, MAX_ITER_COUNT + 1): + res.iter_count = i + x1 = phi(x0) + + res.data.append([i, x0, f(x0), x1, phi(x0), abs(x1 - x0)]) + + if abs(x1 - x0) <= epsilon: + res.root = x1 + res.error = abs(x1 - x0) + break + x0 = x1 + res.znach_f = f(res.root) + return res + + +def _newton_method(f, jack, x_init): + jacobian = jack(*x_init) + vector_b_f_output = f(*x_init) + x_delta = np.linalg.solve(jacobian, vector_b_f_output) + x_plus_1 = x_delta + x_init + return x_plus_1 + + +def system_newton_method(f, jack, x_init, epsilon): + result = SystemResult() + + x_old = x_init + x_new = _newton_method(f, jack, x_old) + diff = np.linalg.norm(x_old-x_new) + + while diff > epsilon or result.iteration == MAX_ITER_COUNT: + x_new = _newton_method(f, jack, x_old) + diff = np.linalg.norm(x_old-x_new) + x_old = x_new + result.iteration += 1 + convergent_val = x_new + + if result.iteration != MAX_ITER_COUNT: + result.solved = True + + result.roots = convergent_val + return result diff --git "a/\320\2403265-69/furzikova_368979/lab2/\320\222\321\213\321\207\320\274\320\260\321\2022.pdf" "b/\320\2403265-69/furzikova_368979/lab2/\320\222\321\213\321\207\320\274\320\260\321\2022.pdf" new file mode 100644 index 0000000..6f0a205 Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab2/\320\222\321\213\321\207\320\274\320\260\321\2022.pdf" differ diff --git "a/\320\2403265-69/furzikova_368979/lab3/Exceptions/IncorrectValueException.py" "b/\320\2403265-69/furzikova_368979/lab3/Exceptions/IncorrectValueException.py" new file mode 100644 index 0000000..7f89217 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab3/Exceptions/IncorrectValueException.py" @@ -0,0 +1,4 @@ +class IncorrectValueException(Exception): + + def __init__(self, message): + self.message = message diff --git "a/\320\2403265-69/furzikova_368979/lab3/Exceptions/__pycache__/IncorrectValueException.cpython-312.pyc" "b/\320\2403265-69/furzikova_368979/lab3/Exceptions/__pycache__/IncorrectValueException.cpython-312.pyc" new file mode 100644 index 0000000..077eb30 Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab3/Exceptions/__pycache__/IncorrectValueException.cpython-312.pyc" differ diff --git "a/\320\2403265-69/furzikova_368979/lab3/Functions.py" "b/\320\2403265-69/furzikova_368979/lab3/Functions.py" new file mode 100644 index 0000000..6c5ec14 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab3/Functions.py" @@ -0,0 +1,42 @@ +import numexpr as ne +from sympy import * + +x = symbols('x') + +METHODS = ['Метод правых прямоугольников', + 'Метод левых прямоугольников', + 'Метод средних прямоугольников', + 'Метод трапеций', + 'Метод Симпсона'] + +FUNCTIONS = { + 1: + { + 'FUNCTION': 'f(x)=sin(x)+cos(x)' + }, + 2: + { + 'FUNCTION': 'f(x)=19*x**5-67*x**2+100*x-191' + }, + 3: + { + 'FUNCTION': 'f(x)=5**x+5*x' + }, + 4: + { + 'FUNCTION': 'f(x)=(cos(x))**2' + }, + 5: + { + 'FUNCTION': 'f(x)=x**2' + }, +6: + { + 'FUNCTION': 'f(x)=5*x**3 - 2*x**2 + 3*x - 15' + } + +} + + +def calculateFunction(number_of_function, x: float) -> float: + return ne.evaluate(FUNCTIONS[number_of_function]['FUNCTION'].split('=')[1], local_dict={'x': x}) diff --git "a/\320\2403265-69/furzikova_368979/lab3/ImproperIntegralSolver.py" "b/\320\2403265-69/furzikova_368979/lab3/ImproperIntegralSolver.py" new file mode 100644 index 0000000..175cd85 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab3/ImproperIntegralSolver.py" @@ -0,0 +1,136 @@ +import numpy as np +from scipy import integrate + + +class ImproperIntegralSolver: + """ + Класс для вычисления несобственных интегралов 2 рода + с использованием различных численных методов + """ + + def __init__(self, func, interval, singularity_type): + self.func = func + self.a, self.b = interval + self.singularity_type = singularity_type + self.convergent = False + + def _check_convergence(self): + """Проверка сходимости интеграла""" + try: + if self.singularity_type == 'a': + test = (1e-12) ** 0.5 * self.func(self.a + 1e-12) + elif self.singularity_type == 'b': + test = (1e-12) ** 0.5 * self.func(self.b - 1e-12) + else: + mid = (self.a + self.b) / 2 + left = ImproperIntegralSolver(self.func, (self.a, mid), 'b') + right = ImproperIntegralSolver(self.func, (mid, self.b), 'a') + return left.check_convergence() and right.check_convergence() + self.convergent = np.isfinite(test) + return self.convergent + except: + self.convergent = False + return False + + def integrate(self, method='simpson', n=100000): + """ + Основной метод вычисления интеграла + :param method: метод интегрирования ('left_rect', 'mid_rect', 'right_rect', 'trapezoid', 'simpson') + :param n: количество интервалов разбиения + """ + if not self._check_convergence(): + print("Интеграл не существует") + return None + + try: + if self.singularity_type == 'internal': + return self._handle_internal_singularity(method, n) + + if method in ['left_rect', 'mid_rect', 'right_rect']: + return self._rectangle_method(method, n) + elif method == 'trapezoid': + return self._trapezoid_method(n) + elif method == 'simpson': + return self._simpson_method(n) + else: + raise ValueError("Неизвестный метод интегрирования") + except Exception as e: + print(f"Ошибка: {str(e)}") + return None + + def _generate_partition(self, n): + """Генерация разбиения с учётом особенности""" + if self.singularity_type == 'a': + return np.linspace(self.a + 1e-12, self.b, n + 1) + elif self.singularity_type == 'b': + return np.linspace(self.a, self.b - 1e-12, n + 1) + else: + mid = (self.a + self.b) / 2 + return np.concatenate([ + np.linspace(self.a, mid - 1e-12, n // 2 + 1), + np.linspace(mid + 1e-12, self.b, n // 2 + 1)[1:] + ]) + + def _rectangle_method(self, method, n): + """Метод прямоугольников""" + x = self._generate_partition(n) + h = (x[-1] - x[0]) / n + + if method == 'left_rect': + points = x[:-1] + elif method == 'right_rect': + points = x[1:] + else: # mid_rect + points = (x[:-1] + x[1:]) / 2 + + y = self.func(points) + return h * np.sum(y) + + def _trapezoid_method(self, n): + """Метод трапеций""" + x = self._generate_partition(n) + y = self.func(x) + return np.trapezoid(y, x) + + def _simpson_method(self, n): + """Метод Симпсона""" + if n % 2 != 0: + n += 1 # Делаем четное количество интервалов + x = self._generate_partition(n) + y = self.func(x) + h = (x[-1] - x[0]) / n + return h / 3 * (y[0] + 4 * np.sum(y[1:-1:2]) + 2 * np.sum(y[2:-2:2]) + y[-1]) + + def _handle_internal_singularity(self, method, n): + """Обработка внутренней особенности""" + c = (self.a + self.b) / 2 + left = ImproperIntegralSolver(self.func, (self.a, c), 'b') + right = ImproperIntegralSolver(self.func, (c, self.b), 'a') + return left.integrate(method, n // 2) + right.integrate(method, n // 2) + + +# Примеры использования +if __name__ == "__main__": + # Тестовые интегралы + tests = [ + ("∫1/√x dx от 0 до 1", lambda x: 1 / np.sqrt(x), (0, 1), 'a'), + ("∫1/√(1-x) dx от 0 до 1", lambda x: 1 / np.sqrt(1 - x), (0, 1), 'b'), + ("∫1/|x-0.5|^(1/3) dx от 0 до 1", lambda x: 1 / np.abs(x - 0.5) ** (1 / 3), (0, 1), 'internal'), + ("∫1/x dx от 0 до 1 (расходится)", lambda x: 1 / x, (0, 1), 'a') + + ] + + methods = ['left_rect', 'mid_rect', 'right_rect', 'trapezoid', 'simpson'] + + for desc, func, interval, stype in tests: + print(f"\n{desc}") + solver = ImproperIntegralSolver(func, interval, stype) + + for method in methods: + result = solver.integrate(method, n=100000) + if result is not None: + print(f"{method:10} → {result:.6f}") + + # Проверка расходимости + if not solver._check_convergence(): + print("Результат: Интеграл не существует") \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab3/Methods/MethodRectangles.py" "b/\320\2403265-69/furzikova_368979/lab3/Methods/MethodRectangles.py" new file mode 100644 index 0000000..63e401e --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab3/Methods/MethodRectangles.py" @@ -0,0 +1,118 @@ +from Functions import * +from NumericalIntegrations.NumericalIntegration import * + + +K = 2 + + +class MethodRectangles(NumericalIntegration): + + def iterateRightRectangles(self, number_of_function): + eps = self.getEpsilon() + iterations = 0 + while True: + print(f'Номер итерации №{iterations}') + square_1, n_1 = self.rightRectangles(number_of_function=number_of_function, n=self.getN()) + self.doubleN() + square_2, n_2 = self.rightRectangles(number_of_function=number_of_function, n=self.getN()) + if self.ruleRunge(square_1, square_2, 2, self.getEpsilon()): + print(f"Решение интеграла {FUNCTIONS[number_of_function]['FUNCTION']} " + f"с границами a={self.getLeftBorder()} и b={self.getRightBorder()}:\n\t\t\t " + f"{square_2} \nдля разбиения на {n_2} отрезков.") + break + iterations += 1 + + def rightRectangles(self, number_of_function, n): + a = self.getLeftBorder() + b = self.getRightBorder() + h = (b - a) / n + iterations = [[0.0 for x in range(self.AMOUNT_OF_COLUMNS)] for i in range(n + 1)] + square = 0 + for i in range(n + 1): + iterations[i][0] = i + if i == 0: + iterations[i][1] = a + else: + iterations[i][1] = a + h + iterations[i][2] = calculateFunction(number_of_function, iterations[i][1]) + if i != 0: + square += iterations[i][2] + a = iterations[i][1] + square *= h + print(f'\nМетод правых прямоугольников. Численное интегрирование для n={n} и h={h}') + self.printTableForMethods(iterations, method='right') + print(f'Найденный ответ:{square} для {n} отрезков разбиения.') + return square, n + + def iterateLeftRectangles(self, number_of_function): + eps = self.getEpsilon() + iterations = 0 + while True: + print(f'Номер итерации №{iterations}') + square_1, n_1 = self.leftRectangles(number_of_function=number_of_function, n=self.getN()) + self.doubleN() + square_2, n_2 = self.leftRectangles(number_of_function=number_of_function, n=self.getN()) + if self.ruleRunge(square_1, square_2, 2, self.getEpsilon()): + print(f"Решение интеграла {FUNCTIONS[number_of_function]['FUNCTION']} " + f"с границами a={self.getLeftBorder()} и b={self.getRightBorder()}:\n\t\t\t " + f"{square_2} \nдля разбиения на {n_2} отрезков.") + break + iterations += 1 + + def leftRectangles(self, number_of_function, n): + a = self.getLeftBorder() + b = self.getRightBorder() + h = (b - a) / n + iterations = [[0.0 for x in range(self.AMOUNT_OF_COLUMNS)] for i in range(n + 1)] + square = 0 + for i in range(1, n + 2): + if i == 1: + iterations[i - 1][1] = a + else: + iterations[i - 1][1] = a + h + iterations[i - 1][0] = i - 1 + iterations[i - 1][2] = calculateFunction(number_of_function, iterations[i - 1][1]) + if i != n + 1: + square += iterations[i - 1][2] + a = iterations[i - 1][1] + square *= h + print(f'\nМетод левых прямоугольников. Численное интегрирование для n={n} и h={h}') + self.printTableForMethods(iterations, method='left') + print(f'Найденный ответ:{square} для {n} отрезков разбиения.') + return square, n + + def iterateMiddleRectangles(self, number_of_function): + eps = self.getEpsilon() + iterations = 0 + while True: + print(f'Номер итерации №{iterations}') + square_1, n_1 = self.middleRectangles(number_of_function=number_of_function, n=self.getN()) + self.doubleN() + square_2, n_2 = self.middleRectangles(number_of_function=number_of_function, n=self.getN()) + if self.ruleRunge(square_1, square_2, 2, self.getEpsilon()): + print(f"Решение интеграла {FUNCTIONS[number_of_function]['FUNCTION']} " + f"с границами a={self.getLeftBorder()} и b={self.getRightBorder()}:\n\t\t\t " + f"{square_2} \nдля разбиения на {n_2} отрезков.") + break + iterations += 1 + + def middleRectangles(self, number_of_function, n): + a = self.getLeftBorder() + b = self.getRightBorder() + h = (b - a) / n + iterations = [[0.0 for x in range(self.AMOUNT_OF_COLUMNS)] for i in range(n + 1)] + square = 0 + for i in range(1, n + 1): + iterations[i][0] = i + if i == 1: + iterations[i][1] = (a + a + h) / 2 + else: + iterations[i][1] = a + h + iterations[i][2] = calculateFunction(number_of_function, iterations[i][1]) + square += iterations[i][2] + a = iterations[i][1] + square *= h + print(f'\nМетод средних прямоугольников. Численное интегрирование для n={n} и h={h}') + self.printTableForMethods(iterations, method='middle') + print(f'Найденный ответ:{square} для {n} отрезков разбиения.') + return square, n \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab3/Methods/MethodSympson.py" "b/\320\2403265-69/furzikova_368979/lab3/Methods/MethodSympson.py" new file mode 100644 index 0000000..b6304bf --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab3/Methods/MethodSympson.py" @@ -0,0 +1,43 @@ +from Functions import calculateFunction, FUNCTIONS +from NumericalIntegrations.NumericalIntegration import NumericalIntegration + + +class MethodSympson(NumericalIntegration): + + def iterateSympsonlMethod(self, number_of_function): + eps = self.getEpsilon() + iterations = 0 + while True: + print(f'Номер итерации №{iterations}') + square_1, n_1 = self.sympsonMethod(number_of_function=number_of_function, n=self.getN()) + self.doubleN() + square_2, n_2 = self.sympsonMethod(number_of_function=number_of_function, n=self.getN()) + if self.ruleRunge(square_1, square_2, 2, self.getEpsilon()): + print(f"Решение интеграла {FUNCTIONS[number_of_function]['FUNCTION']} " + f"с границами a={self.getLeftBorder()} и b={self.getRightBorder()}:\n\t\t\t " + f"{square_2} \nдля разбиения на {n_2} отрезков.") + break + iterations += 1 + + def sympsonMethod(self, number_of_function, n): + a = self.getLeftBorder() + b = self.getRightBorder() + h = (b - a) / n + iterations = [[0.0 for x in range(self.AMOUNT_OF_COLUMNS)] for i in range(n + 1)] + square_even = 0 + square_odd = 0 + for i in range(n + 1): + iterations[i][0] = i + iterations[i][1] = a if i == 0 else a + h + iterations[i][2] = calculateFunction(number_of_function, iterations[i][1]) + if i != 0 and i != n: + if i % 2 == 0: + square_even += iterations[i][2] + else: + square_odd += iterations[i][2] + a = iterations[i][1] + square = h / 3 * (iterations[0][2] + iterations[-1][2] + 2 * square_even + 4 * square_odd) + print(f'\nМетод Симпсона. Численное интегрирование для n={n} и h={h}') + self.printTableForMethods(iterations, method='trapezoidal') + print(f'Найденный ответ:{square} для {n} отрезков разбиения.') + return square, n \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab3/Methods/MethodTrapezoidal.py" "b/\320\2403265-69/furzikova_368979/lab3/Methods/MethodTrapezoidal.py" new file mode 100644 index 0000000..559e6dd --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab3/Methods/MethodTrapezoidal.py" @@ -0,0 +1,42 @@ +from Functions import calculateFunction, FUNCTIONS +from NumericalIntegrations.NumericalIntegration import NumericalIntegration + + +class MethodTrapezoidal(NumericalIntegration): + + def iterateTrapezoidalMethod(self, number_of_function): + eps = self.getEpsilon() + iterations = 0 + while True: + print(f'Номер итерации №{iterations}') + square_1, n_1 = self.trapezoidalMethod(number_of_function=number_of_function, n=self.getN()) + self.doubleN() + square_2, n_2 = self.trapezoidalMethod(number_of_function=number_of_function, n=self.getN()) + if self.ruleRunge(square_1, square_2, 2, self.getEpsilon()): + print(f"Решение интеграла {FUNCTIONS[number_of_function]['FUNCTION']} " + f"с границами a={self.getLeftBorder()} и b={self.getRightBorder()}:\n\t\t\t " + f"{square_2} \nдля разбиения на {n_2} отрезков.") + break + iterations += 1 + + def trapezoidalMethod(self, number_of_function, n): + a = self.getLeftBorder() + b = self.getRightBorder() + h = (b - a) / n + iterations = [[0.0 for x in range(self.AMOUNT_OF_COLUMNS)] for i in range(n + 1)] + square = 0 + for i in range(n + 1): + iterations[i][0] = i + if i == 0: + iterations[i][1] = a + else: + iterations[i][1] = a + h + iterations[i][2] = calculateFunction(number_of_function, iterations[i][1]) + if i != 0 and i != n: + square += iterations[i][2] + a = iterations[i][1] + square = h * ((iterations[0][2] + iterations[-1][2]) / 2 + square) + print(f'\nМетод трапеций. Численное интегрирование для n={n} и h={h}') + self.printTableForMethods(iterations, method='trapezoidal') + print(f'Найденный ответ:{square} для {n} отрезков разбиения.') + return square, n diff --git "a/\320\2403265-69/furzikova_368979/lab3/Methods/__pycache__/MethodRectangles.cpython-312.pyc" "b/\320\2403265-69/furzikova_368979/lab3/Methods/__pycache__/MethodRectangles.cpython-312.pyc" new file mode 100644 index 0000000..a239873 Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab3/Methods/__pycache__/MethodRectangles.cpython-312.pyc" differ diff --git "a/\320\2403265-69/furzikova_368979/lab3/Methods/__pycache__/MethodSympson.cpython-312.pyc" "b/\320\2403265-69/furzikova_368979/lab3/Methods/__pycache__/MethodSympson.cpython-312.pyc" new file mode 100644 index 0000000..3aeec40 Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab3/Methods/__pycache__/MethodSympson.cpython-312.pyc" differ diff --git "a/\320\2403265-69/furzikova_368979/lab3/Methods/__pycache__/MethodTrapezoidal.cpython-312.pyc" "b/\320\2403265-69/furzikova_368979/lab3/Methods/__pycache__/MethodTrapezoidal.cpython-312.pyc" new file mode 100644 index 0000000..07d5432 Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab3/Methods/__pycache__/MethodTrapezoidal.cpython-312.pyc" differ diff --git "a/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/NumericalIntegration.py" "b/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/NumericalIntegration.py" new file mode 100644 index 0000000..6b3db38 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/NumericalIntegration.py" @@ -0,0 +1,44 @@ +from Validator import Validator + +class NumericalIntegration: + AMOUNT_OF_COLUMNS = 3 + + def __init__(self, epsilon, left_border, right_border, n): + self.__right_border = right_border + self.__left_border = left_border + self.__n = n + self.__epsilon = epsilon + + def getEpsilon(self): + return self.__epsilon + + def getN(self): + return self.__n + + def doubleN(self): + self.__n *= 2 + + def getLeftBorder(self): + return self.__left_border + + def getRightBorder(self): + return self.__right_border + + def ruleRunge(self, I_h, I_h2, k, eps): #Правило Рунге + delta = abs(I_h2 - I_h) / (2 ** k - 1) + print( + f'Погрешность вычислений между значениями {I_h2} и {I_h} составляет {delta} {"<" if delta < eps else ">"} {eps}.') + if delta <= eps: + return True + else: + return False + + def printTableForMethods(self, iterations, method): + if method == 'middle': + print('i | x(i-1/2) | y(i-1/2) |') + else: + print('i | xi | yi |') + for i in range(len(iterations)): + for j in range(len(iterations[i])): + print(iterations[i][j], end=' | ') + print() diff --git "a/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/Terminal.py" "b/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/Terminal.py" new file mode 100644 index 0000000..c573976 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/Terminal.py" @@ -0,0 +1,89 @@ +from Methods.MethodRectangles import MethodRectangles +from Methods.MethodSympson import MethodSympson +from Methods.MethodTrapezoidal import MethodTrapezoidal +from Validator import Validator +from Exceptions.IncorrectValueException import IncorrectValueException +from Functions import * + + +class Terminal: + + def work(self): + try: + print('\t\t\tЛабораторная работа №3\n\t\t\tЧисленное интегрирование') + for i in range(len(FUNCTIONS)): + print(f"{i + 1}. {FUNCTIONS[i + 1]['FUNCTION']}") + function_number = self.enterFunctionNumber() + print('\t\tМетоды решения:') + for i in range(len(METHODS)): + print(f'{i + 1}.{METHODS[i]}') + method_number = self.enterFunctionMethod() + a, b = self.enterBorders() + epsilon = self.enterEpsilon() + n = self.enterN() + + if method_number == 1: + right_rectangles = MethodRectangles(epsilon, a, b, n) + right_rectangles.iterateRightRectangles(number_of_function=function_number) + elif method_number == 2: + left_rectangles = MethodRectangles(epsilon, a, b, n) + left_rectangles.iterateLeftRectangles(number_of_function=function_number) + elif method_number == 3: + middle_rectangles = MethodRectangles(epsilon, a, b, n) + middle_rectangles.iterateMiddleRectangles(number_of_function=function_number) + elif method_number == 4: + trapezoidal_method = MethodTrapezoidal(epsilon, a, b, n) + trapezoidal_method.iterateTrapezoidalMethod(number_of_function=function_number) + else: + sympson_method = MethodSympson(epsilon, a, b, n) + sympson_method.iterateSympsonlMethod(number_of_function=function_number) + except IncorrectValueException as e: + print(e.message) + return + + def enterFunctionNumber(self): + try: + print('Введите номер функции:') + return Validator.validateFunctionNumber() + except IncorrectValueException as e: + print(e.message) + return self.enterFunctionNumber() + + def enterFunctionMethod(self): + try: + print('Введите номер метода:') + return Validator.validateFunctionMethod() + except IncorrectValueException as e: + print(e.message) + return self.enterFunctionMethod() + + def enterN(self): + try: + print('Введите начальное число отрезков для разбиения:') + n = Validator.validateN() + return n + except IncorrectValueException as e: + print(e.message) + return self.enterN() + + def enterBorders(self): + try: + print('Введите границы интервала a и b:') + print('a = ', end='') + a = Validator.validateNumber(input()) + print('b = ', end='') + b = Validator.validateNumber(input()) + Validator.validateBorders(a, b) + return a, b + except IncorrectValueException as e: + print(e.message) + return self.enterBorders() + + def enterEpsilon(self): + try: + print('Введите точность epsilon:') + eps = Validator.validateEpsilon(input()) + return eps + except IncorrectValueException as e: + print(e.message) + return self.enterEpsilon() \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/__pycache__/NumericalIntegration.cpython-312.pyc" "b/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/__pycache__/NumericalIntegration.cpython-312.pyc" new file mode 100644 index 0000000..ff38db6 Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/__pycache__/NumericalIntegration.cpython-312.pyc" differ diff --git "a/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/__pycache__/Terminal.cpython-312.pyc" "b/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/__pycache__/Terminal.cpython-312.pyc" new file mode 100644 index 0000000..d9bddd8 Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/__pycache__/Terminal.cpython-312.pyc" differ diff --git "a/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/main.py" "b/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/main.py" new file mode 100644 index 0000000..6faae51 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab3/NumericalIntegrations/main.py" @@ -0,0 +1,11 @@ + +from NumericalIntegrations.Terminal import Terminal + +if __name__ == "__main__": + + terminal = Terminal() + while True: + terminal.work() + print("Хотите продолжить работу с программой? y/n") + if not input().__eq__('y'): + break diff --git "a/\320\2403265-69/furzikova_368979/lab3/Validator.py" "b/\320\2403265-69/furzikova_368979/lab3/Validator.py" new file mode 100644 index 0000000..12f11b3 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab3/Validator.py" @@ -0,0 +1,57 @@ +from Exceptions.IncorrectValueException import IncorrectValueException +from Functions import FUNCTIONS, METHODS + + +class Validator: + MIN_EPSILON = 0 + + @staticmethod + def validateEpsilon(epsilon: str): + try: + epsilon = float(epsilon) + if epsilon >= Validator.MIN_EPSILON: + return epsilon + else: + raise IncorrectValueException(f'Точность (эпсилон) должна быть больше или равна 0.') + except ValueError: + raise IncorrectValueException(f'Точность (эпсилон) - число с плавающей точкой.') + + @staticmethod + def validateNumber(number: str): + try: + number = float(number) + return number + except ValueError: + raise IncorrectValueException(f'Необходимо ввести число.') + + @staticmethod + def validateFunctionNumber(): + equation_number = int(Validator.validateNumber(input())) + if 0 < equation_number <= len(FUNCTIONS): + return equation_number + else: + raise IncorrectValueException('Неверное введен номер функции. Попробуйте еще раз.') + + + @staticmethod + def validateFunctionMethod(): + equation_method = int(Validator.validateNumber(input())) + if 0 < equation_method <= len(METHODS): + return equation_method + else: + raise IncorrectValueException('Неверное введен номер метода. Попробуйте еще раз.') + + @staticmethod + def validateN(): + n = int(Validator.validateNumber(input())) + if n > 3: + return n + else: + raise IncorrectValueException('Неверное введено значение числа разбиения интервала интегрирования. Число должно быть строго больше 3.. Попробуйте еще раз.') + + @staticmethod + def validateBorders(border_left: float, border_right: float): + if border_left < border_right: + return True + else: + raise IncorrectValueException(f'Левая граница должна быть строго меньше правой.') \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab3/\320\222\321\213\321\207\320\274\320\260\321\2023.pdf" "b/\320\2403265-69/furzikova_368979/lab3/\320\222\321\213\321\207\320\274\320\260\321\2023.pdf" new file mode 100644 index 0000000..3da1acf Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab3/\320\222\321\213\321\207\320\274\320\260\321\2023.pdf" differ diff --git "a/\320\2403265-69/furzikova_368979/lab4/Approximation.py" "b/\320\2403265-69/furzikova_368979/lab4/Approximation.py" new file mode 100644 index 0000000..df6052b --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab4/Approximation.py" @@ -0,0 +1,93 @@ +from numpy import sqrt, log, exp + + +class Approximation: + + def __init__(self, x_arr, y_arr): + self.__x_array = x_arr + self.__y_array = y_arr + self.__n = len(self.__x_array) + self.__p_x = [] + self.__epsilon = [] + + def getArrayX(self): + return self.__x_array + + def setArrayX(self, arr): + self.__x_array = arr + + def getArrayY(self): + return self.__y_array + + def setArrayY(self, arr): + self.__y_array = arr + + def getN(self): + return self.__n + + def getEpsilon(self): + return self.__epsilon + + def _setEpsilon(self, eps): + self.__epsilon = eps + + def getPX(self): + return self.__p_x + + def _setPX(self, p_x): + self.__p_x = p_x + + def calculateSumX(self, degree): + return sum([x ** degree for x in self.__x_array]) + + def calculateSumY(self): + return sum(self.__y_array) + + def calculateSumXY(self, degree): + return sum([self.__x_array[i] ** degree * self.__y_array[i] for i in range(self.__n)]) + + def _calculateEpsilon(self): + return [self.__p_x[i] - self.__y_array[i] for i in range(self.__n)] + + def _calculateExponentialValues(self, a, b): + return [a * x ** b for x in self.__x_array] + + def _calculateLogarithmValues(self, a, b): + return [a * log(x) + b for x in self.__x_array] + + def _calculateExponentValues(self, a, b): + return [a * exp(b * x) for x in self.__x_array] + + def _calculateLinearValues(self, a, b): + return [a * x + b for x in self.__x_array] + + def _calculatePolynomialSecondValues(self, a0, a1, a2): + return [a0 + a1 * x + a2 * x ** 2 for x in self.__x_array] + + def _calculatePolynomialThirdValues(self, a0, a1, a2, a3): + return [a0 + a1 * x + a2 * x ** 2 + a3 * x ** 3 for x in self.__x_array] + + def _deviationMeasure(self): + return sum([eps ** 2 for eps in self.__epsilon]) + + def _standardDeviation(self): + return sqrt(self._deviationMeasure() / self.__n) + + def _printTable(self): + print('| X | Y | P(x) | epsilon |') + for i in range(self.__n): + print(f"| {self.__x_array[i]} | {self.__y_array[i]} | {self.__p_x[i]} | {self.__epsilon[i]} |") + + def _coefficientCorrelation(self): + x_mean = self._calculateMeanX() + y_mean = self._calculateMeanY() + return sum([(self.__x_array[i] - x_mean) * (self.__y_array[i] - y_mean) + for i in range(self.__n)]) / sqrt( + sum([(self.__x_array[i] - x_mean) ** 2 for i in range(self.__n)]) * + sum([(self.__y_array[i] - y_mean) ** 2 for i in range(self.__n)])) + + def _calculateMeanX(self): + return sum(self.__x_array) / self.__n + + def _calculateMeanY(self): + return sum(self.__y_array) / self.__n \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab4/ApproximationFunctions.py" "b/\320\2403265-69/furzikova_368979/lab4/ApproximationFunctions.py" new file mode 100644 index 0000000..be63611 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab4/ApproximationFunctions.py" @@ -0,0 +1,208 @@ +import math + +from numpy import exp, log + +from Approximation import Approximation +import numpy as np + + +class ApproximationFunctions(Approximation): + + def __calculateLinearFunctionCoefficient(self): + SX = self.calculateSumX(1) + SXX = self.calculateSumX(2) + SY = self.calculateSumY() + SXY = self.calculateSumXY(1) + N = self.getN() + delta = SXX * N - SX * SX + delta1 = SXY * N - SX * SY + delta2 = SXX * SY - SX * SXY + a = delta1 / delta + b = delta2 / delta + self._setPX(self._calculateLinearValues(a, b)) + self._setEpsilon(self._calculateEpsilon()) + S = self._deviationMeasure() + SD = self._standardDeviation() + return {'SX': SX, 'SXX': SXX, 'SY': SY, + 'SXY': SXY, 'N': N, 'delta': delta, + 'delta1': delta1, 'delta2': delta2, + 'a': a, 'b': b, 'S': S, 'SD': SD} + + # Линейная функция + def linearFunction(self): + coefficients = self.__calculateLinearFunctionCoefficient() + print('\t\t\tЛинейная аппроксимация') + print(f"\tCистема уравнений:\n" + f"\t\t{coefficients['SXX']}a + {coefficients['SX']}b = {coefficients['SXY']}\n" + f"\t\t{coefficients['SX']}a + {coefficients['N']}b = {coefficients['SY']}") + print(f"\tИз нее находим:\n" + f"\t\tdelta = {coefficients['SXX']}*{coefficients['N']} - {coefficients['SX']}*{coefficients['SX']} = {coefficients['delta']}\n" + f"\t\tdelta1 = {coefficients['SXY']}*{coefficients['N']} - {coefficients['SX']}*{coefficients['SY']} = {coefficients['delta1']}\n" + f"\t\tdelta2 = {coefficients['SXX']}*{coefficients['SY']} - {coefficients['SX']}*{coefficients['SXY']} = {coefficients['delta2']}\n" + f"\t\t\ta = {coefficients['delta1']}/{coefficients['delta']} = {coefficients['a']}\n" + f"\t\t\tb = {coefficients['delta2']}/{coefficients['delta']} = {coefficients['b']}\n") + function = f"P1(x) = {coefficients['a']}x + ({coefficients['b']})" + self.__printCoefficients(coefficients, function) + print(f"Коэффициент корреляции Пирсона: {self._coefficientCorrelation()}") + return function, {'a': coefficients['a'], 'b': coefficients['b']}, coefficients['S'], coefficients['SD'] + + def __calculatePolynomialSecondFunctionCoefficient(self): # Полиномиальная функция 2-й степени + SX = self.calculateSumX(1) + SXX = self.calculateSumX(2) + SXXX = self.calculateSumX(3) + SXXXX = self.calculateSumX(4) + SY = self.calculateSumY() + SXY = self.calculateSumXY(1) + SXXY = self.calculateSumXY(2) + N = self.getN() + M1 = np.array([[N, SX, SXX], [SX, SXX, SXXX], [SXX, SXXX, SXXXX]]) # Матрица (левая часть системы) + V1 = np.array([SY, SXY, SXXY]) # Вектор (правая часть системы) + a0, a1, a2 = np.linalg.solve(M1, V1) + self._setPX(self._calculatePolynomialSecondValues(a0, a1, a2)) + self._setEpsilon(self._calculateEpsilon()) + S = self._deviationMeasure() + SD = self._standardDeviation() + return {'SX': SX, 'SXX': SXX, 'SXXX': SXXX, 'SXXXX': SXXXX, + 'SY': SY, 'SXY': SXY, 'SXXY': SXXY, 'N': N, + 'a0': round(a0, 5), 'a1': round(a1, 5), 'a2': round(a2, 5), 'S': S, 'SD': SD} + + def polynomialSecondFunction(self): + print('\t\t\tПолиномиальная функция 2-ой степени') + coefficients = self.__calculatePolynomialSecondFunctionCoefficient() + function = f"P2(x) = {coefficients['a0']} + ({coefficients['a1']}x)+ ({coefficients['a2']}x^2)" + print(f"\tПолучаем систему уравнений:\n" + f"\t\t{coefficients['N']}a0 + {coefficients['SX']}a1 + {coefficients['SXX']}a2 = {coefficients['SY']}\n" + f"\t\t{coefficients['SX']}a0 + {coefficients['SXX']}a1 + {coefficients['SXXX']}a2= {coefficients['SXY']}\n" + f"\t\t{coefficients['SXX']}a0 + {coefficients['SXXX']}a1 + {coefficients['SXXXX']}a2= {coefficients['SXXY']}\n") + print(f"\tНайденные коэффициенты:\n" + f"\t\ta0 = {coefficients['a0']}\n" + f"\t\ta1 = {coefficients['a1']}\n" + f"\t\ta2 = {coefficients['a2']}\n") + self.__printCoefficients(coefficients, function) + return function, {'a0': coefficients['a0'], 'a1': coefficients['a1'], 'a2': coefficients['a2']}, \ + coefficients['S'], coefficients['SD'] + + def __calculatePolynomialThirdFunctionCoefficient(self): # Полиномиальная функция 3-й степени + SX = self.calculateSumX(1) + SXX = self.calculateSumX(2) + SXXX = self.calculateSumX(3) + SXXXX = self.calculateSumX(4) + SXXXXX = self.calculateSumX(5) + SXXXXXX = self.calculateSumX(6) + SY = self.calculateSumY() + SXY = self.calculateSumXY(1) + SXXY = self.calculateSumXY(2) + SXXXY = self.calculateSumXY(3) + N = self.getN() + M1 = np.array([[N, SX, SXX, SXXX], [SX, SXX, SXXX, SXXXX], [SXX, SXXX, SXXXX, SXXXXX], + [SXXX, SXXXX, SXXXXX, SXXXXXX]]) # Матрица (левая часть системы) + V1 = np.array([SY, SXY, SXXY, SXXXY]) # Вектор (правая часть системы) + a0, a1, a2, a3 = np.linalg.solve(M1, V1) + self._setPX(self._calculatePolynomialThirdValues(a0, a1, a2, a3)) + self._setEpsilon(self._calculateEpsilon()) + S = self._deviationMeasure() + SD = self._standardDeviation() + return {'SX': SX, 'SXX': SXX, 'SXXX': SXXX, 'SXXXX': SXXXX, 'SXXXXX': SXXXXX, 'SXXXXXX': SXXXXXX, + 'SY': SY, 'SXY': SXY, 'SXXY': SXXY, 'SXXXY': SXXXY, 'N': N, + 'a0': round(a0, 5), 'a1': round(a1, 5), 'a2': round(a2, 5), 'a3': round(a3, 5), 'S': S, 'SD': SD} + + def polynomialThirdFunction(self): + print('\t\t\tПолиномиальная функция 3-ей степени') + coefficients = self.__calculatePolynomialThirdFunctionCoefficient() + function = f"P3(x) = {coefficients['a0']} + ({coefficients['a1']}x)+ ({coefficients['a2']}x^2) + ({coefficients['a3']}x^3)" + print(f"\tПолучим систему уравнений:\n" + f"\t\t{coefficients['N']}a0 + {coefficients['SX']}a1 + {coefficients['SXX']}a2 + {coefficients['SXXX']}a3 = {coefficients['SY']}\n" + f"\t\t{coefficients['SX']}a0 + {coefficients['SXX']}a1 + {coefficients['SXXX']}a2 + {coefficients['SXXXX']}a3= {coefficients['SXY']}\n" + f"\t\t{coefficients['SXX']}a0 + {coefficients['SXXX']}a1 + {coefficients['SXXXX']}a2 + {coefficients['SXXXXX']}a3= {coefficients['SXXY']}\n" + f"\t\t{coefficients['SXXX']}a0 + {coefficients['SXXXX']}a1 + {coefficients['SXXXXX']}a2 + {coefficients['SXXXXXX']}a3= {coefficients['SXXXY']}\n") + print(f"\tНайденные коэффициенты:\n" + f"\t\ta0 = {coefficients['a0']}\n" + f"\t\ta1 = {coefficients['a1']}\n" + f"\t\ta2 = {coefficients['a2']}\n" + f"\t\ta3 = {coefficients['a3']}\n") + self.__printCoefficients(coefficients, function) + return function, {'a0': coefficients['a0'], 'a1': coefficients['a1'], 'a2': coefficients['a2'], + 'a3': coefficients['a3']}, \ + coefficients['S'], coefficients['SD'] + + # Экспоненциальная + def __calculateExponentFunctionCoefficient(self): + y_arr = self.getArrayY() + self.setArrayY([log(y) for y in y_arr]) + A, B, a, b = self.calculateLinearForOtherFunctions() + self.setArrayY(y_arr) + self._setPX(self._calculateExponentValues(a, b)) + self._setEpsilon(self._calculateEpsilon()) + S = self._deviationMeasure() + SD = self._standardDeviation() + return {'A': A, 'B': B, 'a': a, + 'b': b, 'S': S, 'SD': SD} + + def exponentFunction(self): + print('\t\t\tЭкспоненциальная функция') + coefficients = self.__calculateExponentFunctionCoefficient() + function = f"P4(x) = {coefficients['a']}*e({coefficients['b']}*x)" + self.__printCoefficients(coefficients, function) + return function, {'a': coefficients['a'], 'b': coefficients['b']}, \ + coefficients['S'], coefficients['SD'] + + # Cтепенная + def __calculateExponentialFunctionCoefficient(self): + y_arr, x_arr = self.getArrayY(), self.getArrayX() + self.setArrayY([log(y) for y in y_arr]) + self.setArrayX([log(x) for x in x_arr]) + A, B, a, b = self.calculateLinearForOtherFunctions() + self.setArrayY(y_arr) + self.setArrayX(x_arr) + self._setPX(self._calculateExponentialValues(a, b)) + self._setEpsilon(self._calculateEpsilon()) + S = self._deviationMeasure() + SD = self._standardDeviation() + return {'A': A, 'B': B, 'a': a, + 'b': b, 'S': S, 'SD': SD} + + def exponentialFunction(self): + print('\t\t\tСтепенная функция') + coefficients = self.__calculateExponentialFunctionCoefficient() + function = f"P5(x) = {coefficients['a']}*x^({coefficients['b']})" + self.__printCoefficients(coefficients, function) + return function, {'a': coefficients['a'], 'b': coefficients['b']}, \ + coefficients['S'], coefficients['SD'] + + # Логарифмическая + def __calculateLogarithmFunctionCoefficient(self): + x_arr = self.getArrayX() + self.setArrayX([log(x) for x in x_arr]) + coefficient = self.__calculateLinearFunctionCoefficient() + A, B = coefficient['a'], coefficient['b'] + a, b = A, B + self.setArrayX(x_arr) + self._setPX(self._calculateLogarithmValues(a, b)) + self._setEpsilon(self._calculateEpsilon()) + S = self._deviationMeasure() + SD = self._standardDeviation() + return {'A': A, 'B': B, 'a': a, + 'b': b, 'S': S, 'SD': SD} + + def logarithmFunction(self): + print('\t\t\tЛогарифмическая функция') + coefficients = self.__calculateLogarithmFunctionCoefficient() + function = f"P6(x) = {coefficients['a']}*ln(x)+{coefficients['b']}" + self.__printCoefficients(coefficients, function) + return function, {'a': coefficients['a'], 'b': coefficients['b']}, \ + coefficients['S'], coefficients['SD'] + + def __printCoefficients(self, coefficients, function): + for key, val in coefficients.items(): + print(f" {key} = {val}.") + print(f"Аппроксимирующая функция имеет вид {function}") + self._printTable() + print(f"Мера отклонения S = {coefficients['S']}") + print(f"Среднеквадратическое отклонение SD = {coefficients['SD']}") + + def calculateLinearForOtherFunctions(self): + coefficient = self.__calculateLinearFunctionCoefficient() + A, B = coefficient['b'], coefficient['a'] + a, b = math.exp(A), B + return A, B, a, b + diff --git "a/\320\2403265-69/furzikova_368979/lab4/Exceptions/IncorrectValueException.py" "b/\320\2403265-69/furzikova_368979/lab4/Exceptions/IncorrectValueException.py" new file mode 100644 index 0000000..afbdb08 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab4/Exceptions/IncorrectValueException.py" @@ -0,0 +1,4 @@ +class IncorrectValueException(Exception): + + def __init__(self, message): + self.message = message \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab4/Exceptions/__pycache__/IncorrectValueException.cpython-312.pyc" "b/\320\2403265-69/furzikova_368979/lab4/Exceptions/__pycache__/IncorrectValueException.cpython-312.pyc" new file mode 100644 index 0000000..3c44d3c Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab4/Exceptions/__pycache__/IncorrectValueException.cpython-312.pyc" differ diff --git "a/\320\2403265-69/furzikova_368979/lab4/Terminal.py" "b/\320\2403265-69/furzikova_368979/lab4/Terminal.py" new file mode 100644 index 0000000..e493ae0 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab4/Terminal.py" @@ -0,0 +1,146 @@ +from numpy import exp, log + +import numpy as np + +from ApproximationFunctions import ApproximationFunctions +from Validation.Validator import Validator +from Exceptions.IncorrectValueException import IncorrectValueException +import matplotlib.pyplot as plt + +INTERVAL_FOR_GRAPHIC_X = 1 + + +class Terminal: + def __init__(self): + self.__isFromFile: bool = False + + def isFile(self, mode) -> bool: + if mode == 0: + print("Выберите формат ввода(c клавиатуры - k или из файла - f):") + else: + print("Хотите записать результаты в файл?(нет - k или да - f):") + is_file = input() + if is_file.__eq__('k'): + return False + elif is_file.__eq__('f'): + return True + else: + return self.isFile(mode) + + def refresh(self): + self.__isFromFile = False + + def work(self): + try: + print('\t\t\tАппроксимация функции методом наименьших квадратов') + self.__isFromFile = self.isFile(0) + if self.__isFromFile: + x_array, y_array = self.enterArraysFromFile() + else: + x_array, y_array = self.enterArraysFromKeyboard() + min_x, max_x = min(x_array), max(x_array) + x = np.arange(min_x, max_x, 0.1) + self.__isFromFile = self.isFile(1) + results = list() + approximation = ApproximationFunctions(x_array, y_array) + results.append(approximation.linearFunction()) + results.append(approximation.polynomialSecondFunction()) + results.append(approximation.polynomialThirdFunction()) + results.append(approximation.exponentialFunction()) + results.append(approximation.exponentFunction()) + results.append(approximation.logarithmFunction()) + self.printTableOfCompare(results) + index = self.minSD(results) + print(f'Наилучшее приближение :\n' + f'1.Аппроксимирующая функция: {results[index][0]}\n' + f'2. Коэффициенты:{results[index][1]}\n' + f'3. Среднеквадратичное отклонение: {results[index][3]}') + + plt.scatter(x_array, y_array, color='red', s=40, marker='o', label='f(x)') + plt.plot(x, [results[0][1]['a'] * x + results[0][1]['b'] for x in x], color='green', label=results[0][0]) + plt.plot(x, + [results[1][1]['a0'] + x * results[1][1]['a1'] + results[1][1]['a2'] * x ** 2 for x in x], + '--', + color='blue', label=results[1][0]) + plt.plot(x, + [results[2][1]['a0'] + x * results[2][1]['a1'] + results[2][1]['a2'] * x ** 2 + results[2][1][ + 'a3'] * x ** 3 for x in x], '--', + color='black', label=results[2][0]) + plt.plot(x, + [results[5][1]['a'] * log(x) + results[5][1]['b'] for x in x], '--', + color='purple', label=results[5][0]) + plt.legend() + plt.grid() + plt.figure(2) + plt.plot(x, [results[3][1]['a'] * x ** results[3][1]['b'] for x in x], '--', + color='pink', label=results[3][0]) + plt.scatter(x_array, y_array, color='red', s=40, marker='o', label='f(x)') + plt.legend() + plt.grid() + plt.figure(3) + plt.plot(x, + [results[4][1]['a'] * exp(x * results[4][1]['b']) for x in x], '--', + color='orange', label=results[4][0]) + plt.scatter(x_array, y_array, color='red', s=40, marker='o', label='f(x)') + plt.legend() + plt.grid() + except IncorrectValueException as e: + print(e.message) + return + except ValueError as e: + print(e.message) + return + except RuntimeWarning: + pass + finally: + plt.show() + + def enterArray(self, variable) -> object: + try: + print(f'Введите значения {variable} (через ;):') + arr = [Validator.validateNumber(x) for x in input().split(';')] + Validator.validateArraySize(arr) + return arr + except IncorrectValueException as e: + print(e.message) + return self.enterArray(variable) + + def enterArraysFromKeyboard(self): + x_array = self.enterArray('x') + y_array = self.enterArray('y') + Validator.validateEqualityLengths(x_array, y_array) + return x_array, y_array + + def enterArraysFromFile(self): + try: + f = open(input('Введите путь к файлу:'), 'r') + x_array = [Validator.validateNumber(x) for x in f.readline().split(';')] + Validator.validateArraySize(x_array) + y_array = [Validator.validateNumber(x) for x in f.readline().split(';')] + Validator.validateArraySize(y_array) + Validator.validateEqualityLengths(x_array, y_array) + return x_array, y_array + except IncorrectValueException as e: + print(e.message) + return self.enterArraysFromFile() + except FileNotFoundError as e: + print(e.strerror) + return self.enterArraysFromFile() + + def printTableOfCompare(self, results): + print('\t\t\tРезультаты ') + print('| Вид функции | Коэффициенты ' + '| Мера отклонения | Среднеквадратичное отклонение |') + for i in range(len(results)): + print(f'| {results[i][0]} | ', end='') + for key, val in results[i][1].items(): + print(f'{key} = {val}|', end='') + print(f"| {results[i][2]} | {results[i][3]} |") + + def minSD(self, results): + min = results[0][3] + index = 0 + for i in range(len(results)): + if results[i][3] < min: + index = i + return index \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab4/Validation/Validator.py" "b/\320\2403265-69/furzikova_368979/lab4/Validation/Validator.py" new file mode 100644 index 0000000..eb78e7b --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab4/Validation/Validator.py" @@ -0,0 +1,28 @@ +from Exceptions.IncorrectValueException import IncorrectValueException + +AMOUNT_OF_INPUT_ARRAYS = 2 +MIN_DOTS = 8 +MAX_DOTS = 12 + + +class Validator: + + @staticmethod + def validateNumber(number: str): + try: + number = float(number) + return number + except ValueError: + raise IncorrectValueException(f'Необходимо ввести число.') + + + @staticmethod + def validateArraySize(arr): + length = len(arr) + if MIN_DOTS > length or length > MAX_DOTS: + raise IncorrectValueException('Размер массива должен находится в пределах [8;12].') + + @staticmethod + def validateEqualityLengths(arr_1, arr_2): + if len(arr_1) != len(arr_2): + raise IncorrectValueException('Длины массивов не равны.') \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab4/Validation/__pycache__/Validator.cpython-312.pyc" "b/\320\2403265-69/furzikova_368979/lab4/Validation/__pycache__/Validator.cpython-312.pyc" new file mode 100644 index 0000000..3922386 Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab4/Validation/__pycache__/Validator.cpython-312.pyc" differ diff --git "a/\320\2403265-69/furzikova_368979/lab4/files/test.txt" "b/\320\2403265-69/furzikova_368979/lab4/files/test.txt" new file mode 100644 index 0000000..f5eb7ff --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab4/files/test.txt" @@ -0,0 +1,2 @@ +1;3;5;7;9;11;13;15 +2.5;4;6.5;10;9;10.1;10.05;13.2 \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab4/main.py" "b/\320\2403265-69/furzikova_368979/lab4/main.py" new file mode 100644 index 0000000..527b9ec --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab4/main.py" @@ -0,0 +1,13 @@ +import warnings + +from Terminal import Terminal + +if __name__ == "__main__": + warnings.filterwarnings('ignore') + terminal = Terminal() + while True: + terminal.refresh() + terminal.work() + print("Хотите продолжить работу с программой? y/n") + if not input().__eq__('y'): + break \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab4/\320\262\321\213\321\207\320\274\320\260\321\2024\320\276\321\202\321\207\320\265\321\202.pdf" "b/\320\2403265-69/furzikova_368979/lab4/\320\262\321\213\321\207\320\274\320\260\321\2024\320\276\321\202\321\207\320\265\321\202.pdf" new file mode 100644 index 0000000..7d0373c Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab4/\320\262\321\213\321\207\320\274\320\260\321\2024\320\276\321\202\321\207\320\265\321\202.pdf" differ diff --git "a/\320\2403265-69/furzikova_368979/lab5/Main.py" "b/\320\2403265-69/furzikova_368979/lab5/Main.py" new file mode 100644 index 0000000..8659824 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab5/Main.py" @@ -0,0 +1,568 @@ +import math +import matplotlib.pyplot as plt +import numpy as np + + +def read_input_data(): + """Основная функция для выбора способа ввода данных""" + while True: + print("1. Ручной ввод") + print("2. Загрузка из файла") + print("3. Генерация по математической функции") + + while True: + try: + choice = int(input("Выберите вариант (1-3): ")) + if 1 <= choice <= 3: + break + print("Ошибка: Введите число от 1 до 3") + except ValueError: + print("Ошибка: Введите целое число") + + if choice == 1: + return input_from_keyboard() + elif choice == 2: + return input_from_file_with_retry() + else: + return generate_data_from_function_with_retry() + + +def input_from_keyboard(): + """Ввод данных с клавиатуры""" + while True: + try: + point_count = int(input("Введите количество точек: ")) + if point_count > 0: + break + print("Ошибка: Количество точек должно быть положительным") + except ValueError: + print("Ошибка: Введите целое число") + + x_values = [] + y_values = [] + print(f"Введите {point_count} точек в формате x y:") + + for i in range(point_count): + while True: + try: + data = input(f"Точка {i + 1}: ").strip() + if not data: + print("Ошибка: Пустой ввод") + continue + + x, y = map(float, data.split()) + x_values.append(x) + y_values.append(y) + break + except ValueError: + print("Ошибка: Точка должна состоять из двух чисел. Попробуйте снова") + except Exception: + print("Ошибка ввода. Попробуйте снова") + + while len(set(x_values)) != len(x_values): + print("Ошибка: Узлы интерполяции не должны совпадать. Введите точки заново") + x_values.clear() + y_values.clear() + for i in range(point_count): + while True: + try: + data = input(f"Точка {i + 1}: ").strip() + if not data: + print("Ошибка: Пустой ввод") + continue + + x, y = map(float, data.split()) + x_values.append(x) + y_values.append(y) + break + except ValueError: + print("Ошибка: Точка должна состоять из двух чисел. Попробуйте снова") + except Exception: + print("Ошибка ввода. Попробуйте снова") + + return x_values, y_values + + +def input_from_file_with_retry(): + """Чтение данных из файла с обработкой ошибок""" + while True: + filename = input("Введите имя файла: ") + try: + x_data, y_data = read_data_from_file(filename) + + if len(set(x_data)) != len(x_data): + print("Ошибка: Узлы интерполяции не должны совпадать") + continue + + return x_data, y_data + except FileNotFoundError: + print("Ошибка: Файл не найден. Проверьте имя файла и попробуйте снова") + except ValueError as e: + print(f"Ошибка в файле: {e}. Попробуйте другой файл") + except Exception as e: + print(f"Ошибка: {e}. Попробуйте другой файл") + + +def read_data_from_file(filename): + """Чтение данных из файла""" + x_data = [] + y_data = [] + with open(filename, 'r') as file: + for line_number, content in enumerate(file, 1): + content = content.strip() + if not content: + continue + + try: + x_val, y_val = map(float, content.split()) + x_data.append(x_val) + y_data.append(y_val) + except ValueError: + raise ValueError(f"Некорректные данные в строке {line_number}: '{content}'") + + if not x_data: + raise ValueError("Файл пуст или содержит только пустые строки") + + return x_data, y_data + + +def generate_data_from_function_with_retry(): + """Генерация данных на основе математической функции""" + while True: + function_name = input("Введите имя функции (sin/cos/exp/log): ").lower() + if function_name in ["sin", "cos", "exp", "log"]: + break + print("Ошибка: Несуществующая функция. Доступные: sin, cos, exp, log") + + while True: + try: + start_point = float(input("Введите начало отрезка: ")) + break + except ValueError: + print("Ошибка: Начало должно быть числом") + + while True: + try: + end_point = float(input("Введите конец отрезка: ")) + if end_point > start_point: + break + print("Ошибка: Конец должен быть больше начала") + except ValueError: + print("Ошибка: Конец должен быть числом") + + while True: + try: + point_count = int(input("Введите количество точек: ")) + if point_count > 1: + break + print("Ошибка: Количество точек должно быть больше 1") + except ValueError: + print("Ошибка: Введите целое число") + + while True: + try: + x_vals, y_vals = generate_data_from_function(function_name, start_point, end_point, point_count) + return x_vals, y_vals + except ValueError as e: + print(f"Ошибка: {e}") + if function_name == "log": + print("Для функции log все x должны быть > 0") + while True: + try: + start_point = float(input("Введите новое начало отрезка (>0): ")) + if start_point > 0: + break + print("Ошибка: Начало должно быть > 0") + except ValueError: + print("Ошибка: Начало должно быть числом") + + while True: + try: + end_point = float(input("Введите новый конец отрезка (> начала): ")) + if end_point > start_point: + break + print("Ошибка: Конец должен быть больше начала") + except ValueError: + print("Ошибка: Конец должен быть числом") + + +def generate_data_from_function(func_name, start_val, end_val, point_count): + """Генерация данных на основе выбранной функции""" + function_map = { + 'sin': math.sin, + 'cos': math.cos, + 'exp': math.exp, + 'log': lambda x: math.log(x) if x > 0 else None, + } + + x_vals = [] + y_vals = [] + step_size = (end_val - start_val) / (point_count - 1) if point_count > 1 else 0 + + for i in range(point_count): + x = start_val + i * step_size + y = function_map[func_name](x) + if y is None: + raise ValueError(f"Недопустимое значение x={x} для функции {func_name}") + x_vals.append(x) + y_vals.append(y) + + return x_vals, y_vals + + +def main(): + print("Программа интерполяции функций") + print("-----------------------------") + + while True: + try: + x_data, y_data = read_input_data() + interpolator = InterpolationSolver(x_data, y_data) + + while True: + try: + target_x = float(input("\nВведите аргумент для интерполяции: ")) + break + except ValueError: + print("Ошибка: Аргумент должен быть числом") + + print("\nТаблица конечных разностей:") + diff_table = interpolator.compute_finite_differences() + for row in diff_table: + print(" ".join(map(lambda val: f"{val:.4f}", row))) + + print("\nРезультаты интерполяции:") + methods = [ + ("Лагранж", interpolator.interpolate_lagrange(target_x)), + ("Ньютон (разделённые разности)", interpolator.interpolate_newton_divided(target_x)), + ("Ньютон (конечные разности)", interpolator.interpolate_newton_finite(target_x)), + ("Стирлинг", interpolator.interpolate_stirling(target_x)), + ("Бессель", interpolator.interpolate_bessel(target_x)) + ] + + for method_name, result_value in methods: + if result_value is not None: + print(f"{method_name}: {result_value:.6f}") + else: + print(f"{method_name}: не применимо для данных узлов") + + interpolator.plot_interpolation(target_x=target_x) + + while True: + choice = input("\nХотите выполнить еще одну интерполяцию? (y/n): ").lower() + if choice in ['y', 'n']: + break + print("Ошибка: Введите 'y' или 'n'") + + if choice == 'n': + print("Завершение программы.") + break + + except KeyboardInterrupt: + print("\nПрограмма прервана пользователем") + break + except Exception as e: + print(f"\nПроизошла ошибка: {e}") + raise e + print("Попробуйте снова.\n") + + +class InterpolationSolver: + def __init__(self, x_nodes, y_values): + self.x_nodes = x_nodes + self.y_values = y_values + + def interpolate_lagrange(self, x_target): + """Интерполяция методом Лагранжа""" + result = 0.0 + n = len(self.x_nodes) + + for i in range(n): + term = self.y_values[i] + for j in range(n): + if j != i: + term *= (x_target - self.x_nodes[j]) / (self.x_nodes[i] - self.x_nodes[j]) + result += term + + return result + + def interpolate_newton_divided(self, x_target): + """Интерполяция методом Ньютона с разделенными разностями""" + n = len(self.x_nodes) + div_diff_table = self.compute_divided_differences() + + result = div_diff_table[0][n - 1] + for i in range(n - 2, -1, -1): + result = result * (x_target - self.x_nodes[i]) + div_diff_table[0][i] + + return result + + def interpolate_newton_finite(self, x_target): + """Интерполяция методом Ньютона с конечными разностями""" + n = len(self.x_nodes) + if n < 2: + return None + + step = abs(self.x_nodes[1] - self.x_nodes[0]) + + for i in range(1, n - 1): + if abs((self.x_nodes[i + 1] - self.x_nodes[i]) - step) > 1e-10: + return None + + diff_table = self.compute_finite_differences() + result = self.y_values[0] + + for i in range(1, n): + coefficient = diff_table[0][i] / math.factorial(i) + t_param = (x_target - self.x_nodes[0]) / step + term = 1 + for k in range(i): + term *= (t_param - k) + result += coefficient * term + + return result + + def compute_divided_differences(self): + """Вычисление таблицы разделенных разностей""" + n = len(self.x_nodes) + div_diff = [[0.0] * n for _ in range(n)] + + for i in range(n): + div_diff[i][0] = self.y_values[i] + + for j in range(1, n): + for i in range(n - j): + div_diff[i][j] = (div_diff[i + 1][j - 1] - div_diff[i][j - 1]) / (self.x_nodes[i + j] - self.x_nodes[i]) + + return div_diff + + def compute_finite_differences(self): + """Вычисление таблицы конечных разностей""" + n = len(self.y_values) + fin_diff = [[0.0] * n for _ in range(n)] + + for i in range(n): + fin_diff[i][0] = self.y_values[i] + + for j in range(1, n): + for i in range(n - j): + fin_diff[i][j] = fin_diff[i + 1][j - 1] - fin_diff[i][j - 1] + + return fin_diff + + def interpolate_stirling(self, x_target): + """Интерполяция по формуле Стирлинга""" + n = len(self.x_nodes) + if n % 2 == 0: # Требуется нечетное количество точек + return None + + # Проверка равномерности шага + step = abs(self.x_nodes[1] - self.x_nodes[0]) + for i in range(1, n - 1): + if abs((self.x_nodes[i + 1] - self.x_nodes[i]) - step) > 1e-10: + return None + + center_idx = n // 2 # Центральный узел + t_param = (x_target - self.x_nodes[center_idx]) / step + diff_table = self.compute_finite_differences() + + result = self.y_values[center_idx] + + # Первый член: t * (Δy0 + Δy_{-1})/2 + if center_idx >= 1 and center_idx < n - 1: + if center_idx < len(diff_table) and len(diff_table[center_idx]) > 1 and \ + center_idx - 1 < len(diff_table) and len(diff_table[center_idx - 1]) > 1: + result += t_param * (diff_table[center_idx][1] + diff_table[center_idx - 1][1]) / 2 + + # Основной цикл по i + for i in range(1, center_idx + 1): + # Проверка доступности индексов для нечетных разностей + row1 = center_idx - i + row2 = center_idx - i - 1 + order = 2 * i - 1 + + if row1 < 0 or row1 >= len(diff_table) or order >= len(diff_table[row1]) or \ + row2 < 0 or row2 >= len(diff_table) or order >= len(diff_table[row2]): + break + + delta_val = (diff_table[row1][order] + diff_table[row2][order]) / 2 + term = delta_val + + # Вычисление произведения (t^2 - k^2) + for k in range(1, i): + term *= (t_param ** 2 - k ** 2) + + term *= t_param # Дополнительный множитель t + term /= math.factorial(2 * i - 1) + result += term + + # Проверка доступности индексов для четных разностей + row_even = center_idx - i - 1 + order_even = 2 * i + + if i < center_idx: # Для четных разностей (кроме последней итерации) + if row_even < 0 or row_even >= len(diff_table) or order_even >= len(diff_table[row_even]): + break + + term_even = diff_table[row_even][order_even] + for k in range(1, i + 1): + term_even *= (t_param ** 2 - k ** 2) + + term_even /= math.factorial(2 * i) + result += term_even + else: + break + + return result + + def find_central_node_index(self, x_target): + """Поиск центрального узла для интерполяции""" + n = len(self.x_nodes) + mid_idx = n // 2 + if x_target < self.x_nodes[mid_idx]: + while mid_idx > 0 and x_target < self.x_nodes[mid_idx - 1]: + mid_idx -= 1 + else: + while mid_idx < n - 1 and x_target > self.x_nodes[mid_idx + 1]: + mid_idx += 1 + return mid_idx + + def interpolate_bessel(self, x_target): + """Интерполяция по формуле Бесселя""" + + n = len(self.x_nodes) + + # Метод Бесселя требует чётное количество узлов + if n % 2 != 0: + return None + + # Проверка, что шаг равномерный + step = self.x_nodes[1] - self.x_nodes[0] + for i in range(1, n - 1): + if abs((self.x_nodes[i + 1] - self.x_nodes[i]) - step) > 1e-10: + return None + + # Найдём центральный индекс (левая из двух центральных точек) + center_idx = self.find_central_interval_index(x_target) + center_idx = max(1, min(center_idx, n - 3)) + + # Центральная точка x + center_x = (self.x_nodes[center_idx] + self.x_nodes[center_idx + 1]) / 2 + t_param = (x_target - center_x) / step + + # Таблица конечных разностей + diff_table = self.compute_finite_differences() + + # Начальное приближение: среднее значение в центре + result = (self.y_values[center_idx] + self.y_values[center_idx + 1]) / 2 + + # Добавляем первую разность первого порядка (нечётная) + result += t_param * diff_table[center_idx][1] + + max_order = len(diff_table[0]) - 1 # Максимальный порядок разности + + for i in range(1, n // 2): + even_order = 2 * i + odd_order = 2 * i + 1 + + # Проверка на выход за границы таблицы разностей + if center_idx - i < 0 or center_idx - i + 1 >= n: + break + if even_order >= max_order: + break + + # Чётные разности: центральные + delta_even = diff_table[center_idx - i][even_order] + product_even = 1 + for k in range(1, i + 1): + product_even *= (t_param ** 2 - (k - 0.5) ** 2) + term_even = delta_even * product_even / math.factorial(even_order) + result += term_even + + # Проверка наличия нечётной разности + if odd_order >= max_order: + break + + # Нечётные разности: смещены на +1 + delta_odd = diff_table[center_idx - i + 1][odd_order] + product_odd = t_param + for k in range(1, i + 1): + product_odd *= (t_param ** 2 - k ** 2) + term_odd = delta_odd * product_odd / math.factorial(odd_order) + result += term_odd + + return result + + def find_central_interval_index(self, x_target): + """Поиск центрального интервала""" + for i in range(len(self.x_nodes) - 1): + if self.x_nodes[i] <= x_target <= self.x_nodes[i + 1]: + return i + return len(self.x_nodes) // 2 - 1 + + def plot_interpolation(self, method='all', target_x=None): + """Визуализация результатов интерполяции""" + plt.figure(figsize=(12, 8)) # Создание холста 12x8 дюймов + x_plot = np.linspace(min(self.x_nodes), max(self.x_nodes), 500) # 500 точек для плавного графика + + plt.scatter(self.x_nodes, self.y_values, color='black', s=100, label='Узлы интерполяции', zorder=5) + + + if method in ['all', 'lagrange']: + y_lagrange = [self.interpolate_lagrange(x) for x in x_plot] + plt.plot(x_plot, y_lagrange, color='#FF4500', label='Метод Лагранжа', linewidth=2) # Оранжево-красный + + if method in ['all', 'newtone_div']: + y_newton_div = [self.interpolate_newton_divided(x) for x in x_plot] + plt.plot(x_plot, y_newton_div, '--', color='#1E90FF', label='Ньютон (раздел. разности)', + linewidth=2) # Ярко-синий + + if method in ['all', 'newton_fin'] and len(self.x_nodes) > 1: + step = abs(self.x_nodes[1] - self.x_nodes[0]) + if all(abs((self.x_nodes[i + 1] - self.x_nodes[i]) - step) < 1e-10 for i in range(len(self.x_nodes) - 1)): + y_newton_fin = [ + self.interpolate_newton_finite(x) if self.interpolate_newton_finite(x) is not None else np.nan for x + in x_plot] + plt.plot(x_plot, y_newton_fin, ':', color='#32CD32', label='Ньютон (кон. разности)', + linewidth=2) # Лаймовый + + if method in ['all', 'stirling'] and len(self.x_nodes) > 1: + step = abs(self.x_nodes[1] - self.x_nodes[0]) + if all(abs((self.x_nodes[i + 1] - self.x_nodes[i]) - step) < 1e-10 for i in + range(len(self.x_nodes) - 1)) and len(self.x_nodes) % 2 != 0:# Для Стирлинга (нечетное) + y_stirling = [self.interpolate_stirling(x) if self.interpolate_stirling(x) is not None else np.nan for x + in x_plot] + plt.plot(x_plot, y_stirling, '-.', color='#9370DB', label='Стирлинг', linewidth=2) # Фиолетовый + + if method in ['all', 'bessel'] and len(self.x_nodes) > 1: + step = abs(self.x_nodes[1] - self.x_nodes[0]) + if all(abs((self.x_nodes[i + 1] - self.x_nodes[i]) - step) < 1e-10 for i in + range(len(self.x_nodes) - 1)) and len(self.x_nodes) % 2 == 0: # Для Бесселя (четное) + y_bessel = [self.interpolate_bessel(x) if self.interpolate_bessel(x) is not None else np.nan for x in + x_plot] + plt.plot(x_plot, y_bessel, ':', color='#FF69B4', label='Бессель', linewidth=2) # Розовый + + if target_x is not None: + plt.axvline(x=target_x, color='red', linestyle=':', alpha=0.5, label=f'x = {target_x}') + methods = [ + ('lagrange', self.interpolate_lagrange(target_x), '#FF4500'), # Оранжево-красный + ('newtone_div', self.interpolate_newton_divided(target_x), '#1E90FF'), # Ярко-синий + ('newton_fin', self.interpolate_newton_finite(target_x), '#32CD32'), # Лаймовый + ('stirling', self.interpolate_stirling(target_x), '#9370DB'), # Фиолетовый + ('bessel', self.interpolate_bessel(target_x), '#FF69B4') # Розовый + ] + + for method_name, value, color in methods: + if method in ['all', method_name] and value is not None: + plt.scatter([target_x], [value], color=color, s=100, zorder=5, edgecolors='black') # Отображение точек на графике + + plt.title('Сравнение методов интерполяции') + plt.xlabel('x') + plt.ylabel('y') + plt.legend() + plt.grid(True) + plt.show() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab5/test1.txt" "b/\320\2403265-69/furzikova_368979/lab5/test1.txt" new file mode 100644 index 0000000..86e04dc --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab5/test1.txt" @@ -0,0 +1,10 @@ +0 0 +1 3 +2 8 +3 15 +4 24 +5 35 +6 48 +7 63 +8 80 +9 99 \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab5/test2.txt" "b/\320\2403265-69/furzikova_368979/lab5/test2.txt" new file mode 100644 index 0000000..9314975 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab5/test2.txt" @@ -0,0 +1,5 @@ +1 0.0 +2 0.5 +3 1.0 +4 1.5 +5 2.0 \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab5/test3.txt" "b/\320\2403265-69/furzikova_368979/lab5/test3.txt" new file mode 100644 index 0000000..91143c0 --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab5/test3.txt" @@ -0,0 +1,28 @@ +1 0.0 +2 2.121320343559643 +3 4.618802153517006 +4 7.5 +5 10.73312629199899 +6 14.288690166235206 +7 18.142294704442907 +8 22.27386360737625 +9 26.666666666666668 +10 31.306548835666955 +11 36.18136134933164 +12 41.280544247058245 +13 46.59481648291925 +14 52.11594217292276 +15 57.83655130336409 +16 63.75 +17 69.85026001046388 +18 76.13183010775163 +19 82.58966419340223 +20 89.21911230224161 +21 96.01587170383665 +22 102.97594599975983 +23 110.09561062213547 +24 117.37138350836062 +25 124.8 +26 132.3783912182742 +27 140.1036653233492 +28 147.97309118311247 \ No newline at end of file diff --git "a/\320\2403265-69/furzikova_368979/lab5/\320\262\321\213\321\207\320\274\320\260\321\2025\320\276\321\202\321\207\320\265\321\202.pdf" "b/\320\2403265-69/furzikova_368979/lab5/\320\262\321\213\321\207\320\274\320\260\321\2025\320\276\321\202\321\207\320\265\321\202.pdf" new file mode 100644 index 0000000..0addb32 Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab5/\320\262\321\213\321\207\320\274\320\260\321\2025\320\276\321\202\321\207\320\265\321\202.pdf" differ diff --git "a/\320\2403265-69/furzikova_368979/lab6/6 \320\262\321\213\321\207\320\274\320\260\321\202.pdf" "b/\320\2403265-69/furzikova_368979/lab6/6 \320\262\321\213\321\207\320\274\320\260\321\202.pdf" new file mode 100644 index 0000000..c3e597f Binary files /dev/null and "b/\320\2403265-69/furzikova_368979/lab6/6 \320\262\321\213\321\207\320\274\320\260\321\202.pdf" differ diff --git "a/\320\2403265-69/furzikova_368979/lab6/Main.py" "b/\320\2403265-69/furzikova_368979/lab6/Main.py" new file mode 100644 index 0000000..84c07ba --- /dev/null +++ "b/\320\2403265-69/furzikova_368979/lab6/Main.py" @@ -0,0 +1,447 @@ +import warnings +import matplotlib.pyplot as plt +import numpy as np +import numexpr as ne + + +class IncorrectValueException(Exception): + def __init__(self, message): + self.message = message + + +EQUATIONS = { + 1: "(x-y)**2", + 2: "(x-y)**2+y**2", + 3: "y+(1+x)*y**2" +} + +ANSWERS = { + 1: "1/(c*exp(2*x) + 1/2) + x - 1", + 2: "x - c - sqrt(c**2 - x + c)", + 3: "-1/(c - x - x**2/2)" +} + +C = { + 1: "((y - x + 1)**2 - 1)/exp(-2*x)", + 2: "x - y - sqrt(y**2 - (x - y)**2)", + 3: "x + x**2/2 + 1/y" +} + +METHODS = [ + 'Одношаговый. Метод Эйлера', + 'Одношаговый. Метод Рунге-Кутта 4-го порядка', + 'Многошаговый. Метод Адамса' +] + + +def calculateFunction(xi, yi, function_number): + return float(ne.evaluate(EQUATIONS[function_number], local_dict={'x': xi, 'y': yi})) + + +def calculateC(x0, y0, function_number): + try: + return float(ne.evaluate(C[function_number], local_dict={'x': x0, 'y': y0})) + except Exception as e: + print(f"Ошибка вычисления константы C: {str(e)}") + return float('nan') + + +def calculateAnswer(x0, y0, xi, function_number): + try: + c_val = calculateC(x0, y0, function_number) + if np.isnan(c_val) or np.isinf(c_val): + return float('nan') + result = ne.evaluate(ANSWERS[function_number], local_dict={'x': xi, 'c': c_val}) + return float(result) + except Exception as e: + print(f"Ошибка вычисления аналитического решения: {str(e)}") + return float('nan') + + +class Validator: + @staticmethod + def validateNumber(number: str): + try: + return float(number) + except ValueError: + raise IncorrectValueException('Необходимо ввести число.') + + @staticmethod + def validateEpsilon(epsilon: str): + try: + epsilon = float(epsilon) + if epsilon >= 0: + return epsilon + raise IncorrectValueException('Точность должна быть >= 0.') + except ValueError: + raise IncorrectValueException('Точность должна быть числом.') + + @staticmethod + def validateFunctionNumber(): + try: + number = int(input()) + if 1 <= number <= len(EQUATIONS): + return number + raise IncorrectValueException('Недопустимый номер функции.') + except ValueError: + raise IncorrectValueException('Введите целое число.') + + @staticmethod + def validateMethodNumber(): + try: + number = int(input()) + if 1 <= number <= len(METHODS): + return number + raise IncorrectValueException('Недопустимый номер метода.') + except ValueError: + raise IncorrectValueException('Введите целое число.') + + @staticmethod + def validateBorders(border_left: float, border_right: float): + if border_left < border_right: + return True + raise IncorrectValueException('Левая граница должна быть меньше правой.') + + @staticmethod + def validateH(): + try: + h = float(input()) + if h > 0: + return h + raise IncorrectValueException('Шаг должен быть > 0.') + except ValueError: + raise IncorrectValueException('Шаг должен быть числом.') + + +class DifferentialEquations: + def __init__(self, x0, y0, xn, h, eps): + self.__x0 = x0 + self.__y0 = y0 + self.__xn = xn + self.__h = h + self.__eps = eps + self.__x_array = list(np.arange(x0, xn + 1e-10, h)) + + def getY0(self): return self.__y0 + + def getX0(self): return self.__x0 + + def getXN(self): return self.__xn + + def getH(self): return self.__h + + def getEps(self): return self.__eps + + def getArrayX(self): return self.__x_array + + def ruleRunge(self, I_h, I_h2, k, eps): + delta = abs(I_h2 - I_h) / (2 ** k - 1) + print(f'Погрешность: {delta} {"<" if delta < eps else ">="} {eps}') + return delta <= eps + + +class DifferentialEquationsMethods(DifferentialEquations): + # ================== МЕТОД ЭЙЛЕРА ================== + def methodEiler(self, function_number): + results = self._calculateEilerMethod(function_number) + self._printEilerTable(results) + return results + + def _calculateEilerMethod(self, function_number): + x_arr = self.getArrayX() + n = len(x_arr) + h = self.getH() + x0_val = self.getX0() + y0_val = self.getY0() + + iterations = [[0.0] * 5 for _ in range(n)] + + for i in range(n): + xi = x_arr[i] + iterations[i][0] = i + iterations[i][1] = round(xi, 5) + + if i == 0: + y = y0_val + else: + x_prev = x_arr[i - 1] + y_prev = iterations[i - 1][2] + f_prev = calculateFunction(x_prev, y_prev, function_number) + y = y_prev + h * f_prev + + iterations[i][2] = round(y, 5) + iterations[i][3] = round(calculateFunction(xi, y, function_number), 5) + iterations[i][4] = round(calculateAnswer(x0_val, y0_val, xi, function_number), 5) + + return iterations + + def _printEilerTable(self, iterations): + print('\n\t\tМетод Эйлера') + print('i | x | y | f(x,y) | Точное решение |') + for row in iterations: + exact = row[4] if not np.isnan(row[4]) else "N/A" + print(f"{int(row[0]):2} | {row[1]:7.5f} | {row[2]:7.5f} | {row[3]:9.5f} | {exact:14} |") + + # ================== МЕТОД РУНГЕ-КУТТА ================== + def methodRungeCutta4(self, function_number): + results = self._calculateRungeCutta4(function_number) + self._printRungeCuttaTable(results) + return results + + def _calculateRungeCutta4(self, function_number): + x_arr = self.getArrayX() + n = len(x_arr) + h = self.getH() + x0_val = self.getX0() + y0_val = self.getY0() + iterations = [[0.0] * 9 for _ in range(n)] + + for i in range(n): + xi = x_arr[i] + iterations[i][0] = i + iterations[i][1] = round(xi, 5) + + if i == 0: + y = y0_val + else: + y = iterations[i - 1][2] + iterations[i - 1][7] + + iterations[i][2] = round(y, 5) + + try: + k1 = h * calculateFunction(xi, y, function_number) + k2 = h * calculateFunction(xi + h / 2, y + k1 / 2, function_number) + k3 = h * calculateFunction(xi + h / 2, y + k2 / 2, function_number) + k4 = h * calculateFunction(xi + h, y + k3, function_number) + delta_y = (k1 + 2 * k2 + 2 * k3 + k4) / 6 + except Exception as e: + print(f"Ошибка расчета коэффициентов: {str(e)}") + k1 = k2 = k3 = k4 = delta_y = float('nan') + + iterations[i][3] = round(k1, 5) + iterations[i][4] = round(k2, 5) + iterations[i][5] = round(k3, 5) + iterations[i][6] = round(k4, 5) + iterations[i][7] = round(delta_y, 5) + iterations[i][8] = round(calculateAnswer(x0_val, y0_val, xi, function_number), 5) + + return iterations + + def _printRungeCuttaTable(self, iterations): + print('\n\t\tМетод Рунге-Кутта 4-го порядка') + print('i | x | y | k1 | k2 | k3 | k4 | delta | Точное решение |') + for row in iterations: + exact = row[8] if not np.isnan(row[8]) else "N/A" + print(f"{int(row[0]):2} | {row[1]:7.5f} | {row[2]:7.5f} | " + f"{row[3]:8.5f} | {row[4]:8.5f} | {row[5]:8.5f} | " + f"{row[6]:8.5f} | {row[7]:7.5f} | {exact:14} |") + + # ================== МЕТОД АДАМСА ================== + def methodAdams(self, function_number): + try: + runge_results = self._calculateRungeCutta4(function_number)[:4] + adams_results = self._calculateAdams(function_number, runge_results) + self._printAdamsTable(adams_results) + return adams_results + except Exception as e: + print(f"Ошибка в методе Адамса: {str(e)}") + return [] + + def _calculateAdams(self, function_number, runge_results): + x_arr = self.getArrayX() + n = len(x_arr) + h = self.getH() + x0_val = self.getX0() + y0_val = self.getY0() + iterations = [[0.0] * 8 for _ in range(n)] + + # Инициализация первых 4 точек из Рунге-Кутта + for i in range(4): + iterations[i][0] = i + iterations[i][1] = runge_results[i][1] + iterations[i][2] = runge_results[i][2] + iterations[i][3] = runge_results[i][3] / h if not np.isnan(runge_results[i][3]) else float('nan') + if i > 0: + iterations[i][4] = iterations[i][3] - iterations[i - 1][3] if not np.isnan(iterations[i][3]) else float( + 'nan') + if i > 1: + iterations[i][5] = iterations[i][3] - 2 * iterations[i - 1][3] + iterations[i - 2][3] if not np.isnan( + iterations[i][3]) else float('nan') + if i > 2: + iterations[i][6] = iterations[i][3] - 3 * iterations[i - 1][3] + 3 * iterations[i - 2][3] - \ + iterations[i - 3][3] if not np.isnan(iterations[i][3]) else float('nan') + iterations[i][7] = runge_results[i][8] + + # Прогноз для последующих точек + for i in range(3, n - 1): + try: + # Прогноз + y_pred = iterations[i][2] + h * ( + iterations[i][3] + + (h / 2) * iterations[i][4] + + (5 * h ** 2 / 12) * iterations[i][5] + + (3 * h ** 3 / 8) * iterations[i][6] + ) + + # Коррекция + x_next = x_arr[i + 1] + f_next = calculateFunction(x_next, y_pred, function_number) + + # Обновление конечных разностей + f_i = f_next + df_i = f_i - iterations[i][3] + d2f_i = f_i - 2 * iterations[i][3] + iterations[i - 1][3] + d3f_i = f_i - 3 * iterations[i][3] + 3 * iterations[i - 1][3] - iterations[i - 2][3] + + # Уточнение значения y + y_corr = iterations[i][2] + h * ( + f_i + + (h / 2) * df_i + + (5 * h ** 2 / 12) * d2f_i + + (3 * h ** 3 / 8) * d3f_i + ) + except Exception as e: + print(f"Ошибка расчета точки {i + 1}: {str(e)}") + y_corr = float('nan') + f_i = df_i = d2f_i = d3f_i = float('nan') + + # Сохранение результатов + iterations[i + 1][0] = i + 1 + iterations[i + 1][1] = round(x_next, 5) + iterations[i + 1][2] = round(y_corr, 5) + iterations[i + 1][3] = f_i + iterations[i + 1][4] = df_i + iterations[i + 1][5] = d2f_i + iterations[i + 1][6] = d3f_i + iterations[i + 1][7] = round(calculateAnswer(x0_val, y0_val, x_next, function_number), 5) + + return iterations + + def _printAdamsTable(self, iterations): + print('\n\t\tМногошаговый метод Адамса') + print('i | x | y | fi | Δfi | Δ²fi | Δ³fi | Точное решение |') + for row in iterations: + exact = row[7] if not np.isnan(row[7]) else "N/A" + print(f"{int(row[0]):2} | {row[1]:7.5f} | {row[2]:7.5f} | {row[3]:8.5f} | " + f"{row[4]:7.5f} | {row[5]:7.5f} | {row[6]:7.5f} | {exact:14} |") + + +class Terminal: + def work(self): + try: + print('\t\tЧисленное решение ОДУ') + function_number = self.enterFunctionNumber() + method_number = self.enterMethodNumber() + x0 = self.enterArgument('x0') + y0 = self.enterArgument('y0') + xn = self.enterInterval(x0) + h = self.enterH() + eps = self.enterEpsilon() + diff = DifferentialEquationsMethods(x0, y0, xn, h, eps) + + if method_number == 1: + full_results = diff.methodEiler(function_number) + elif method_number == 2: + full_results = diff.methodRungeCutta4(function_number) + else: + full_results = diff.methodAdams(function_number) + + # Построение графика + if full_results: + x_values = diff.getArrayX() + y_values = [row[2] for row in full_results] + + # Рассчет аналитического решения + exact_solution = [] + for x in x_values: + try: + exact = calculateAnswer(x0, y0, x, function_number) + exact_solution.append(exact if not np.isnan(exact) else None) + except: + exact_solution.append(None) + + plt.figure(figsize=(10, 6)) + plt.plot(x_values, y_values, 'b-', label='Численное решение') + + # Фильтрация валидных точек аналитического решения + valid_exact = [(x, y) for x, y in zip(x_values, exact_solution) if y is not None] + if valid_exact: + x_valid, y_valid = zip(*valid_exact) + plt.plot(x_valid, y_valid, 'r--', label='Точное решение') + + plt.xlabel('x') + plt.ylabel('y') + plt.title(f'Решение ОДУ ({METHODS[method_number - 1]})') + plt.legend() + plt.grid(True) + plt.show() + + except IncorrectValueException as e: + print(f"Ошибка: {e.message}") + except Exception as e: + print(f"Непредвиденная ошибка: {str(e)}") + + def enterInterval(self, x0): + try: + print('Введите границу интервала xn (x0 задано):') + xn = Validator.validateNumber(input()) + Validator.validateBorders(x0, xn) + return xn + except IncorrectValueException as e: + print(e.message) + return self.enterInterval(x0) + + def enterH(self): + try: + print('Введите шаг h:') + h = Validator.validateH() + return h + except IncorrectValueException as e: + print(e.message) + return self.enterH() + + def enterArgument(self, arg): + try: + print(f'Введите значение {arg}:') + return Validator.validateNumber(input()) + except IncorrectValueException as e: + print(e.message) + return self.enterArgument(arg) + + def enterFunctionNumber(self): + try: + print('Выберите функцию:') + for i in range(1, len(EQUATIONS) + 1): + print(f'{i}. y\' = {EQUATIONS[i]}') + return Validator.validateFunctionNumber() + except IncorrectValueException as e: + print(e.message) + return self.enterFunctionNumber() + + def enterMethodNumber(self): + try: + print('Выберите метод:') + for i, method in enumerate(METHODS, 1): + print(f'{i}. {method}') + return Validator.validateMethodNumber() + except IncorrectValueException as e: + print(e.message) + return self.enterMethodNumber() + + def enterEpsilon(self): + try: + print('Введите точность epsilon:') + return Validator.validateEpsilon(input()) + except IncorrectValueException as e: + print(e.message) + return self.enterEpsilon() + + +if __name__ == "__main__": + warnings.filterwarnings('ignore') + terminal = Terminal() + while True: + terminal.work() + print("Хотите продолжить? (y/n)") + if input().lower() != 'y': + break \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab1/2.txt" "b/\320\2403265-69/saveleva_409492/lab1/2.txt" new file mode 100644 index 0000000..833e909 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab1/2.txt" @@ -0,0 +1,2 @@ +1 5 | 7 +3 -2 | 4 diff --git "a/\320\2403265-69/saveleva_409492/lab1/3.txt" "b/\320\2403265-69/saveleva_409492/lab1/3.txt" new file mode 100644 index 0000000..8376d26 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab1/3.txt" @@ -0,0 +1,3 @@ +1 -1 3 | 5 +4 -1 5 | 4 +2 -2 4 | 6 diff --git "a/\320\2403265-69/saveleva_409492/lab1/5.txt" "b/\320\2403265-69/saveleva_409492/lab1/5.txt" new file mode 100644 index 0000000..d4d5d46 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab1/5.txt" @@ -0,0 +1,5 @@ +1 -1 3 1 3 | 5 +4 -1 5 4 -2 | 4 +2 -2 4 1 3 | 6 +1 -4 5 -1 -4 | 3 +2 -4 5 -1 5 | 3 diff --git "a/\320\2403265-69/saveleva_409492/lab1/main.py" "b/\320\2403265-69/saveleva_409492/lab1/main.py" new file mode 100644 index 0000000..7c2e800 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab1/main.py" @@ -0,0 +1,211 @@ +import numpy as np + +# Функция для округления чисел +def round_number(num, digits=3): + return f'{num:.{digits}f}' + +# Функция для чтения системы уравнений из файла +def read_from_file(file_path): + try: + n = 0 + equations = [] + with open(file_path, 'r', encoding='utf-8') as file: + for line in file: + if line.strip(): # Пропускаем пустые строки + n += 1 + if n > 20: + print('Файл содержит более 20 уравнений. Пожалуйста, уменьшите количество уравнений и попробуйте снова.') + return + with open(file_path, 'r', encoding='utf-8') as file: + for row in file: + if row.strip(): # Пропускаем пустые строки + parts = row.split() + if parts[-2] != '|' or len(parts) - 2 != n: + print('Ошибка формата файла. Пожалуйста, проверьте формат и попробуйте снова.') + return + equations.append(parts) + solver = EquationSolver(n, prepare_equations(equations, n)) + solver.solve() + except FileNotFoundError: + print('Файл не найден по указанному пути:', file_path) + +# Функция для ввода системы уравнений вручную +def input_manually(): + try: + n = int(input('Введите количество уравнений (не более 20): ')) + if 1 < n <= 20: + equations = [] + print('Введите коэффициенты уравнений в формате:') + print('\t', 'a1 a2 ... an | b') + for i in range(n): + while True: + line = input(f'{i + 1}: ').split() + if len(line) - 2 != n or line[-2] != '|': + print('Количество коэффициентов не соответствует количеству уравнений или неправильный формат.') + print('Пожалуйста, попробуйте снова.') + else: + equations.append(line) + break + solver = EquationSolver(n, prepare_equations(equations, n)) + solver.solve() + else: + print('Некорректный ввод! Количество уравнений должно быть от 2 до 20.') + except ValueError: + print('Некорректный ввод! Пожалуйста, введите целое число.') + +# Преобразуем строки в числа +def prepare_equations(arr, n): + for i in range(n): + for j in range(n): + arr[i][j] = float(arr[i][j]) + arr[i][-1] = float(arr[i][-1]) + return arr + +# Решение системы уравнений с использованием numpy +def solve_with_numpy(equations, n): + # Преобразуем уравнения в матрицу коэффициентов и вектор свободных членов + A = np.array([equations[i][:n] for i in range(n)], dtype=float) + B = np.array([equations[i][-1] for i in range(n)], dtype=float) + + # Решаем систему уравнений + solutions = np.linalg.solve(A, B) + + # Вычисляем определитель матрицы + determinant = np.linalg.det(A) + + return solutions, determinant + +class EquationSolver: + def __init__(self, n, equations): + self.n = n + self.original_equations = [row.copy() for row in equations] # Сохраняем исходную матрицу + self.equations = equations # Матрица для преобразований + self.solutions = [] + self.swaps = 0 + + def solve(self): + try: + print('\nИсходная система уравнений:') + self.print_equations() + + self.convert_to_triangle() + print('\nТреугольная матрица:') + self.print_equations() + + print('\nКоличество перестановок:', self.swaps) + + self.calculate_determinant() + + self.find_solutions() + self.print_solutions() + + self.print_residuals() + + # Передаем исходную матрицу в numpy, а не модифицированную + numpy_solutions, numpy_determinant = solve_with_numpy(self.original_equations, self.n) + print('\nРешения системы через numpy:') + for i in range(self.n): + print(f'\tx[{i}] = {round_number(numpy_solutions[i])}') + print(f'\nОпределитель матрицы через numpy: {round_number(numpy_determinant)}') + + # Сравнение результатов + print('\nСравнение результатов:') + print(f'\tРазница в решениях: {np.linalg.norm(np.array(self.solutions) - numpy_solutions)}') + print(f'\tРазница в определителях: {abs(self.determinant - numpy_determinant)}') + + except ZeroDivisionError: + print('Ошибка: деление на ноль!') + except ArithmeticError: + print('Ошибка: система не имеет решений!') + except np.linalg.LinAlgError as e: + print(f'Ошибка при решении системы через numpy: {e}') + + def check_diagonal(self, i): + for j in range(i, self.n): + if self.equations[j][i] != 0: + self.equations[i], self.equations[j] = self.equations[j], self.equations[i] + self.swaps += 1 + return + print('Система не имеет решений!') + raise ArithmeticError + + def convert_to_triangle(self): + for i in range(self.n): + if self.equations[i][i] == 0: + self.check_diagonal(i) + for m in range(i + 1, self.n): + factor = -(self.equations[m][i] / self.equations[i][i]) + for j in range(i, self.n): + self.equations[m][j] += factor * self.equations[i][j] + self.equations[m][-1] += factor * self.equations[i][-1] + + def print_equations(self): + for i in range(self.n): + equation = ' '.join([f'{round_number(self.equations[i][j])} * x[{j}]' for j in range(self.n)]) + print(f'{equation} | {round_number(self.equations[i][-1])}') + + def calculate_determinant(self): + self.determinant = 1 + for i in range(self.n): + self.determinant *= self.equations[i][i] + if self.swaps % 2 == 1: + self.determinant *= -1 + print(f'\nОпределитель матрицы: {round_number(self.determinant)}\n') + if self.determinant == 0: + print('Система вырождена и не имеет решений.') + raise ArithmeticError + + def find_solutions(self): + self.solutions = [0] * self.n + for i in range(self.n - 1, -1, -1): + self.solutions[i] = self.equations[i][-1] / self.equations[i][i] + for j in range(i - 1, -1, -1): + self.equations[j][-1] -= self.equations[j][i] * self.solutions[i] + + def print_solutions(self): + print('Решения системы:') + for i in range(self.n): + print(f'\tx[{i}] = {round_number(self.solutions[i])}') + + def print_residuals(self): + print('\nВеличины невязок:') + for i in range(self.n): + residual = sum(self.equations[i][j] * self.solutions[j] for j in range(self.n)) - self.equations[i][-1] + print(f'\tНевязка для уравнения {i + 1}: {round_number(abs(residual))}') + +# Основное меню программы +def main(): + print('Решение систем линейных уравнений методом Гаусса') + + while True: + try: + print('\nДоступные действия:') + print('\t1: Загрузить систему уравнений из файла.') + print('\t2: Ввести систему уравнений вручную.') + print('\t3: Выйти из программы.') + choice = int(input('Выберите действие: ')) + + if choice == 1: + print('Загрузка системы уравнений из файла.') + print('Формат файла должен быть следующим (максимум 20 уравнений):') + print('\ta11 a12 ... a1n | b1') + print('\ta21 a22 ... a2n | b2') + print('\t... ... ... ... | ..') + print('\tan1 an2 ... ann | bn') + file_path = input('Введите путь к файлу: ').strip() + read_from_file(file_path) + elif choice == 2: + print('Ручной ввод системы уравнений.') + input_manually() + elif choice == 3: + print('Программа завершена. До свидания!') + break + else: + print('Некорректный выбор. Пожалуйста, выберите действие от 1 до 3.') + except KeyboardInterrupt: + print('\nПрограмма была прервана пользователем.') + except Exception as e: + print(f'Произошла ошибка: {e}') + +if __name__ == '__main__': + main() \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab1/\320\222\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\261\320\260 1.pdf" "b/\320\2403265-69/saveleva_409492/lab1/\320\222\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\261\320\260 1.pdf" new file mode 100644 index 0000000..80a5e0d Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab1/\320\222\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\261\320\260 1.pdf" differ diff --git "a/\320\2403265-69/saveleva_409492/lab2/graph.py" "b/\320\2403265-69/saveleva_409492/lab2/graph.py" new file mode 100644 index 0000000..0d065ca --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab2/graph.py" @@ -0,0 +1,29 @@ +from typing import Callable, List, Tuple + +import numpy as np +from matplotlib import pyplot as plt + + +def show_2d(y: Callable, points: List[Tuple]): + width = max(abs(points[0][0]), abs(points[len(points) - 1][0])) + 1 + height = abs(y(width)) + + vf = np.vectorize(y) + x = np.linspace(-width, width, 100) + + fig = plt.figure() + ax = fig.add_subplot(1, 1, 1) + + plt.grid(True) + plt.xlim((-width, width)) + plt.ylim((-height, height)) + + ax.spines['left'].set_position('center') + ax.spines['bottom'].set_position('center') + ax.spines['right'].set_color('none') + ax.spines['top'].set_color('none') + + ax.plot(x, vf(x), 'g', label='y=f(x)') + ax.plot(*list(zip(*points)), 'ro') + + plt.show() diff --git "a/\320\2403265-69/saveleva_409492/lab2/main.py" "b/\320\2403265-69/saveleva_409492/lab2/main.py" new file mode 100644 index 0000000..ce2affd --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab2/main.py" @@ -0,0 +1,169 @@ +# variant number: 15 + + +# 3 - Метод Ньютона +# 5 - Метод простой итерации +# 6 - Метод Ньютона + + +from math import sqrt + +import numpy as np + +from solvers import horde_method, newton_method, simple_iteration_method, system_newton_method +from graph import show_2d + +A, B, C, D = -2.40, 1.27, 8.63, 2.31 +f = lambda x: A * x ** 3 + B * x ** 2 + C * x + D +df = lambda x: 3 * A * x ** 2 + 2 * B * x + C +ddf = lambda x: 6 * A * x + 2 * B + + +def dphi(x): + return abs(sqrt(abs(1/A)) / 3 * (B * x**2 + C * x + D) ** (-2/3) * (2*B*x + C)) + + +def phi(x): + base = -(B * x ** 2 + C * x + D) / A + if base < 0: + return -(-base) ** (1 / 3) + return base ** (1 / 3) + + +def non_linear(output_file): + left, right = map(float, input('Границы левого корня через пробел (-2 -1): ').split()) + #c_x0 = float(input('Нулевое приближение центрального корня (0): ')) + + a, b = map(float, input('Границы для второго корня: (-1 0): ').split()) + if f(a) * ddf(a) > 0: + c_x0 = a + else: + c_x0 = b + + print(f'x0 для второго корня равен равен: {c_x0}') + + # r_x0 = float(input('Нулевое приближение правого корня (5): ')) + a1, b1 = map(float, input('Границы для правого корня: (2 3): ').split()) + if f(a1) * ddf(a1) > 0: + r_x0 = a1 + else: + r_x0 = b1 + + print(f'dpfi в a1 = {dphi(a1)}') + print(f'dpfi в b1 = {dphi(b1)}') + + epsilon = float(input('Погрешность (0.01): ')) + + left_x = horde_method(f, left=left, right=right, epsilon=epsilon) + center_x = newton_method(f, df, c_x0, epsilon=epsilon) + right_x = simple_iteration_method(f, phi, r_x0, epsilon=epsilon) + + show_2d(f, [(left_x.root, 0), (center_x.root, 0), (right_x.root, 0)]) + + print(f'Левый корень x_0={left_x.root:.7f}, знач-e: {left_x.znach_f:.7f}, n: {left_x.iter_count}') + # Значение функции + количество итераций + print(f'Центральный корень x_1={center_x.root:.7f}, знач-e: {center_x.znach_f:.7f}, n: {center_x.iter_count}') + # Значение функции + количество итераций + print(f'Правый корень x_2={right_x.root:.7f}, знач-e: {right_x.znach_f:.7f}, n: {right_x.iter_count}') + # Значение функции + количество итераций + + print(f'Таблица для метода хорд:') + print(left_x) + + print('Таблица для метода Ньютана:') + print(center_x) + + print('Таблица для метода простой итерации:') + print(right_x) + + if output_file != None: + with open(output_file, 'a') as fl: + fl.write(f'Таблица для метода хорд:') + fl.write(str(left_x)) + + fl.write('Таблица для метода Ньютана:') + fl.write(str(center_x)) + + fl.write('Таблица для метода простой итерации:') + fl.write(str(right_x)) + + +def function_1(x, y): + return [ + (-1)*(x+(2*y)-2), + (-1)*((x**2)+(4*(y**2))-4) + ] + + +def jacobian_1(x, y): + return [ + [1, 2], + [2*x, 8*y] + ] + + +def function_2(x, y, z): + return [ + (-1)*(x+y+z-3), + (-1)*((x**2)+(y**2)+(z**2)-5), + (-1)*((np.exp(x))+(x*y)-(x*z)-1) + ] + + +def jacobian_2(x, y, z): + return [[1, 1, 1], [2*x, 2*y, 2*z], [np.exp(x), x, -x]] + + +FUNCTIONS = [ + { + 'disp': 'f1(x1, x2) = x + 2*y - 2\nf2(x1, x2) = x^2 + 4*y^2 - 4)', + 'func': function_1, + 'jacob': jacobian_1, + 'init': [1, 1], + }, + { + 'disp': 'f1(x1, x2, x3) = x + y + z - 3\nf2(x1, x2, x3) = x^2 + y^2 + z^2 - 5\nf3(x1, x2, x3) = exp(x) + x*y - x*z -1', + 'func': function_2, + 'jacob': jacobian_2, + 'init': [100, 200, 3], + }, +] + + +def non_linear_system(output_file): + print(f'Выберите систему нелинейных уравнений:') + for i, group in enumerate(FUNCTIONS, 1): + print(f'Система №{i}') + print(group['disp']) + print() + n = int(input()) + f = FUNCTIONS[n - 1]['func'] + hint = FUNCTIONS[n-1]['init'] + jacob = FUNCTIONS[n - 1]['jacob'] + + x0 = list(map(float, input(f'Начальные приближения ({" ".join(str(num) for num in hint)}): ').split())) + eps = float(input('Погрешность (0.001): ')) + + res = system_newton_method(f, jacob, x0, eps) + + print(res) + if output_file != None: + with open(output_file, 'a') as fl: + fl.write(f'Решение системы нелинейных уравнений:') + fl.write(str(res)) + +def main(): + read_from_file = input('Нужно ли записать результат в файл (y/n): ') + output_file = None + if(read_from_file == 'y'): + output_file = input('Введите название файла (out.txt): ') + + + print('Решение нелейного уравнения: ') + non_linear(output_file) + print('Решение системы нелинейных уравнений: ') + non_linear_system(output_file) + + +if __name__ == '__main__': + main() diff --git "a/\320\2403265-69/saveleva_409492/lab2/out.txt" "b/\320\2403265-69/saveleva_409492/lab2/out.txt" new file mode 100644 index 0000000..afc473c --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab2/out.txt" @@ -0,0 +1,240 @@ + :+---+--------+--------+--------+--------+-------+-------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+--------+-------+-------+-------+ +| 1 | -2.000 | -1.000 | -1.295 | -7.963 | 3.327 | 1.828 | 1.000 | +| 2 | -2.000 | -1.295 | -1.426 | -7.963 | 1.828 | 0.697 | 0.705 | +| 3 | -2.000 | -1.426 | -1.473 | -7.963 | 0.697 | 0.229 | 0.574 | +| 4 | -2.000 | -1.473 | -1.487 | -7.963 | 0.229 | 0.071 | 0.527 | +| 5 | -2.000 | -1.487 | -1.492 | -7.963 | 0.071 | 0.022 | 0.513 | +| 6 | -2.000 | -1.492 | -1.493 | -7.963 | 0.022 | 0.007 | 0.508 | ++---+--------+--------+--------+--------+-------+-------+-------+ :+---+--------+---------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+---------+---------+---------+---------------+ +| 1 | 1.000 | -13.093 | -15.210 | 0.139 | 0.861 | +| 2 | 0.139 | -1.749 | -10.405 | -0.029 | 0.168 | +| 3 | -0.029 | -0.120 | -8.947 | -0.042 | 0.013 | ++---+--------+---------+---------+---------+---------------+ :+---+-------+--------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+--------+---------+----------+---------------+ +| 1 | 6.000 | -1.643 | 6.015 | 6.015 | 0.015 | +| 2 | 6.015 | -0.960 | 6.024 | 6.024 | 0.009 | +| 3 | 6.024 | -0.560 | 6.029 | 6.029 | 0.005 | +| 4 | 6.029 | -0.326 | 6.032 | 6.032 | 0.003 | +| 5 | 6.032 | -0.190 | 6.034 | 6.034 | 0.002 | ++---+-------+--------+---------+----------+---------------+ :+---+--------+--------+--------+--------+-------+-------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+--------+-------+-------+-------+ +| 1 | -2.000 | -1.000 | -1.295 | -7.963 | 3.327 | 1.828 | 1.000 | +| 2 | -2.000 | -1.295 | -1.426 | -7.963 | 1.828 | 0.697 | 0.705 | +| 3 | -2.000 | -1.426 | -1.473 | -7.963 | 0.697 | 0.229 | 0.574 | +| 4 | -2.000 | -1.473 | -1.487 | -7.963 | 0.229 | 0.071 | 0.527 | +| 5 | -2.000 | -1.487 | -1.492 | -7.963 | 0.071 | 0.022 | 0.513 | +| 6 | -2.000 | -1.492 | -1.493 | -7.963 | 0.022 | 0.007 | 0.508 | +| 7 | -2.000 | -1.493 | -1.494 | -7.963 | 0.007 | 0.002 | 0.507 | ++---+--------+--------+--------+--------+-------+-------+-------+ :+---+--------+---------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+---------+---------+---------+---------------+ +| 1 | 1.000 | -13.093 | -15.210 | 0.139 | 0.861 | +| 2 | 0.139 | -1.749 | -10.405 | -0.029 | 0.168 | +| 3 | -0.029 | -0.120 | -8.947 | -0.042 | 0.013 | ++---+--------+---------+---------+---------+---------------+ :+---+-------+--------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+--------+---------+----------+---------------+ +| 1 | 6.000 | -1.643 | 6.015 | 6.015 | 0.015 | +| 2 | 6.015 | -0.960 | 6.024 | 6.024 | 0.009 | +| 3 | 6.024 | -0.560 | 6.029 | 6.029 | 0.005 | +| 4 | 6.029 | -0.326 | 6.032 | 6.032 | 0.003 | +| 5 | 6.032 | -0.190 | 6.034 | 6.034 | 0.002 | +| 6 | 6.034 | -0.110 | 6.035 | 6.035 | 0.001 | +| 7 | 6.035 | -0.064 | 6.035 | 6.035 | 0.001 | ++---+-------+--------+---------+----------+---------------+ :+---+--------+--------+--------+--------+-------+-------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+--------+-------+-------+-------+ +| 1 | -2.000 | -1.000 | -1.295 | -7.963 | 3.327 | 1.828 | 1.000 | +| 2 | -2.000 | -1.295 | -1.426 | -7.963 | 1.828 | 0.697 | 0.705 | +| 3 | -2.000 | -1.426 | -1.473 | -7.963 | 0.697 | 0.229 | 0.574 | +| 4 | -2.000 | -1.473 | -1.487 | -7.963 | 0.229 | 0.071 | 0.527 | +| 5 | -2.000 | -1.487 | -1.492 | -7.963 | 0.071 | 0.022 | 0.513 | ++---+--------+--------+--------+--------+-------+-------+-------+ :+---+--------+---------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+---------+---------+---------+---------------+ +| 1 | 1.000 | -13.093 | -15.210 | 0.139 | 0.861 | +| 2 | 0.139 | -1.749 | -10.405 | -0.029 | 0.168 | +| 3 | -0.029 | -0.120 | -8.947 | -0.042 | 0.013 | ++---+--------+---------+---------+---------+---------------+ :+---+-------+--------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+--------+---------+----------+---------------+ +| 1 | 6.000 | -1.643 | 6.015 | 6.015 | 0.015 | +| 2 | 6.015 | -0.960 | 6.024 | 6.024 | 0.009 | ++---+-------+--------+---------+----------+---------------+ :: -0.000 1.000 +: + 5 + :+---+--------+--------+--------+-------+--------+--------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+-------+--------+--------+-------+ +| 1 | -2.000 | -1.000 | -1.221 | 9.330 | -2.650 | -1.964 | 1.000 | +| 2 | -2.000 | -1.221 | -1.357 | 9.330 | -1.964 | -1.068 | 0.779 | +| 3 | -2.000 | -1.357 | -1.423 | 9.330 | -1.068 | -0.486 | 0.643 | +| 4 | -2.000 | -1.423 | -1.451 | 9.330 | -0.486 | -0.203 | 0.577 | +| 5 | -2.000 | -1.451 | -1.463 | 9.330 | -0.203 | -0.082 | 0.549 | +| 6 | -2.000 | -1.463 | -1.468 | 9.330 | -0.082 | -0.033 | 0.537 | ++---+--------+--------+--------+-------+--------+--------+-------+ :+---+--------+--------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+--------+---------+---------+---------------+ +| 1 | 0.000 | 2.310 | 8.630 | -0.268 | 0.268 | +| 2 | -0.268 | 0.137 | 7.434 | -0.286 | 0.018 | ++---+--------+--------+---------+---------+---------------+ :+---+-------+---------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+---------+---------+----------+---------------+ +| 1 | 3.000 | -25.170 | 2.546 | 2.546 | 0.454 | +| 2 | 2.546 | -7.109 | 2.384 | 2.384 | 0.162 | +| 3 | 2.384 | -2.418 | 2.323 | 2.323 | 0.061 | +| 4 | 2.323 | -0.886 | 2.300 | 2.300 | 0.023 | +| 5 | 2.300 | -0.334 | 2.292 | 2.292 | 0.009 | ++---+-------+---------+---------+----------+---------------+ :+---+--------+--------+--------+-------+--------+--------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+-------+--------+--------+-------+ +| 1 | -2.000 | -1.000 | -1.221 | 9.330 | -2.650 | -1.964 | 1.000 | +| 2 | -2.000 | -1.221 | -1.357 | 9.330 | -1.964 | -1.068 | 0.779 | +| 3 | -2.000 | -1.357 | -1.423 | 9.330 | -1.068 | -0.486 | 0.643 | +| 4 | -2.000 | -1.423 | -1.451 | 9.330 | -0.486 | -0.203 | 0.577 | +| 5 | -2.000 | -1.451 | -1.463 | 9.330 | -0.203 | -0.082 | 0.549 | +| 6 | -2.000 | -1.463 | -1.468 | 9.330 | -0.082 | -0.033 | 0.537 | +| 7 | -2.000 | -1.468 | -1.470 | 9.330 | -0.033 | -0.013 | 0.532 | +| 8 | -2.000 | -1.470 | -1.470 | 9.330 | -0.013 | -0.005 | 0.530 | ++---+--------+--------+--------+-------+--------+--------+-------+ :+---+--------+--------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+--------+---------+---------+---------------+ +| 1 | 0.000 | 2.310 | 8.630 | -0.268 | 0.268 | +| 2 | -0.268 | 0.137 | 7.434 | -0.286 | 0.018 | ++---+--------+--------+---------+---------+---------------+ :+---+-------+---------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+---------+---------+----------+---------------+ +| 1 | 3.000 | -25.170 | 2.546 | 2.546 | 0.454 | +| 2 | 2.546 | -7.109 | 2.384 | 2.384 | 0.162 | +| 3 | 2.384 | -2.418 | 2.323 | 2.323 | 0.061 | +| 4 | 2.323 | -0.886 | 2.300 | 2.300 | 0.023 | +| 5 | 2.300 | -0.334 | 2.292 | 2.292 | 0.009 | +| 6 | 2.292 | -0.127 | 2.288 | 2.288 | 0.003 | +| 7 | 2.288 | -0.049 | 2.287 | 2.287 | 0.001 | +| 8 | 2.287 | -0.019 | 2.286 | 2.286 | 0.000 | ++---+-------+---------+---------+----------+---------------+ :: -0.004 1.008 1.996 +: + 197 + :+---+--------+--------+--------+-------+--------+--------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+-------+--------+--------+-------+ +| 1 | -2.000 | -1.000 | -1.221 | 9.330 | -2.650 | -1.964 | 1.000 | +| 2 | -2.000 | -1.221 | -1.357 | 9.330 | -1.964 | -1.068 | 0.779 | +| 3 | -2.000 | -1.357 | -1.423 | 9.330 | -1.068 | -0.486 | 0.643 | +| 4 | -2.000 | -1.423 | -1.451 | 9.330 | -0.486 | -0.203 | 0.577 | +| 5 | -2.000 | -1.451 | -1.463 | 9.330 | -0.203 | -0.082 | 0.549 | +| 6 | -2.000 | -1.463 | -1.468 | 9.330 | -0.082 | -0.033 | 0.537 | +| 7 | -2.000 | -1.468 | -1.470 | 9.330 | -0.033 | -0.013 | 0.532 | +| 8 | -2.000 | -1.470 | -1.470 | 9.330 | -0.013 | -0.005 | 0.530 | ++---+--------+--------+--------+-------+--------+--------+-------+ :+---+--------+--------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+--------+---------+---------+---------------+ +| 1 | 0.000 | 2.310 | 8.630 | -0.268 | 0.268 | +| 2 | -0.268 | 0.137 | 7.434 | -0.286 | 0.018 | ++---+--------+--------+---------+---------+---------------+ :+---+-------+---------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+---------+---------+----------+---------------+ +| 1 | 3.000 | -25.170 | 2.546 | 2.546 | 0.454 | +| 2 | 2.546 | -7.109 | 2.384 | 2.384 | 0.162 | +| 3 | 2.384 | -2.418 | 2.323 | 2.323 | 0.061 | +| 4 | 2.323 | -0.886 | 2.300 | 2.300 | 0.023 | +| 5 | 2.300 | -0.334 | 2.292 | 2.292 | 0.009 | +| 6 | 2.292 | -0.127 | 2.288 | 2.288 | 0.003 | +| 7 | 2.288 | -0.049 | 2.287 | 2.287 | 0.001 | +| 8 | 2.287 | -0.019 | 2.286 | 2.286 | 0.000 | ++---+-------+---------+---------+----------+---------------+ :+---+--------+--------+--------+-------+--------+--------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+-------+--------+--------+-------+ +| 1 | -2.000 | -1.000 | -1.221 | 9.330 | -2.650 | -1.964 | 1.000 | +| 2 | -2.000 | -1.221 | -1.357 | 9.330 | -1.964 | -1.068 | 0.779 | +| 3 | -2.000 | -1.357 | -1.423 | 9.330 | -1.068 | -0.486 | 0.643 | +| 4 | -2.000 | -1.423 | -1.451 | 9.330 | -0.486 | -0.203 | 0.577 | +| 5 | -2.000 | -1.451 | -1.463 | 9.330 | -0.203 | -0.082 | 0.549 | +| 6 | -2.000 | -1.463 | -1.468 | 9.330 | -0.082 | -0.033 | 0.537 | +| 7 | -2.000 | -1.468 | -1.470 | 9.330 | -0.033 | -0.013 | 0.532 | +| 8 | -2.000 | -1.470 | -1.470 | 9.330 | -0.013 | -0.005 | 0.530 | ++---+--------+--------+--------+-------+--------+--------+-------+ :+---+--------+--------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+--------+---------+---------+---------------+ +| 1 | 0.000 | 2.310 | 8.630 | -0.268 | 0.268 | +| 2 | -0.268 | 0.137 | 7.434 | -0.286 | 0.018 | ++---+--------+--------+---------+---------+---------------+ :+---+-------+---------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+---------+---------+----------+---------------+ +| 1 | 3.000 | -25.170 | 2.546 | 2.546 | 0.454 | +| 2 | 2.546 | -7.109 | 2.384 | 2.384 | 0.162 | +| 3 | 2.384 | -2.418 | 2.323 | 2.323 | 0.061 | +| 4 | 2.323 | -0.886 | 2.300 | 2.300 | 0.023 | +| 5 | 2.300 | -0.334 | 2.292 | 2.292 | 0.009 | +| 6 | 2.292 | -0.127 | 2.288 | 2.288 | 0.003 | +| 7 | 2.288 | -0.049 | 2.287 | 2.287 | 0.001 | +| 8 | 2.287 | -0.019 | 2.286 | 2.286 | 0.000 | ++---+-------+---------+---------+----------+---------------+ :+---+--------+--------+--------+-------+--------+--------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++---+--------+--------+--------+-------+--------+--------+-------+ +| 1 | -2.000 | -1.000 | -1.221 | 9.330 | -2.650 | -1.964 | 1.000 | +| 2 | -2.000 | -1.221 | -1.357 | 9.330 | -1.964 | -1.068 | 0.779 | +| 3 | -2.000 | -1.357 | -1.423 | 9.330 | -1.068 | -0.486 | 0.643 | +| 4 | -2.000 | -1.423 | -1.451 | 9.330 | -0.486 | -0.203 | 0.577 | +| 5 | -2.000 | -1.451 | -1.463 | 9.330 | -0.203 | -0.082 | 0.549 | +| 6 | -2.000 | -1.463 | -1.468 | 9.330 | -0.082 | -0.033 | 0.537 | +| 7 | -2.000 | -1.468 | -1.470 | 9.330 | -0.033 | -0.013 | 0.532 | +| 8 | -2.000 | -1.470 | -1.470 | 9.330 | -0.013 | -0.005 | 0.530 | ++---+--------+--------+--------+-------+--------+--------+-------+ :+---+--------+--------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+--------+---------+---------+---------------+ +| 1 | 0.000 | 2.310 | 8.630 | -0.268 | 0.268 | +| 2 | -0.268 | 0.137 | 7.434 | -0.286 | 0.018 | ++---+--------+--------+---------+---------+---------------+ :+---+-------+---------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++---+-------+---------+---------+----------+---------------+ +| 1 | 3.000 | -25.170 | 2.546 | 2.546 | 0.454 | +| 2 | 2.546 | -7.109 | 2.384 | 2.384 | 0.162 | +| 3 | 2.384 | -2.418 | 2.323 | 2.323 | 0.061 | +| 4 | 2.323 | -0.886 | 2.300 | 2.300 | 0.023 | +| 5 | 2.300 | -0.334 | 2.292 | 2.292 | 0.009 | +| 6 | 2.292 | -0.127 | 2.288 | 2.288 | 0.003 | +| 7 | 2.288 | -0.049 | 2.287 | 2.287 | 0.001 | +| 8 | 2.287 | -0.019 | 2.286 | 2.286 | 0.000 | ++---+-------+---------+---------+----------+---------------+ :+----+--------+--------+--------+-------+--------+--------+-------+ +| | a | b | x | f(a) | f(b) | f(x) | |a-b| | ++----+--------+--------+--------+-------+--------+--------+-------+ +| 1 | -2.000 | -1.000 | -1.221 | 9.330 | -2.650 | -1.964 | 1.000 | +| 2 | -2.000 | -1.221 | -1.357 | 9.330 | -1.964 | -1.068 | 0.779 | +| 3 | -2.000 | -1.357 | -1.423 | 9.330 | -1.068 | -0.486 | 0.643 | +| 4 | -2.000 | -1.423 | -1.451 | 9.330 | -0.486 | -0.203 | 0.577 | +| 5 | -2.000 | -1.451 | -1.463 | 9.330 | -0.203 | -0.082 | 0.549 | +| 6 | -2.000 | -1.463 | -1.468 | 9.330 | -0.082 | -0.033 | 0.537 | +| 7 | -2.000 | -1.468 | -1.470 | 9.330 | -0.033 | -0.013 | 0.532 | +| 8 | -2.000 | -1.470 | -1.470 | 9.330 | -0.013 | -0.005 | 0.530 | +| 9 | -2.000 | -1.470 | -1.471 | 9.330 | -0.005 | -0.002 | 0.530 | +| 10 | -2.000 | -1.471 | -1.471 | 9.330 | -0.002 | -0.001 | 0.529 | +| 11 | -2.000 | -1.471 | -1.471 | 9.330 | -0.001 | -0.000 | 0.529 | ++----+--------+--------+--------+-------+--------+--------+-------+ :+---+--------+--------+---------+---------+---------------+ +| | x_k | f(x_k) | f'(x_k) | x_{k+1} | |x_k-x_{k+1}| | ++---+--------+--------+---------+---------+---------------+ +| 1 | 0.000 | 2.310 | 8.630 | -0.268 | 0.268 | +| 2 | -0.268 | 0.137 | 7.434 | -0.286 | 0.018 | +| 3 | -0.286 | 0.001 | 7.314 | -0.286 | 0.000 | ++---+--------+--------+---------+---------+---------------+ :+----+-------+---------+---------+----------+---------------+ +| | x_k | f(x_k) | x_{k+1} | phi(x_k) | |x_k-x_{k+1}| | ++----+-------+---------+---------+----------+---------------+ +| 1 | 3.000 | -25.170 | 2.546 | 2.546 | 0.454 | +| 2 | 2.546 | -7.109 | 2.384 | 2.384 | 0.162 | +| 3 | 2.384 | -2.418 | 2.323 | 2.323 | 0.061 | +| 4 | 2.323 | -0.886 | 2.300 | 2.300 | 0.023 | +| 5 | 2.300 | -0.334 | 2.292 | 2.292 | 0.009 | +| 6 | 2.292 | -0.127 | 2.288 | 2.288 | 0.003 | +| 7 | 2.288 | -0.049 | 2.287 | 2.287 | 0.001 | +| 8 | 2.287 | -0.019 | 2.286 | 2.286 | 0.000 | +| 9 | 2.286 | -0.007 | 2.286 | 2.286 | 0.000 | +| 10 | 2.286 | -0.003 | 2.286 | 2.286 | 0.000 | ++----+-------+---------+---------+----------+---------------+ :: -0.001 1.003 1.999 +: + 409 diff --git "a/\320\2403265-69/saveleva_409492/lab2/solvers.py" "b/\320\2403265-69/saveleva_409492/lab2/solvers.py" new file mode 100644 index 0000000..57ce68c --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab2/solvers.py" @@ -0,0 +1,127 @@ +from typing import Callable, Optional, List + +import numpy as np +from attr import dataclass, field +from prettytable import PrettyTable + + +MAX_ITER_COUNT = 100 + + +@dataclass +class Result: + root: Optional[float] = None + error: Optional[float] = None + header: list = field(factory=list) + data: list = field(factory=list) + znach_f: float = field(default=0) + iter_count: int = field(default=0) + + def __str__(self): + tt = PrettyTable(self.header) + data = [(n, *map(lambda x: f'{x:.3f}', floats)) for n, *floats in self.data] + tt.add_rows(data) + return str(tt) + + +@dataclass +class SystemResult: + iteration: int = field(default=0) + solved: bool = field(default=False) + roots: list = field(factory=list) + errors: list = field(factory=list) + + def __str__(self): + if self.solved: + return 'Решение: ' + ' '.join(f'{x:.3f}' for x in self.roots) + '\n' + \ + 'Погрешности: ' + ' '.join(str(x) for x in self.errors) + '\n' + \ + f'Количество итераций {self.iteration}\n' + else: + return 'Решений не найдено!' + + +def horde_method(f: Callable, left: float, right: float, fix=-1, epsilon=10e-3): + # [left, right] - интервал изоляции корня + res = Result(header=['№', 'a', 'b', 'x', 'f(a)', 'f(b)', 'f(x)', '|a-b|']) + + x0 = left if fix == -1 else right + for i in range(1, MAX_ITER_COUNT + 1): + res.iter_count = i + x1 = (left * f(right) - right * f(left)) / (f(right) - f(left)) + res.data.append([i, left, right, x1, f(left), f(right), f(x1), abs(left - right)]) + if abs(x1 - x0) <= epsilon or abs(f(x1)) <= epsilon: + res.root = x1 + res.error = abs(x1 - x0) + break + if f(x1) * f(left) < 0: + right = x1 + else: + left = x1 + x0 = x1 + + res.znach_f = f(res.root) + return res + + +def newton_method(y: Callable, df: Callable, x0: float, epsilon=10e-3): + res = Result(header=['№', 'x_k', 'f(x_k)', "f'(x_k)", 'x_{k+1}', '|x_k-x_{k+1}|']) + + for i in range(1, MAX_ITER_COUNT + 1): + res.iter_count = i + x1 = x0 - y(x0) / df(x0) + res.data.append([i, x0, y(x0), df(x0), x1, abs(x1 - x0)]) + + if abs(x1 - x0) <= epsilon or abs(y(x1) / df(x1)) <= epsilon or abs(y(x1)) <= epsilon: + res.root = x1 + res.error = abs(x1 - x0) + break + x0 = x1 + res.znach_f = y(res.root) + return res + + +def simple_iteration_method(f: Callable, phi: Callable, x0=1, epsilon=10e-3): + res = Result(header=['№', 'x_k', 'f(x_k)', 'x_{k+1}', 'phi(x_k)', '|x_k-x_{k+1}|']) + + for i in range(1, MAX_ITER_COUNT + 1): + res.iter_count = i + x1 = phi(x0) + + res.data.append([i, x0, f(x0), x1, phi(x0), abs(x1 - x0)]) + + if abs(x1 - x0) <= epsilon: + res.root = x1 + res.error = abs(x1 - x0) + break + x0 = x1 + res.znach_f = f(res.root) + return res + + +def _newton_method(f, jack, x_init): + jacobian = jack(*x_init) + vector_b_f_output = f(*x_init) + x_delta = np.linalg.solve(jacobian, vector_b_f_output) + x_plus_1 = x_delta + x_init + return x_plus_1 + + +def system_newton_method(f, jack, x_init, epsilon): + result = SystemResult() + + x_old = x_init + x_new = _newton_method(f, jack, x_old) + diff = np.linalg.norm(x_old-x_new) + + while diff > epsilon or result.iteration == MAX_ITER_COUNT: + x_new = _newton_method(f, jack, x_old) + diff = np.linalg.norm(x_old-x_new) + x_old = x_new + result.iteration += 1 + convergent_val = x_new + + if result.iteration != MAX_ITER_COUNT: + result.solved = True + + result.roots = convergent_val + return result diff --git "a/\320\2403265-69/saveleva_409492/lab2/\320\222\321\213\321\207\320\274\320\260\321\2022.pdf" "b/\320\2403265-69/saveleva_409492/lab2/\320\222\321\213\321\207\320\274\320\260\321\2022.pdf" new file mode 100644 index 0000000..6f0a205 Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab2/\320\222\321\213\321\207\320\274\320\260\321\2022.pdf" differ diff --git "a/\320\2403265-69/saveleva_409492/lab3/Exceptions/IncorrectValueException.py" "b/\320\2403265-69/saveleva_409492/lab3/Exceptions/IncorrectValueException.py" new file mode 100644 index 0000000..7f89217 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab3/Exceptions/IncorrectValueException.py" @@ -0,0 +1,4 @@ +class IncorrectValueException(Exception): + + def __init__(self, message): + self.message = message diff --git "a/\320\2403265-69/saveleva_409492/lab3/Exceptions/__pycache__/IncorrectValueException.cpython-312.pyc" "b/\320\2403265-69/saveleva_409492/lab3/Exceptions/__pycache__/IncorrectValueException.cpython-312.pyc" new file mode 100644 index 0000000..077eb30 Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab3/Exceptions/__pycache__/IncorrectValueException.cpython-312.pyc" differ diff --git "a/\320\2403265-69/saveleva_409492/lab3/Functions.py" "b/\320\2403265-69/saveleva_409492/lab3/Functions.py" new file mode 100644 index 0000000..6c5ec14 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab3/Functions.py" @@ -0,0 +1,42 @@ +import numexpr as ne +from sympy import * + +x = symbols('x') + +METHODS = ['Метод правых прямоугольников', + 'Метод левых прямоугольников', + 'Метод средних прямоугольников', + 'Метод трапеций', + 'Метод Симпсона'] + +FUNCTIONS = { + 1: + { + 'FUNCTION': 'f(x)=sin(x)+cos(x)' + }, + 2: + { + 'FUNCTION': 'f(x)=19*x**5-67*x**2+100*x-191' + }, + 3: + { + 'FUNCTION': 'f(x)=5**x+5*x' + }, + 4: + { + 'FUNCTION': 'f(x)=(cos(x))**2' + }, + 5: + { + 'FUNCTION': 'f(x)=x**2' + }, +6: + { + 'FUNCTION': 'f(x)=5*x**3 - 2*x**2 + 3*x - 15' + } + +} + + +def calculateFunction(number_of_function, x: float) -> float: + return ne.evaluate(FUNCTIONS[number_of_function]['FUNCTION'].split('=')[1], local_dict={'x': x}) diff --git "a/\320\2403265-69/saveleva_409492/lab3/ImproperIntegralSolver.py" "b/\320\2403265-69/saveleva_409492/lab3/ImproperIntegralSolver.py" new file mode 100644 index 0000000..175cd85 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab3/ImproperIntegralSolver.py" @@ -0,0 +1,136 @@ +import numpy as np +from scipy import integrate + + +class ImproperIntegralSolver: + """ + Класс для вычисления несобственных интегралов 2 рода + с использованием различных численных методов + """ + + def __init__(self, func, interval, singularity_type): + self.func = func + self.a, self.b = interval + self.singularity_type = singularity_type + self.convergent = False + + def _check_convergence(self): + """Проверка сходимости интеграла""" + try: + if self.singularity_type == 'a': + test = (1e-12) ** 0.5 * self.func(self.a + 1e-12) + elif self.singularity_type == 'b': + test = (1e-12) ** 0.5 * self.func(self.b - 1e-12) + else: + mid = (self.a + self.b) / 2 + left = ImproperIntegralSolver(self.func, (self.a, mid), 'b') + right = ImproperIntegralSolver(self.func, (mid, self.b), 'a') + return left.check_convergence() and right.check_convergence() + self.convergent = np.isfinite(test) + return self.convergent + except: + self.convergent = False + return False + + def integrate(self, method='simpson', n=100000): + """ + Основной метод вычисления интеграла + :param method: метод интегрирования ('left_rect', 'mid_rect', 'right_rect', 'trapezoid', 'simpson') + :param n: количество интервалов разбиения + """ + if not self._check_convergence(): + print("Интеграл не существует") + return None + + try: + if self.singularity_type == 'internal': + return self._handle_internal_singularity(method, n) + + if method in ['left_rect', 'mid_rect', 'right_rect']: + return self._rectangle_method(method, n) + elif method == 'trapezoid': + return self._trapezoid_method(n) + elif method == 'simpson': + return self._simpson_method(n) + else: + raise ValueError("Неизвестный метод интегрирования") + except Exception as e: + print(f"Ошибка: {str(e)}") + return None + + def _generate_partition(self, n): + """Генерация разбиения с учётом особенности""" + if self.singularity_type == 'a': + return np.linspace(self.a + 1e-12, self.b, n + 1) + elif self.singularity_type == 'b': + return np.linspace(self.a, self.b - 1e-12, n + 1) + else: + mid = (self.a + self.b) / 2 + return np.concatenate([ + np.linspace(self.a, mid - 1e-12, n // 2 + 1), + np.linspace(mid + 1e-12, self.b, n // 2 + 1)[1:] + ]) + + def _rectangle_method(self, method, n): + """Метод прямоугольников""" + x = self._generate_partition(n) + h = (x[-1] - x[0]) / n + + if method == 'left_rect': + points = x[:-1] + elif method == 'right_rect': + points = x[1:] + else: # mid_rect + points = (x[:-1] + x[1:]) / 2 + + y = self.func(points) + return h * np.sum(y) + + def _trapezoid_method(self, n): + """Метод трапеций""" + x = self._generate_partition(n) + y = self.func(x) + return np.trapezoid(y, x) + + def _simpson_method(self, n): + """Метод Симпсона""" + if n % 2 != 0: + n += 1 # Делаем четное количество интервалов + x = self._generate_partition(n) + y = self.func(x) + h = (x[-1] - x[0]) / n + return h / 3 * (y[0] + 4 * np.sum(y[1:-1:2]) + 2 * np.sum(y[2:-2:2]) + y[-1]) + + def _handle_internal_singularity(self, method, n): + """Обработка внутренней особенности""" + c = (self.a + self.b) / 2 + left = ImproperIntegralSolver(self.func, (self.a, c), 'b') + right = ImproperIntegralSolver(self.func, (c, self.b), 'a') + return left.integrate(method, n // 2) + right.integrate(method, n // 2) + + +# Примеры использования +if __name__ == "__main__": + # Тестовые интегралы + tests = [ + ("∫1/√x dx от 0 до 1", lambda x: 1 / np.sqrt(x), (0, 1), 'a'), + ("∫1/√(1-x) dx от 0 до 1", lambda x: 1 / np.sqrt(1 - x), (0, 1), 'b'), + ("∫1/|x-0.5|^(1/3) dx от 0 до 1", lambda x: 1 / np.abs(x - 0.5) ** (1 / 3), (0, 1), 'internal'), + ("∫1/x dx от 0 до 1 (расходится)", lambda x: 1 / x, (0, 1), 'a') + + ] + + methods = ['left_rect', 'mid_rect', 'right_rect', 'trapezoid', 'simpson'] + + for desc, func, interval, stype in tests: + print(f"\n{desc}") + solver = ImproperIntegralSolver(func, interval, stype) + + for method in methods: + result = solver.integrate(method, n=100000) + if result is not None: + print(f"{method:10} → {result:.6f}") + + # Проверка расходимости + if not solver._check_convergence(): + print("Результат: Интеграл не существует") \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab3/Methods/MethodRectangles.py" "b/\320\2403265-69/saveleva_409492/lab3/Methods/MethodRectangles.py" new file mode 100644 index 0000000..63e401e --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab3/Methods/MethodRectangles.py" @@ -0,0 +1,118 @@ +from Functions import * +from NumericalIntegrations.NumericalIntegration import * + + +K = 2 + + +class MethodRectangles(NumericalIntegration): + + def iterateRightRectangles(self, number_of_function): + eps = self.getEpsilon() + iterations = 0 + while True: + print(f'Номер итерации №{iterations}') + square_1, n_1 = self.rightRectangles(number_of_function=number_of_function, n=self.getN()) + self.doubleN() + square_2, n_2 = self.rightRectangles(number_of_function=number_of_function, n=self.getN()) + if self.ruleRunge(square_1, square_2, 2, self.getEpsilon()): + print(f"Решение интеграла {FUNCTIONS[number_of_function]['FUNCTION']} " + f"с границами a={self.getLeftBorder()} и b={self.getRightBorder()}:\n\t\t\t " + f"{square_2} \nдля разбиения на {n_2} отрезков.") + break + iterations += 1 + + def rightRectangles(self, number_of_function, n): + a = self.getLeftBorder() + b = self.getRightBorder() + h = (b - a) / n + iterations = [[0.0 for x in range(self.AMOUNT_OF_COLUMNS)] for i in range(n + 1)] + square = 0 + for i in range(n + 1): + iterations[i][0] = i + if i == 0: + iterations[i][1] = a + else: + iterations[i][1] = a + h + iterations[i][2] = calculateFunction(number_of_function, iterations[i][1]) + if i != 0: + square += iterations[i][2] + a = iterations[i][1] + square *= h + print(f'\nМетод правых прямоугольников. Численное интегрирование для n={n} и h={h}') + self.printTableForMethods(iterations, method='right') + print(f'Найденный ответ:{square} для {n} отрезков разбиения.') + return square, n + + def iterateLeftRectangles(self, number_of_function): + eps = self.getEpsilon() + iterations = 0 + while True: + print(f'Номер итерации №{iterations}') + square_1, n_1 = self.leftRectangles(number_of_function=number_of_function, n=self.getN()) + self.doubleN() + square_2, n_2 = self.leftRectangles(number_of_function=number_of_function, n=self.getN()) + if self.ruleRunge(square_1, square_2, 2, self.getEpsilon()): + print(f"Решение интеграла {FUNCTIONS[number_of_function]['FUNCTION']} " + f"с границами a={self.getLeftBorder()} и b={self.getRightBorder()}:\n\t\t\t " + f"{square_2} \nдля разбиения на {n_2} отрезков.") + break + iterations += 1 + + def leftRectangles(self, number_of_function, n): + a = self.getLeftBorder() + b = self.getRightBorder() + h = (b - a) / n + iterations = [[0.0 for x in range(self.AMOUNT_OF_COLUMNS)] for i in range(n + 1)] + square = 0 + for i in range(1, n + 2): + if i == 1: + iterations[i - 1][1] = a + else: + iterations[i - 1][1] = a + h + iterations[i - 1][0] = i - 1 + iterations[i - 1][2] = calculateFunction(number_of_function, iterations[i - 1][1]) + if i != n + 1: + square += iterations[i - 1][2] + a = iterations[i - 1][1] + square *= h + print(f'\nМетод левых прямоугольников. Численное интегрирование для n={n} и h={h}') + self.printTableForMethods(iterations, method='left') + print(f'Найденный ответ:{square} для {n} отрезков разбиения.') + return square, n + + def iterateMiddleRectangles(self, number_of_function): + eps = self.getEpsilon() + iterations = 0 + while True: + print(f'Номер итерации №{iterations}') + square_1, n_1 = self.middleRectangles(number_of_function=number_of_function, n=self.getN()) + self.doubleN() + square_2, n_2 = self.middleRectangles(number_of_function=number_of_function, n=self.getN()) + if self.ruleRunge(square_1, square_2, 2, self.getEpsilon()): + print(f"Решение интеграла {FUNCTIONS[number_of_function]['FUNCTION']} " + f"с границами a={self.getLeftBorder()} и b={self.getRightBorder()}:\n\t\t\t " + f"{square_2} \nдля разбиения на {n_2} отрезков.") + break + iterations += 1 + + def middleRectangles(self, number_of_function, n): + a = self.getLeftBorder() + b = self.getRightBorder() + h = (b - a) / n + iterations = [[0.0 for x in range(self.AMOUNT_OF_COLUMNS)] for i in range(n + 1)] + square = 0 + for i in range(1, n + 1): + iterations[i][0] = i + if i == 1: + iterations[i][1] = (a + a + h) / 2 + else: + iterations[i][1] = a + h + iterations[i][2] = calculateFunction(number_of_function, iterations[i][1]) + square += iterations[i][2] + a = iterations[i][1] + square *= h + print(f'\nМетод средних прямоугольников. Численное интегрирование для n={n} и h={h}') + self.printTableForMethods(iterations, method='middle') + print(f'Найденный ответ:{square} для {n} отрезков разбиения.') + return square, n \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab3/Methods/MethodSympson.py" "b/\320\2403265-69/saveleva_409492/lab3/Methods/MethodSympson.py" new file mode 100644 index 0000000..b6304bf --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab3/Methods/MethodSympson.py" @@ -0,0 +1,43 @@ +from Functions import calculateFunction, FUNCTIONS +from NumericalIntegrations.NumericalIntegration import NumericalIntegration + + +class MethodSympson(NumericalIntegration): + + def iterateSympsonlMethod(self, number_of_function): + eps = self.getEpsilon() + iterations = 0 + while True: + print(f'Номер итерации №{iterations}') + square_1, n_1 = self.sympsonMethod(number_of_function=number_of_function, n=self.getN()) + self.doubleN() + square_2, n_2 = self.sympsonMethod(number_of_function=number_of_function, n=self.getN()) + if self.ruleRunge(square_1, square_2, 2, self.getEpsilon()): + print(f"Решение интеграла {FUNCTIONS[number_of_function]['FUNCTION']} " + f"с границами a={self.getLeftBorder()} и b={self.getRightBorder()}:\n\t\t\t " + f"{square_2} \nдля разбиения на {n_2} отрезков.") + break + iterations += 1 + + def sympsonMethod(self, number_of_function, n): + a = self.getLeftBorder() + b = self.getRightBorder() + h = (b - a) / n + iterations = [[0.0 for x in range(self.AMOUNT_OF_COLUMNS)] for i in range(n + 1)] + square_even = 0 + square_odd = 0 + for i in range(n + 1): + iterations[i][0] = i + iterations[i][1] = a if i == 0 else a + h + iterations[i][2] = calculateFunction(number_of_function, iterations[i][1]) + if i != 0 and i != n: + if i % 2 == 0: + square_even += iterations[i][2] + else: + square_odd += iterations[i][2] + a = iterations[i][1] + square = h / 3 * (iterations[0][2] + iterations[-1][2] + 2 * square_even + 4 * square_odd) + print(f'\nМетод Симпсона. Численное интегрирование для n={n} и h={h}') + self.printTableForMethods(iterations, method='trapezoidal') + print(f'Найденный ответ:{square} для {n} отрезков разбиения.') + return square, n \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab3/Methods/MethodTrapezoidal.py" "b/\320\2403265-69/saveleva_409492/lab3/Methods/MethodTrapezoidal.py" new file mode 100644 index 0000000..559e6dd --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab3/Methods/MethodTrapezoidal.py" @@ -0,0 +1,42 @@ +from Functions import calculateFunction, FUNCTIONS +from NumericalIntegrations.NumericalIntegration import NumericalIntegration + + +class MethodTrapezoidal(NumericalIntegration): + + def iterateTrapezoidalMethod(self, number_of_function): + eps = self.getEpsilon() + iterations = 0 + while True: + print(f'Номер итерации №{iterations}') + square_1, n_1 = self.trapezoidalMethod(number_of_function=number_of_function, n=self.getN()) + self.doubleN() + square_2, n_2 = self.trapezoidalMethod(number_of_function=number_of_function, n=self.getN()) + if self.ruleRunge(square_1, square_2, 2, self.getEpsilon()): + print(f"Решение интеграла {FUNCTIONS[number_of_function]['FUNCTION']} " + f"с границами a={self.getLeftBorder()} и b={self.getRightBorder()}:\n\t\t\t " + f"{square_2} \nдля разбиения на {n_2} отрезков.") + break + iterations += 1 + + def trapezoidalMethod(self, number_of_function, n): + a = self.getLeftBorder() + b = self.getRightBorder() + h = (b - a) / n + iterations = [[0.0 for x in range(self.AMOUNT_OF_COLUMNS)] for i in range(n + 1)] + square = 0 + for i in range(n + 1): + iterations[i][0] = i + if i == 0: + iterations[i][1] = a + else: + iterations[i][1] = a + h + iterations[i][2] = calculateFunction(number_of_function, iterations[i][1]) + if i != 0 and i != n: + square += iterations[i][2] + a = iterations[i][1] + square = h * ((iterations[0][2] + iterations[-1][2]) / 2 + square) + print(f'\nМетод трапеций. Численное интегрирование для n={n} и h={h}') + self.printTableForMethods(iterations, method='trapezoidal') + print(f'Найденный ответ:{square} для {n} отрезков разбиения.') + return square, n diff --git "a/\320\2403265-69/saveleva_409492/lab3/Methods/__pycache__/MethodRectangles.cpython-312.pyc" "b/\320\2403265-69/saveleva_409492/lab3/Methods/__pycache__/MethodRectangles.cpython-312.pyc" new file mode 100644 index 0000000..a239873 Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab3/Methods/__pycache__/MethodRectangles.cpython-312.pyc" differ diff --git "a/\320\2403265-69/saveleva_409492/lab3/Methods/__pycache__/MethodSympson.cpython-312.pyc" "b/\320\2403265-69/saveleva_409492/lab3/Methods/__pycache__/MethodSympson.cpython-312.pyc" new file mode 100644 index 0000000..3aeec40 Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab3/Methods/__pycache__/MethodSympson.cpython-312.pyc" differ diff --git "a/\320\2403265-69/saveleva_409492/lab3/Methods/__pycache__/MethodTrapezoidal.cpython-312.pyc" "b/\320\2403265-69/saveleva_409492/lab3/Methods/__pycache__/MethodTrapezoidal.cpython-312.pyc" new file mode 100644 index 0000000..07d5432 Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab3/Methods/__pycache__/MethodTrapezoidal.cpython-312.pyc" differ diff --git "a/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/NumericalIntegration.py" "b/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/NumericalIntegration.py" new file mode 100644 index 0000000..6b3db38 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/NumericalIntegration.py" @@ -0,0 +1,44 @@ +from Validator import Validator + +class NumericalIntegration: + AMOUNT_OF_COLUMNS = 3 + + def __init__(self, epsilon, left_border, right_border, n): + self.__right_border = right_border + self.__left_border = left_border + self.__n = n + self.__epsilon = epsilon + + def getEpsilon(self): + return self.__epsilon + + def getN(self): + return self.__n + + def doubleN(self): + self.__n *= 2 + + def getLeftBorder(self): + return self.__left_border + + def getRightBorder(self): + return self.__right_border + + def ruleRunge(self, I_h, I_h2, k, eps): #Правило Рунге + delta = abs(I_h2 - I_h) / (2 ** k - 1) + print( + f'Погрешность вычислений между значениями {I_h2} и {I_h} составляет {delta} {"<" if delta < eps else ">"} {eps}.') + if delta <= eps: + return True + else: + return False + + def printTableForMethods(self, iterations, method): + if method == 'middle': + print('i | x(i-1/2) | y(i-1/2) |') + else: + print('i | xi | yi |') + for i in range(len(iterations)): + for j in range(len(iterations[i])): + print(iterations[i][j], end=' | ') + print() diff --git "a/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/Terminal.py" "b/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/Terminal.py" new file mode 100644 index 0000000..c573976 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/Terminal.py" @@ -0,0 +1,89 @@ +from Methods.MethodRectangles import MethodRectangles +from Methods.MethodSympson import MethodSympson +from Methods.MethodTrapezoidal import MethodTrapezoidal +from Validator import Validator +from Exceptions.IncorrectValueException import IncorrectValueException +from Functions import * + + +class Terminal: + + def work(self): + try: + print('\t\t\tЛабораторная работа №3\n\t\t\tЧисленное интегрирование') + for i in range(len(FUNCTIONS)): + print(f"{i + 1}. {FUNCTIONS[i + 1]['FUNCTION']}") + function_number = self.enterFunctionNumber() + print('\t\tМетоды решения:') + for i in range(len(METHODS)): + print(f'{i + 1}.{METHODS[i]}') + method_number = self.enterFunctionMethod() + a, b = self.enterBorders() + epsilon = self.enterEpsilon() + n = self.enterN() + + if method_number == 1: + right_rectangles = MethodRectangles(epsilon, a, b, n) + right_rectangles.iterateRightRectangles(number_of_function=function_number) + elif method_number == 2: + left_rectangles = MethodRectangles(epsilon, a, b, n) + left_rectangles.iterateLeftRectangles(number_of_function=function_number) + elif method_number == 3: + middle_rectangles = MethodRectangles(epsilon, a, b, n) + middle_rectangles.iterateMiddleRectangles(number_of_function=function_number) + elif method_number == 4: + trapezoidal_method = MethodTrapezoidal(epsilon, a, b, n) + trapezoidal_method.iterateTrapezoidalMethod(number_of_function=function_number) + else: + sympson_method = MethodSympson(epsilon, a, b, n) + sympson_method.iterateSympsonlMethod(number_of_function=function_number) + except IncorrectValueException as e: + print(e.message) + return + + def enterFunctionNumber(self): + try: + print('Введите номер функции:') + return Validator.validateFunctionNumber() + except IncorrectValueException as e: + print(e.message) + return self.enterFunctionNumber() + + def enterFunctionMethod(self): + try: + print('Введите номер метода:') + return Validator.validateFunctionMethod() + except IncorrectValueException as e: + print(e.message) + return self.enterFunctionMethod() + + def enterN(self): + try: + print('Введите начальное число отрезков для разбиения:') + n = Validator.validateN() + return n + except IncorrectValueException as e: + print(e.message) + return self.enterN() + + def enterBorders(self): + try: + print('Введите границы интервала a и b:') + print('a = ', end='') + a = Validator.validateNumber(input()) + print('b = ', end='') + b = Validator.validateNumber(input()) + Validator.validateBorders(a, b) + return a, b + except IncorrectValueException as e: + print(e.message) + return self.enterBorders() + + def enterEpsilon(self): + try: + print('Введите точность epsilon:') + eps = Validator.validateEpsilon(input()) + return eps + except IncorrectValueException as e: + print(e.message) + return self.enterEpsilon() \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/__pycache__/NumericalIntegration.cpython-312.pyc" "b/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/__pycache__/NumericalIntegration.cpython-312.pyc" new file mode 100644 index 0000000..ff38db6 Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/__pycache__/NumericalIntegration.cpython-312.pyc" differ diff --git "a/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/__pycache__/Terminal.cpython-312.pyc" "b/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/__pycache__/Terminal.cpython-312.pyc" new file mode 100644 index 0000000..d9bddd8 Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/__pycache__/Terminal.cpython-312.pyc" differ diff --git "a/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/main.py" "b/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/main.py" new file mode 100644 index 0000000..6faae51 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab3/NumericalIntegrations/main.py" @@ -0,0 +1,11 @@ + +from NumericalIntegrations.Terminal import Terminal + +if __name__ == "__main__": + + terminal = Terminal() + while True: + terminal.work() + print("Хотите продолжить работу с программой? y/n") + if not input().__eq__('y'): + break diff --git "a/\320\2403265-69/saveleva_409492/lab3/Validator.py" "b/\320\2403265-69/saveleva_409492/lab3/Validator.py" new file mode 100644 index 0000000..12f11b3 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab3/Validator.py" @@ -0,0 +1,57 @@ +from Exceptions.IncorrectValueException import IncorrectValueException +from Functions import FUNCTIONS, METHODS + + +class Validator: + MIN_EPSILON = 0 + + @staticmethod + def validateEpsilon(epsilon: str): + try: + epsilon = float(epsilon) + if epsilon >= Validator.MIN_EPSILON: + return epsilon + else: + raise IncorrectValueException(f'Точность (эпсилон) должна быть больше или равна 0.') + except ValueError: + raise IncorrectValueException(f'Точность (эпсилон) - число с плавающей точкой.') + + @staticmethod + def validateNumber(number: str): + try: + number = float(number) + return number + except ValueError: + raise IncorrectValueException(f'Необходимо ввести число.') + + @staticmethod + def validateFunctionNumber(): + equation_number = int(Validator.validateNumber(input())) + if 0 < equation_number <= len(FUNCTIONS): + return equation_number + else: + raise IncorrectValueException('Неверное введен номер функции. Попробуйте еще раз.') + + + @staticmethod + def validateFunctionMethod(): + equation_method = int(Validator.validateNumber(input())) + if 0 < equation_method <= len(METHODS): + return equation_method + else: + raise IncorrectValueException('Неверное введен номер метода. Попробуйте еще раз.') + + @staticmethod + def validateN(): + n = int(Validator.validateNumber(input())) + if n > 3: + return n + else: + raise IncorrectValueException('Неверное введено значение числа разбиения интервала интегрирования. Число должно быть строго больше 3.. Попробуйте еще раз.') + + @staticmethod + def validateBorders(border_left: float, border_right: float): + if border_left < border_right: + return True + else: + raise IncorrectValueException(f'Левая граница должна быть строго меньше правой.') \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab3/\320\222\321\213\321\207\320\274\320\260\321\2023.pdf" "b/\320\2403265-69/saveleva_409492/lab3/\320\222\321\213\321\207\320\274\320\260\321\2023.pdf" new file mode 100644 index 0000000..3da1acf Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab3/\320\222\321\213\321\207\320\274\320\260\321\2023.pdf" differ diff --git "a/\320\2403265-69/saveleva_409492/lab4/Approximation.py" "b/\320\2403265-69/saveleva_409492/lab4/Approximation.py" new file mode 100644 index 0000000..df6052b --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab4/Approximation.py" @@ -0,0 +1,93 @@ +from numpy import sqrt, log, exp + + +class Approximation: + + def __init__(self, x_arr, y_arr): + self.__x_array = x_arr + self.__y_array = y_arr + self.__n = len(self.__x_array) + self.__p_x = [] + self.__epsilon = [] + + def getArrayX(self): + return self.__x_array + + def setArrayX(self, arr): + self.__x_array = arr + + def getArrayY(self): + return self.__y_array + + def setArrayY(self, arr): + self.__y_array = arr + + def getN(self): + return self.__n + + def getEpsilon(self): + return self.__epsilon + + def _setEpsilon(self, eps): + self.__epsilon = eps + + def getPX(self): + return self.__p_x + + def _setPX(self, p_x): + self.__p_x = p_x + + def calculateSumX(self, degree): + return sum([x ** degree for x in self.__x_array]) + + def calculateSumY(self): + return sum(self.__y_array) + + def calculateSumXY(self, degree): + return sum([self.__x_array[i] ** degree * self.__y_array[i] for i in range(self.__n)]) + + def _calculateEpsilon(self): + return [self.__p_x[i] - self.__y_array[i] for i in range(self.__n)] + + def _calculateExponentialValues(self, a, b): + return [a * x ** b for x in self.__x_array] + + def _calculateLogarithmValues(self, a, b): + return [a * log(x) + b for x in self.__x_array] + + def _calculateExponentValues(self, a, b): + return [a * exp(b * x) for x in self.__x_array] + + def _calculateLinearValues(self, a, b): + return [a * x + b for x in self.__x_array] + + def _calculatePolynomialSecondValues(self, a0, a1, a2): + return [a0 + a1 * x + a2 * x ** 2 for x in self.__x_array] + + def _calculatePolynomialThirdValues(self, a0, a1, a2, a3): + return [a0 + a1 * x + a2 * x ** 2 + a3 * x ** 3 for x in self.__x_array] + + def _deviationMeasure(self): + return sum([eps ** 2 for eps in self.__epsilon]) + + def _standardDeviation(self): + return sqrt(self._deviationMeasure() / self.__n) + + def _printTable(self): + print('| X | Y | P(x) | epsilon |') + for i in range(self.__n): + print(f"| {self.__x_array[i]} | {self.__y_array[i]} | {self.__p_x[i]} | {self.__epsilon[i]} |") + + def _coefficientCorrelation(self): + x_mean = self._calculateMeanX() + y_mean = self._calculateMeanY() + return sum([(self.__x_array[i] - x_mean) * (self.__y_array[i] - y_mean) + for i in range(self.__n)]) / sqrt( + sum([(self.__x_array[i] - x_mean) ** 2 for i in range(self.__n)]) * + sum([(self.__y_array[i] - y_mean) ** 2 for i in range(self.__n)])) + + def _calculateMeanX(self): + return sum(self.__x_array) / self.__n + + def _calculateMeanY(self): + return sum(self.__y_array) / self.__n \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab4/ApproximationFunctions.py" "b/\320\2403265-69/saveleva_409492/lab4/ApproximationFunctions.py" new file mode 100644 index 0000000..be63611 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab4/ApproximationFunctions.py" @@ -0,0 +1,208 @@ +import math + +from numpy import exp, log + +from Approximation import Approximation +import numpy as np + + +class ApproximationFunctions(Approximation): + + def __calculateLinearFunctionCoefficient(self): + SX = self.calculateSumX(1) + SXX = self.calculateSumX(2) + SY = self.calculateSumY() + SXY = self.calculateSumXY(1) + N = self.getN() + delta = SXX * N - SX * SX + delta1 = SXY * N - SX * SY + delta2 = SXX * SY - SX * SXY + a = delta1 / delta + b = delta2 / delta + self._setPX(self._calculateLinearValues(a, b)) + self._setEpsilon(self._calculateEpsilon()) + S = self._deviationMeasure() + SD = self._standardDeviation() + return {'SX': SX, 'SXX': SXX, 'SY': SY, + 'SXY': SXY, 'N': N, 'delta': delta, + 'delta1': delta1, 'delta2': delta2, + 'a': a, 'b': b, 'S': S, 'SD': SD} + + # Линейная функция + def linearFunction(self): + coefficients = self.__calculateLinearFunctionCoefficient() + print('\t\t\tЛинейная аппроксимация') + print(f"\tCистема уравнений:\n" + f"\t\t{coefficients['SXX']}a + {coefficients['SX']}b = {coefficients['SXY']}\n" + f"\t\t{coefficients['SX']}a + {coefficients['N']}b = {coefficients['SY']}") + print(f"\tИз нее находим:\n" + f"\t\tdelta = {coefficients['SXX']}*{coefficients['N']} - {coefficients['SX']}*{coefficients['SX']} = {coefficients['delta']}\n" + f"\t\tdelta1 = {coefficients['SXY']}*{coefficients['N']} - {coefficients['SX']}*{coefficients['SY']} = {coefficients['delta1']}\n" + f"\t\tdelta2 = {coefficients['SXX']}*{coefficients['SY']} - {coefficients['SX']}*{coefficients['SXY']} = {coefficients['delta2']}\n" + f"\t\t\ta = {coefficients['delta1']}/{coefficients['delta']} = {coefficients['a']}\n" + f"\t\t\tb = {coefficients['delta2']}/{coefficients['delta']} = {coefficients['b']}\n") + function = f"P1(x) = {coefficients['a']}x + ({coefficients['b']})" + self.__printCoefficients(coefficients, function) + print(f"Коэффициент корреляции Пирсона: {self._coefficientCorrelation()}") + return function, {'a': coefficients['a'], 'b': coefficients['b']}, coefficients['S'], coefficients['SD'] + + def __calculatePolynomialSecondFunctionCoefficient(self): # Полиномиальная функция 2-й степени + SX = self.calculateSumX(1) + SXX = self.calculateSumX(2) + SXXX = self.calculateSumX(3) + SXXXX = self.calculateSumX(4) + SY = self.calculateSumY() + SXY = self.calculateSumXY(1) + SXXY = self.calculateSumXY(2) + N = self.getN() + M1 = np.array([[N, SX, SXX], [SX, SXX, SXXX], [SXX, SXXX, SXXXX]]) # Матрица (левая часть системы) + V1 = np.array([SY, SXY, SXXY]) # Вектор (правая часть системы) + a0, a1, a2 = np.linalg.solve(M1, V1) + self._setPX(self._calculatePolynomialSecondValues(a0, a1, a2)) + self._setEpsilon(self._calculateEpsilon()) + S = self._deviationMeasure() + SD = self._standardDeviation() + return {'SX': SX, 'SXX': SXX, 'SXXX': SXXX, 'SXXXX': SXXXX, + 'SY': SY, 'SXY': SXY, 'SXXY': SXXY, 'N': N, + 'a0': round(a0, 5), 'a1': round(a1, 5), 'a2': round(a2, 5), 'S': S, 'SD': SD} + + def polynomialSecondFunction(self): + print('\t\t\tПолиномиальная функция 2-ой степени') + coefficients = self.__calculatePolynomialSecondFunctionCoefficient() + function = f"P2(x) = {coefficients['a0']} + ({coefficients['a1']}x)+ ({coefficients['a2']}x^2)" + print(f"\tПолучаем систему уравнений:\n" + f"\t\t{coefficients['N']}a0 + {coefficients['SX']}a1 + {coefficients['SXX']}a2 = {coefficients['SY']}\n" + f"\t\t{coefficients['SX']}a0 + {coefficients['SXX']}a1 + {coefficients['SXXX']}a2= {coefficients['SXY']}\n" + f"\t\t{coefficients['SXX']}a0 + {coefficients['SXXX']}a1 + {coefficients['SXXXX']}a2= {coefficients['SXXY']}\n") + print(f"\tНайденные коэффициенты:\n" + f"\t\ta0 = {coefficients['a0']}\n" + f"\t\ta1 = {coefficients['a1']}\n" + f"\t\ta2 = {coefficients['a2']}\n") + self.__printCoefficients(coefficients, function) + return function, {'a0': coefficients['a0'], 'a1': coefficients['a1'], 'a2': coefficients['a2']}, \ + coefficients['S'], coefficients['SD'] + + def __calculatePolynomialThirdFunctionCoefficient(self): # Полиномиальная функция 3-й степени + SX = self.calculateSumX(1) + SXX = self.calculateSumX(2) + SXXX = self.calculateSumX(3) + SXXXX = self.calculateSumX(4) + SXXXXX = self.calculateSumX(5) + SXXXXXX = self.calculateSumX(6) + SY = self.calculateSumY() + SXY = self.calculateSumXY(1) + SXXY = self.calculateSumXY(2) + SXXXY = self.calculateSumXY(3) + N = self.getN() + M1 = np.array([[N, SX, SXX, SXXX], [SX, SXX, SXXX, SXXXX], [SXX, SXXX, SXXXX, SXXXXX], + [SXXX, SXXXX, SXXXXX, SXXXXXX]]) # Матрица (левая часть системы) + V1 = np.array([SY, SXY, SXXY, SXXXY]) # Вектор (правая часть системы) + a0, a1, a2, a3 = np.linalg.solve(M1, V1) + self._setPX(self._calculatePolynomialThirdValues(a0, a1, a2, a3)) + self._setEpsilon(self._calculateEpsilon()) + S = self._deviationMeasure() + SD = self._standardDeviation() + return {'SX': SX, 'SXX': SXX, 'SXXX': SXXX, 'SXXXX': SXXXX, 'SXXXXX': SXXXXX, 'SXXXXXX': SXXXXXX, + 'SY': SY, 'SXY': SXY, 'SXXY': SXXY, 'SXXXY': SXXXY, 'N': N, + 'a0': round(a0, 5), 'a1': round(a1, 5), 'a2': round(a2, 5), 'a3': round(a3, 5), 'S': S, 'SD': SD} + + def polynomialThirdFunction(self): + print('\t\t\tПолиномиальная функция 3-ей степени') + coefficients = self.__calculatePolynomialThirdFunctionCoefficient() + function = f"P3(x) = {coefficients['a0']} + ({coefficients['a1']}x)+ ({coefficients['a2']}x^2) + ({coefficients['a3']}x^3)" + print(f"\tПолучим систему уравнений:\n" + f"\t\t{coefficients['N']}a0 + {coefficients['SX']}a1 + {coefficients['SXX']}a2 + {coefficients['SXXX']}a3 = {coefficients['SY']}\n" + f"\t\t{coefficients['SX']}a0 + {coefficients['SXX']}a1 + {coefficients['SXXX']}a2 + {coefficients['SXXXX']}a3= {coefficients['SXY']}\n" + f"\t\t{coefficients['SXX']}a0 + {coefficients['SXXX']}a1 + {coefficients['SXXXX']}a2 + {coefficients['SXXXXX']}a3= {coefficients['SXXY']}\n" + f"\t\t{coefficients['SXXX']}a0 + {coefficients['SXXXX']}a1 + {coefficients['SXXXXX']}a2 + {coefficients['SXXXXXX']}a3= {coefficients['SXXXY']}\n") + print(f"\tНайденные коэффициенты:\n" + f"\t\ta0 = {coefficients['a0']}\n" + f"\t\ta1 = {coefficients['a1']}\n" + f"\t\ta2 = {coefficients['a2']}\n" + f"\t\ta3 = {coefficients['a3']}\n") + self.__printCoefficients(coefficients, function) + return function, {'a0': coefficients['a0'], 'a1': coefficients['a1'], 'a2': coefficients['a2'], + 'a3': coefficients['a3']}, \ + coefficients['S'], coefficients['SD'] + + # Экспоненциальная + def __calculateExponentFunctionCoefficient(self): + y_arr = self.getArrayY() + self.setArrayY([log(y) for y in y_arr]) + A, B, a, b = self.calculateLinearForOtherFunctions() + self.setArrayY(y_arr) + self._setPX(self._calculateExponentValues(a, b)) + self._setEpsilon(self._calculateEpsilon()) + S = self._deviationMeasure() + SD = self._standardDeviation() + return {'A': A, 'B': B, 'a': a, + 'b': b, 'S': S, 'SD': SD} + + def exponentFunction(self): + print('\t\t\tЭкспоненциальная функция') + coefficients = self.__calculateExponentFunctionCoefficient() + function = f"P4(x) = {coefficients['a']}*e({coefficients['b']}*x)" + self.__printCoefficients(coefficients, function) + return function, {'a': coefficients['a'], 'b': coefficients['b']}, \ + coefficients['S'], coefficients['SD'] + + # Cтепенная + def __calculateExponentialFunctionCoefficient(self): + y_arr, x_arr = self.getArrayY(), self.getArrayX() + self.setArrayY([log(y) for y in y_arr]) + self.setArrayX([log(x) for x in x_arr]) + A, B, a, b = self.calculateLinearForOtherFunctions() + self.setArrayY(y_arr) + self.setArrayX(x_arr) + self._setPX(self._calculateExponentialValues(a, b)) + self._setEpsilon(self._calculateEpsilon()) + S = self._deviationMeasure() + SD = self._standardDeviation() + return {'A': A, 'B': B, 'a': a, + 'b': b, 'S': S, 'SD': SD} + + def exponentialFunction(self): + print('\t\t\tСтепенная функция') + coefficients = self.__calculateExponentialFunctionCoefficient() + function = f"P5(x) = {coefficients['a']}*x^({coefficients['b']})" + self.__printCoefficients(coefficients, function) + return function, {'a': coefficients['a'], 'b': coefficients['b']}, \ + coefficients['S'], coefficients['SD'] + + # Логарифмическая + def __calculateLogarithmFunctionCoefficient(self): + x_arr = self.getArrayX() + self.setArrayX([log(x) for x in x_arr]) + coefficient = self.__calculateLinearFunctionCoefficient() + A, B = coefficient['a'], coefficient['b'] + a, b = A, B + self.setArrayX(x_arr) + self._setPX(self._calculateLogarithmValues(a, b)) + self._setEpsilon(self._calculateEpsilon()) + S = self._deviationMeasure() + SD = self._standardDeviation() + return {'A': A, 'B': B, 'a': a, + 'b': b, 'S': S, 'SD': SD} + + def logarithmFunction(self): + print('\t\t\tЛогарифмическая функция') + coefficients = self.__calculateLogarithmFunctionCoefficient() + function = f"P6(x) = {coefficients['a']}*ln(x)+{coefficients['b']}" + self.__printCoefficients(coefficients, function) + return function, {'a': coefficients['a'], 'b': coefficients['b']}, \ + coefficients['S'], coefficients['SD'] + + def __printCoefficients(self, coefficients, function): + for key, val in coefficients.items(): + print(f" {key} = {val}.") + print(f"Аппроксимирующая функция имеет вид {function}") + self._printTable() + print(f"Мера отклонения S = {coefficients['S']}") + print(f"Среднеквадратическое отклонение SD = {coefficients['SD']}") + + def calculateLinearForOtherFunctions(self): + coefficient = self.__calculateLinearFunctionCoefficient() + A, B = coefficient['b'], coefficient['a'] + a, b = math.exp(A), B + return A, B, a, b + diff --git "a/\320\2403265-69/saveleva_409492/lab4/Exceptions/IncorrectValueException.py" "b/\320\2403265-69/saveleva_409492/lab4/Exceptions/IncorrectValueException.py" new file mode 100644 index 0000000..afbdb08 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab4/Exceptions/IncorrectValueException.py" @@ -0,0 +1,4 @@ +class IncorrectValueException(Exception): + + def __init__(self, message): + self.message = message \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab4/Exceptions/__pycache__/IncorrectValueException.cpython-312.pyc" "b/\320\2403265-69/saveleva_409492/lab4/Exceptions/__pycache__/IncorrectValueException.cpython-312.pyc" new file mode 100644 index 0000000..3c44d3c Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab4/Exceptions/__pycache__/IncorrectValueException.cpython-312.pyc" differ diff --git "a/\320\2403265-69/saveleva_409492/lab4/Terminal.py" "b/\320\2403265-69/saveleva_409492/lab4/Terminal.py" new file mode 100644 index 0000000..e493ae0 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab4/Terminal.py" @@ -0,0 +1,146 @@ +from numpy import exp, log + +import numpy as np + +from ApproximationFunctions import ApproximationFunctions +from Validation.Validator import Validator +from Exceptions.IncorrectValueException import IncorrectValueException +import matplotlib.pyplot as plt + +INTERVAL_FOR_GRAPHIC_X = 1 + + +class Terminal: + def __init__(self): + self.__isFromFile: bool = False + + def isFile(self, mode) -> bool: + if mode == 0: + print("Выберите формат ввода(c клавиатуры - k или из файла - f):") + else: + print("Хотите записать результаты в файл?(нет - k или да - f):") + is_file = input() + if is_file.__eq__('k'): + return False + elif is_file.__eq__('f'): + return True + else: + return self.isFile(mode) + + def refresh(self): + self.__isFromFile = False + + def work(self): + try: + print('\t\t\tАппроксимация функции методом наименьших квадратов') + self.__isFromFile = self.isFile(0) + if self.__isFromFile: + x_array, y_array = self.enterArraysFromFile() + else: + x_array, y_array = self.enterArraysFromKeyboard() + min_x, max_x = min(x_array), max(x_array) + x = np.arange(min_x, max_x, 0.1) + self.__isFromFile = self.isFile(1) + results = list() + approximation = ApproximationFunctions(x_array, y_array) + results.append(approximation.linearFunction()) + results.append(approximation.polynomialSecondFunction()) + results.append(approximation.polynomialThirdFunction()) + results.append(approximation.exponentialFunction()) + results.append(approximation.exponentFunction()) + results.append(approximation.logarithmFunction()) + self.printTableOfCompare(results) + index = self.minSD(results) + print(f'Наилучшее приближение :\n' + f'1.Аппроксимирующая функция: {results[index][0]}\n' + f'2. Коэффициенты:{results[index][1]}\n' + f'3. Среднеквадратичное отклонение: {results[index][3]}') + + plt.scatter(x_array, y_array, color='red', s=40, marker='o', label='f(x)') + plt.plot(x, [results[0][1]['a'] * x + results[0][1]['b'] for x in x], color='green', label=results[0][0]) + plt.plot(x, + [results[1][1]['a0'] + x * results[1][1]['a1'] + results[1][1]['a2'] * x ** 2 for x in x], + '--', + color='blue', label=results[1][0]) + plt.plot(x, + [results[2][1]['a0'] + x * results[2][1]['a1'] + results[2][1]['a2'] * x ** 2 + results[2][1][ + 'a3'] * x ** 3 for x in x], '--', + color='black', label=results[2][0]) + plt.plot(x, + [results[5][1]['a'] * log(x) + results[5][1]['b'] for x in x], '--', + color='purple', label=results[5][0]) + plt.legend() + plt.grid() + plt.figure(2) + plt.plot(x, [results[3][1]['a'] * x ** results[3][1]['b'] for x in x], '--', + color='pink', label=results[3][0]) + plt.scatter(x_array, y_array, color='red', s=40, marker='o', label='f(x)') + plt.legend() + plt.grid() + plt.figure(3) + plt.plot(x, + [results[4][1]['a'] * exp(x * results[4][1]['b']) for x in x], '--', + color='orange', label=results[4][0]) + plt.scatter(x_array, y_array, color='red', s=40, marker='o', label='f(x)') + plt.legend() + plt.grid() + except IncorrectValueException as e: + print(e.message) + return + except ValueError as e: + print(e.message) + return + except RuntimeWarning: + pass + finally: + plt.show() + + def enterArray(self, variable) -> object: + try: + print(f'Введите значения {variable} (через ;):') + arr = [Validator.validateNumber(x) for x in input().split(';')] + Validator.validateArraySize(arr) + return arr + except IncorrectValueException as e: + print(e.message) + return self.enterArray(variable) + + def enterArraysFromKeyboard(self): + x_array = self.enterArray('x') + y_array = self.enterArray('y') + Validator.validateEqualityLengths(x_array, y_array) + return x_array, y_array + + def enterArraysFromFile(self): + try: + f = open(input('Введите путь к файлу:'), 'r') + x_array = [Validator.validateNumber(x) for x in f.readline().split(';')] + Validator.validateArraySize(x_array) + y_array = [Validator.validateNumber(x) for x in f.readline().split(';')] + Validator.validateArraySize(y_array) + Validator.validateEqualityLengths(x_array, y_array) + return x_array, y_array + except IncorrectValueException as e: + print(e.message) + return self.enterArraysFromFile() + except FileNotFoundError as e: + print(e.strerror) + return self.enterArraysFromFile() + + def printTableOfCompare(self, results): + print('\t\t\tРезультаты ') + print('| Вид функции | Коэффициенты ' + '| Мера отклонения | Среднеквадратичное отклонение |') + for i in range(len(results)): + print(f'| {results[i][0]} | ', end='') + for key, val in results[i][1].items(): + print(f'{key} = {val}|', end='') + print(f"| {results[i][2]} | {results[i][3]} |") + + def minSD(self, results): + min = results[0][3] + index = 0 + for i in range(len(results)): + if results[i][3] < min: + index = i + return index \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab4/Validation/Validator.py" "b/\320\2403265-69/saveleva_409492/lab4/Validation/Validator.py" new file mode 100644 index 0000000..eb78e7b --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab4/Validation/Validator.py" @@ -0,0 +1,28 @@ +from Exceptions.IncorrectValueException import IncorrectValueException + +AMOUNT_OF_INPUT_ARRAYS = 2 +MIN_DOTS = 8 +MAX_DOTS = 12 + + +class Validator: + + @staticmethod + def validateNumber(number: str): + try: + number = float(number) + return number + except ValueError: + raise IncorrectValueException(f'Необходимо ввести число.') + + + @staticmethod + def validateArraySize(arr): + length = len(arr) + if MIN_DOTS > length or length > MAX_DOTS: + raise IncorrectValueException('Размер массива должен находится в пределах [8;12].') + + @staticmethod + def validateEqualityLengths(arr_1, arr_2): + if len(arr_1) != len(arr_2): + raise IncorrectValueException('Длины массивов не равны.') \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab4/Validation/__pycache__/Validator.cpython-312.pyc" "b/\320\2403265-69/saveleva_409492/lab4/Validation/__pycache__/Validator.cpython-312.pyc" new file mode 100644 index 0000000..3922386 Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab4/Validation/__pycache__/Validator.cpython-312.pyc" differ diff --git "a/\320\2403265-69/saveleva_409492/lab4/files/test.txt" "b/\320\2403265-69/saveleva_409492/lab4/files/test.txt" new file mode 100644 index 0000000..f5eb7ff --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab4/files/test.txt" @@ -0,0 +1,2 @@ +1;3;5;7;9;11;13;15 +2.5;4;6.5;10;9;10.1;10.05;13.2 \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab4/main.py" "b/\320\2403265-69/saveleva_409492/lab4/main.py" new file mode 100644 index 0000000..527b9ec --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab4/main.py" @@ -0,0 +1,13 @@ +import warnings + +from Terminal import Terminal + +if __name__ == "__main__": + warnings.filterwarnings('ignore') + terminal = Terminal() + while True: + terminal.refresh() + terminal.work() + print("Хотите продолжить работу с программой? y/n") + if not input().__eq__('y'): + break \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab4/\320\262\321\213\321\207\320\274\320\260\321\2024\320\276\321\202\321\207\320\265\321\202.pdf" "b/\320\2403265-69/saveleva_409492/lab4/\320\262\321\213\321\207\320\274\320\260\321\2024\320\276\321\202\321\207\320\265\321\202.pdf" new file mode 100644 index 0000000..7d0373c Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab4/\320\262\321\213\321\207\320\274\320\260\321\2024\320\276\321\202\321\207\320\265\321\202.pdf" differ diff --git "a/\320\2403265-69/saveleva_409492/lab5/Main.py" "b/\320\2403265-69/saveleva_409492/lab5/Main.py" new file mode 100644 index 0000000..8659824 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab5/Main.py" @@ -0,0 +1,568 @@ +import math +import matplotlib.pyplot as plt +import numpy as np + + +def read_input_data(): + """Основная функция для выбора способа ввода данных""" + while True: + print("1. Ручной ввод") + print("2. Загрузка из файла") + print("3. Генерация по математической функции") + + while True: + try: + choice = int(input("Выберите вариант (1-3): ")) + if 1 <= choice <= 3: + break + print("Ошибка: Введите число от 1 до 3") + except ValueError: + print("Ошибка: Введите целое число") + + if choice == 1: + return input_from_keyboard() + elif choice == 2: + return input_from_file_with_retry() + else: + return generate_data_from_function_with_retry() + + +def input_from_keyboard(): + """Ввод данных с клавиатуры""" + while True: + try: + point_count = int(input("Введите количество точек: ")) + if point_count > 0: + break + print("Ошибка: Количество точек должно быть положительным") + except ValueError: + print("Ошибка: Введите целое число") + + x_values = [] + y_values = [] + print(f"Введите {point_count} точек в формате x y:") + + for i in range(point_count): + while True: + try: + data = input(f"Точка {i + 1}: ").strip() + if not data: + print("Ошибка: Пустой ввод") + continue + + x, y = map(float, data.split()) + x_values.append(x) + y_values.append(y) + break + except ValueError: + print("Ошибка: Точка должна состоять из двух чисел. Попробуйте снова") + except Exception: + print("Ошибка ввода. Попробуйте снова") + + while len(set(x_values)) != len(x_values): + print("Ошибка: Узлы интерполяции не должны совпадать. Введите точки заново") + x_values.clear() + y_values.clear() + for i in range(point_count): + while True: + try: + data = input(f"Точка {i + 1}: ").strip() + if not data: + print("Ошибка: Пустой ввод") + continue + + x, y = map(float, data.split()) + x_values.append(x) + y_values.append(y) + break + except ValueError: + print("Ошибка: Точка должна состоять из двух чисел. Попробуйте снова") + except Exception: + print("Ошибка ввода. Попробуйте снова") + + return x_values, y_values + + +def input_from_file_with_retry(): + """Чтение данных из файла с обработкой ошибок""" + while True: + filename = input("Введите имя файла: ") + try: + x_data, y_data = read_data_from_file(filename) + + if len(set(x_data)) != len(x_data): + print("Ошибка: Узлы интерполяции не должны совпадать") + continue + + return x_data, y_data + except FileNotFoundError: + print("Ошибка: Файл не найден. Проверьте имя файла и попробуйте снова") + except ValueError as e: + print(f"Ошибка в файле: {e}. Попробуйте другой файл") + except Exception as e: + print(f"Ошибка: {e}. Попробуйте другой файл") + + +def read_data_from_file(filename): + """Чтение данных из файла""" + x_data = [] + y_data = [] + with open(filename, 'r') as file: + for line_number, content in enumerate(file, 1): + content = content.strip() + if not content: + continue + + try: + x_val, y_val = map(float, content.split()) + x_data.append(x_val) + y_data.append(y_val) + except ValueError: + raise ValueError(f"Некорректные данные в строке {line_number}: '{content}'") + + if not x_data: + raise ValueError("Файл пуст или содержит только пустые строки") + + return x_data, y_data + + +def generate_data_from_function_with_retry(): + """Генерация данных на основе математической функции""" + while True: + function_name = input("Введите имя функции (sin/cos/exp/log): ").lower() + if function_name in ["sin", "cos", "exp", "log"]: + break + print("Ошибка: Несуществующая функция. Доступные: sin, cos, exp, log") + + while True: + try: + start_point = float(input("Введите начало отрезка: ")) + break + except ValueError: + print("Ошибка: Начало должно быть числом") + + while True: + try: + end_point = float(input("Введите конец отрезка: ")) + if end_point > start_point: + break + print("Ошибка: Конец должен быть больше начала") + except ValueError: + print("Ошибка: Конец должен быть числом") + + while True: + try: + point_count = int(input("Введите количество точек: ")) + if point_count > 1: + break + print("Ошибка: Количество точек должно быть больше 1") + except ValueError: + print("Ошибка: Введите целое число") + + while True: + try: + x_vals, y_vals = generate_data_from_function(function_name, start_point, end_point, point_count) + return x_vals, y_vals + except ValueError as e: + print(f"Ошибка: {e}") + if function_name == "log": + print("Для функции log все x должны быть > 0") + while True: + try: + start_point = float(input("Введите новое начало отрезка (>0): ")) + if start_point > 0: + break + print("Ошибка: Начало должно быть > 0") + except ValueError: + print("Ошибка: Начало должно быть числом") + + while True: + try: + end_point = float(input("Введите новый конец отрезка (> начала): ")) + if end_point > start_point: + break + print("Ошибка: Конец должен быть больше начала") + except ValueError: + print("Ошибка: Конец должен быть числом") + + +def generate_data_from_function(func_name, start_val, end_val, point_count): + """Генерация данных на основе выбранной функции""" + function_map = { + 'sin': math.sin, + 'cos': math.cos, + 'exp': math.exp, + 'log': lambda x: math.log(x) if x > 0 else None, + } + + x_vals = [] + y_vals = [] + step_size = (end_val - start_val) / (point_count - 1) if point_count > 1 else 0 + + for i in range(point_count): + x = start_val + i * step_size + y = function_map[func_name](x) + if y is None: + raise ValueError(f"Недопустимое значение x={x} для функции {func_name}") + x_vals.append(x) + y_vals.append(y) + + return x_vals, y_vals + + +def main(): + print("Программа интерполяции функций") + print("-----------------------------") + + while True: + try: + x_data, y_data = read_input_data() + interpolator = InterpolationSolver(x_data, y_data) + + while True: + try: + target_x = float(input("\nВведите аргумент для интерполяции: ")) + break + except ValueError: + print("Ошибка: Аргумент должен быть числом") + + print("\nТаблица конечных разностей:") + diff_table = interpolator.compute_finite_differences() + for row in diff_table: + print(" ".join(map(lambda val: f"{val:.4f}", row))) + + print("\nРезультаты интерполяции:") + methods = [ + ("Лагранж", interpolator.interpolate_lagrange(target_x)), + ("Ньютон (разделённые разности)", interpolator.interpolate_newton_divided(target_x)), + ("Ньютон (конечные разности)", interpolator.interpolate_newton_finite(target_x)), + ("Стирлинг", interpolator.interpolate_stirling(target_x)), + ("Бессель", interpolator.interpolate_bessel(target_x)) + ] + + for method_name, result_value in methods: + if result_value is not None: + print(f"{method_name}: {result_value:.6f}") + else: + print(f"{method_name}: не применимо для данных узлов") + + interpolator.plot_interpolation(target_x=target_x) + + while True: + choice = input("\nХотите выполнить еще одну интерполяцию? (y/n): ").lower() + if choice in ['y', 'n']: + break + print("Ошибка: Введите 'y' или 'n'") + + if choice == 'n': + print("Завершение программы.") + break + + except KeyboardInterrupt: + print("\nПрограмма прервана пользователем") + break + except Exception as e: + print(f"\nПроизошла ошибка: {e}") + raise e + print("Попробуйте снова.\n") + + +class InterpolationSolver: + def __init__(self, x_nodes, y_values): + self.x_nodes = x_nodes + self.y_values = y_values + + def interpolate_lagrange(self, x_target): + """Интерполяция методом Лагранжа""" + result = 0.0 + n = len(self.x_nodes) + + for i in range(n): + term = self.y_values[i] + for j in range(n): + if j != i: + term *= (x_target - self.x_nodes[j]) / (self.x_nodes[i] - self.x_nodes[j]) + result += term + + return result + + def interpolate_newton_divided(self, x_target): + """Интерполяция методом Ньютона с разделенными разностями""" + n = len(self.x_nodes) + div_diff_table = self.compute_divided_differences() + + result = div_diff_table[0][n - 1] + for i in range(n - 2, -1, -1): + result = result * (x_target - self.x_nodes[i]) + div_diff_table[0][i] + + return result + + def interpolate_newton_finite(self, x_target): + """Интерполяция методом Ньютона с конечными разностями""" + n = len(self.x_nodes) + if n < 2: + return None + + step = abs(self.x_nodes[1] - self.x_nodes[0]) + + for i in range(1, n - 1): + if abs((self.x_nodes[i + 1] - self.x_nodes[i]) - step) > 1e-10: + return None + + diff_table = self.compute_finite_differences() + result = self.y_values[0] + + for i in range(1, n): + coefficient = diff_table[0][i] / math.factorial(i) + t_param = (x_target - self.x_nodes[0]) / step + term = 1 + for k in range(i): + term *= (t_param - k) + result += coefficient * term + + return result + + def compute_divided_differences(self): + """Вычисление таблицы разделенных разностей""" + n = len(self.x_nodes) + div_diff = [[0.0] * n for _ in range(n)] + + for i in range(n): + div_diff[i][0] = self.y_values[i] + + for j in range(1, n): + for i in range(n - j): + div_diff[i][j] = (div_diff[i + 1][j - 1] - div_diff[i][j - 1]) / (self.x_nodes[i + j] - self.x_nodes[i]) + + return div_diff + + def compute_finite_differences(self): + """Вычисление таблицы конечных разностей""" + n = len(self.y_values) + fin_diff = [[0.0] * n for _ in range(n)] + + for i in range(n): + fin_diff[i][0] = self.y_values[i] + + for j in range(1, n): + for i in range(n - j): + fin_diff[i][j] = fin_diff[i + 1][j - 1] - fin_diff[i][j - 1] + + return fin_diff + + def interpolate_stirling(self, x_target): + """Интерполяция по формуле Стирлинга""" + n = len(self.x_nodes) + if n % 2 == 0: # Требуется нечетное количество точек + return None + + # Проверка равномерности шага + step = abs(self.x_nodes[1] - self.x_nodes[0]) + for i in range(1, n - 1): + if abs((self.x_nodes[i + 1] - self.x_nodes[i]) - step) > 1e-10: + return None + + center_idx = n // 2 # Центральный узел + t_param = (x_target - self.x_nodes[center_idx]) / step + diff_table = self.compute_finite_differences() + + result = self.y_values[center_idx] + + # Первый член: t * (Δy0 + Δy_{-1})/2 + if center_idx >= 1 and center_idx < n - 1: + if center_idx < len(diff_table) and len(diff_table[center_idx]) > 1 and \ + center_idx - 1 < len(diff_table) and len(diff_table[center_idx - 1]) > 1: + result += t_param * (diff_table[center_idx][1] + diff_table[center_idx - 1][1]) / 2 + + # Основной цикл по i + for i in range(1, center_idx + 1): + # Проверка доступности индексов для нечетных разностей + row1 = center_idx - i + row2 = center_idx - i - 1 + order = 2 * i - 1 + + if row1 < 0 or row1 >= len(diff_table) or order >= len(diff_table[row1]) or \ + row2 < 0 or row2 >= len(diff_table) or order >= len(diff_table[row2]): + break + + delta_val = (diff_table[row1][order] + diff_table[row2][order]) / 2 + term = delta_val + + # Вычисление произведения (t^2 - k^2) + for k in range(1, i): + term *= (t_param ** 2 - k ** 2) + + term *= t_param # Дополнительный множитель t + term /= math.factorial(2 * i - 1) + result += term + + # Проверка доступности индексов для четных разностей + row_even = center_idx - i - 1 + order_even = 2 * i + + if i < center_idx: # Для четных разностей (кроме последней итерации) + if row_even < 0 or row_even >= len(diff_table) or order_even >= len(diff_table[row_even]): + break + + term_even = diff_table[row_even][order_even] + for k in range(1, i + 1): + term_even *= (t_param ** 2 - k ** 2) + + term_even /= math.factorial(2 * i) + result += term_even + else: + break + + return result + + def find_central_node_index(self, x_target): + """Поиск центрального узла для интерполяции""" + n = len(self.x_nodes) + mid_idx = n // 2 + if x_target < self.x_nodes[mid_idx]: + while mid_idx > 0 and x_target < self.x_nodes[mid_idx - 1]: + mid_idx -= 1 + else: + while mid_idx < n - 1 and x_target > self.x_nodes[mid_idx + 1]: + mid_idx += 1 + return mid_idx + + def interpolate_bessel(self, x_target): + """Интерполяция по формуле Бесселя""" + + n = len(self.x_nodes) + + # Метод Бесселя требует чётное количество узлов + if n % 2 != 0: + return None + + # Проверка, что шаг равномерный + step = self.x_nodes[1] - self.x_nodes[0] + for i in range(1, n - 1): + if abs((self.x_nodes[i + 1] - self.x_nodes[i]) - step) > 1e-10: + return None + + # Найдём центральный индекс (левая из двух центральных точек) + center_idx = self.find_central_interval_index(x_target) + center_idx = max(1, min(center_idx, n - 3)) + + # Центральная точка x + center_x = (self.x_nodes[center_idx] + self.x_nodes[center_idx + 1]) / 2 + t_param = (x_target - center_x) / step + + # Таблица конечных разностей + diff_table = self.compute_finite_differences() + + # Начальное приближение: среднее значение в центре + result = (self.y_values[center_idx] + self.y_values[center_idx + 1]) / 2 + + # Добавляем первую разность первого порядка (нечётная) + result += t_param * diff_table[center_idx][1] + + max_order = len(diff_table[0]) - 1 # Максимальный порядок разности + + for i in range(1, n // 2): + even_order = 2 * i + odd_order = 2 * i + 1 + + # Проверка на выход за границы таблицы разностей + if center_idx - i < 0 or center_idx - i + 1 >= n: + break + if even_order >= max_order: + break + + # Чётные разности: центральные + delta_even = diff_table[center_idx - i][even_order] + product_even = 1 + for k in range(1, i + 1): + product_even *= (t_param ** 2 - (k - 0.5) ** 2) + term_even = delta_even * product_even / math.factorial(even_order) + result += term_even + + # Проверка наличия нечётной разности + if odd_order >= max_order: + break + + # Нечётные разности: смещены на +1 + delta_odd = diff_table[center_idx - i + 1][odd_order] + product_odd = t_param + for k in range(1, i + 1): + product_odd *= (t_param ** 2 - k ** 2) + term_odd = delta_odd * product_odd / math.factorial(odd_order) + result += term_odd + + return result + + def find_central_interval_index(self, x_target): + """Поиск центрального интервала""" + for i in range(len(self.x_nodes) - 1): + if self.x_nodes[i] <= x_target <= self.x_nodes[i + 1]: + return i + return len(self.x_nodes) // 2 - 1 + + def plot_interpolation(self, method='all', target_x=None): + """Визуализация результатов интерполяции""" + plt.figure(figsize=(12, 8)) # Создание холста 12x8 дюймов + x_plot = np.linspace(min(self.x_nodes), max(self.x_nodes), 500) # 500 точек для плавного графика + + plt.scatter(self.x_nodes, self.y_values, color='black', s=100, label='Узлы интерполяции', zorder=5) + + + if method in ['all', 'lagrange']: + y_lagrange = [self.interpolate_lagrange(x) for x in x_plot] + plt.plot(x_plot, y_lagrange, color='#FF4500', label='Метод Лагранжа', linewidth=2) # Оранжево-красный + + if method in ['all', 'newtone_div']: + y_newton_div = [self.interpolate_newton_divided(x) for x in x_plot] + plt.plot(x_plot, y_newton_div, '--', color='#1E90FF', label='Ньютон (раздел. разности)', + linewidth=2) # Ярко-синий + + if method in ['all', 'newton_fin'] and len(self.x_nodes) > 1: + step = abs(self.x_nodes[1] - self.x_nodes[0]) + if all(abs((self.x_nodes[i + 1] - self.x_nodes[i]) - step) < 1e-10 for i in range(len(self.x_nodes) - 1)): + y_newton_fin = [ + self.interpolate_newton_finite(x) if self.interpolate_newton_finite(x) is not None else np.nan for x + in x_plot] + plt.plot(x_plot, y_newton_fin, ':', color='#32CD32', label='Ньютон (кон. разности)', + linewidth=2) # Лаймовый + + if method in ['all', 'stirling'] and len(self.x_nodes) > 1: + step = abs(self.x_nodes[1] - self.x_nodes[0]) + if all(abs((self.x_nodes[i + 1] - self.x_nodes[i]) - step) < 1e-10 for i in + range(len(self.x_nodes) - 1)) and len(self.x_nodes) % 2 != 0:# Для Стирлинга (нечетное) + y_stirling = [self.interpolate_stirling(x) if self.interpolate_stirling(x) is not None else np.nan for x + in x_plot] + plt.plot(x_plot, y_stirling, '-.', color='#9370DB', label='Стирлинг', linewidth=2) # Фиолетовый + + if method in ['all', 'bessel'] and len(self.x_nodes) > 1: + step = abs(self.x_nodes[1] - self.x_nodes[0]) + if all(abs((self.x_nodes[i + 1] - self.x_nodes[i]) - step) < 1e-10 for i in + range(len(self.x_nodes) - 1)) and len(self.x_nodes) % 2 == 0: # Для Бесселя (четное) + y_bessel = [self.interpolate_bessel(x) if self.interpolate_bessel(x) is not None else np.nan for x in + x_plot] + plt.plot(x_plot, y_bessel, ':', color='#FF69B4', label='Бессель', linewidth=2) # Розовый + + if target_x is not None: + plt.axvline(x=target_x, color='red', linestyle=':', alpha=0.5, label=f'x = {target_x}') + methods = [ + ('lagrange', self.interpolate_lagrange(target_x), '#FF4500'), # Оранжево-красный + ('newtone_div', self.interpolate_newton_divided(target_x), '#1E90FF'), # Ярко-синий + ('newton_fin', self.interpolate_newton_finite(target_x), '#32CD32'), # Лаймовый + ('stirling', self.interpolate_stirling(target_x), '#9370DB'), # Фиолетовый + ('bessel', self.interpolate_bessel(target_x), '#FF69B4') # Розовый + ] + + for method_name, value, color in methods: + if method in ['all', method_name] and value is not None: + plt.scatter([target_x], [value], color=color, s=100, zorder=5, edgecolors='black') # Отображение точек на графике + + plt.title('Сравнение методов интерполяции') + plt.xlabel('x') + plt.ylabel('y') + plt.legend() + plt.grid(True) + plt.show() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab5/test1.txt" "b/\320\2403265-69/saveleva_409492/lab5/test1.txt" new file mode 100644 index 0000000..86e04dc --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab5/test1.txt" @@ -0,0 +1,10 @@ +0 0 +1 3 +2 8 +3 15 +4 24 +5 35 +6 48 +7 63 +8 80 +9 99 \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab5/test2.txt" "b/\320\2403265-69/saveleva_409492/lab5/test2.txt" new file mode 100644 index 0000000..9314975 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab5/test2.txt" @@ -0,0 +1,5 @@ +1 0.0 +2 0.5 +3 1.0 +4 1.5 +5 2.0 \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab5/test3.txt" "b/\320\2403265-69/saveleva_409492/lab5/test3.txt" new file mode 100644 index 0000000..91143c0 --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab5/test3.txt" @@ -0,0 +1,28 @@ +1 0.0 +2 2.121320343559643 +3 4.618802153517006 +4 7.5 +5 10.73312629199899 +6 14.288690166235206 +7 18.142294704442907 +8 22.27386360737625 +9 26.666666666666668 +10 31.306548835666955 +11 36.18136134933164 +12 41.280544247058245 +13 46.59481648291925 +14 52.11594217292276 +15 57.83655130336409 +16 63.75 +17 69.85026001046388 +18 76.13183010775163 +19 82.58966419340223 +20 89.21911230224161 +21 96.01587170383665 +22 102.97594599975983 +23 110.09561062213547 +24 117.37138350836062 +25 124.8 +26 132.3783912182742 +27 140.1036653233492 +28 147.97309118311247 \ No newline at end of file diff --git "a/\320\2403265-69/saveleva_409492/lab5/\320\262\321\213\321\207\320\274\320\260\321\2025\320\276\321\202\321\207\320\265\321\202.pdf" "b/\320\2403265-69/saveleva_409492/lab5/\320\262\321\213\321\207\320\274\320\260\321\2025\320\276\321\202\321\207\320\265\321\202.pdf" new file mode 100644 index 0000000..0addb32 Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab5/\320\262\321\213\321\207\320\274\320\260\321\2025\320\276\321\202\321\207\320\265\321\202.pdf" differ diff --git "a/\320\2403265-69/saveleva_409492/lab6/6 \320\262\321\213\321\207\320\274\320\260\321\202.pdf" "b/\320\2403265-69/saveleva_409492/lab6/6 \320\262\321\213\321\207\320\274\320\260\321\202.pdf" new file mode 100644 index 0000000..c3e597f Binary files /dev/null and "b/\320\2403265-69/saveleva_409492/lab6/6 \320\262\321\213\321\207\320\274\320\260\321\202.pdf" differ diff --git "a/\320\2403265-69/saveleva_409492/lab6/Main.py" "b/\320\2403265-69/saveleva_409492/lab6/Main.py" new file mode 100644 index 0000000..84c07ba --- /dev/null +++ "b/\320\2403265-69/saveleva_409492/lab6/Main.py" @@ -0,0 +1,447 @@ +import warnings +import matplotlib.pyplot as plt +import numpy as np +import numexpr as ne + + +class IncorrectValueException(Exception): + def __init__(self, message): + self.message = message + + +EQUATIONS = { + 1: "(x-y)**2", + 2: "(x-y)**2+y**2", + 3: "y+(1+x)*y**2" +} + +ANSWERS = { + 1: "1/(c*exp(2*x) + 1/2) + x - 1", + 2: "x - c - sqrt(c**2 - x + c)", + 3: "-1/(c - x - x**2/2)" +} + +C = { + 1: "((y - x + 1)**2 - 1)/exp(-2*x)", + 2: "x - y - sqrt(y**2 - (x - y)**2)", + 3: "x + x**2/2 + 1/y" +} + +METHODS = [ + 'Одношаговый. Метод Эйлера', + 'Одношаговый. Метод Рунге-Кутта 4-го порядка', + 'Многошаговый. Метод Адамса' +] + + +def calculateFunction(xi, yi, function_number): + return float(ne.evaluate(EQUATIONS[function_number], local_dict={'x': xi, 'y': yi})) + + +def calculateC(x0, y0, function_number): + try: + return float(ne.evaluate(C[function_number], local_dict={'x': x0, 'y': y0})) + except Exception as e: + print(f"Ошибка вычисления константы C: {str(e)}") + return float('nan') + + +def calculateAnswer(x0, y0, xi, function_number): + try: + c_val = calculateC(x0, y0, function_number) + if np.isnan(c_val) or np.isinf(c_val): + return float('nan') + result = ne.evaluate(ANSWERS[function_number], local_dict={'x': xi, 'c': c_val}) + return float(result) + except Exception as e: + print(f"Ошибка вычисления аналитического решения: {str(e)}") + return float('nan') + + +class Validator: + @staticmethod + def validateNumber(number: str): + try: + return float(number) + except ValueError: + raise IncorrectValueException('Необходимо ввести число.') + + @staticmethod + def validateEpsilon(epsilon: str): + try: + epsilon = float(epsilon) + if epsilon >= 0: + return epsilon + raise IncorrectValueException('Точность должна быть >= 0.') + except ValueError: + raise IncorrectValueException('Точность должна быть числом.') + + @staticmethod + def validateFunctionNumber(): + try: + number = int(input()) + if 1 <= number <= len(EQUATIONS): + return number + raise IncorrectValueException('Недопустимый номер функции.') + except ValueError: + raise IncorrectValueException('Введите целое число.') + + @staticmethod + def validateMethodNumber(): + try: + number = int(input()) + if 1 <= number <= len(METHODS): + return number + raise IncorrectValueException('Недопустимый номер метода.') + except ValueError: + raise IncorrectValueException('Введите целое число.') + + @staticmethod + def validateBorders(border_left: float, border_right: float): + if border_left < border_right: + return True + raise IncorrectValueException('Левая граница должна быть меньше правой.') + + @staticmethod + def validateH(): + try: + h = float(input()) + if h > 0: + return h + raise IncorrectValueException('Шаг должен быть > 0.') + except ValueError: + raise IncorrectValueException('Шаг должен быть числом.') + + +class DifferentialEquations: + def __init__(self, x0, y0, xn, h, eps): + self.__x0 = x0 + self.__y0 = y0 + self.__xn = xn + self.__h = h + self.__eps = eps + self.__x_array = list(np.arange(x0, xn + 1e-10, h)) + + def getY0(self): return self.__y0 + + def getX0(self): return self.__x0 + + def getXN(self): return self.__xn + + def getH(self): return self.__h + + def getEps(self): return self.__eps + + def getArrayX(self): return self.__x_array + + def ruleRunge(self, I_h, I_h2, k, eps): + delta = abs(I_h2 - I_h) / (2 ** k - 1) + print(f'Погрешность: {delta} {"<" if delta < eps else ">="} {eps}') + return delta <= eps + + +class DifferentialEquationsMethods(DifferentialEquations): + # ================== МЕТОД ЭЙЛЕРА ================== + def methodEiler(self, function_number): + results = self._calculateEilerMethod(function_number) + self._printEilerTable(results) + return results + + def _calculateEilerMethod(self, function_number): + x_arr = self.getArrayX() + n = len(x_arr) + h = self.getH() + x0_val = self.getX0() + y0_val = self.getY0() + + iterations = [[0.0] * 5 for _ in range(n)] + + for i in range(n): + xi = x_arr[i] + iterations[i][0] = i + iterations[i][1] = round(xi, 5) + + if i == 0: + y = y0_val + else: + x_prev = x_arr[i - 1] + y_prev = iterations[i - 1][2] + f_prev = calculateFunction(x_prev, y_prev, function_number) + y = y_prev + h * f_prev + + iterations[i][2] = round(y, 5) + iterations[i][3] = round(calculateFunction(xi, y, function_number), 5) + iterations[i][4] = round(calculateAnswer(x0_val, y0_val, xi, function_number), 5) + + return iterations + + def _printEilerTable(self, iterations): + print('\n\t\tМетод Эйлера') + print('i | x | y | f(x,y) | Точное решение |') + for row in iterations: + exact = row[4] if not np.isnan(row[4]) else "N/A" + print(f"{int(row[0]):2} | {row[1]:7.5f} | {row[2]:7.5f} | {row[3]:9.5f} | {exact:14} |") + + # ================== МЕТОД РУНГЕ-КУТТА ================== + def methodRungeCutta4(self, function_number): + results = self._calculateRungeCutta4(function_number) + self._printRungeCuttaTable(results) + return results + + def _calculateRungeCutta4(self, function_number): + x_arr = self.getArrayX() + n = len(x_arr) + h = self.getH() + x0_val = self.getX0() + y0_val = self.getY0() + iterations = [[0.0] * 9 for _ in range(n)] + + for i in range(n): + xi = x_arr[i] + iterations[i][0] = i + iterations[i][1] = round(xi, 5) + + if i == 0: + y = y0_val + else: + y = iterations[i - 1][2] + iterations[i - 1][7] + + iterations[i][2] = round(y, 5) + + try: + k1 = h * calculateFunction(xi, y, function_number) + k2 = h * calculateFunction(xi + h / 2, y + k1 / 2, function_number) + k3 = h * calculateFunction(xi + h / 2, y + k2 / 2, function_number) + k4 = h * calculateFunction(xi + h, y + k3, function_number) + delta_y = (k1 + 2 * k2 + 2 * k3 + k4) / 6 + except Exception as e: + print(f"Ошибка расчета коэффициентов: {str(e)}") + k1 = k2 = k3 = k4 = delta_y = float('nan') + + iterations[i][3] = round(k1, 5) + iterations[i][4] = round(k2, 5) + iterations[i][5] = round(k3, 5) + iterations[i][6] = round(k4, 5) + iterations[i][7] = round(delta_y, 5) + iterations[i][8] = round(calculateAnswer(x0_val, y0_val, xi, function_number), 5) + + return iterations + + def _printRungeCuttaTable(self, iterations): + print('\n\t\tМетод Рунге-Кутта 4-го порядка') + print('i | x | y | k1 | k2 | k3 | k4 | delta | Точное решение |') + for row in iterations: + exact = row[8] if not np.isnan(row[8]) else "N/A" + print(f"{int(row[0]):2} | {row[1]:7.5f} | {row[2]:7.5f} | " + f"{row[3]:8.5f} | {row[4]:8.5f} | {row[5]:8.5f} | " + f"{row[6]:8.5f} | {row[7]:7.5f} | {exact:14} |") + + # ================== МЕТОД АДАМСА ================== + def methodAdams(self, function_number): + try: + runge_results = self._calculateRungeCutta4(function_number)[:4] + adams_results = self._calculateAdams(function_number, runge_results) + self._printAdamsTable(adams_results) + return adams_results + except Exception as e: + print(f"Ошибка в методе Адамса: {str(e)}") + return [] + + def _calculateAdams(self, function_number, runge_results): + x_arr = self.getArrayX() + n = len(x_arr) + h = self.getH() + x0_val = self.getX0() + y0_val = self.getY0() + iterations = [[0.0] * 8 for _ in range(n)] + + # Инициализация первых 4 точек из Рунге-Кутта + for i in range(4): + iterations[i][0] = i + iterations[i][1] = runge_results[i][1] + iterations[i][2] = runge_results[i][2] + iterations[i][3] = runge_results[i][3] / h if not np.isnan(runge_results[i][3]) else float('nan') + if i > 0: + iterations[i][4] = iterations[i][3] - iterations[i - 1][3] if not np.isnan(iterations[i][3]) else float( + 'nan') + if i > 1: + iterations[i][5] = iterations[i][3] - 2 * iterations[i - 1][3] + iterations[i - 2][3] if not np.isnan( + iterations[i][3]) else float('nan') + if i > 2: + iterations[i][6] = iterations[i][3] - 3 * iterations[i - 1][3] + 3 * iterations[i - 2][3] - \ + iterations[i - 3][3] if not np.isnan(iterations[i][3]) else float('nan') + iterations[i][7] = runge_results[i][8] + + # Прогноз для последующих точек + for i in range(3, n - 1): + try: + # Прогноз + y_pred = iterations[i][2] + h * ( + iterations[i][3] + + (h / 2) * iterations[i][4] + + (5 * h ** 2 / 12) * iterations[i][5] + + (3 * h ** 3 / 8) * iterations[i][6] + ) + + # Коррекция + x_next = x_arr[i + 1] + f_next = calculateFunction(x_next, y_pred, function_number) + + # Обновление конечных разностей + f_i = f_next + df_i = f_i - iterations[i][3] + d2f_i = f_i - 2 * iterations[i][3] + iterations[i - 1][3] + d3f_i = f_i - 3 * iterations[i][3] + 3 * iterations[i - 1][3] - iterations[i - 2][3] + + # Уточнение значения y + y_corr = iterations[i][2] + h * ( + f_i + + (h / 2) * df_i + + (5 * h ** 2 / 12) * d2f_i + + (3 * h ** 3 / 8) * d3f_i + ) + except Exception as e: + print(f"Ошибка расчета точки {i + 1}: {str(e)}") + y_corr = float('nan') + f_i = df_i = d2f_i = d3f_i = float('nan') + + # Сохранение результатов + iterations[i + 1][0] = i + 1 + iterations[i + 1][1] = round(x_next, 5) + iterations[i + 1][2] = round(y_corr, 5) + iterations[i + 1][3] = f_i + iterations[i + 1][4] = df_i + iterations[i + 1][5] = d2f_i + iterations[i + 1][6] = d3f_i + iterations[i + 1][7] = round(calculateAnswer(x0_val, y0_val, x_next, function_number), 5) + + return iterations + + def _printAdamsTable(self, iterations): + print('\n\t\tМногошаговый метод Адамса') + print('i | x | y | fi | Δfi | Δ²fi | Δ³fi | Точное решение |') + for row in iterations: + exact = row[7] if not np.isnan(row[7]) else "N/A" + print(f"{int(row[0]):2} | {row[1]:7.5f} | {row[2]:7.5f} | {row[3]:8.5f} | " + f"{row[4]:7.5f} | {row[5]:7.5f} | {row[6]:7.5f} | {exact:14} |") + + +class Terminal: + def work(self): + try: + print('\t\tЧисленное решение ОДУ') + function_number = self.enterFunctionNumber() + method_number = self.enterMethodNumber() + x0 = self.enterArgument('x0') + y0 = self.enterArgument('y0') + xn = self.enterInterval(x0) + h = self.enterH() + eps = self.enterEpsilon() + diff = DifferentialEquationsMethods(x0, y0, xn, h, eps) + + if method_number == 1: + full_results = diff.methodEiler(function_number) + elif method_number == 2: + full_results = diff.methodRungeCutta4(function_number) + else: + full_results = diff.methodAdams(function_number) + + # Построение графика + if full_results: + x_values = diff.getArrayX() + y_values = [row[2] for row in full_results] + + # Рассчет аналитического решения + exact_solution = [] + for x in x_values: + try: + exact = calculateAnswer(x0, y0, x, function_number) + exact_solution.append(exact if not np.isnan(exact) else None) + except: + exact_solution.append(None) + + plt.figure(figsize=(10, 6)) + plt.plot(x_values, y_values, 'b-', label='Численное решение') + + # Фильтрация валидных точек аналитического решения + valid_exact = [(x, y) for x, y in zip(x_values, exact_solution) if y is not None] + if valid_exact: + x_valid, y_valid = zip(*valid_exact) + plt.plot(x_valid, y_valid, 'r--', label='Точное решение') + + plt.xlabel('x') + plt.ylabel('y') + plt.title(f'Решение ОДУ ({METHODS[method_number - 1]})') + plt.legend() + plt.grid(True) + plt.show() + + except IncorrectValueException as e: + print(f"Ошибка: {e.message}") + except Exception as e: + print(f"Непредвиденная ошибка: {str(e)}") + + def enterInterval(self, x0): + try: + print('Введите границу интервала xn (x0 задано):') + xn = Validator.validateNumber(input()) + Validator.validateBorders(x0, xn) + return xn + except IncorrectValueException as e: + print(e.message) + return self.enterInterval(x0) + + def enterH(self): + try: + print('Введите шаг h:') + h = Validator.validateH() + return h + except IncorrectValueException as e: + print(e.message) + return self.enterH() + + def enterArgument(self, arg): + try: + print(f'Введите значение {arg}:') + return Validator.validateNumber(input()) + except IncorrectValueException as e: + print(e.message) + return self.enterArgument(arg) + + def enterFunctionNumber(self): + try: + print('Выберите функцию:') + for i in range(1, len(EQUATIONS) + 1): + print(f'{i}. y\' = {EQUATIONS[i]}') + return Validator.validateFunctionNumber() + except IncorrectValueException as e: + print(e.message) + return self.enterFunctionNumber() + + def enterMethodNumber(self): + try: + print('Выберите метод:') + for i, method in enumerate(METHODS, 1): + print(f'{i}. {method}') + return Validator.validateMethodNumber() + except IncorrectValueException as e: + print(e.message) + return self.enterMethodNumber() + + def enterEpsilon(self): + try: + print('Введите точность epsilon:') + return Validator.validateEpsilon(input()) + except IncorrectValueException as e: + print(e.message) + return self.enterEpsilon() + + +if __name__ == "__main__": + warnings.filterwarnings('ignore') + terminal = Terminal() + while True: + terminal.work() + print("Хотите продолжить? (y/n)") + if input().lower() != 'y': + break \ No newline at end of file