diff --git "a/\320\2403208/vasilev_366389/lab1/main.py" "b/\320\2403208/vasilev_366389/lab1/main.py" new file mode 100644 index 0000000..f5e1da0 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab1/main.py" @@ -0,0 +1,182 @@ +import csv +import numpy as np +import random + + +def generate_random_matrix(min_val=-25, max_val=25): + size = random.randint(2, 20) + matrix = [[random.uniform(min_val, max_val) for _ in range(size)] for _ in range(size)] + vector = [random.uniform(min_val, max_val) for _ in range(size)] + + for i in range(size): + matrix[i].append(vector[i]) + + return matrix + + +def read_matrix_from_file(filename): + matrix = [] + try: + with open(filename, newline='') as file: + if filename.endswith('.csv'): + reader = csv.reader(file) + rows = [row for row in reader] + else: + rows = [line.split() for line in file] + + for row in rows: + if not all(num.replace('.', '', 1).replace('-', '', 1).isdigit() for num in row): + raise ValueError("Ошибка: все элементы должны быть вещественными числами") + matrix.append([float(num) for num in row]) + return matrix + except FileNotFoundError: + print("Такой файл не найден. Попробуйте снова.") + return read_matrix_from_file(input()) + + +def validate_matrix(matrix): + n = len(matrix) + for row in matrix: + if len(row) != n + 1: + raise ValueError("Ошибка: каждая строка должна содержать n элементов матрицы и один элемент вектора") + + +def diagonal_dominance(matrix): + matrix = np.array(matrix) + n = len(matrix) + for i in range(n): + row_sum = sum(abs(matrix[i, j]) for j in range(n) if j != i) + if abs(matrix[i, i]) <= row_sum: + return False + return True + + +def rearrange_matrix(matrix, vector): + n = len(matrix) + matrix = np.array(matrix, dtype=float) + vector = np.array(vector, dtype=float) + for i in range(n): + max_index = max(range(i, n), + key=lambda k: abs(matrix[k, i]) - sum(abs(matrix[k, j]) for j in range(n) if j != i)) + if max_index != i: + matrix[[i, max_index]] = matrix[[max_index, i]] + vector[i], vector[max_index] = vector[max_index], vector[i] + return matrix, vector + + +def norm_matrix(matrix): + return max(sum(abs(element) for element in row) for row in matrix) + + +def iteration(matrix, x, vector): + n = len(matrix) + x_new = np.zeros(n) + for i in range(n): + sum_ax = sum(matrix[i][j] * x[j] for j in range(n) if j != i) + x_new[i] = (vector[i] - sum_ax) / matrix[i][i] + return x_new + + +def iterative_method(matrix, vector, precision, max_iterations=1000): + n = len(matrix) + x = np.zeros(n) + iterations = 0 + errors = [] + + while iterations <= max_iterations: + x_new = iteration(matrix, x, vector) + errors.append(np.abs(x_new - x)) + + iterations += 1 + + if np.max(np.abs(x_new - x)) < precision: + return x_new, iterations, errors + + x = x_new + + print("Метод не сошёлся за", max_iterations, "итераций") + return x, max_iterations, errors + + +def calculate_matrix(matrix, precision): + validate_matrix(matrix) + matrix = np.array(matrix, dtype=float) + vector = matrix[:, -1] + matrix = matrix[:, :-1] + + if not diagonal_dominance(matrix): + matrix, vector = rearrange_matrix(matrix, vector) + if not diagonal_dominance(matrix): + print("Ошибка: матрица не является диагонально доминирующей и не может быть преобразована") + return + + norm = norm_matrix(matrix) + x, iterations, errors = iterative_method(matrix, vector, precision) + + print("Матрица после преобразований: ") + for i in range(len(matrix)): + print([float('%.2f' % elem) for elem in matrix[i]]) + print("Вектор свободных членов после преобразований: ", vector) + print("Норма матрицы: ", norm) + print("Вектор неизвестных: ", x) + print("Количество итераций: ", iterations) + print("Погрешность: ", errors[-1] if errors else None) + + +def is_valid_number(value): + try: + float(value) + return True + except ValueError: + return False + + +def main(): + print("Решение системы линейных алгебраических уравнений СЛАУ") + while True: + try: + print("Введите точность:") + precision = float(input()) + if precision <= 0: + raise ValueError("Ошибка: точность должна быть положительным числом.") + break + except ValueError: + print("Ошибка: введите корректное положительное число для точности.") + print( + "Введите матрицу в формате 'a11 a12 a13 ... a1n b1; a21 a22 a23 ... a2n b2; ... a3n1 an2 an3 ... ann bn' или введите имя файла с матрицей (.txt или .csv)") + print("Матрица должна быть квадратной. n <= 20") + print("Введите имя файла или первую строку матрицы: (Для генерации случайной матрицы введите RANDOM)") + while True: + try: + input_data = input().strip() + if input_data.endswith('.csv') or input_data.endswith('.txt'): + matrix = read_matrix_from_file(input_data) + elif input_data == 'RANDOM': + matrix = generate_random_matrix() + print("Сгенерированная матрица:") + for i in range(len(matrix)): + print([float('%.2f' % elem) for elem in matrix[i]]) + else: + matrix = [[float(num) for num in input_data.split()]] + if len(matrix[0]) > 21: + raise ValueError("Ошибка: размерность матрицы должна быть не больше 20.") + current_row = 1 + while current_row < len(matrix[0]) - 1: + input_data = input().strip() + row = input_data.split() + if len(row) != len(matrix[0]) or not all(is_valid_number(num) for num in row): + print(f"Ошибка: строка должна содержать {len(matrix[0])} вещественных чисел.") + continue + matrix.append([float(num) for num in row]) + current_row += 1 + break + except ValueError as e: + print(f"Ошибка: {e}. Попробуйте снова.") + try: + calculate_matrix(matrix, precision) + except ValueError as e: + print(e) + + +if __name__ == '__main__': + main() diff --git "a/\320\2403208/vasilev_366389/lab2/calculation.py" "b/\320\2403208/vasilev_366389/lab2/calculation.py" new file mode 100644 index 0000000..24cd7cc --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab2/calculation.py" @@ -0,0 +1,69 @@ +import numpy as np +import verificator +import plots + + +def method_of_chords(f, a, b, epsilon, max_iter=1000): + if not verificator.check_root(f, a, b): + return None + + x0, x1 = a, b + for _ in range(max_iter): + f0, f1 = f(x0), f(x1) + if abs(f1 - f0) < 1e-12: + break + x2 = x1 - f1 * (x1 - x0) / (f1 - f0) + if abs(x2 - x1) < epsilon: + plots.plot_function(f, a, b, x2) + return x2, f(x2), _ + 1 + x0, x1 = x1, x2 + plots.plot_function(f, a, b, x2) + return max_iter + + +def newtons_method(f, df, x0, epsilon, max_iter=1000): + for _ in range(max_iter): + f0, df0 = f(x0), df(f, x0) + if abs(df0) < 1e-12: + break + x1 = x0 - f0 / df0 + if abs(x1 - x0) < epsilon: + plots.plot_function_without_points(f, x0, x1) + return x1, f(x1), _ + 1 + x0 = x1 + plots.plot_function_without_points(f, x0, x1) + return max_iter + + +def simple_iterations(f, phi, x0, epsilon, max_iter=1000): + x = x0 + for _ in range(max_iter): + x_next = phi(f, x) + if abs(x_next - x) < epsilon: + plots.plot_function_without_points(f, x0, x_next) + return x_next, f(x_next), _ + 1 + x = x_next + plots.plot_function_without_points(f, x0, x_next) + return max_iter + + +def newton_system_method(f, J, x0, epsilon, max_iter=1000): + x = np.array(x0) + errors = [] + for _ in range(max_iter): + F = np.array([fi(x) for fi in f]) + J_matrix = J(f, x) + try: + J_inv = np.linalg.inv(J_matrix) + except np.linalg.LinAlgError: + return None + delta = np.dot(J_inv, F) + x_next = x - delta + error = np.linalg.norm(x_next - x) + errors.append(float(error)) + if error < epsilon: + plots.plot_functions_system(f[0], f[1], x_next, x0) + return x_next, _, errors + x = x_next + return max_iter + diff --git "a/\320\2403208/vasilev_366389/lab2/examples.py" "b/\320\2403208/vasilev_366389/lab2/examples.py" new file mode 100644 index 0000000..529d929 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab2/examples.py" @@ -0,0 +1,44 @@ +import numpy as np + +functions = [ + lambda x: 2.74 * x**3 - 1.93 * x**2 - 15.28 * x - 3.72, + lambda x: np.sin(x) - 0.5 * x**2 + 3, + lambda x: np.cos(x) + 3 * x**4 - 2, + lambda x: x**5 - 10 * x**3 + 4 * x**2 - 7, + lambda x: np.exp(x) - x**10 + 1 +] + +function_strings = [ + "2.74 * x**3 - 1.93 * x**2 - 15.28 * x - 3.72", + "sin(x) - 0.5 * x^2 + 3", + "cos(x) + 3 * x^4 - 2", + "x^5 - 10 * x^3 + 4 * x^2 - 7", + "exp(x) - x^10 + 1" +] + +methods_strings = [ + "Метод хорд", + "Метод Ньютона", + "Метод простой итерации" +] + +system_strings = [ + "f1(x, y) = tan(xy + 0.3) - x^2, f2(x, y) = 0.9x^2 + 2y^2 - 1", + "f1(x, y) = sin(x + y) - 1.4x, f2(x, y) = x^2 + y ^2 - 1" +] + +system_variables = [ + ['x', 'y'], + ['x', 'y'] +] + +systems = [ + [ + lambda x: np.tan(x[0] * x[1] + 0.3) - x[0]**2, + lambda x: 0.9 * x[0]**2 + 2 * x[1]**2 - 1 + ], + [ + lambda x: np.sin(x[0] + x[1]) - x[0]*1.4, + lambda x: x[0]**2 + x[1]**2 - 1 + ] +] \ No newline at end of file diff --git "a/\320\2403208/vasilev_366389/lab2/main.py" "b/\320\2403208/vasilev_366389/lab2/main.py" new file mode 100644 index 0000000..73d859d --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab2/main.py" @@ -0,0 +1,183 @@ +import calculation +import examples +import sideCalculations as sc + + +def get_int(prompt, valid_range=None): + while True: + try: + value = int(input(prompt)) + if valid_range and value not in valid_range: + print(f"Введите значение из диапазона: {valid_range}") + continue + return value + except ValueError: + print("Ошибка: введите целое число.") + + +def get_float(prompt): + while True: + try: + return float(input(prompt)) + except ValueError: + print("Ошибка: введите число с плавающей точкой.") + + +def get_data_from_file(file_name): + try: + with open(file_name, "r") as file: + lines = [line.strip() for line in file.readlines()] + accuracy = float(lines[0]) + if len(lines) >= 3: + return accuracy, float(lines[1]), float(lines[2]) + elif len(lines) >= 2: + return accuracy, float(lines[1]) + else: + return accuracy, + except Exception as e: + print(f"Ошибка при чтении файла: {e}") + return None + + +def solve_nonlinear_equation(): + print("Введите номер уравнения, которое нужно решить:") + for i, s in enumerate(examples.function_strings, 1): + print(f"{i}. {s}") + fun = get_int("Ваш выбор: ", range(1, len(examples.function_strings) + 1)) + + print("Введите номер метода решения:") + for i, s in enumerate(examples.methods_strings, 1): + print(f"{i}. {s}") + method = get_int("Ваш выбор: ", range(1, len(examples.methods_strings) + 1)) + + input_type = get_int("Для ввода данных с клавиатуры введите 1. Из файла — 2: ", [1, 2]) + + accuracy, a, b, x0 = None, None, None, None + + if input_type == 1: + accuracy = get_float("Введите точность: ") + else: + file_name = input("Введите имя файла (txt): ") + result = get_data_from_file(file_name) + if result is None: + return + accuracy = result[0] + if method == 1 and len(result) >= 3: + a, b = result[1], result[2] + elif method != 1 and len(result) >= 2: + x0 = result[1] + + if method == 1: + if input_type == 1: + print("Введите границы интервала:") + a = get_float("a: ") + b = get_float("b: ") + result = calculation.method_of_chords(examples.functions[fun - 1], a, b, accuracy) + else: + if input_type == 1: + x0 = get_float("Введите начальное приближение: ") + if method == 2: + result = calculation.newtons_method(examples.functions[fun - 1], sc.numerical_derivative, x0, accuracy) + else: + result = calculation.simple_iterations(examples.functions[fun - 1], sc.iteration_function, x0, accuracy) + + if result is None: + output = "Корней нет или система не имеет решения." + elif result == 1000: + output = "Не удалось найти решение за 1000 итераций." + else: + output = ( + f"Корень: {result[0]}\n" + f"Значение функции: {result[1]}\n" + f"Количество итераций: {result[2]}" + ) + + print("Выберите способ вывода результата:") + print("1 — вывести в консоль") + print("2 — сохранить в файл result.txt") + choice = input("Ваш выбор: ") + + if choice == "2": + try: + with open("result.txt", "w", encoding="utf-8") as file: + file.write(output) + print("Результат сохранён в файл result.txt") + except Exception as e: + print(f"Ошибка при записи в файл: {e}") + else: + print(output) + + +def solve_system_of_equations(): + print("Введите номер системы уравнений, которую нужно решить:") + for i, s in enumerate(examples.system_strings, 1): + print(f"{i}. {s}") + system_choice = get_int("Ваш выбор: ", range(1, len(examples.system_strings) + 1)) + + input_type = get_int("Для ввода данных с клавиатуры введите 1. Из файла — 2: ", [1, 2]) + accuracy = None + x0 = [] + + if input_type == 1: + accuracy = get_float("Введите точность: ") + + print("Введите начальные приближения для каждой переменной:") + for i in range(len(examples.system_variables[system_choice - 1])): + x0.append(get_float(f"Введите начальное приближение для x{i + 1}: ")) + + elif input_type == 2: + file_name = input("Введите имя файла (txt): ") + result = get_data_from_file(file_name) + if result is None: + return + accuracy = result[0] + if len(result) >= 3: + x0 = [result[1], result[2]] + elif len(result) >= 2: + x0 = [result[1]] + + result = calculation.newton_system_method(examples.systems[system_choice - 1], sc.numerical_jacobian, x0, accuracy) + + if result is None: + output = "Корней нет или система не имеет решения." + elif result == 1000: + output = "Не удалось найти решение за 1000 итераций." + else: + output = ( + f"Решение системы: {result[0]}\n" + f"Количество итераций: {result[1]}\n" + f"Погрешности: {result[2]}" + ) + + print("Выберите способ вывода результата:") + print("1 — вывести в консоль") + print("2 — сохранить в файл result.txt") + choice = input("Ваш выбор: ") + + if choice == "2": + try: + with open("result.txt", "w", encoding="utf-8") as file: + file.write(output) + print("Результат сохранён в файл result.txt") + except Exception as e: + print(f"Ошибка при записи в файл: {e}") + else: + print(output) + + +def main(): + while True: + print("Для решения нелинейного уравнения введите 1. Для системы нелинейных уравнений — 2.") + type_choice = get_int("Ваш выбор: ", [1, 2]) + if type_choice == 1: + solve_nonlinear_equation() + break + elif type_choice == 2: + solve_system_of_equations() + break + else: + print("Вы ввели что-то не то. Пожалуйста, введите 1 или 2.") + + +if __name__ == "__main__": + main() diff --git "a/\320\2403208/vasilev_366389/lab2/plots.py" "b/\320\2403208/vasilev_366389/lab2/plots.py" new file mode 100644 index 0000000..54d90ac --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab2/plots.py" @@ -0,0 +1,72 @@ +import numpy as np +import matplotlib.pyplot as plt + +def plot_function(f, a, b, x2, step=0.01): + x_vals = np.arange(a, b, step) + y_vals = np.array([f(x) for x in x_vals]) + + + plt.plot(x_vals, y_vals, label="f(x)") + plt.plot(x2, 0, 'bo') + plt.axhline(0, color='black',linewidth=1) + plt.axvline(0, color='black',linewidth=1) + plt.xlabel("x") + plt.ylabel("f(x)") + plt.title("График функции") + plt.legend() + plt.grid(True) + plt.show() + +def plot_function_without_points(f, x2, x0): + + if isinstance(x0, np.ndarray): + x0 = x0[0] + + delta_x = 2 + a = x0 - delta_x + b = x0 + delta_x + + step = 0.01 + x_vals = np.arange(a, b, step) + y_vals = np.array([f(x) for x in x_vals]) + + plt.plot(x_vals, y_vals, label="f(x)") + plt.plot(x2, 0, 'bo') + plt.axhline(0, color='black', linewidth=1) + plt.axvline(0, color='black', linewidth=1) + plt.xlabel("x") + plt.ylabel("f(x)") + plt.title("График функции") + plt.legend() + plt.grid(True) + plt.show() + +def plot_functions_system(f1, f2, x_next, x0, step=0.01): + if isinstance(x0, (list, np.ndarray)): + x0 = np.array(x0) + + if isinstance(x_next, (list, np.ndarray)): + x_next = np.array(x_next) + + delta_x = 4 + a = x0[0] - delta_x + b = x0[0] + delta_x + + x = x_next[0] + y = x_next[1] + + x_vals = np.arange(a, b, step) + y_vals1 = np.array([f1(np.array([x, x])) for x in x_vals]) + y_vals2 = np.array([f2(np.array([x, x])) for x in x_vals]) + + plt.plot(x_vals, y_vals1, label="f1(x)", color='blue') + plt.plot(x_vals, y_vals2, label="f2(x)", color='red') + plt.plot(x, y, 'bo') + plt.axhline(0, color='black', linewidth=1) + plt.axvline(0, color='black', linewidth=1) + plt.xlabel("x") + plt.ylabel("f(x)") + plt.title("Графики функций f1(x) и f2(x)") + plt.legend() + plt.grid(True) + plt.show() \ No newline at end of file diff --git "a/\320\2403208/vasilev_366389/lab2/sideCalculations.py" "b/\320\2403208/vasilev_366389/lab2/sideCalculations.py" new file mode 100644 index 0000000..2a0dcfb --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab2/sideCalculations.py" @@ -0,0 +1,25 @@ +import numpy as np + + +def numerical_derivative(f, x, h=1e-5): + return (f(x + h) - f(x - h)) / (2 * h) + + +def iteration_function(f, x, h=1e-5): + df = (f(x + h) - f(x - h)) / (2 * h) + return x - f(x) / df + + +def numerical_jacobian(system, x, h=1e-5): + n = len(system) + jacobian = np.zeros((n, n)) + + for i in range(n): + for j in range(n): + x_plus = x.copy() + x_minus = x.copy() + x_plus[j] += h + x_minus[j] -= h + jacobian[i, j] = (system[i](x_plus) - system[i](x_minus)) / (2 * h) + + return jacobian diff --git "a/\320\2403208/vasilev_366389/lab2/verificator.py" "b/\320\2403208/vasilev_366389/lab2/verificator.py" new file mode 100644 index 0000000..64591a4 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab2/verificator.py" @@ -0,0 +1,4 @@ +def check_root(f, a, b): + if f(a) * f(b) > 0: + return False + return True \ No newline at end of file diff --git "a/\320\2403208/vasilev_366389/lab3/calculation.py" "b/\320\2403208/vasilev_366389/lab3/calculation.py" new file mode 100644 index 0000000..393e863 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab3/calculation.py" @@ -0,0 +1,72 @@ +class Calculation: + def __init__(self, function, lower_limit, upper_limit, accuracy, method): + self.function = function + self.lower_limit = lower_limit + self.upper_limit = upper_limit + self.accuracy = accuracy + self.method = method + + def left_rectangle(self, n): + h = (self.upper_limit - self.lower_limit) / n + return h * sum(self.function(self.lower_limit + i * h) for i in range(n)) + + def right_rectangle(self, n): + h = (self.upper_limit - self.lower_limit) / n + return h * sum(self.function(self.lower_limit + (i + 1) * h) for i in range(n)) + + def middle_rectangle(self, n): + h = (self.upper_limit - self.lower_limit) / n + return h * sum(self.function(self.lower_limit + (i + 0.5) * h) for i in range(n)) + + def trapezoid(self, n): + h = (self.upper_limit - self.lower_limit) / n + return h * (0.5 * self.function(self.lower_limit) + 0.5 * self.function(self.upper_limit) + sum( + self.function(self.lower_limit + i * h) for i in range(1, n))) + + def simpson(self, n): + h = (self.upper_limit - self.lower_limit) / n + result = self.function(self.lower_limit) + self.function(self.upper_limit) + + odd_sum = sum(self.function(self.lower_limit + i * h) for i in range(1, n, 2)) + result += 4 * odd_sum + + even_sum = sum(self.function(self.lower_limit + i * h) for i in range(2, n - 1, 2)) + result += 2 * even_sum + + return (h / 3) * result + + def runge(self, I1, I2, k): + return abs(I1 - I2) / (2 ** k - 1) + + def calculate(self): + n = 2 + max_n = 10000000 + max_iterations = 1000 + I_old = 0 + iteration = 0 + while iteration < max_iterations: + if self.method == 1: + I_new = self.left_rectangle(n) + elif self.method == 2: + I_new = self.right_rectangle(n) + elif self.method == 3: + I_new = self.middle_rectangle(n) + elif self.method == 4: + I_new = self.trapezoid(n) + elif self.method == 5: + I_new = self.simpson(n) + + if iteration > 0: + k = 1 if self.method in [1, 2] else 2 if self.method == 3 else 4 + error = self.runge(I_old, I_new, k) + if error < self.accuracy: + return I_new, n + + I_old = I_new + n *= 2 + iteration += 1 + + if n > max_n: + return None + + return I_old, n diff --git "a/\320\2403208/vasilev_366389/lab3/examples.py" "b/\320\2403208/vasilev_366389/lab3/examples.py" new file mode 100644 index 0000000..f0d46c7 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab3/examples.py" @@ -0,0 +1,31 @@ +import math + +functions_strings = [ + "f(x) = 2x³-4x²+6x-25", + "f(x) = x³-5x²+3x-16", + "f(x) = -x³-x²-2x+1", + "f(x) = sin(x)", + "f(x) = 1/(x+1)", + "f(x) = e^(-x)", + "f(x) = 1/x", + "f(x) = 1/(√x)" +] + +methods_strings = [ + "Метод левых прямоугольников", + "Метод правых прямоугольников", + "Метод центральных прямоугольников", + "Метод трапеций", + "Метод Симпсона" +] + +functions = [ + lambda x: 2 * x ** 3 - 4 * x ** 2 + 6 * x - 25, + lambda x: x ** 3 - 5 * x ** 2 + 3 * x - 16, + lambda x: -x ** 3 - x ** 2 - 2 * x + 1, + lambda x: math.sin(x), + lambda x: 1 / (x + 1), + lambda x: math.exp(-x), + lambda x: 1 / x, + lambda x: 1 / math.sqrt(x) +] diff --git "a/\320\2403208/vasilev_366389/lab3/improperCalculation.py" "b/\320\2403208/vasilev_366389/lab3/improperCalculation.py" new file mode 100644 index 0000000..a9e0c6d --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab3/improperCalculation.py" @@ -0,0 +1,94 @@ +import math + + +class ImproperIntegralCalculator: + def __init__(self, function, lower_limit, upper_limit): + self.function = function + self.lower_limit = lower_limit + self.upper_limit = upper_limit + self.check_points = 1000 + self.eps = 1e-6 + self.n = math.ceil(self.upper_limit - self.lower_limit) * self.check_points + + def get_breakpoints(self): + breakpoints = [] + + try: + self.function(self.lower_limit) + except (ZeroDivisionError, ValueError, Exception): + breakpoints.append(self.lower_limit) + + try: + self.function(self.upper_limit) + except (ZeroDivisionError, ValueError, Exception): + breakpoints.append(self.upper_limit) + + step = (self.upper_limit - self.lower_limit) / self.n + for i in range(self.n): + x = self.lower_limit + i * step + try: + self.function(x) + except (ZeroDivisionError, ValueError, Exception): + breakpoints.append(x) + + return list(set(breakpoints)) + + def try_to_evaluate(self, x): + try: + return self.function(x) + except (ZeroDivisionError, ValueError, Exception): + return None + + def get_coverage(self): + threshold = 1e6 - 1 + coverage = True + for point in self.get_breakpoints(): + a = self.try_to_evaluate(point - self.eps) + b = self.try_to_evaluate(point + self.eps) + if a is None or b is None: + return False + if abs(a) > threshold or abs(b) > threshold: + if self.lower_limit < 0 < self.upper_limit: + if abs(a) == abs(b): + return True + return False + return coverage + + def find_limits(self): + limits = [] + breakpoints = self.get_breakpoints() + if len(breakpoints) == 1: + if breakpoints[0] == self.lower_limit: + limits.append(self.lower_limit + self.eps) + limits.append(self.upper_limit) + elif breakpoints[0] == self.upper_limit: + limits.append(self.lower_limit) + limits.append(self.upper_limit - self.eps) + return limits + + if not (self.try_to_evaluate(self.lower_limit) is None or self.try_to_evaluate( + breakpoints[0] + self.eps) is None): + limits.append(self.lower_limit) + limits.append(breakpoints[0] + self.eps) + return limits + + if not (self.try_to_evaluate(self.upper_limit) is None or self.try_to_evaluate( + breakpoints[0] - self.eps) is None): + limits.append(self.upper_limit) + limits.append(breakpoints[0] - self.eps) + return limits + + for point in range(len(breakpoints) - 1): + cur = breakpoints[point] + next = breakpoints[point + 1] + + if not (self.try_to_evaluate(cur + self.eps) is None or self.try_to_evaluate(next - self.eps) is None): + limits.append(cur + self.eps) + limits.append(next - self.eps) + return limits + + if not breakpoints or self.lower_limit - self.eps in breakpoints or self.upper_limit + self.eps in breakpoints: + limits.append(self.lower_limit) + limits.append(self.upper_limit) + + return limits \ No newline at end of file diff --git "a/\320\2403208/vasilev_366389/lab3/main.py" "b/\320\2403208/vasilev_366389/lab3/main.py" new file mode 100644 index 0000000..c4f6dae --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab3/main.py" @@ -0,0 +1,99 @@ +import examples +from improperCalculation import ImproperIntegralCalculator +from calculation import Calculation + + +def get_int(prompt, valid_range=None): + while True: + try: + value = int(input(prompt)) + if valid_range and value not in valid_range: + print(f"Введите значение из диапазона: {valid_range}") + continue + return value + except ValueError: + print("Ошибка: введите целое число.") + + +def get_float(prompt): + while True: + try: + return float(input(prompt)) + except ValueError: + print("Ошибка: введите число с плавающей точкой.") + + +def main(): + while True: + print("Введите номер функции, интеграл которой нужно решить:") + for i, s in enumerate(examples.functions_strings, 1): + print(f"{i}. {s}") + fun = get_int("Ваш выбор: ", range(1, len(examples.functions_strings) + 1)) + + while True: + lower_limit = get_int("Введите нижний предел интегрирования: ") + upper_limit = get_int("Введите верхний предел интегрирования: ") + + if lower_limit >= upper_limit: + print("Ошибка: нижний предел должен быть меньше верхнего предела.") + else: + break + + improper = ImproperIntegralCalculator(examples.functions[fun - 1], lower_limit, upper_limit) + breakpoints = improper.get_breakpoints() + limits = None + + if breakpoints: + if not improper.get_coverage(): + print("Интеграл расходится и не существует") + break + else: + print(f"Точки разрыва: {breakpoints}") + print("Интеграл сходится") + limits = improper.find_limits() + + if limits: + lower_limit = limits[0] + upper_limit = limits[1] + + if 0 in breakpoints: + limits.append(lower_limit) + limits.append(-improper.eps) + limits.append(improper.eps) + limits.append(upper_limit) + + if improper.try_to_evaluate(lower_limit) is None or improper.try_to_evaluate(upper_limit) is None: + print("Интеграл невозможно вычислить в пространстве действительных чисел") + break + + print("Введите номер метода, которым нужно решить интеграл:") + for i, s in enumerate(examples.methods_strings, 1): + print(f"{i}. {s}") + method = get_int("Ваш выбор: ", range(1, len(examples.methods_strings) + 1)) + + accuracy = get_float("Введите точность: ") + + if limits and len(limits) == 4: + result1 = Calculation(examples.functions[fun - 1], limits[0], limits[1], accuracy, method) + result2 = Calculation(examples.functions[fun - 1], limits[2], limits[3], accuracy, method) + result = result1.calculate()[0] + result2.calculate()[0] + if result1 is None or result2 is None: + print("Достигнуто максимальное количество разбиений (1000000), но ответ не найден.") + break + else: + print(f'Результат интегрирования: {result.__round__(2) if result < 1e-5 else result}') + print(f'Количество разбиений: {result1.calculate()[1] + result2.calculate()[1]}') + break + else: + result = Calculation(examples.functions[fun - 1], lower_limit, upper_limit, accuracy, method) + if result.calculate() is None: + print("Достигнуто максимальное количество разбиений (1000000), но ответ не найден.") + break + else: + print(f'Результат интегрирования: {result.calculate()[0]}') + print(f'Количество разбиений: {result.calculate()[1]}') + break + + +if __name__ == "__main__": + main() diff --git "a/\320\2403208/vasilev_366389/lab4/approximation.py" "b/\320\2403208/vasilev_366389/lab4/approximation.py" new file mode 100644 index 0000000..6343ae3 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab4/approximation.py" @@ -0,0 +1,97 @@ +import numpy as np + + +def linear_approximation(x, y, n): + x = np.array(x) + y = np.array(y) + + sx = np.sum(x) + sxx = np.sum(x ** 2) + sy = np.sum(y) + sxy = np.sum(x * y) + + a, b = np.linalg.solve( + [ + [n, sx], + [sx, sxx] + ], + [sy, sxy]) + return lambda xi: a + b * xi, a.item(), b.item() + + +def quadratic_approximation(x, y, n): + x = np.array(x) + y = np.array(y) + + sx = np.sum(x) + sxx = np.sum(x ** 2) + sxxx = np.sum(x ** 3) + sxxxx = np.sum(x ** 4) + sy = np.sum(y) + sxy = np.sum(x * y) + sxxy = np.sum(x ** 2 * y) + + a, b, c = np.linalg.solve( + [ + [n, sx, sxx], + [sx, sxx, sxxx], + [sxx, sxxx, sxxxx] + ], + [sy, sxy, sxxy] + ) + return lambda xi: a + b * xi + c * xi ** 2, a.item(), b.item(), c.item() + + +def cubic_approximation(x, y, n): + x = np.array(x) + y = np.array(y) + + sx = np.sum(x) + sy = np.sum(y) + sxy = np.sum(x * y) + sxx = np.sum(x ** 2) + sxxx = np.sum(x ** 3) + sxxxx = np.sum(x ** 4) + sxxxxx = np.sum(x ** 5) + sxxxxxx = np.sum(x ** 6) + sxxy = np.sum(x ** 2 * y) + sxxxy = np.sum(x ** 3 * y) + + a, b, c, d = np.linalg.solve( + [ + [n, sx, sxx, sxxx], + [sx, sxx, sxxx, sxxxx], + [sxx, sxxx, sxxxx, sxxxxx], + [sxxx, sxxxx, sxxxxx, sxxxxxx] + ], + [sy, sxy, sxxy, sxxxy] + ) + return lambda xi: a + b * xi + c * xi ** 2 + d * xi ** 3, a.item(), b.item(), c.item(), d.item() + +def exponential_approximation(x, y, n): + y_log = np.log(y) + _, a_log, b_log = linear_approximation(x, y_log, n) + + a = np.exp(a_log) + b = b_log + + return lambda xi: a * np.exp(b * xi), a.item(), b + + +def logarithmic_approximation(x, y, n): + x_log = np.log(x) + _, a, b = linear_approximation(x_log, y, n) + + return lambda xi: a + b * np.log(xi), a, b + + +def power_approximation(x, y, n): + x_log = np.log(x) + y_log = np.log(y) + + _, a_log, b_log = linear_approximation(x_log, y_log, n) + + a = np.exp(a_log) + b = b_log + + return lambda xi: a * xi ** b, a.item(), b diff --git "a/\320\2403208/vasilev_366389/lab4/calculation.py" "b/\320\2403208/vasilev_366389/lab4/calculation.py" new file mode 100644 index 0000000..9928ba9 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab4/calculation.py" @@ -0,0 +1,39 @@ +import numpy as np + + +def compute_pearson_correlation(x, y): + av_x = np.mean(x) + av_y = np.mean(y) + + numerator = np.sum((x - av_x) * (y - av_y)) + denominator = np.sqrt(np.sum((x - av_x) ** 2) * np.sum((y - av_y) ** 2)) + + return numerator / denominator + + +def compute_mean_squared_error(x, y, phi): + x = np.array(x) + y = np.array(y) + + errors = phi(x) - y + mse = np.mean(errors ** 2) + return np.sqrt(mse) + + +def compute_measure_of_deviation(x, y, phi): + x = np.array(x) + y = np.array(y) + + deviations = phi(x) - y + return np.sum(deviations ** 2) + + +def compute_coefficient_of_determination(x, y, phi, n): + x = np.array(x) + y = np.array(y) + + av_phi = np.sum(phi(x)) / n + total_variation = np.sum((y - av_phi) ** 2) + unexplained_variation = np.sum((y - phi(x)) ** 2) + + return 1 - (unexplained_variation / total_variation) \ No newline at end of file diff --git "a/\320\2403208/vasilev_366389/lab4/in.txt" "b/\320\2403208/vasilev_366389/lab4/in.txt" new file mode 100644 index 0000000..0aba377 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab4/in.txt" @@ -0,0 +1,10 @@ +0.2 2.396 +0.4 4.68 +0.6 6.374 +0.8 6.810 +1 6 +1.2 4.685 +1.4 3.47 +1.6 2.542 +1.8 1.879 +2 1.412 \ No newline at end of file diff --git "a/\320\2403208/vasilev_366389/lab4/main.py" "b/\320\2403208/vasilev_366389/lab4/main.py" new file mode 100644 index 0000000..fe23d15 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab4/main.py" @@ -0,0 +1,170 @@ +import sys +from approximation import (linear_approximation, quadratic_approximation, cubic_approximation, + exponential_approximation, logarithmic_approximation, power_approximation) +from calculation import (compute_mean_squared_error, compute_measure_of_deviation, + compute_coefficient_of_determination, compute_pearson_correlation) +from plots import draw_func, draw_plot + + +def get_int(prompt, valid_range=None): + while True: + try: + value = int(input(prompt)) + if valid_range and value not in valid_range: + print(f"Введите значение из диапазона: {valid_range}") + else: + return value + except ValueError: + print("Ошибка: введите целое число.") + + +def run(functions, x, y, n): + best_mse = float("inf") + mses = [] + + for approximation, name in functions: + try: + phi, *coeffs = approximation(x, y, n) + s = compute_measure_of_deviation(x, y, phi) + mse = compute_mean_squared_error(x, y, phi) + r2 = compute_coefficient_of_determination(x, y, phi, n) + + mses.append((mse, name)) + if mse <= best_mse: + best_mse, best_func = mse, name + + draw_func(phi, name, x) + print_results(name, coeffs, mse, r2, s, approximation, x, y, n) + except Exception as e: + print(f"Ошибка приближения {name} функции: {e}\n") + + print_best_functions(mses, best_mse) + draw_plot(x, y) + + +def print_results(name, coeffs, mse, r2, s, approximation, x, y, n): + print(f"{name} аппроксимация:") + print(f" Коэффициенты: {list(map(lambda cf: round(cf, 4), coeffs))}") + print(f" Среднеквадратичное отклонение: {mse:.5f}") + print(f" Коэффициент детерминации: {r2:.5f}") + print(f" Мера отклонения: S = {s:.5f}") + if approximation == linear_approximation: + correlation = compute_pearson_correlation(x, y) + print(f" Коэффициент корреляции Пирсона: r = {correlation}\n") + else: + print("\n") + + +def print_best_functions(mses, best_mse): + best_funcs = [name for mse, name in mses if abs(mse - best_mse) < 1e-7] + if len(best_funcs) == 1: + print(f"Лучшая функция приближения: {best_funcs[0]}") + else: + print("Лучшие функции приближения:") + for name in best_funcs: + print(f' {name}') + + +def get_data_from_file(filename): + try: + with open(filename, 'r') as file: + x, y = zip(*[(float(line.split()[0]), float(line.split()[1])) for line in file if len(line.split()) == 2]) + return list(x), list(y), None + except IOError as err: + return None, None, f"Невозможно прочитать файл {filename}: {err}" + + +def read_data_from_input(): + x, y = [], [] + while True: + data = input().strip() + if data == '/stop': + break + try: + xi, yi = map(float, data.split()) + x.append(xi) + y.append(yi) + except ValueError: + print("Некорректный ввод. Попробуйте еще раз") + return x, y + + +def main(): + while True: + print("Для ввода данных выберите опцию:") + print("1. Ввод из файла") + print("2. Ввод с клавиатуры") + option = get_int("Ваш выбор: ", [1, 2]) + + if option == 1: + while True: + filename = input("Введите имя файла: ") + x, y, error = get_data_from_file(filename) + if error: + print(error) + else: + break + n = len(x) + break + elif option == 2: + print("Введите /stop, чтобы закончить ввод") + x, y = read_data_from_input() + n = len(x) + break + else: + print("Некорректный ввод. Попробуйте еще раз.") + + functions = select_functions(x, y) + output_choice = select_output_choice() + + with open('output.txt', 'w') as output: + if output_choice == 1: + print("Выбран вариант вывода в файл 'output.txt'") + sys.stdout = output + + run(functions, x, y, n) + + +def select_functions(x, y): + if all(xi > 0 for xi in x): + if all(yi > 0 for yi in y): + return [ + (linear_approximation, "Линейная"), + (quadratic_approximation, "Полиноминальная 2-й степени"), + (cubic_approximation, "Полиноминальная 3-й степени"), + (exponential_approximation, "Экспоненциальная"), + (logarithmic_approximation, "Логарифмическая"), + (power_approximation, "Степенная") + ] + else: + return [ + (linear_approximation, "Линейная"), + (quadratic_approximation, "Полиноминальная 2-й степени"), + (cubic_approximation, "Полиноминальная 3-й степени"), + (logarithmic_approximation, "Логарифмическая"), + ] + else: + if all(yi > 0 for yi in y): + return [ + (linear_approximation, "Линейная"), + (quadratic_approximation, "Полиноминальная 2-й степени"), + (cubic_approximation, "Полиноминальная 3-й степени"), + (exponential_approximation, "Экспоненциальная"), + ] + else: + return [ + (linear_approximation, "Линейная"), + (quadratic_approximation, "Полиноминальная 2-й степени"), + (cubic_approximation, "Полиноминальная 3-й степени"), + ] + + +def select_output_choice(): + print("Вывод в файл 'output.txt' или в терминал?") + print("1. Вывод в файл") + print("2. Вывод в терминал") + return get_int("Ваш выбор: ", [1, 2]) + + +if __name__ == "__main__": + main() diff --git "a/\320\2403208/vasilev_366389/lab4/output.txt" "b/\320\2403208/vasilev_366389/lab4/output.txt" new file mode 100644 index 0000000..e69de29 diff --git "a/\320\2403208/vasilev_366389/lab4/plots.py" "b/\320\2403208/vasilev_366389/lab4/plots.py" new file mode 100644 index 0000000..e257423 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab4/plots.py" @@ -0,0 +1,25 @@ +import matplotlib.pyplot as plt +import numpy as np + + +def draw_plot(x, y): + plt.scatter(x, y, label="Введенные точки", color='red') + plt.legend() + plt.xlabel("x") + plt.ylabel("y") + plt.title("Аппроксимация функции") + plt.grid(True) + plt.show() + + +def draw_func(func, name, x, dx=0.001): + x_min, x_max = min(x), max(x) + x_min -= 0.1 * (x_max - x_min) + x_max += 0.1 * (x_max - x_min) + + xs = np.arange(x_min, x_max, dx) + ys = func(xs) + + plt.plot(xs, ys, label=name) + plt.legend() + diff --git "a/\320\2403208/vasilev_366389/lab5/IO.py" "b/\320\2403208/vasilev_366389/lab5/IO.py" new file mode 100644 index 0000000..ca68bea --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab5/IO.py" @@ -0,0 +1,75 @@ +def get_int(prompt, valid_range=None): + while True: + try: + value = int(input(prompt)) + if valid_range and value not in valid_range: + print(f"Введите значение из диапазона: {valid_range}") + continue + return value + except ValueError: + print("Ошибка: введите целое число.") + + +def get_float(prompt): + while True: + try: + return float(input(prompt)) + except ValueError: + print("Ошибка: введите число с плавающей точкой.") + + +def print_difference_table(table): + num_columns = len(table[0]) + + headers = ["x", "y"] + [f"Δ^{i}y" for i in range(1, num_columns - 1)] + + column_widths = [] + for i in range(num_columns): + max_len = max( + len(headers[i]) if i < len(headers) else 0, + max(len(f"{row[i]:.3f}") if isinstance(row[i], float) else 0 for row in table) + ) + column_widths.append(max_len + 2) + + header_line = "|".join(headers[i].center(column_widths[i]) for i in range(len(headers))) + separator = "-" * len(header_line) + print(separator) + print(header_line) + print(separator) + + for row in table: + row_str = [] + for i in range(num_columns): + if i < len(row) and row[i] is not None: + cell = f"{row[i]:.3f}" + else: + cell = "" + row_str.append(cell.center(column_widths[i])) + print("|".join(row_str)) + print(separator) + + +def read_data_from_file(filename): + xi = [] + yi = [] + try: + with open(filename, 'r', encoding='utf-8') as f: + lines = [line.strip() for line in f if line.strip()] + + if len(lines) < 2: + raise ValueError("Файл должен содержать как минимум 2 строки: точку интерполяции и один узел.") + + x = float(lines[0]) + + for line in lines[1:]: + parts = line.split() + if len(parts) != 2: + raise ValueError(f"Неправильный формат строки: '{line}'. Ожидается два числа.") + xi.append(float(parts[0])) + yi.append(float(parts[1])) + + return x, xi, yi + + except Exception as e: + print(f"Ошибка при чтении файла: {e}") + return None, [], [] diff --git "a/\320\2403208/vasilev_366389/lab5/calculation.py" "b/\320\2403208/vasilev_366389/lab5/calculation.py" new file mode 100644 index 0000000..6f85241 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab5/calculation.py" @@ -0,0 +1,93 @@ +def compute_differences(x, y): + n = len(x) + table = [[x[i], y[i]] + [None] * (n - 1) for i in range(n)] + + for order in range(1, n): + for i in range(n - order): + if order == 1: + table[i][order + 1] = round(table[i + 1][order] - table[i][order], 4) + else: + table[i][order + 1] = round(table[i + 1][order] - table[i][order], 4) + + return table + + +def lagrange_interpolation(x_values, y_values, x): + n = len(x_values) + result = 0.0 + + for i in range(n): + term = y_values[i] + for j in range(n): + if j != i: + term *= (x - x_values[j]) / (x_values[i] - x_values[j]) + result += term + + return result + + +def newton_divided_differences(x_values, y_values, x): + n = len(x_values) + coefficients = y_values.copy() + + for j in range(1, n): + for i in range(n - 1, j - 1, -1): + coefficients[i] = (coefficients[i] - coefficients[i - 1]) / (x_values[i] - x_values[i - j]) + + return evaluate_newton_divided(x_values, coefficients, x) + + +def evaluate_newton_divided(x_values, coefficients, x): + n = len(coefficients) + result = coefficients[-1] + + for i in range(n - 2, -1, -1): + result = result * (x - x_values[i]) + coefficients[i] + + return result + + +def newton_forward_difference(x_values, y_values, x): + n = len(x_values) + h = x_values[1] - x_values[0] + + diff_table = [y_values.copy()] + for i in range(1, n): + diff_table.append([]) + for j in range(n - i): + diff_table[i].append(diff_table[i - 1][j + 1] - diff_table[i - 1][j]) + + t = (x - x_values[0]) / h + + result = diff_table[0][0] + product = 1.0 + for i in range(1, n): + product *= (t - (i - 1)) / i + result += product * diff_table[i][0] + + return result + + +def newton_backward_difference(x_values, y_values, x): + n = len(x_values) + h = x_values[1] - x_values[0] + + diff_table = [y_values.copy()] + for i in range(1, n): + diff_table.append([]) + for j in range(n - i): + diff_table[i].append(diff_table[i - 1][j + 1] - diff_table[i - 1][j]) + + t = (x - x_values[-1]) / h + + result = diff_table[0][-1] + product = 1.0 + + for i in range(1, n): + product *= (t + (i - 1)) / i + if n - i - 1 >= 0 and i < len(diff_table) and n - i - 1 < len(diff_table[i]): + result += product * diff_table[i][n - i - 1] + else: + break + + return result diff --git "a/\320\2403208/vasilev_366389/lab5/data.txt" "b/\320\2403208/vasilev_366389/lab5/data.txt" new file mode 100644 index 0000000..7c1cd75 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab5/data.txt" @@ -0,0 +1,6 @@ +0.25 +0.1 1.0 +0.2 1.44 +0.3 2.25 +0.4 3.24 +0.5 4.41 diff --git "a/\320\2403208/vasilev_366389/lab5/examples.py" "b/\320\2403208/vasilev_366389/lab5/examples.py" new file mode 100644 index 0000000..dbc7b1a --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab5/examples.py" @@ -0,0 +1,18 @@ +import math + +func_names = [ + "Лагранж", + "Ньютон (раздел)", + "Ньютон (вперед)", + "Ньютон (назад)", + "Стирлинг", + "Бессель" +] + +available_functions = { + 1: ("sin(x)", lambda x: math.sin(x)), + 2: ("cos(x)", lambda x: math.cos(x)), + 3: ("exp(x)", lambda x: math.exp(x)), + 4: ("x^2", lambda x: x**2), + 5: ("ln(x)", lambda x: math.log(x)), +} diff --git "a/\320\2403208/vasilev_366389/lab5/main.py" "b/\320\2403208/vasilev_366389/lab5/main.py" new file mode 100644 index 0000000..92f12fa --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab5/main.py" @@ -0,0 +1,103 @@ +import IO +import calculation +import plots +import examples + + +def main(): + io = IO + print("Вы можете вести данные в одном из трех форматов:") + print("1. Ввод через консоль в виде набора данных") + print("2. Ввод из файла") + print("3. На основе выбранной функции, из тех, которые предлагает программа") + type = io.get_int("Введите тип ввода: ", [1, 2, 3]) + if type == 1: + x = io.get_float("Введите точку интерполяции: ") + xi = [] + yi = [] + print("\nВведите узлы интерполяции в формате 'x y' (например, '1.0 2.0')") + print("Для завершения ввода введите 'q' или оставьте строку пустой") + while True: + user_input = input("> ").strip() + + if user_input.lower() in ('q', ''): + if len(xi) < 2: + print("Нужно ввести хотя бы 2 узла!") + continue + break + + parts = user_input.split() + if len(parts) != 2: + print("Ошибка! Нужно ввести ровно 2 числа через пробел") + continue + + try: + x_val = float(parts[0]) + y_val = float(parts[1]) + if x_val in xi: + print(f"Ошибка! Узел с x = {x_val} уже существует. Введите уникальное значение x.") + continue + xi.append(x_val) + yi.append(y_val) + except ValueError: + print("Ошибка! Введите числа в формате 'x y'") + elif type == 2: + filename = input("Введите имя файла (например, data.txt): ").strip() + x, xi, yi = io.read_data_from_file(filename) + if len(xi) < 2: + print("Недостаточно узлов для интерполяции.") + return + if len(set(xi)) != len(xi): + print("Ошибка! В файле содержатся одинаковые значения x. Убедитесь, что x уникальны.") + return + elif type == 3: + print("\nВыберите функцию:") + for key, (name, _) in examples.available_functions.items(): + print(f"{key}. {name}") + + func_choice = io.get_int("Введите номер функции: ", list(examples.available_functions.keys())) + func_name, func = examples.available_functions[func_choice] + + a = io.get_float("Введите левую границу интервала a: ") + if func_choice == 5 and a <= 0: + print("Ошибка: Левая граница не может быть меньше 0.") + return + b = io.get_float("Введите правую границу интервала b: ") + + if a >= b: + print("Ошибка: Левая граница должна быть меньше правой.") + return + + n = io.get_int("Введите количество точек (n >= 2): ", range(2, 1000)) + x = io.get_float("Введите точку интерполяции: ") + + if not (a <= x <= b): + print("Ошибка: Точка интерполяции должна быть внутри интервала.") + return + + xi = [a + i * (b - a) / (n - 1) for i in range(n)] + yi = [func(x_val) for x_val in xi] + if not (min(xi) <= x <= max(xi)): + print("Ошибка: Точка интерполяции должна быть внутри диапазона известных точек") + return + print("\nВы ввели узлы интерполяции:") + for x_val, y_val in zip(xi, yi): + print(f"x = {x_val}, y = {y_val}") + print("\nТаблица разностей:") + io.print_difference_table(calculation.compute_differences(xi, yi)) + print("\nРезультат интерполяции:") + func_values = [ + calculation.lagrange_interpolation(xi, yi, x), + calculation.newton_divided_differences(xi, yi, x), + calculation.newton_forward_difference(xi, yi, x), + calculation.newton_backward_difference(xi, yi, x), + ] + print("\nМногочлен Лагранжа:", func_values[0]) + print("\nМногочлен Ньютона с разделенными разностями:", func_values[1]) + print("\nМногочлен Ньютона с прямыми разностями (первая формула):", func_values[2]) + print("\nМногочлен Ньютона с прямыми разностями (вторая формула):", func_values[3]) + plots.plot_interpolation_results(xi, yi, x, func_values, examples.func_names) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git "a/\320\2403208/vasilev_366389/lab5/plots.py" "b/\320\2403208/vasilev_366389/lab5/plots.py" new file mode 100644 index 0000000..eba36d3 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab5/plots.py" @@ -0,0 +1,73 @@ +import matplotlib.pyplot as plt +import numpy as np +import calculation + + +def plot_interpolation_results(xi, yi, x, func_values, func_names): + line_styles = { + "Лагранж": {'color': 'blue', 'linestyle': '-', 'linewidth': 2}, + "Ньютон (раздел)": {'color': 'green', 'linestyle': '-', 'linewidth': 2}, + "Ньютон (вперед)": {'color': 'purple', 'linestyle': '-', 'linewidth': 2}, + "Ньютон (назад)": {'color': 'orange', 'linestyle': '-', 'linewidth': 2} + } + + plt.figure(figsize=(15, 10)) + x_plot = np.linspace(min(xi), max(xi), 500) + + for i, (name, value) in enumerate(zip(func_names, func_values)): + plt.subplot(2, 2, i + 1) + + if isinstance(value, str): + plt.text(0.5, 0.5, value, ha='center', va='center', fontsize=10, + bbox=dict(facecolor='red', alpha=0.2)) + plt.title(name) + plt.axis('off') + continue + + y_plot = [] + valid_points = 0 + for xp in x_plot: + try: + if name == "Лагранж": + y_val = calculation.lagrange_interpolation(xi, yi, xp) + elif name == "Ньютон (раздел)": + y_val = calculation.newton_divided_differences(xi, yi, xp) + elif name == "Ньютон (вперед)": + y_val = calculation.newton_forward_difference(xi, yi, xp) + elif name == "Ньютон (назад)": + y_val = calculation.newton_backward_difference(xi, yi, xp) + + if y_val is not None: + y_plot.append(y_val) + valid_points += 1 + else: + y_plot.append(np.nan) + except: + y_plot.append(np.nan) + + style = line_styles.get(name, {'color': 'black', 'linestyle': '-'}) + + if valid_points > 0: + plt.plot(x_plot, y_plot, + label=f'{name}', + **style) + + plt.scatter(xi, yi, color='red', s=50, zorder=5, + label='Узлы интерполяции', alpha=0.7) + + if isinstance(value, (int, float)): + plt.scatter([x], [value], color='green', s=100, zorder=5, + label=f'f({x:.2f}) = {value:.6f}', marker='x') + + plt.title(f"{name} (n={len(xi)})", fontsize=12) + plt.grid(True, linestyle=':', alpha=0.7) + plt.legend(fontsize=9, loc='upper left' if x > np.mean(xi) else 'upper right') + else: + plt.text(0.5, 0.5, "Не удалось построить график", + ha='center', va='center', fontsize=10, + bbox=dict(facecolor='yellow', alpha=0.3)) + plt.title(name, fontsize=12) + plt.axis('off') + + plt.tight_layout(pad=3.0) + plt.show() \ No newline at end of file diff --git "a/\320\2403208/vasilev_366389/lab6/IO.py" "b/\320\2403208/vasilev_366389/lab6/IO.py" new file mode 100644 index 0000000..af578d9 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab6/IO.py" @@ -0,0 +1,87 @@ +def get_int(prompt, valid_range=None): + while True: + try: + value = int(input(prompt)) + if valid_range and value not in valid_range: + print(f"Введите значение из диапазона: {valid_range}") + continue + return value + except ValueError: + print("Ошибка: введите целое число.") + + +def get_float(prompt): + while True: + try: + return float(input(prompt)) + except ValueError: + print("Ошибка: введите число с плавающей точкой.") + + +def print_euler_table(results): + col_widths = [4, 10, 10, 12] + header = ["i", "x", "y", "f(x, y)"] + + line = "-" * (sum(col_widths) + 5 * 3 + 1) + + print(line) + print("|", end="") + for h, w in zip(header, col_widths): + print(f" {h:^{w}} |", end="") + print("\n" + line) + + for row in results: + print("|", end="") + for i, (value, w) in enumerate(zip(row, col_widths)): + if i == 0: + print(f" {int(value):^{w}} |", end="") + else: + print(f" {value:^{w}.6f} |", end="") + print("\n" + line) + + +def print_rk4_table(results): + col_widths = [4, 10, 10, 10, 10, 10, 10] + headers = ["i", "x", "y", "k1", "k2", "k3", "k4"] + + line = "-" * (sum(col_widths) + 7 * 3 + 1) + + print(line) + print("|", end="") + for h, w in zip(headers, col_widths): + print(f" {h:^{w}} |", end="") + print("\n" + line) + + for row in results: + print("|", end="") + for i, (value, w) in enumerate(zip(row, col_widths)): + if i == 0: + print(f" {int(value):^{w}} |", end="") + else: + print(f" {value:^{w}.6f} |", end="") + print("\n" + line) + + +def print_adams_table(results): + col_widths = [4, 10, 14, 14] + headers = ["i", "x", "y (corrector)", "f(x,y)"] + line = "-" * (sum(col_widths) + len(col_widths) * 3 + 1) + + print(line) + print("|", end="") + for h, w in zip(headers, col_widths): + print(f" {h:^{w}} |", end="") + print("\n" + line) + + for row in results: + full_row = list(row) + [None] * (len(col_widths) - len(row)) + + print("|", end="") + for i, (value, w) in enumerate(zip(full_row, col_widths)): + if i == 0: + print(f" {int(value):^{w}} |", end="") + elif value is None: + print(f" {'---':^{w}} |", end="") + else: + print(f" {value:^{w}.6f} |", end="") + print("\n" + line) diff --git "a/\320\2403208/vasilev_366389/lab6/calculation.py" "b/\320\2403208/vasilev_366389/lab6/calculation.py" new file mode 100644 index 0000000..894344a --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab6/calculation.py" @@ -0,0 +1,124 @@ +import math + +from examples import ODU + + +class Calculation: + def __init__(self, equation, initial, start, finish, h, accuracy): + self.equation = equation + self.initial = initial + self.start = start + self.finish = finish + self.h = h + self.accuracy = accuracy + + def euler(self): + x = self.start + y = self.initial + results = [(0, x, y, self.equation(x, y))] + n = int((self.finish - self.start) / self.h) + + for i in range(1, n + 1): + y += self.h * self.equation(x, y) + x = self.start + i * self.h + results.append((i, x, y, self.equation(x, y))) + + return results + + def runge_kutt(self): + n = int((self.finish - self.start) / self.h) + x = self.start + y = self.initial + k1 = self.h * self.equation(x, y) + k2 = self.h * self.equation(x + self.h / 2, y + k1 / 2) + k3 = self.h * self.equation(x + self.h / 2, y + k2 / 2) + k4 = self.h * self.equation(x + self.h, y + k3) + results = [(0, x, y, k1, k2, k3, k4)] + + for i in range(1, n + 1): + k1 = self.h * self.equation(x, y) + k2 = self.h * self.equation(x + self.h / 2, y + k1 / 2) + k3 = self.h * self.equation(x + self.h / 2, y + k2 / 2) + k4 = self.h * self.equation(x + self.h, y + k3) + + results.append((i, x + self.h, y + (k1 + 2 * k2 + 2 * k3 + k4) / 6, k1, k2, k3, k4)) + y += (k1 + 2 * k2 + 2 * k3 + k4) / 6 + x += self.h + + return results + + def adams(self): + n = int((self.finish - self.start) / self.h) + x_vals = [self.start + i * self.h for i in range(n + 1)] + y_vals = [0.0] * (n + 1) + + rk = self.runge_kutt() + for i in range(4): + _, xi, yi, *_ = rk[i] + x_vals[i] = xi + y_vals[i] = yi + + for i in range(3, n): + f0 = self.equation(x_vals[i], y_vals[i]) + f1 = self.equation(x_vals[i - 1], y_vals[i - 1]) + f2 = self.equation(x_vals[i - 2], y_vals[i - 2]) + f3 = self.equation(x_vals[i - 3], y_vals[i - 3]) + + y_vals[i + 1] = ( + y_vals[i] + + self.h * (55 * f0 - 59 * f1 + 37 * f2 - 9 * f3) / 24 + ) + + results = [] + for i in range(n + 1): + fxy = self.equation(x_vals[i], y_vals[i]) + results.append((i, x_vals[i], y_vals[i], fxy)) + + return results + + def exact_solution(self, x): + if self.equation.__code__.co_code == ODU[0].__code__.co_code: + return -math.exp(x) / (x * math.exp(x) - ( + self.start * math.exp(self.start) * self.initial + math.exp(self.start)) / self.initial) + elif self.equation.__code__.co_code == ODU[1].__code__.co_code: + return (math.exp(self.start) * self.initial + (-self.start ** 2 + 2 * self.start - 2) * math.exp( + self.start)) / (math.exp(x)) + x ** 2 - 2 * x + 2 + elif self.equation.__code__.co_code == ODU[2].__code__.co_code: + return (2 * math.exp(self.start) * self.initial - math.exp(2 * self.start)) / (2 * math.exp(x)) + ( + math.exp(x) / 2) + else: + raise NotImplementedError("Точное решение не определено для этого уравнения.") + + def error_adams_vs_exact(self): + adams_results = self.adams() + return max(abs(self.exact_solution(x) - y) for (_, x, y, *_rest) in adams_results) + + def error_runge_rule_euler(self): + def method(step): + calc = Calculation(self.equation, self.initial, self.start, self.finish, step, self.accuracy) + return calc.euler() + + coarse = method(self.h) + fine = method(self.h / 2) + + errors = [ + abs(y1 - y2) + for (_, x1, y1, *_), (_, x2, y2, *_) in zip(coarse, fine[::2]) + if abs(x1 - x2) < 1e-8 + ] + return max(errors) / (2 ** 1 - 1) + + def error_runge_rule_rk4(self): + def method(step): + calc = Calculation(self.equation, self.initial, self.start, self.finish, step, self.accuracy) + return calc.runge_kutt() + + coarse = method(self.h) + fine = method(self.h / 2) + + errors = [ + abs(y1 - y2) + for (_, x1, y1, *_), (_, x2, y2, *_) in zip(coarse, fine[::2]) + if abs(x1 - x2) < 1e-8 + ] + return max(errors) / (2 ** 4 - 1) diff --git "a/\320\2403208/vasilev_366389/lab6/examples.py" "b/\320\2403208/vasilev_366389/lab6/examples.py" new file mode 100644 index 0000000..93191af --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab6/examples.py" @@ -0,0 +1,13 @@ +import math + +ODU_strings = [ + "y′ = y + (1 + x)·y²", + "y′ = x² − y", + "y′ = eˣ − y" +] + +ODU = [ + lambda x, y: y + (1 + x) * y**2, + lambda x, y: x**2 - y, + lambda x, y: math.exp(x) - y +] diff --git "a/\320\2403208/vasilev_366389/lab6/main.py" "b/\320\2403208/vasilev_366389/lab6/main.py" new file mode 100644 index 0000000..490a615 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab6/main.py" @@ -0,0 +1,56 @@ +import examples +from IO import * +from calculation import * +from plots import plot_solutions + + +def main(): + while True: + print("Выберите ОДУ:") + for i, s in enumerate(examples.ODU_strings, 1): + print(f"{i}. {s}") + system_choice = get_int("Ваш выбор: ", range(1, len(examples.ODU_strings) + 1)) + + initial_conditions = get_float("Введите начальный y₀=y(x₀): ") + while True: + start = get_float("Введите начальную границу интервала: ") + finish = get_float("Введите конечную границу интервала: ") + if start >= finish: + print("Ошибка: Начальная граница должна быть меньше конечной. Попробуйте снова.") + else: + break + while True: + h = get_float("Введите шаг: ") + if h > (finish - start): + print("Ошибка: Шаг больше, чем введенный интервал. Попробуйте снова.") + else: + break + while True: + accuracy = get_float("Введите точность: ") + if accuracy <= 0: + print("Ошибка: Точность должна быть положительным числом. Попробуйте снова.") + else: + break + results = Calculation(examples.ODU[system_choice - 1], initial_conditions, start, finish, h, accuracy) + print("\nРешение методом Эйлера:") + print_euler_table(results.euler()) + print("\nПогрешность метода Эйлера (правило Рунге):") + print(results.error_runge_rule_euler()) + plot_solutions(results, results.runge_kutt(), "Метод Эйлера vs точное решение") + print("\nРешение методом Рунге-Кутта 4-го порядка:") + print_rk4_table(results.runge_kutt()) + print("\nПогрешность метода Рунге-Кутта (правило Рунге):") + print(results.error_runge_rule_rk4()) + plot_solutions(results, results.runge_kutt(), "Метод Рунге-Кутта 4 порядка vs точное решение") + print("\nРешение методом Адамса:") + print_adams_table(results.adams()) + print("\nПогрешность метода Адамса (сравнение с точным решением):") + print(results.error_adams_vs_exact()) + plot_solutions(results, results.adams(), "Метод Адамса vs точное решение") + + break + + + +if __name__ == '__main__': + main() diff --git "a/\320\2403208/vasilev_366389/lab6/plots.py" "b/\320\2403208/vasilev_366389/lab6/plots.py" new file mode 100644 index 0000000..cf42f79 --- /dev/null +++ "b/\320\2403208/vasilev_366389/lab6/plots.py" @@ -0,0 +1,20 @@ +import matplotlib.pyplot as plt + +def plot_solutions(calc, method_results, title="Сравнение решений"): + xs = [x for (_, x, _, *_) in method_results] + ys_approx = [y for (_, _, y, *_) in method_results] + ys_exact = [calc.exact_solution(x) for x in xs] + + plt.figure(figsize=(10, 6)) + + plt.plot(xs, ys_exact, label="Точное решение", color="orange", linestyle="--", linewidth=2) + + plt.scatter(xs, ys_approx, label="Численное решение", color="blue", zorder=5) + + plt.title(title) + plt.xlabel("x") + plt.ylabel("y") + plt.grid(True) + plt.legend() + plt.tight_layout() + plt.show() diff --git "a/\320\2403208/vasilev_366389/reports/lab1.pdf" "b/\320\2403208/vasilev_366389/reports/lab1.pdf" new file mode 100644 index 0000000..763d88f Binary files /dev/null and "b/\320\2403208/vasilev_366389/reports/lab1.pdf" differ diff --git "a/\320\2403208/vasilev_366389/reports/lab2.pdf" "b/\320\2403208/vasilev_366389/reports/lab2.pdf" new file mode 100644 index 0000000..6deb520 Binary files /dev/null and "b/\320\2403208/vasilev_366389/reports/lab2.pdf" differ diff --git "a/\320\2403208/vasilev_366389/reports/lab3.pdf" "b/\320\2403208/vasilev_366389/reports/lab3.pdf" new file mode 100644 index 0000000..bdd6d52 Binary files /dev/null and "b/\320\2403208/vasilev_366389/reports/lab3.pdf" differ diff --git "a/\320\2403208/vasilev_366389/reports/lab4.pdf" "b/\320\2403208/vasilev_366389/reports/lab4.pdf" new file mode 100644 index 0000000..d4f9559 Binary files /dev/null and "b/\320\2403208/vasilev_366389/reports/lab4.pdf" differ diff --git "a/\320\2403208/vasilev_366389/reports/lab5.pdf" "b/\320\2403208/vasilev_366389/reports/lab5.pdf" new file mode 100644 index 0000000..05e2f4f Binary files /dev/null and "b/\320\2403208/vasilev_366389/reports/lab5.pdf" differ diff --git "a/\320\2403208/vasilev_366389/reports/lab6.pdf" "b/\320\2403208/vasilev_366389/reports/lab6.pdf" new file mode 100644 index 0000000..dffa301 Binary files /dev/null and "b/\320\2403208/vasilev_366389/reports/lab6.pdf" differ