diff --git "a/\320\2403265-69/mamontov_409075/lab1/Program.java" "b/\320\2403265-69/mamontov_409075/lab1/Program.java" new file mode 100644 index 0000000..58cdb0f --- /dev/null +++ "b/\320\2403265-69/mamontov_409075/lab1/Program.java" @@ -0,0 +1,115 @@ +package Program; + +import java.io.*; +import java.util.*; + +public class Program { + + // Проверяет, является ли матрица диагонально преобладающей + private static boolean isDiagonallyDominant(double[][] A) { + int n = A.length; + for (int i = 0; i < n; i++) { + double sum = 0; + for (int j = 0; j < n; j++) { + if (i != j) sum += Math.abs(A[i][j]); + } + if (Math.abs(A[i][i]) < sum) return false; + } + return true; + } + + private static double[] gaussSeidel(double[][] A, double[] b, double tol, List errors) { + int n = A.length; + double[] x = new double[n]; // Начальное приближение (нулевое) + int iterations = 0; + double maxError; + + do { + maxError = 0; + for (int i = 0; i < n; i++) { + double sum = 0; + for (int j = 0; j < n; j++) { + if (i != j) { + sum += A[i][j] * x[j]; // Используем уже обновленные значения + } + } + double newX = (b[i] - sum) / A[i][i]; + maxError = Math.max(maxError, Math.abs(newX - x[i])); // Считаем максимальную ошибку + x[i] = newX; // Обновляем x[i] + } + errors.add(maxError); + iterations++; + } while (maxError > tol); + + System.out.println("Итерации: " + iterations); + return x; + } + + // Чтение матрицы и вектора из файла + private static void readFromFile(String filename, double[][] A, double[] b) throws IOException { + BufferedReader reader = new BufferedReader(new FileReader(filename)); + int n = A.length; + for (int i = 0; i < n; i++) { + String[] line = reader.readLine().split(" "); + for (int j = 0; j < n; j++) { + A[i][j] = Double.parseDouble(line[j]); + } + } + String[] line = reader.readLine().split(" "); + for (int i = 0; i < n; i++) { + b[i] = Double.parseDouble(line[i]); + } + reader.close(); + } + + public static void main(String[] args) throws IOException { + Scanner scanner = new Scanner(System.in); + System.out.print("Введите размерность матрицы (n <= 20): "); + int n = scanner.nextInt(); + if (n > 20 || n < 1) { + System.out.println("Неверно введенная размерность"); + return; + } + + double[][] A = new double[n][n]; + double[] b = new double[n]; + + System.out.print("Прочитать данные из файла (f) или с клавиатуры (k)? "); + char inputChoice = scanner.next().charAt(0); + + if (inputChoice == 'f') { + System.out.print("Введите имя файла "); + String filename = scanner.next(); + readFromFile(filename, A, b); + } else { + System.out.println("Введите коэффиценты матрицы ряд за рядом:"); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + A[i][j] = scanner.nextDouble(); + } + } + System.out.println("Введите вектор b:"); + for (int i = 0; i < n; i++) { + b[i] = scanner.nextDouble(); + } + } + + System.out.print("Введите точность: "); + double tol = scanner.nextDouble(); + scanner.close(); + + if (!isDiagonallyDominant(A)) { + System.out.println("В матрице нет диагонального преобладания. Дальнейшее выполнение программы невозможно."); + return; + } + + // Вычисляем норму матрицы (максимальная сумма по строкам) + double norm = Arrays.stream(A).mapToDouble(row -> Arrays.stream(row).map(Math::abs).sum()).max().orElse(0); + System.out.println("Норма матрицы " + norm); + + List errors = new ArrayList<>(); + double[] result = gaussSeidel(A, b, tol, errors); + System.out.println("Решение: " + Arrays.toString(result)); + System.out.println("Вектор погрешностей: " + errors); + } +} diff --git "a/\320\2403265-69/mamontov_409075/lab1/\320\222\321\213\321\207\320\234\320\260\321\202 \320\2331.pdf" "b/\320\2403265-69/mamontov_409075/lab1/\320\222\321\213\321\207\320\234\320\260\321\202 \320\2331.pdf" new file mode 100644 index 0000000..cc45057 Binary files /dev/null and "b/\320\2403265-69/mamontov_409075/lab1/\320\222\321\213\321\207\320\234\320\260\321\202 \320\2331.pdf" differ diff --git "a/\320\2403265-69/mamontov_409075/lab2/code/untitled2.py" "b/\320\2403265-69/mamontov_409075/lab2/code/untitled2.py" new file mode 100644 index 0000000..0a105e1 --- /dev/null +++ "b/\320\2403265-69/mamontov_409075/lab2/code/untitled2.py" @@ -0,0 +1,279 @@ +# -*- coding: utf-8 -*- +"""Untitled2.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/17OdidLbk-OukHDjd1h0XM-D2OYoiy5QT +""" + +import matplotlib.pyplot as plt +import numpy as np +import math +from typing import Callable, Tuple, Optional + +class NonlinearEquationSolver: + def __init__(self): + self.equations = { + 1: ("x^3 - x + 1", lambda x: x**3 - x + 1), + 2: ("sin(x) + 0.5", lambda x: math.sin(x) + 0.5), + 3: ("e^x - 2", lambda x: math.exp(x) - 2), + 4: ("x^2 - 4", lambda x: x**2 - 4), + 5: ("cos(x) - x", lambda x: math.cos(x) - x) + } + self.methods = { + 1: ("Метод хорд", self.chord_method), + 2: ("Метод секущих", self.secant_method), + 3: ("Метод простой итерации", self.simple_iteration_method) + } + + def display_menu(self, items: dict, title: str) -> int: + """Отображает меню и возвращает выбор пользователя""" + print(f"\n{title}:") + for key, (desc, _) in items.items(): + print(f"{key}. {desc}") + while True: + try: + choice = int(input("Выберите пункт: ")) + if choice in items: + return choice + print("Неверный выбор. Попробуйте снова.") + except ValueError: + print("Введите число.") + + def get_input_source(self) -> Tuple[float, float, float]: + """Получает источник ввода данных""" + print("\nВыберите источник ввода данных:") + print("1. Клавиатура") + print("2. Файл") + choice = input("Ваш выбор: ") + + if choice == "1": + a = float(input("Введите левую границу интервала a: ")) + b = float(input("Введите правую границу интервала b: ")) + eps = float(input("Введите точность eps: ")) + return a, b, eps + elif choice == "2": + filename = input("Введите имя файла: ") + with open(filename, 'r') as f: + a, b, eps = map(float, f.readline().split()) + return a, b, eps + + def get_output_destination(self) -> str: + """Получает место вывода результатов""" + print("\nВыберите куда выводить результаты:") + print("1. Экран") + print("2. Файл") + choice = input("Ваш выбор: ") + return "screen" if choice == "1" else "file" + + def verify_interval(self, f: Callable[[float], float], a: float, b: float) -> bool: + """Проверяет наличие корня на интервале""" + if a >= b: + print("Ошибка: a должно быть меньше b") + return False + + fa = f(a) + fb = f(b) + + if fa * fb > 0: + print(f"Ошибка: На интервале [{a}, {b}] функция не меняет знак (f(a)={fa:.3f}, f(b)={fb:.3f})") + return False + + return True + + def find_initial_guess(self, f: Callable[[float], float], a: float, b: float) -> float: + """Выбирает начальное приближение для методов""" + fa = f(a) + fb = f(b) + return a if abs(fa) < abs(fb) else b + + def chord_method(self, f: Callable[[float], float], a: float, b: float, eps: float) -> Tuple[float, float, int]: + """Метод хорд""" + x_prev = a + x_curr = b + iterations = 0 + + while True: + iterations += 1 + x_next = x_curr - f(x_curr) * (x_curr - x_prev) / (f(x_curr) - f(x_prev)) + + if abs(x_next - x_curr) < eps: + break + + x_prev, x_curr = x_curr, x_next + + return x_next, f(x_next), iterations + + def secant_method(self, f: Callable[[float], float], a: float, b: float, eps: float) -> Tuple[float, float, int]: + """Метод секущих""" + x0 = a + x1 = b + iterations = 0 + + while True: + iterations += 1 + if abs(f(x1) - f(x0)) < 1e-12: + print("Предупреждение: знаменатель близок к нулю в методе секущих") + break + + x_next = x1 - f(x1) * (x1 - x0) / (f(x1) - f(x0)) + + if abs(x_next - x1) < eps: + break + + x0, x1 = x1, x_next + + return x_next, f(x_next), iterations + + def simple_iteration_method(self, f: Callable[[float], float], a: float, b: float, eps: float) -> Tuple[Optional[float], Optional[float], int]: + """Метод простой итерации с строгой проверкой условия сходимости""" + try: + # Шаг для вычисления производных + h = max((b - a) / 100, 1e-5) + x_points = np.linspace(a, b, 100) + + # Вычисляем максимальное значение производной f + df_values = [] + for x in x_points: + try: + df = (f(x + h) - f(x)) / h + df_values.append(abs(df)) + except: + continue + + if not df_values: + print("Ошибка: не удалось вычислить производную функции на интервале") + return None, None, 0 + + df_max = max(df_values) + + if df_max < 1e-12: + print("Ошибка: производная слишком близка к нулю") + return None, None, 0 + + # Выбираем параметр преобразования + lambda_ = 1 / df_max + phi = lambda x: x - lambda_ * f(x) + + # Проверяем условие сходимости |phi'(x)| < 1 + dphi_values = [] + for x in x_points: + try: + dphi = (phi(x + h) - phi(x)) / h + dphi_values.append(abs(dphi)) + except: + continue + + if not dphi_values: + print("Ошибка: не удалось вычислить производную phi(x)") + return None, None, 0 + + dphi_max = max(dphi_values) + + # Жёсткая проверка условия сходимости + if dphi_max >= 1: + print(f"Ошибка: условие сходимости не выполняется (max|phi'|={dphi_max:.3f} ≥ 1)") + print("Метод простой итерации не может быть применён") + return None, None, 0 + + # Если условие сходимости выполняется, выполняем итерации + x_prev = (a + b) / 2 + iterations = 0 + max_iter = 1000 + + while iterations < max_iter: + iterations += 1 + try: + x_next = phi(x_prev) + except: + print("Ошибка при вычислении phi(x)") + return None, None, 0 + + if abs(x_next - x_prev) < eps: + return x_next, f(x_next), iterations + + x_prev = x_next + + print("Предупреждение: достигнуто максимальное число итераций") + return x_prev, f(x_prev), iterations + + except Exception as e: + print(f"Ошибка в методе простой итерации: {str(e)}") + return None, None, 0 + + def plot_function(self, f: Callable[[float], float], a: float, b: float, root: Optional[float] = None): + """Строит график функции""" + x = np.linspace(a, b, 400) + y = np.vectorize(f)(x) + + plt.figure(figsize=(10, 6)) + plt.plot(x, y, label="f(x)") + plt.axhline(0, color='black', linewidth=0.5) + plt.axvline(0, color='black', linewidth=0.5) + + if root is not None: + plt.scatter([root], [f(root)], color='red', label=f"Корень ({root:.5f})") + + plt.title("График функции") + plt.xlabel("x") + plt.ylabel("f(x)") + plt.grid(True) + plt.legend() + plt.show() + + def run(self): + """Основной цикл программы""" + print("Программа для решения нелинейных уравнений") + + # Выбор уравнения + eq_choice = self.display_menu(self.equations, "Доступные уравнения") + eq_name, f = self.equations[eq_choice] + print(f"\nВыбрано уравнение: {eq_name}") + + # Ввод данных + a, b, eps = self.get_input_source() + print(f"\nИсходные данные: a={a}, b={b}, eps={eps}") + + # Проверка интервала + if not self.verify_interval(f, a, b): + return + + # Выбор метода + method_choice = self.display_menu(self.methods, "Доступные методы") + method_name, method_func = self.methods[method_choice] + print(f"\nВыбран метод: {method_name}") + + # Вычисление корня + if method_choice == 3: # Метод простой итерации + root, f_root, iterations = method_func(f, a, b, eps) + # Если метод не выполнился из-за невыполнения условия сходимости + if root is None: + print("\nРасчёт не выполнен из-за невыполнения условий сходимости.") + return + else: + x0 = self.find_initial_guess(f, a, b) + root, f_root, iterations = method_func(f, a, b, eps) + + # Вывод результатов + output_dest = self.get_output_destination() + result = (f"\nРезультаты для уравнения {eq_name} на интервале [{a}, {b}]:\n" + f"Метод: {method_name}\n" + f"Найденный корень: {root:.8f}\n" + f"Значение функции в корне: {f_root:.8f}\n" + f"Количество итераций: {iterations}\n" + f"Точность: {eps}") + + if output_dest == "screen": + print(result) + else: + with open("result.txt", "w") as f_out: + f_out.write(result) + print("Результаты сохранены в файл 'result.txt'") + + # Построение графика + self.plot_function(f, a, b, root) + +if __name__ == "__main__": + solver = NonlinearEquationSolver() + solver.run() \ No newline at end of file diff --git "a/\320\2403265-69/mamontov_409075/lab2/reports/\320\222\321\213\321\207\320\234\320\260\321\202 2\320\273\320\260\320\261.pdf" "b/\320\2403265-69/mamontov_409075/lab2/reports/\320\222\321\213\321\207\320\234\320\260\321\202 2\320\273\320\260\320\261.pdf" new file mode 100644 index 0000000..d263c20 Binary files /dev/null and "b/\320\2403265-69/mamontov_409075/lab2/reports/\320\222\321\213\321\207\320\234\320\260\321\202 2\320\273\320\260\320\261.pdf" differ diff --git "a/\320\2403265-69/mamontov_409075/lab3/code/lab3.py" "b/\320\2403265-69/mamontov_409075/lab3/code/lab3.py" new file mode 100644 index 0000000..78cc034 --- /dev/null +++ "b/\320\2403265-69/mamontov_409075/lab3/code/lab3.py" @@ -0,0 +1,150 @@ +import math + +class FunctionCalculator: + @staticmethod + def calculate(func_id, x): + if func_id == 1: + return math.sin(x) + elif func_id == 2: + return x**2 + elif func_id == 3: + return math.exp(x) + elif func_id == 4: + return math.sqrt(x) + elif func_id == 5: + return 1 / (1 + x**2) + else: + raise ValueError("Неизвестный идентификатор функции") + + +class Integrator: + def __init__(self, func_id, a, b, epsilon, initial_n=4): + self.func_id = func_id + self.a = a + self.b = b + self.epsilon = epsilon + self.initial_n = initial_n + + def left_rectangles(self, n): + h = (self.b - self.a) / n + integral = 0.0 + for i in range(n): + x = self.a + i * h + integral += FunctionCalculator.calculate(self.func_id, x) + return integral * h + + def right_rectangles(self, n): + h = (self.b - self.a) / n + integral = 0.0 + for i in range(1, n+1): + x = self.a + i * h + integral += FunctionCalculator.calculate(self.func_id, x) + return integral * h + + def middle_rectangles(self, n): + h = (self.b - self.a) / n + integral = 0.0 + for i in range(n): + x = self.a + (i + 0.5) * h + integral += FunctionCalculator.calculate(self.func_id, x) + return integral * h + + def trapezoids(self, n): + h = (self.b - self.a) / n + integral = (FunctionCalculator.calculate(self.func_id, self.a) + + FunctionCalculator.calculate(self.func_id, self.b)) / 2 + for i in range(1, n): + x = self.a + i * h + integral += FunctionCalculator.calculate(self.func_id, x) + return integral * h + + def simpson(self, n): + if n % 2 != 0: + n += 1 # Метод Симпсона требует четное количество разбиений + h = (self.b - self.a) / n + integral = FunctionCalculator.calculate(self.func_id, self.a) + FunctionCalculator.calculate(self.func_id, self.b) + for i in range(1, n): + x = self.a + i * h + if i % 2 == 0: + integral += 2 * FunctionCalculator.calculate(self.func_id, x) + else: + integral += 4 * FunctionCalculator.calculate(self.func_id, x) + return integral * h / 3 + + def runge_rule(self, method, p): + n = self.initial_n + integral_n = method(n) + integral_2n = method(2 * n) + error = abs(integral_2n - integral_n) / (2**p - 1) + + while error > self.epsilon: + n *= 2 + integral_n = method(n) + integral_2n = method(2 * n) + error = abs(integral_2n - integral_n) / (2**p - 1) + + return integral_2n, 2 * n + + def integrate(self, method_name): + methods = { + 'left_rectangles': (self.left_rectangles, 1), + 'right_rectangles': (self.right_rectangles, 1), + 'middle_rectangles': (self.middle_rectangles, 2), + 'trapezoids': (self.trapezoids, 2), + 'simpson': (self.simpson, 4) + } + + if method_name not in methods: + raise ValueError("Неизвестный метод интегрирования") + + method, p = methods[method_name] + return self.runge_rule(method, p) + + +def print_functions(): + print("Доступные функции:") + print("1. sin(x)") + print("2. x^2") + print("3. e^x") + print("4. sqrt(x)") + print("5. 1/(1+x^2)") + + +def print_methods(): + print("Доступные методы интегрирования:") + print("1. Метод левых прямоугольников") + print("2. Метод правых прямоугольников") + print("3. Метод средних прямоугольников") + print("4. Метод трапеций") + print("5. Метод Симпсона") + + +print_functions() +func_id = int(input("Выберите функцию (1-5): ")) + +a = float(input("Введите нижний предел интегрирования: ")) +b = float(input("Введите верхний предел интегрирования: ")) +epsilon = float(input("Введите точность вычисления: ")) + +print_methods() +method_choice = int(input("Выберите метод интегрирования (1-5): ")) + +method_map = { + 1: 'left_rectangles', + 2: 'right_rectangles', + 3: 'middle_rectangles', + 4: 'trapezoids', + 5: 'simpson' +} + +method_name = method_map[method_choice] + +integrator = Integrator(func_id, a, b, epsilon) +result, n = integrator.integrate(method_name) + +print("\nРезультаты интегрирования:") +print(f"Значение интеграла: {result}") +print(f"Число разбиений интервала: {n}") +print(f"Достигнутая точность: {epsilon}") + + diff --git "a/\320\2403265-69/mamontov_409075/lab3/reports/\320\222\321\213\321\207\320\234\320\260\321\202 \320\273\320\260\320\261 3 \320\234\320\260\320\274\320\276\320\275\321\202\320\276\320\262.pdf" "b/\320\2403265-69/mamontov_409075/lab3/reports/\320\222\321\213\321\207\320\234\320\260\321\202 \320\273\320\260\320\261 3 \320\234\320\260\320\274\320\276\320\275\321\202\320\276\320\262.pdf" new file mode 100644 index 0000000..05adc40 Binary files /dev/null and "b/\320\2403265-69/mamontov_409075/lab3/reports/\320\222\321\213\321\207\320\234\320\260\321\202 \320\273\320\260\320\261 3 \320\234\320\260\320\274\320\276\320\275\321\202\320\276\320\262.pdf" differ diff --git "a/\320\2403265-69/mamontov_409075/lab4/code/lab4.py" "b/\320\2403265-69/mamontov_409075/lab4/code/lab4.py" new file mode 100644 index 0000000..dcbba7f --- /dev/null +++ "b/\320\2403265-69/mamontov_409075/lab4/code/lab4.py" @@ -0,0 +1,272 @@ +# -*- coding: utf-8 -*- +"""lab4.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1bh6XImx_E863m2C2C1gw2wPUMHMpkGVw +""" + +import math +import matplotlib.pyplot as plt + +# Ввод с клавиатуры +def read_data_console(): + n = int(input("Введите количество точек: ")) + x, y = [], [] + for _ in range(n): + xi, yi = map(float, input("Введите x и y: ").split()) + x.append(xi) + y.append(yi) + return x, y + +# Ввод из файла: формат — по одной паре x y на строку +def read_data_file(): + filename = input("Введите имя файла: ") + x, y = [], [] + with open(filename, 'r') as f: + for line in f: + if line.strip(): + xi, yi = map(float, line.strip().split()) + x.append(xi) + y.append(yi) + return x, y + + + +def mean(values): + return sum(values) / len(values) + + +# Решение системы линейных уравнений методом Гаусса +def solve_slae(A, b): + n = len(b) + + for i in range(n): + max_row = max(range(i, n), key=lambda k: abs(A[k][i])) + A[i], A[max_row] = A[max_row], A[i] + b[i], b[max_row] = b[max_row], b[i] + + for j in range(i + 1, n): + coef = A[j][i] / A[i][i] + for k in range(i, n): + A[j][k] -= coef * A[i][k] + b[j] -= coef * b[i] + + x = [0] * n + for i in reversed(range(n)): + s = sum(A[i][j] * x[j] for j in range(i + 1, n)) + x[i] = (b[i] - s) / A[i][i] + return x + + + +# Линейная: y = a·x + b +def lin_approx(x, y): + + #Строим приближающую прямую y = a·x + b по МНК. + n = len(x) + sx = sum(x) + sy = sum(y) + sxx = sum(xi**2 for xi in x) + sxy = sum(xi * yi for xi, yi in zip(x, y)) + + # Решаем систему: + # a * Σx^2 + b * Σx = Σx*y + # a * Σx + b * n = Σy + + a = (n * sxy - sx * sy) / (n * sxx - sx**2) + b = (sy - a * sx) / n + + return lambda t: a * t + b, (a, b) + +# Квадратичная: y = a2·x² + a1·x + a0 +def quad_approx(x, y): + + #Строим параболу по методу наименьших квадратов. + n = len(x) + + # Вычисляем все необходимые суммы: + sx = sum(x) + sx2 = sum(xi**2 for xi in x) + sx3 = sum(xi**3 for xi in x) + sx4 = sum(xi**4 for xi in x) + sy = sum(y) + sxy = sum(xi * yi for xi, yi in zip(x, y)) + sx2y = sum(xi**2 * yi for xi, yi in zip(x, y)) + + # Составляем систему: + # a2*Σx^4 + a1*Σx^3 + a0*Σx^2 = Σx^2·y + # a2*Σx^3 + a1*Σx^2 + a0*Σx = Σx·y + # a2*Σx^2 + a1*Σx + a0*n = Σy + + A = [ + [sx4, sx3, sx2], + [sx3, sx2, sx], + [sx2, sx, n] + ] + b = [sx2y, sxy, sy] + + a2, a1, a0 = solve_slae(A, b) + + return lambda t: a2 * t**2 + a1 * t + a0, (a2, a1, a0) + + +# Кубическая: y = a3·x³ + a2·x² + a1·x + a0 +def cubic_approx(x, y): + + # Строим кубическую кривую по методу наименьших квадратов. + n = len(x) + + # Вычисляем все суммы до шестой степени + sx = sum(x) + sx2 = sum(xi**2 for xi in x) + sx3 = sum(xi**3 for xi in x) + sx4 = sum(xi**4 for xi in x) + sx5 = sum(xi**5 for xi in x) + sx6 = sum(xi**6 for xi in x) + sy = sum(y) + sxy = sum(xi * yi for xi, yi in zip(x, y)) + sx2y = sum(xi**2 * yi for xi, yi in zip(x, y)) + sx3y = sum(xi**3 * yi for xi, yi in zip(x, y)) + + # Составляем систему на 4 неизвестных: a3, a2, a1, a0 + A = [ + [sx6, sx5, sx4, sx3], + [sx5, sx4, sx3, sx2], + [sx4, sx3, sx2, sx], + [sx3, sx2, sx, n] + ] + b = [sx3y, sx2y, sxy, sy] + + a3, a2, a1, a0 = solve_slae(A, b) + + return lambda t: a3*t**3 + a2*t**2 + a1*t + a0, (a3, a2, a1, a0) + + +# Экспоненциальная: y = a·e^(b·x) +def exp_approx(x, y): + # Линеаризуем модель: ln(y) = ln(a) + b·x, решаем как линейную. + + Y = [math.log(yi) for yi in y] # ln(y) + f, (b, ln_a) = lin_approx(x, Y) + a = math.exp(ln_a) + return lambda t: a * math.exp(b * t), (a, b) + + +# Логарифмическая: y = a·ln(x) + b +def log_approx(x, y): + + #Аппроксимация функции вида y = a * ln(x) + b + #Работает только для x > 0 + # Проверка на допустимость значений + + if any(xi <= 0 for xi in x): + raise ValueError("Логарифмическая аппроксимация применима только при x > 0") + + # Логарифмируем x + X = [math.log(xi) for xi in x] + + # Аппроксимируем линейной функцией: ln(x) → X, y — без изменений + f_lin, (a, b) = lin_approx(X, y) + + # Возвращаем восстановленную функцию по x: y = a * ln(x) + b + def f_log(t): + if t <= 0: + return float('nan') # безопасное значение при попытке log(0) или log(<0) + return a * math.log(t) + b + + return f_log, (a, b) + +# Степенная: y = a·x^b +def power_approx(x, y): + # Логарифмируем обе переменные: ln(y) = ln(a) + b·ln(x) + + X = [math.log(xi) for xi in x] + Y = [math.log(yi) for yi in y] + f, (b, ln_a) = lin_approx(X, Y) + a = math.exp(ln_a) + return lambda t: a * t**b, (a, b) + + +# Среднеквадратическое отклонение +def deviation(f, x, y): + return math.sqrt(sum((f(xi) - yi)**2 for xi, yi in zip(x, y)) / len(x)) + + +# Коэффициент корреляции Пирсона +def correlation(x, y): + mx, my = mean(x), mean(y) + num = sum((xi - mx) * (yi - my) for xi, yi in zip(x, y)) + den = math.sqrt(sum((xi - mx)**2 for xi in x) * sum((yi - my)**2 for yi in y)) + return num / den + +# Коэффициент детерминации +def determination(r): + R2 = r**2 + if R2 > 0.9: + msg = "сильная зависимость" + elif R2 > 0.7: + msg = "умеренная зависимость" + else: + msg = "слабая зависимость" + return R2, msg + + + +def main(): + print("Выберите способ ввода данных:") + print("1 - Ввод с клавиатуры") + print("2 - Ввод из файла") + choice = input("Ваш выбор: ") + + if choice == "1": + x, y = read_data_console() + elif choice == "2": + x, y = read_data_file() + else: + print("Неверный выбор.") + return + + funcs = { + "Линейная": lin_approx, + "Квадратичная": quad_approx, + "Кубическая": cubic_approx, + "Экспоненциальная": exp_approx, + "Логарифмическая": log_approx, + "Степенная": power_approx + } + + results = {} + for name, approx in funcs.items(): + try: + f, coeffs = approx(x, y) + dev = deviation(f, x, y) + results[name] = (f, coeffs, dev) + print(f"{name}: коэффициенты = {coeffs}, отклонение = {dev:.3f}") + except Exception as e: + print(f"{name}: ошибка ({e})") + + best = min(results.items(), key=lambda item: item[1][2]) + print(f"\n Лучшая аппроксимация: {best[0]}") + + if "Линейная" in results: + r = correlation(x, y) + R2, msg = determination(r) + print(f"Коэф. корреляции: {r:.3f}, детерминации: {R2:.3f} — {msg}") + + # Построение графиков + plt.scatter(x, y, label="Исходные данные", color="black") + min_x, max_x = min(x), max(x) + t_vals = [min_x - 1 + i * 0.1 for i in range(int((max_x - min_x + 2) * 10))] + for name, (f, _, _) in results.items(): + y_vals = [f(t) for t in t_vals] + plt.plot(t_vals, y_vals, label=name) + + plt.legend() + plt.grid() + plt.title("Аппроксимации методом наименьших квадратов") + plt.show() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git "a/\320\2403265-69/mamontov_409075/lab4/reports/\320\222\321\213\321\207\320\234\320\260\321\202 \320\233\320\260\320\2614.pdf" "b/\320\2403265-69/mamontov_409075/lab4/reports/\320\222\321\213\321\207\320\234\320\260\321\202 \320\233\320\260\320\2614.pdf" new file mode 100644 index 0000000..b8fb49d Binary files /dev/null and "b/\320\2403265-69/mamontov_409075/lab4/reports/\320\222\321\213\321\207\320\234\320\260\321\202 \320\233\320\260\320\2614.pdf" differ diff --git "a/\320\2403265-69/mamontov_409075/lab5/code/lab5.py" "b/\320\2403265-69/mamontov_409075/lab5/code/lab5.py" new file mode 100644 index 0000000..1b8929e --- /dev/null +++ "b/\320\2403265-69/mamontov_409075/lab5/code/lab5.py" @@ -0,0 +1,233 @@ +# -*- coding: utf-8 -*- +"""lab5.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/103T3_L_UMKZL9wyCRlgRSQmFTqinB9rQ +""" + +import math +import matplotlib.pyplot as plt + +# Метод Лагранжа: позволяет интерполировать значение функции в точке x, +# используя формулу, в которой каждый член строится на основе всех других x. +def lagrange_interpolation(x_values, y_values, x): + result = 0 + n = len(x_values) + for i in range(n): + term = y_values[i] # начинаем с y_i + for j in range(n): + if i != j: + # умножаем на (x - x_j) / (x_i - x_j) для всех j ≠ i + # эта часть формирует базисный полином L_i(x) + term *= (x - x_values[j]) / (x_values[i] - x_values[j]) + result += term # суммируем все члены: f(x) ≈ Σ y_i * L_i(x) + return result + +# Метод Ньютона (разделённые разности): работает с любыми x, даже если шаг не одинаковый +# Постепенно строится таблица разделённых разностей, используется для построения полинома + +def newton_divided_differences(x_values, y_values, x): + n = len(x_values) + coef = y_values.copy() # коэффициенты разделённых разностей, начнем с y_i + for j in range(1, n): + for i in range(n - 1, j - 1, -1): + # формула разделённой разности: + # f[x_i,...,x_{i-j}] = (f[x_i,...,x_{i-j+1}] - f[x_{i-1},...,x_{i-j}]) / (x_i - x_{i-j}) + coef[i] = (coef[i] - coef[i - 1]) / (x_values[i] - x_values[i - j]) + result = coef[-1] # начинаем с самого последнего коэффициента + for i in range(n - 2, -1, -1): + # полином строится справа налево: P(x) = (...(a_n * (x - x_{n-1}) + a_{n-1})...) + a_0 + result = result * (x - x_values[i]) + coef[i] + return result + +# Метод Ньютона (конечные разности вперёд): требует равномерный шаг между x +# Строим таблицу разностей, используем t = (x - x0) / h + +def newton_forward_difference(x_values, y_values, x): + n = len(x_values) + h = x_values[1] - x_values[0] # вычисляем шаг h + for i in range(1, n - 1): + if abs((x_values[i + 1] - x_values[i]) - h) > 1e-10: + raise ValueError("x не равномерны — метод Ньютона с конечными разностями неприменим.") + diff_table = [y_values.copy()] # первая строка таблицы — значения функции + for i in range(1, n): + current_diff = [] + for j in range(n - i): + # вычисляем разности: Δ^k f(x) = Δ^{k-1} f(x_{i+1}) - Δ^{k-1} f(x_i) + current_diff.append(diff_table[i - 1][j + 1] - diff_table[i - 1][j]) + diff_table.append(current_diff) + t = (x - x_values[0]) / h # нормализованное расстояние до x0 + result = y_values[0] # начинаем с f(x0) + term = 1 + for i in range(1, n): + # вычисляем t(t - 1)(t - 2)... / i! + term *= (t - (i - 1)) / i + # добавляем i-ю разность, умноженную на соответствующий коэффициент + result += term * 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] # шаг + for i in range(1, n - 1): + if abs((x_values[i + 1] - x_values[i]) - h) > 1e-10: + raise ValueError("x не равномерны — метод назад неприменим.") + diff_table = [y_values.copy()] # начальные значения + for i in range(1, n): + current_diff = [] + for j in range(n - i): + # строим таблицу разностей, как и для метода вперёд + current_diff.append(diff_table[i - 1][j + 1] - diff_table[i - 1][j]) + diff_table.append(current_diff) + t = (x - x_values[-1]) / h # нормализованное расстояние от последнего узла + result = y_values[-1] # начинаем с f(x_n) + term = 1 + for i in range(1, n): + # коэффициенты вида t(t+1)(t+2)... / i! + term *= (t + i - 1) / i + # добавляем соответствующую разность с конца таблицы + result += term * diff_table[i][-1] + return result + +#Ввод данных +def input_points_from_keyboard(): + print("Введите количество точек:") + n = int(input()) + x_values = [] + y_values = [] + print("Введите значения x и y через пробел, по одной паре на строку:") + for _ in range(n): + x, y = map(float, input().split()) + x_values.append(x) + y_values.append(y) + return x_values, y_values + +def input_points_from_file(): + print("Введите путь к файлу: ") + filename = input().strip() + x_values, y_values = [], [] + with open(filename, 'r') as f: + for line in f: + x, y = map(float, line.strip().split()) + x_values.append(x) + y_values.append(y) + return x_values, y_values + +def input_points_from_function(): + print("Выберите функцию:") + print("1 — sin(x)") + print("2 — cos(x)") + print("3 — exp(x)") + choice = input("Ваш выбор: ") + func = math.sin + if choice == '2': + func = math.cos + elif choice == '3': + func = math.exp + + a = float(input("Начало интервала: ")) + b = float(input("Конец интервала: ")) + n = int(input("Количество точек: ")) + x_values = [a + i * (b - a) / (n - 1) for i in range(n)] + y_values = [func(x) for x in x_values] + return x_values, y_values + +#Таблица конечных разностей +def print_forward_difference_table(x_values, y_values): + n = len(x_values) + table = [y_values.copy()] + for i in range(1, n): + row = [table[i - 1][j + 1] - table[i - 1][j] for j in range(n - i)] + table.append(row) + print("\nТаблица конечных разностей:") + for i in range(n): + print(f"{x_values[i]:>6.3f} |", end='') + for j in range(n - i): + print(f" {table[j][i]:>10.6f}", end='') + print() + +#Графики +def plot_interpolation(x_values, y_values, method_func, label): + xs = [x_values[0] + i * 0.01 for i in range(int((x_values[-1] - x_values[0]) / 0.01) + 1)] + ys = [method_func(x_values, y_values, x) for x in xs] + plt.plot(xs, ys, label=label) + + +def main(): + print("Выберите способ ввода данных:") + print("1 — ввод с клавиатуры") + print("2 — ввод из файла") + print("3 — по заданной функции") + choice = input("Ваш выбор: ") + + if choice == '1': + x_values, y_values = input_points_from_keyboard() + elif choice == '2': + x_values, y_values = input_points_from_file() + elif choice == '3': + x_values, y_values = input_points_from_function() + else: + print("Неверный выбор.") + return + + print_forward_difference_table(x_values, y_values) + + x = float(input("Введите значение x, в котором нужно интерполировать: ")) + + try: + l = lagrange_interpolation(x_values, y_values, x) + print(f"Значение по Лагранжу: {l:.6f}") + except Exception as e: + print(f"Ошибка Лагранжа: {e}") + + try: + nd = newton_divided_differences(x_values, y_values, x) + print(f"Ньютон (разделённые): {nd:.6f}") + except Exception as e: + print(f"Ошибка Ньютона (разделённые): {e}") + + try: + nf = newton_forward_difference(x_values, y_values, x) + print(f"Ньютон (вперёд): {nf:.6f}") + except Exception as e: + print(f"Ошибка Ньютона (вперёд): {e}") + + try: + nb = newton_backward_difference(x_values, y_values, x) + print(f"Ньютон (назад): {nb:.6f}") + except Exception as e: + print(f"Ошибка Ньютона (назад): {e}") + + # Построение графиков + plt.figure(figsize=(10, 6)) + plt.scatter(x_values, y_values, color='black', label='Узлы') + try: + plot_interpolation(x_values, y_values, lagrange_interpolation, 'Лагранж') + except: + pass + try: + plot_interpolation(x_values, y_values, newton_divided_differences, 'Ньютон (разделённые)') + except: + pass + try: + plot_interpolation(x_values, y_values, newton_forward_difference, 'Ньютон (вперёд)') + except: + pass + try: + plot_interpolation(x_values, y_values, newton_backward_difference, 'Ньютон (назад)') + except: + pass + + plt.title("Интерполяционные многочлены") + plt.xlabel("x") + plt.ylabel("f(x)") + plt.grid(True) + plt.legend() + plt.show() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git "a/\320\2403265-69/mamontov_409075/lab5/reports/\320\222\321\213\321\207\320\274\320\260\321\202 \320\233\320\260\320\2615.pdf" "b/\320\2403265-69/mamontov_409075/lab5/reports/\320\222\321\213\321\207\320\274\320\260\321\202 \320\233\320\260\320\2615.pdf" new file mode 100644 index 0000000..a2dce7d Binary files /dev/null and "b/\320\2403265-69/mamontov_409075/lab5/reports/\320\222\321\213\321\207\320\274\320\260\321\202 \320\233\320\260\320\2615.pdf" differ diff --git "a/\320\2403265-69/mamontov_409075/lab6/code/lab6.py" "b/\320\2403265-69/mamontov_409075/lab6/code/lab6.py" new file mode 100644 index 0000000..3a1dde3 --- /dev/null +++ "b/\320\2403265-69/mamontov_409075/lab6/code/lab6.py" @@ -0,0 +1,187 @@ +# -*- coding: utf-8 -*- +"""lab6.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1mUMvb78cVWu84ETx80h_ktkez1grPSXw +""" + +import numpy as np +import matplotlib.pyplot as plt +import math + +# 1. y' = y - x^2 + 1, точное решение: y = (x + 1)^2 - 0.5e^x +def f1(x, y): + return y - x**2 + 1 + +def f1_exact(x): + return (x + 1)**2 - 0.5 * math.exp(x) + +# 2. y' = x * sqrt(y), точное решение: y = (x^2 / 4 + sqrt(y0))^2 +def f2(x, y): + return x * math.sqrt(y) + +def f2_exact(x, y0): + return (x**2 / 4 + math.sqrt(y0))**2 + +# 3. y' = x + y, точное решение: y = Ce^x - x - 1 +def f3(x, y): + return x + y + +def f3_exact(x, x0, y0): + C = (y0 + x0 + 1) * math.exp(-x0) + return C * math.exp(x) - x - 1 + +def choose_equation(x0, y0): + print("Выберите ОДУ для решения:") + print("1: y' = y - x^2 + 1") + print("2: y' = x * sqrt(y)") + print("3: y' = x + y") + + while True: + choice = input("Введите номер уравнения (1, 2 или 3): ") + if choice == '1': + return f1, f1_exact + elif choice == '2': + return f2, lambda x: f2_exact(x, y0) + elif choice == '3': + return f3, lambda x: f3_exact(x, x0, y0) + else: + print("Неверный выбор. Повторите.") + + +def get_user_input(): + x0 = float(input("Введите x0: ")) + y0 = float(input("Введите y0: ")) + xn = float(input("Введите xn: ")) + h = float(input("Введите шаг h: ")) + eps = float(input("Введите точность eps: ")) + return x0, y0, xn, h, eps + +#Метод Эйлера +def euler_method(f, x0, y0, xn, h): + x_vals = [x0] + y_vals = [y0] + x = x0 + y = y0 + # Шаг за шагом вычисляем y_{i+1} = y_i + h*f(x_i, y_i) + while x < xn: + y += h * f(x, y) + x = round(x + h, 10) + x_vals.append(x) + y_vals.append(y) + return x_vals, y_vals + +#Метод Рунге-Кутта 4-го порядка +def runge_kutta_method(f, x0, y0, xn, h): + x_vals = [x0] + y_vals = [y0] + x = x0 + y = y0 + # Вычисляем y_{i+1} с помощью взвешенного среднего значений производных + while x < xn: + k1 = h * f(x, y) + k2 = h * f(x + h / 2, y + k1 / 2) + k3 = h * f(x + h / 2, y + k2 / 2) + k4 = h * f(x + h, y + k3) + y += (k1 + 2*k2 + 2*k3 + k4) / 6 + x = round(x + h, 10) + x_vals.append(x) + y_vals.append(y) + return x_vals, y_vals + +#Метод Милна (предиктор-корректор) +def milne_method(f, x0, y0, xn, h): + # Сначала получаем 4 стартовые точки методом Рунге-Кутта + x_init, y_init = runge_kutta_method(f, x0, y0, x0 + 3 * h, h) + x_vals = x_init.copy() + y_vals = y_init.copy() + i = 3 + # На каждом шаге: + # Предиктор: y_{i+1} = y_{i-3} + (4h/3)(2f_{i-2} - f_{i-1} + 2f_i) + # Корректор: y_{i+1} = y_{i-1} + (h/3)(f_{i-1} + 4f_i + f_{i+1}) + while x_vals[-1] < xn: + y_pred = y_vals[i-3] + (4*h/3)*(2*f(x_vals[i-2], y_vals[i-2]) - f(x_vals[i-1], y_vals[i-1]) + 2*f(x_vals[i], y_vals[i])) + x_next = round(x_vals[i] + h, 10) + f_next = f(x_next, y_pred) + y_corr = y_vals[i-1] + (h/3)*(f(x_vals[i-1], y_vals[i-1]) + 4*f(x_vals[i], y_vals[i]) + f_next) + x_vals.append(x_next) + y_vals.append(y_corr) + i += 1 + return x_vals, y_vals + +#Таблица решений +def print_table(x_vals, y_vals, y_exact_func): + print(f"{'x':>10} | {'y (числ.)':>15} | {'y (точн.)':>15} | {'|погр|':>10}") + print("-" * 60) + for x, y_num in zip(x_vals, y_vals): + y_exact = y_exact_func(x) + error = abs(y_exact - y_num) + print(f"{x:10.5f} | {y_num:15.8f} | {y_exact:15.8f} | {error:10.2e}") + +#Правило Рунге для вычисления ошибок +def runge_error(method, f, x0, y0, xn, h, p): + # Решения при шаге h и h/2 + _, y_h = method(f, x0, y0, xn, h) + _, y_half = method(f, x0, y0, xn, h / 2) + + # Сравниваем только те точки, которые совпадают по x + y_half_aligned = y_half[::2] # каждая вторая точка из шага h/2 + + errors = [abs(y_big - y_small) / (2**p - 1) for y_big, y_small in zip(y_h, y_half_aligned)] + return max(errors) + +#Построение графиков +def plot_solutions(x_vals, y1, y2, y3, y_exact_func): + x_exact = np.linspace(x_vals[0], x_vals[-1], 200) + y_exact = [y_exact_func(x) for x in x_exact] + plt.figure(figsize=(10, 6)) + plt.plot(x_exact, y_exact, label='Точное решение', color='black', linewidth=2) + plt.plot(x_vals, y1, 'o-', label='Метод Эйлера', color='blue') + plt.plot(x_vals, y2, 's-', label='Метод Рунге-Кутта', color='green') + plt.plot(x_vals, y3, '^-', label='Метод Милна', color='red') + plt.xlabel('x') + plt.ylabel('y') + plt.title('Численные и точные решения ОДУ') + plt.legend() + plt.grid(True) + plt.show() + +if __name__ == "__main__": + x0, y0, xn, h, eps = get_user_input() + f, exact = choose_equation(x0, y0) + + x_e, y_euler = euler_method(f, x0, y0, xn, h) + x_rk, y_rk = runge_kutta_method(f, x0, y0, xn, h) + x_milne, y_milne = milne_method(f, x0, y0, xn, h) + + print("\nРезультаты метода Эйлера:") + print_table(x_e, y_euler, exact) + + print("\nРезультаты метода Рунге-Кутта:") + print_table(x_rk, y_rk, exact) + + print("\nРезультаты метода Милна:") + print_table(x_milne, y_milne, exact) + + min_len = min(len(x_e), len(y_rk), len(y_milne)) + + x_vals_common = x_e[:min_len] + y_euler_trimmed = y_euler[:min_len] + y_rk_trimmed = y_rk[:min_len] + y_milne_trimmed = y_milne[:min_len] + + plot_solutions(x_vals_common, y_euler_trimmed, y_rk_trimmed, y_milne_trimmed, exact) + + # Оценка точности по правилу Рунге + euler_runge_error = runge_error(euler_method, f, x0, y0, xn, h, p=1) + rk_runge_error = runge_error(runge_kutta_method, f, x0, y0, xn, h, p=4) + + # Оценка ошибки метода Милна через точное решение + milne_errors = [abs(exact(x) - y) for x, y in zip(x_milne, y_milne)] + milne_max_error = max(milne_errors) + + print(f"\nПогрешность метода Эйлера по правилу Рунге: {euler_runge_error:.2e}") + print(f"Погрешность метода Рунге-Кутта по правилу Рунге: {rk_runge_error:.2e}") + print(f"Максимальная погрешность метода Милна (сравнение с точным): {milne_max_error:.2e}") \ No newline at end of file diff --git "a/\320\2403265-69/mamontov_409075/lab6/reports/\320\233\320\260\320\2616 \320\222\321\213\321\207\320\274\320\260\321\202.pdf" "b/\320\2403265-69/mamontov_409075/lab6/reports/\320\233\320\260\320\2616 \320\222\321\213\321\207\320\274\320\260\321\202.pdf" new file mode 100644 index 0000000..8d96810 Binary files /dev/null and "b/\320\2403265-69/mamontov_409075/lab6/reports/\320\233\320\260\320\2616 \320\222\321\213\321\207\320\274\320\260\321\202.pdf" differ