diff --git "a/\320\2403213/yusupova_409938/lab1/main.py" "b/\320\2403213/yusupova_409938/lab1/main.py" new file mode 100644 index 0000000..2d55db0 --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab1/main.py" @@ -0,0 +1,16 @@ +import sys +from PyQt6.QtWidgets import QApplication +from ui import SLAUSolverUI +from solver import SimpleIterationSolver + +if __name__ == "__main__": + app = QApplication(sys.argv) + + # Создаем объект метода решения + solver_method = SimpleIterationSolver() + + # Передаем метод решения в интерфейс + solver = SLAUSolverUI(solver_method) + solver.show() + + sys.exit(app.exec()) diff --git "a/\320\2403213/yusupova_409938/lab1/reports/\320\233\320\240\342\204\2261.pdf" "b/\320\2403213/yusupova_409938/lab1/reports/\320\233\320\240\342\204\2261.pdf" new file mode 100644 index 0000000..af4460b Binary files /dev/null and "b/\320\2403213/yusupova_409938/lab1/reports/\320\233\320\240\342\204\2261.pdf" differ diff --git "a/\320\2403213/yusupova_409938/lab1/solver.py" "b/\320\2403213/yusupova_409938/lab1/solver.py" new file mode 100644 index 0000000..ba00c53 --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab1/solver.py" @@ -0,0 +1,69 @@ +import numpy as np +import random + +DEFAULT_EPSILON = 1e-6 +MAX_ITERATIONS = 1000 +MAX_MATRIX_SIZE = 20 + +# Абстракция для решения СЛАУ +class SLAUSolverMethod: + def solve(self, A, b, eps=DEFAULT_EPSILON, max_iter=MAX_ITERATIONS): + pass + +# Реализация метода простых итераций +class SimpleIterationSolver(SLAUSolverMethod): + def solve(self, A, b, eps=DEFAULT_EPSILON, max_iter=MAX_ITERATIONS): + A_new, b_new, warning = rearrange_for_diagonal_dominance(A, b) + result_message = warning or "" + + n = len(A_new) + x = np.zeros(n) + B = np.zeros((n, n)) + c = np.zeros(n) + + # Приведение к форме x = Bx + C + for i in range(n): + c[i] = b_new[i] / A_new[i, i] + for j in range(n): + if i != j: + B[i, j] = -A_new[i, j] / A_new[i, i] + + norm_B = np.max(np.sum(np.abs(B), axis=1)) # Норма по строкам + if norm_B >= 1: + return None, f"{result_message}Решений нет. Метод не сходится, так как норма матрицы B ≥ 1.\n", norm_B + + iter_count = 0 + while iter_count < max_iter: + x_new = np.dot(B, x) + c + if np.linalg.norm(x_new - x, ord=np.inf) < eps: + residual = np.dot(A_new, x_new) - b_new + return x_new, iter_count, residual, result_message, norm_B + x = x_new + iter_count += 1 + + return None, f"{result_message}Превышено максимальное количество итераций.", norm_B + + +def rearrange_for_diagonal_dominance(A, b): + n = len(A) + A = A.copy() + b = b.copy() + + for i in range(n): + max_col = np.argmax(np.abs(A[i, :])) # Находим индекс максимального по модулю элемента в строке + if max_col != i: + A[:, [i, max_col]] = A[:, [max_col, i]] # Переставляем столбцы + # Проверка на диагональное преобладание + for i in range(n): + row_sum = np.sum(np.abs(A[i, :])) - np.abs(A[i, i]) + if np.abs(A[i, i]) < row_sum: + return A, b, "Не удалось достичь диагонального преобладания. Пробуем решить без него.\n" + return A, b, None + +def generate_random_matrix(n, min_val=-10, max_val=10): + A = np.random.randint(min_val, max_val + 1, size=(n, n)).astype(float) + b = np.random.randint(min_val, max_val + 1, size=n).astype(float) + + for i in range(n): + A[i, i] = sum(abs(A[i])) + random.uniform(1, 5) + return A, b \ No newline at end of file diff --git "a/\320\2403213/yusupova_409938/lab1/ui.py" "b/\320\2403213/yusupova_409938/lab1/ui.py" new file mode 100644 index 0000000..4f0219f --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab1/ui.py" @@ -0,0 +1,205 @@ +from PyQt6.QtWidgets import ( + QApplication, QWidget, QPushButton, QVBoxLayout, QTextEdit, QFileDialog, QLabel, QLineEdit, QGridLayout, + QMessageBox +) +import numpy as np +from solver import generate_random_matrix + + +class SLAUSolverUI(QWidget): + def __init__(self, solver_method): + super().__init__() + self.solver_method = solver_method + self.initUI() + + def initUI(self): + self.layout = QVBoxLayout() + + self.label = QLabel("Введите размерность матрицы (n ≤ 20):") + self.layout.addWidget(self.label) + + self.size_input = QLineEdit() + self.layout.addWidget(self.size_input) + + self.label_eps = QLabel("Введите точность (epsilon):") + self.layout.addWidget(self.label_eps) + + self.eps_input = QLineEdit() + self.layout.addWidget(self.eps_input) + + self.generate_matrix_button = QPushButton("Создать матрицу") + self.generate_matrix_button.clicked.connect(self.create_matrix_input) + self.layout.addWidget(self.generate_matrix_button) + + self.random_matrix_button = QPushButton("Случайная матрица") + self.random_matrix_button.clicked.connect(self.fill_random_matrix) + self.layout.addWidget(self.random_matrix_button) + + self.matrix_layout = QGridLayout() + self.layout.addLayout(self.matrix_layout) + + self.solveButton = QPushButton("Решить") + self.solveButton.clicked.connect(self.solve_slae) + self.layout.addWidget(self.solveButton) + + self.loadButton = QPushButton("Загрузить из файла") + self.loadButton.clicked.connect(self.load_from_file) + self.layout.addWidget(self.loadButton) + + # Текстовое поле для результатов + self.resultText = QTextEdit() + self.resultText.setReadOnly(True) + self.layout.addWidget(self.resultText) + + self.setLayout(self.layout) + self.setWindowTitle("Решение СЛАУ методом простых итераций") + self.resize(600, 400) + + self.matrix_inputs = [] + + def create_matrix_input(self): + # Очистка текущих полей + for i in reversed(range(self.matrix_layout.count())): + self.matrix_layout.itemAt(i).widget().setParent(None) + + try: + n = int(self.size_input.text()) + if not (1 <= n <= 20): + self.show_error_message("Ошибка: размерность должна быть от 1 до 20.") + return + + eps_text = self.eps_input.text().strip() + if not eps_text: + self.show_error_message("Ошибка: введите точность (epsilon).") + return + + try: + eps = float(eps_text) + if eps <= 0: + raise ValueError + except ValueError: + self.show_error_message("Ошибка: epsilon должен быть положительным числом.") + return + + self.matrix_inputs = [[QLineEdit() for _ in range(n + 1)] for _ in range(n)] + for i in range(n): + for j in range(n + 1): + self.matrix_layout.addWidget(self.matrix_inputs[i][j], i, j) + + except ValueError: + self.show_error_message("Ошибка: введите корректное число.") + + def fill_random_matrix(self): + try: + n = int(self.size_input.text()) + if not (1 <= n <= 20): + self.show_error_message("Ошибка: размерность должна быть от 1 до 20.") + return + + eps_text = self.eps_input.text().strip() + if not eps_text: + self.show_error_message("Ошибка: введите точность (epsilon).") + return + + try: + eps = float(eps_text) + if eps <= 0: + raise ValueError + except ValueError: + self.show_error_message("Ошибка: epsilon должен быть положительным числом.") + return + + A, b = generate_random_matrix(n) + self.create_matrix_input() + + for i in range(n): + for j in range(n): + self.matrix_inputs[i][j].setText(str(A[i, j])) + self.matrix_inputs[i][-1].setText(str(b[i])) + + except ValueError: + self.show_error_message("Введите корректное число.") + + def solve_slae(self): + try: + n = len(self.matrix_inputs) + + # Проверка epsilon + eps_text = self.eps_input.text().strip() + if not eps_text: + self.show_error_message("Ошибка: введите точность (epsilon).") + return + + try: + eps = float(eps_text) + if eps <= 0: + raise ValueError + except ValueError: + self.show_error_message("Ошибка: epsilon должен быть положительным числом.") + return + + A = np.array([[float(self.matrix_inputs[i][j].text()) for j in range(n)] for i in range(n)]) + B = np.array([float(self.matrix_inputs[i][-1].text()) for i in range(n)]) + + result = self.solver_method.solve(A, B, eps) + if result[0] is None: + self.resultText.setText(result[1]) + else: + x, iter_count, residual, warning, norm_B = result + + x_str = ', '.join([f"{int(val) if val.is_integer() else val:.6f}" for val in x]) + residual_str = ', '.join([f"{int(val) if val.is_integer() else val:.6f}" for val in residual]) + + self.resultText.setText( + f"Норма матрицы: {norm_B}\n" + f"Решение: [{x_str}]\n" + f"Количество итераций: {iter_count}\n" + f"Вектор погрешностей: [{residual_str}]\n" + ) + except Exception as e: + self.show_error_message(f"Ошибка ввода данных: {e}") + + def load_from_file(self): + filename, _ = QFileDialog.getOpenFileName(self, "Выберите файл", "", "Text Files (*.txt);;All Files (*)") + if filename: + try: + with open(filename, 'r') as file: + lines = file.readlines() + + n = int(lines[0].strip()) # размерность + eps = float(lines[1].strip()) # точность + + A = [] + b = [] + + for line in lines[2:n + 2]: + values = list(map(float, line.split())) + A.append(values[:-1]) + b.append(values[-1]) + + A = np.array(A) + b = np.array(b) + + # Автоматически подставляем в поля ввода + self.size_input.setText(str(n)) + self.eps_input.setText(str(eps)) + self.create_matrix_input() + + # Заполняем GUI полями из файла + for i in range(n): + for j in range(n): + self.matrix_inputs[i][j].setText(str(A[i, j])) + self.matrix_inputs[i][-1].setText(str(b[i])) + + self.resultText.setText("Файл загружен успешно.") + except Exception as e: + self.show_error_message(f"Ошибка загрузки файла") + + def show_error_message(self, message): + error_dialog = QMessageBox(self) + error_dialog.setIcon(QMessageBox.Icon.Critical) + error_dialog.setWindowTitle("Ошибка") + error_dialog.setText(message) + error_dialog.exec() + + diff --git "a/\320\2403213/yusupova_409938/lab4/approximation.py" "b/\320\2403213/yusupova_409938/lab4/approximation.py" new file mode 100644 index 0000000..19b90ee --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab4/approximation.py" @@ -0,0 +1,133 @@ +import math +from solve import solve_slae +import numpy as np + + +def linear(xs, ys): + n =len(xs) + sx = sum(xs) + sxx = sum(x ** 2 for x in xs) + sy = sum(ys) + sxy = sum(x * y for x, y in zip(xs, ys)) + a, b = solve_slae([[n, sx], [sx, sxx]], [sy, sxy], 2) + print(sxy) + return lambda x: a + b * x, [a, b] + + +def quadratic(xs, ys): + n = len(xs) + sx = sum(xs) + sxx = sum(x ** 2 for x in xs) + sxxx = sum(x ** 3 for x in xs) + sxxxx = sum(x ** 4 for x in xs) + sy = sum(ys) + sxy = sum(x * y for x, y in zip(xs, ys)) + sxxy = sum(x ** 2 * y for x, y in zip(xs, ys)) + a, b, c = solve_slae( + [[n, sx, sxx], + [sx, sxx, sxxx], + [sxx, sxxx, sxxxx]], + [sy, sxy, sxxy], + 3 + ) + + return lambda x: a + b * x + c * x ** 2, [a, b, c] + + +def cubic(xs, ys): + n = len(xs) + sx = sum(xs) + sxx = sum(x ** 2 for x in xs) + sxxx = sum(x ** 3 for x in xs) + sxxxx = sum(x ** 4 for x in xs) + sxxxxx = sum(x ** 5 for x in xs) + sxxxxxx = sum(x ** 6 for x in xs) + sy = sum(ys) + sxy = sum(x * y for x, y in zip(xs, ys)) + sxxy = sum(x ** 2 * y for x, y in zip(xs, ys)) + sxxxy = sum(x ** 3 * y for x, y in zip(xs, ys)) + + a, b, c, d = solve_slae( + [ + [n, sx, sxx, sxxx], + [sx, sxx, sxxx, sxxxx], + [sxx, sxxx, sxxxx, sxxxxx], + [sxxx, sxxxx, sxxxxx, sxxxxxx] + ], + [sy, sxy, sxxy, sxxxy], + 4 + ) + return lambda x: a + b * x + c * x ** 2 + d * x ** 3, [a, b, c, d] + + +def exponential(xs, ys): + if any(y <= 0 for y in ys): + raise ValueError("Экспоненциальная аппроксимация невозможна для y <= 0") + log_ys = [math.log(y) for y in ys] + fi, [a_log, b] = linear(xs, log_ys) + a = math.exp(a_log) + return lambda x: a * math.exp(b * x), [a, b] + + +def logarithmic(xs, ys): + if any(x <= 0 for x in xs): + raise ValueError("Логарифмическая аппроксимация невозможна для x <= 0") + log_xs = [math.log(x) for x in xs] + fi, [a, b] = linear(log_xs, ys) + return lambda x: a * math.log(x) + b, [a, b] + + +def power(xs, ys): + if any(x <= 0 for x in xs) or any(y <= 0 for y in ys): + raise ValueError("Степенная аппроксимация невозможна для x <= 0 или y <= 0") + log_xs = [math.log(x) for x in xs] + log_ys = [math.log(y) for y in ys] + fi, [a_log, b] = linear(log_xs, log_ys) + a = math.exp(a_log) + return lambda x: a * x ** b, [a, b] +def deviation(y_true, y_pred): + return np.sqrt(np.mean((y_true - y_pred) ** 2)) + +def calculate_r_squared(y_true, y_pred): + ss_res = np.sum((y_true - y_pred) ** 2) + ss_tot = np.sum((y_true - np.mean(y_true)) ** 2) + return 1 - ss_res / ss_tot if ss_tot != 0 else float('-inf') + +def perform_approximation(x, y): + """Запускает все методы аппроксимации и возвращает результаты""" + methods = [ + ('Линейная', linear), + ('Квадратичная', quadratic), + ('Кубическая', cubic), + ('Экспоненциальная', exponential), + ('Логарифмическая', logarithmic), + ('Степенная', power) + ] + + results = [] + for name, func in methods: + try: + f, params = func(x, y) # получить функцию и параметры + y_pred = np.array([f(val) for val in x]) # рассчитать предсказанные значения + dev = deviation(y, y_pred) # стандартное отклонение ошибки + r2 = calculate_r_squared(y, y_pred) # коэффициент детерминации + results.append({ + 'name': name, + 'func': f, # обёртка для plot_results + 'params': params, + 'deviation': dev, + 'r_squared': r2, + 'S': np.sum((y_pred - y) ** 2), + 'pearson': np.corrcoef(x, y_pred)[0, 1] if len(x) > 1 else None + }) + except Exception as e: + results.append({ + 'name': name, + 'error': str(e) + }) + + # Отбор лучшего результата + valid_results = [r for r in results if 'error' not in r] + best_result = min(valid_results, key=lambda r: r['deviation']) if valid_results else None + + return results, best_result \ No newline at end of file diff --git "a/\320\2403213/yusupova_409938/lab4/input.py" "b/\320\2403213/yusupova_409938/lab4/input.py" new file mode 100644 index 0000000..f6796cf --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab4/input.py" @@ -0,0 +1,58 @@ +import numpy as np + + +def input_data(): + """Функция для ввода данных с проверкой корректности""" + while True: + print("\nВыберите способ ввода данных:") + print("1 - Вручную") + print("2 - Из файла") + choice = input("Ваш выбор (1/2): ") + + if choice not in ['1', '2']: + print("Ошибка: выберите 1 или 2") + continue + + try: + if choice == '1': + return manual_input() + else: + return file_input() + except Exception as e: + print(f"Ошибка: {str(e)}") + print("Попробуйте ещё раз") + + +def manual_input(): + """Ручной ввод данных""" + while True: + try: + n = int(input("Введите количество точек (8-12): ")) + if n < 8 or n > 12: + raise ValueError("Количество точек должно быть от 8 до 12") + + x, y = [], [] + for i in range(n): + point = input(f"Точка {i + 1} (x y через пробел): ").split() + if len(point) != 2: + raise ValueError("Нужно ввести 2 числа") + x.append(float(point[0])) + y.append(float(point[1])) + return np.array(x), np.array(y) + except ValueError as e: + print(f"Ошибка ввода: {str(e)}") + + +def file_input(): + """Чтение данных из файла""" + while True: + try: + filename = input("Введите имя файла: ") + data = np.loadtxt(filename) + if data.shape[1] != 2: + raise ValueError("Файл должен содержать 2 столбца") + if data.shape[0] < 8 or data.shape[0] > 12: + raise ValueError("Должно быть 8-12 точек") + return data[:, 0], data[:, 1] + except Exception as e: + print(f"Ошибка чтения файла: {str(e)}") \ No newline at end of file diff --git "a/\320\2403213/yusupova_409938/lab4/main.py" "b/\320\2403213/yusupova_409938/lab4/main.py" new file mode 100644 index 0000000..119073f --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab4/main.py" @@ -0,0 +1,25 @@ +from input import input_data +from plot import plot_results +from output import print_results, save_to_file +from approximation import perform_approximation + + +def main(): + while True: + # Ввод данных + x, y = input_data() + + # Выполнение аппроксимации + results, best_result = perform_approximation(x, y) + + # Вывод результатов + print_results(results, best_result) + + # Построение графиков + plot_results(x, y, results, best_result) + + break + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git "a/\320\2403213/yusupova_409938/lab4/output.py" "b/\320\2403213/yusupova_409938/lab4/output.py" new file mode 100644 index 0000000..b6d5ef9 --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab4/output.py" @@ -0,0 +1,62 @@ +def print_results(results, best_result): + print("\nРЕЗУЛЬТАТЫ АППРОКСИМАЦИИ") + + for result in results: + if 'error' in result: + print(f"\n{result['name']}: {result['error']}") + continue + + print(f"\n{result['name']} функция:") + print(f"Параметры: {['%.4f' % p for p in result['params']]}") + print(f"Мера отклонения S: {result['S']:.4f}") + print(f"Среднеквадратичное отклонение (σ): {result['deviation']:.4f}") + print(f"Коэффициент детерминации R²: {result['r_squared']:.4f}") + + if result['pearson'] is not None: + print(f"Коэффициент корреляции Пирсона: {result['pearson']:.4f}") + + # Интерпретация R² + r2 = result['r_squared'] + if r2 >= 0.9: + print("Качество: Отличное (R² ≥ 0.9)") + elif r2 >= 0.7: + print("Качество: Хорошее (0.7 ≤ R² < 0.9)") + elif r2 >= 0.5: + print("Качество: Умеренное (0.5 ≤ R² < 0.7)") + else: + print("Качество: Слабое (R² < 0.5)") + + if best_result: + print("\n" + "=" * 50) + print(f"НАИЛУЧШАЯ АППРОКСИМАЦИЯ: {best_result['name']}") + print(f"Среднеквадратичное отклонение: {best_result['deviation']:.4f}") + print(f"R²: {best_result['r_squared']:.4f}") + + +def save_to_file(results, best_result, filename="results.txt"): + """Сохранение результатов в файл""" + with open(filename, 'w') as f: + f.write("РЕЗУЛЬТАТЫ АППРОКСИМАЦИИ\n") + f.write("=" * 50 + "\n") + + for result in results: + if 'error' in result: + f.write(f"\n{result['name']}: ОШИБКА - {result['error']}\n") + continue + + f.write(f"\n{result['name']} функция:\n") + f.write(f"Параметры: {['%.4f' % p for p in result['params']]}\n") + f.write(f"Мера отклонения S: {result['S']:.4f}\n") + f.write(f"Среднеквадратичное отклонение (σ): {result['deviation']:.4f}\n") + f.write(f"Коэффициент детерминации R²: {result['r_squared']:.4f}\n") + + if result['pearson'] is not None: + f.write(f"Коэффициент корреляции Пирсона: {result['pearson']:.4f}\n") + + if best_result: + f.write("\n" + "=" * 50 + "\n") + f.write(f"НАИЛУЧШАЯ АППРОКСИМАЦИЯ: {best_result['name']}\n") + f.write(f"Среднеквадратичное отклонение: {best_result['deviation']:.4f}\n") + f.write(f"R²: {best_result['r_squared']:.4f}\n") + + print(f"\nРезультаты сохранены в файл {filename}") \ No newline at end of file diff --git "a/\320\2403213/yusupova_409938/lab4/plot.py" "b/\320\2403213/yusupova_409938/lab4/plot.py" new file mode 100644 index 0000000..f687457 --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab4/plot.py" @@ -0,0 +1,41 @@ +def plot_results(x, y, results, best_result): + """Построение графиков""" + import matplotlib.pyplot as plt + import numpy as np + + plt.figure(figsize=(12, 8)) + plt.scatter(x, y, color='black', label='Исходные данные', zorder=5) + + # Диапазон для построения кривых + x_plot = np.linspace(min(x), max(x), 100) + + for result in results: + if 'error' in result: + continue + + try: + # ВАЖНО: тут уже без *result['params'] + y_plot = result['func'](x_plot) + line_style = '-' if result == best_result else '--' + line_width = 2 if result == best_result else 1 + plt.plot(x_plot, y_plot, + label=f"{result['name']} (σ={result['deviation']:.3f})", + linestyle=line_style, + linewidth=line_width) + except Exception as e: + print(f"Ошибка при построении графика для {result['name']}: {e}") + continue + + plt.title("Аппроксимация функции различными методами") + plt.xlabel("x") + plt.ylabel("y") + plt.legend() + plt.grid(True) + + if best_result: + plt.annotate(f"Лучшая: {best_result['name']}\nσ = {best_result['deviation']:.3f}", + xy=(0.05, 0.9), xycoords='axes fraction', + bbox=dict(boxstyle='round', alpha=0.8)) + + plt.tight_layout() + plt.show() diff --git "a/\320\2403213/yusupova_409938/lab4/reports/\320\233\320\240\342\204\2264.pdf" "b/\320\2403213/yusupova_409938/lab4/reports/\320\233\320\240\342\204\2264.pdf" new file mode 100644 index 0000000..da4e258 Binary files /dev/null and "b/\320\2403213/yusupova_409938/lab4/reports/\320\233\320\240\342\204\2264.pdf" differ diff --git "a/\320\2403213/yusupova_409938/lab4/solve.py" "b/\320\2403213/yusupova_409938/lab4/solve.py" new file mode 100644 index 0000000..c2e9e29 --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab4/solve.py" @@ -0,0 +1,62 @@ +import numpy as np +def solve_slae(A, B, n): + if n == 2: + return solve2(A, B) + if n == 3: + return solve3(A, B) + if n == 4: + return solve4(A, B) + raise ValueError(f"Только системы 2x2, 3x3 и 4x4 поддерживаются, получено n={n}") + + +def calc_det2(A): + return (A[0][0] * A[1][0]) - (A[0][1] * A[1][1]) + +def solve2(A, B): + det = calc_det2(A) + + if abs(det) < 1e-12: + raise ValueError("Система вырождена (определитель матрицы равен нулю)") + + det1 = (B[0]* A[1][1]) - (B[1] * A[0][1]) + print((B[0], A[1][1], B[1], A[0][1])) + det2 = (A[0][0] * B[1]) - (A[1][0] * B[0]) + print(det, det1, det2) + # Находим решения + x1 = det1 / det + x2 = det2 / det + + return x1, x2 + +def calc_det3(A): + pos = A[0][0] * A[1][1] * A[2][2] + A[0][1] * A[1][2] * A[2][0] + A[0][2] * A[1][0] * A[2][1] + neg = A[0][2] * A[1][1] * A[2][0] + A[0][1] * A[1][0] * A[2][2] + A[0][0] * A[1][2] * A[2][1] + return pos - neg + + +def solve3(A, B): + det = calc_det3(A) + if abs(det) < 1e-12: + raise ValueError("Система несовместна или имеет бесконечно много решений.") + det1 = calc_det3([[B[r], A[r][1], A[r][2]] for r in range(3)]) + det2 = calc_det3([[A[r][0], B[r], A[r][2]] for r in range(3)]) + det3 = calc_det3([[A[r][0], A[r][1], B[r]] for r in range(3)]) + return det1 / det, det2 / det, det3 / det + + +def calc_det4(A): + result = 0 + for c in range(4): + minor = [[A[r][cc] for cc in range(4) if cc != c] for r in range(1, 4)] + result += ((-1) ** c) * A[0][c] * calc_det3(minor) + return result + +def solve4(A, B): + det = calc_det4(A) + if abs(det) < 1e-12: + raise ValueError("Система несовместна или имеет бесконечно много решений.") + det1 = calc_det4([[B[r], A[r][1], A[r][2], A[r][3]] for r in range(4)]) + det2 = calc_det4([[A[r][0], B[r], A[r][2], A[r][3]] for r in range(4)]) + det3 = calc_det4([[A[r][0], A[r][1], B[r], A[r][3]] for r in range(4)]) + det4 = calc_det4([[A[r][0], A[r][1], A[r][2], B[r]] for r in range(4)]) + return det1 / det, det2 / det, det3 / det, det4 / det \ No newline at end of file diff --git "a/\320\2403213/yusupova_409938/lab5/finite_difference.py" "b/\320\2403213/yusupova_409938/lab5/finite_difference.py" new file mode 100644 index 0000000..218b35c --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab5/finite_difference.py" @@ -0,0 +1,15 @@ +from typing import List + +def calculate_finite_differences(y_values: List[float]) -> List[List[float]]: + n = len(y_values) + table = [y_values.copy()] # только y + for level in range(1, n): + prev_level = table[level - 1] + current_level = [ + round(prev_level[i + 1] - prev_level[i], 4) + for i in range(len(prev_level) - 1) + ] + table.append(current_level) + return table + + diff --git "a/\320\2403213/yusupova_409938/lab5/input_output_handlers.py" "b/\320\2403213/yusupova_409938/lab5/input_output_handlers.py" new file mode 100644 index 0000000..6595900 --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab5/input_output_handlers.py" @@ -0,0 +1,168 @@ +# input_output_handler.py +import numpy as np +import math +from typing import Tuple, List, Dict + +class InputOutputHandler: + def __init__(self): + self.functions = { + 1: ("sin(x)", math.sin), + 2: ("cos(x)", math.cos), + 3: ("exp(x)", math.exp), + 4: ("x^2", lambda x: x ** 2) + } + self.methods = { + 1: "Многочлен Лагранжа", + 2: "Многочлен Ньютона с разделенными разностями", + 3: "Многочлен Ньютона с конечными разностями", + 4: "Схема Стирлинга", + 5: "Схема Бесселя" + } + + def get_input_choice(self) -> int: + print("Выберите способ ввода данных:") + print("1. Ввод с клавиатуры\n2. Чтение из файла\n3. Генерация по функции") + while True: + try: + choice = int(input("Ваш выбор (1-3): ")) + if 1 <= choice <= 3: + return choice + self.print_error("введите число от 1 до 3") + except ValueError: + self.print_error("введите целое число") + + def input_from_keyboard(self) -> Tuple[List[float], List[float]]: + x, y = [], [] + while True: + try: + n = int(input("Введите количество точек (не менее 2): ")) + if n >= 2: + break + self.print_error("должно быть не менее 2 точек") + except ValueError: + self.print_error("введите целое число") + + for i in range(n): + while True: + try: + x_val, y_val = map(float, input(f"Точка {i + 1}: ").strip().split()) + x.append(x_val) + y.append(y_val) + break + except ValueError: + self.print_error("введите два числа через пробел") + return x, y + + def input_from_file(self) -> Tuple[List[float], List[float]]: + while True: + filename = input("Введите имя файла: ").strip() + + try: + with open(filename, 'r') as f: + lines = [line.strip() for line in f.readlines() if line.strip()] + + # Пропускаем пустые строки + lines = [line for line in lines if line] + + if not lines: + self.print_error("Файл пуст") + continue + + try: + num_points = int(lines[0]) # Первая строка - количество точек + except ValueError: + self.print_error("Первая строка должна содержать целое число - количество точек") + continue + + if len(lines) - 1 != num_points: + self.print_error(f"Ожидается {num_points} точек, но найдено {len(lines) - 1}") + continue + + x, y = [], [] + + for line in lines[1:]: # Обрабатываем строки с данными + try: + parts = line.split() + if len(parts) != 2: + raise ValueError("Каждая строка должна содержать ровно 2 значения") + + x_val = float(parts[0]) + y_val = float(parts[1]) + x.append(x_val) + y.append(y_val) + except ValueError as ve: + self.print_error(f"Ошибка в строке '{line}': {str(ve)}") + break + + if len(x) == num_points: + return x, y + else: + self.print_error("Не удалось загрузить все точки") + + except FileNotFoundError: + self.print_error(f"Файл '{filename}' не найден") + except Exception as e: + self.print_error(f"Ошибка при чтении файла: {str(e)}") + + def generate_from_function(self) -> Tuple[List[float], List[float]]: + print("Доступные функции:") + for num, (name, _) in self.functions.items(): + print(f"{num}. {name}") + while True: + try: + func_num = int(input("Выберите номер функции: ")) + if func_num in self.functions: + break + self.print_error("нет функции с таким номером") + except ValueError: + self.print_error("введите целое число") + while True: + try: + a = float(input("Введите начало интервала: ")) + b = float(input("Введите конец интервала: ")) + if b > a: + break + self.print_error("конец интервала должен быть больше начала") + except ValueError: + self.print_error("введите число") + while True: + try: + n = int(input("Введите количество точек (не менее 2): ")) + if n >= 2: + break + self.print_error("должно быть не менее 2 точек") + except ValueError: + self.print_error("введите целое число") + + x = np.linspace(a, b, n).tolist() + y = [self.functions[func_num][1](xi) for xi in x] + return x, y + + def get_interpolation_point(self) -> float: + while True: + try: + return float(input("Введите значение x для интерполяции: ")) + except ValueError: + self.print_error("введите число") + + def print_results(self, results: Dict[int, float]): + print("\nРезультаты интерполяции:") + for method_num, value in results.items(): + print(f"{method_num}. {self.methods[method_num]}: {value:.6f}") + + def print_error(self, message: str): + print(f"Ошибка: {message}") + + def print_finite_diff_table(self, x: List[float], y: List[float], table: List[List[float]]): + print("\nТаблица конечных разностей:") + # Заголовки столбцов + headers = ["x", "y"] + [f"Δ^{i}y" for i in range(1, len(table))] + print("\t".join(f"{h:>10}" for h in headers)) # Выравнивание по правому краю + + for i in range(len(x)): + # Вывод x и y + row = [f"{x[i]:>10.4f}", f"{y[i]:>10.4f}"] + # Вывод разностей (начиная с Δ^1y) + for j in range(min(len(table) - 1, len(x) - i - 1)): + row.append(f"{table[j][i]:>10.4f}") + print("\t".join(row)) \ No newline at end of file diff --git "a/\320\2403213/yusupova_409938/lab5/main.py" "b/\320\2403213/yusupova_409938/lab5/main.py" new file mode 100644 index 0000000..4c16162 --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab5/main.py" @@ -0,0 +1,60 @@ +# main.py +from input_output_handlers import InputOutputHandler +from methods import * +from finite_difference import calculate_finite_differences +from plot import plot_interpolation + +class Interpolation: + def __init__(self): + self.io = InputOutputHandler() + self.x = [] + self.y = [] + self.finite_diff_table = [] + + def run(self): + # Ввод данных + input_choice = self.io.get_input_choice() + if input_choice == 1: + self.x, self.y = self.io.input_from_keyboard() + elif input_choice == 2: + self.x, self.y = self.io.input_from_file() + else: + self.x, self.y = self.io.generate_from_function() + + # Печать введённых данных + print("\nВведённые данные:") + for xi, yi in zip(self.x, self.y): + print(f"x = {xi:.4f}, y = {yi:.4f}") + + # Таблица конечных разностей + self.finite_diff_table = calculate_finite_differences(self.y) + self.io.print_finite_diff_table(self.x, self.y, self.finite_diff_table) + + # Ввод точки интерполяции + x_val = self.io.get_interpolation_point() + + # Вычисление + results = { + 1: lagrange_interpolation(self.x, self.y, x_val), + 2: newton_divided_diff_interpolation(self.x, self.y, x_val), + 3: newton_finite_diff_interpolation(self.x, self.y, self.finite_diff_table, x_val) + } + + try: + if len(self.x) >= 3 and len(self.x) % 2 == 1: + results[4] = stirling_interpolation(self.x, self.y, self.finite_diff_table, x_val) + elif len(self.x) >= 4 and len(self.x) % 2 == 0: + results[5] = bessel_interpolation(self.x, self.y, self.finite_diff_table, x_val) + else: + print("Для схем Стирлинга/Бесселя требуется не менее 3/4 точек соответственно") + except Exception as e: + self.io.print_error(f"Дополнительные методы: {e}") + + self.io.print_results(results) + plot_interpolation(self.x, self.y) + +if __name__ == "__main__": + try: + Interpolation().run() + except Exception as e: + print(f"Произошла ошибка: {e}") diff --git "a/\320\2403213/yusupova_409938/lab5/methods.py" "b/\320\2403213/yusupova_409938/lab5/methods.py" new file mode 100644 index 0000000..3a7cf06 --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab5/methods.py" @@ -0,0 +1,97 @@ +from typing import List + + +def lagrange_interpolation(x, y, x_val): + result = 0.0 + n = len(x) + for i in range(n): + term = y[i] + for j in range(n): + if i != j: + term *= (x_val - x[j]) / (x[i] - x[j]) + result += term + return result + + +def newton_divided_diff_interpolation(x, y, x_val): + n = len(x) + coef = y.copy() + + # Вычисление коэффициентов разделенных разностей + for j in range(1, n): + for i in range(n - 1, j - 1, -1): + coef[i] = (coef[i] - coef[i - 1]) / (x[i] - x[i - j]) + + result = coef[-1] + # Обратное вычисление полинома Ньютона + for i in range(n - 2, -1, -1): + result = result * (x_val - x[i]) + coef[i] + return result + + +def newton_finite_diff_interpolation(x, y, finite_diff_table, x_val): + n = len(x) + h = x[1] - x[0] + t = (x_val - x[0]) / h + result = y[0] + term = 1.0 + + for i in range(1, n): + term *= (t - (i - 1)) / i + result += term * finite_diff_table[i][0] + return result + + +def stirling_interpolation(x, y, finite_diff_table, x_val): + n = len(x) + h = x[1] - x[0] + # Центр таблицы + center = n // 2 + t = (x_val - x[center]) / h + + result = y[center] + term = 1.0 + factorial_term = 1 + + for i in range(1, n): + factorial_term *= i + if i % 2 == 1: + # Для нечётного порядка используем среднее значение конечных разностей + term *= (t ** 2 - ((i - 1) / 2) ** 2) + idx = (i + 1) // 2 + diff = (finite_diff_table[i][center - idx] + finite_diff_table[i][center - idx + 1]) / 2 + else: + term *= t + idx = i // 2 + diff = finite_diff_table[i][center - idx] + result += (term / factorial_term) * diff + return result + + +def bessel_interpolation(x, y, finite_diff_table, x_val): + n = len(x) + if n < 4 or n % 2 != 0: + raise ValueError("Для схемы Бесселя требуется четное количество точек (минимум 4)") + + h = x[1] - x[0] + mid = n // 2 - 1 + t = (x_val - x[mid]) / h - 0.5 + + # Начальное значение как среднее двух центральных узлов + result = (y[mid] + y[mid + 1]) / 2 + + # Первая конечная разность + term = t - 0.5 + result += term * finite_diff_table[1][mid] + + # Вторая конечная разность + if n >= 4: + term2 = term * (t + 0.5) / 2 + result += term2 * finite_diff_table[2][mid] + + # Третья конечная разность (при наличии достаточного количества точек) + if n >= 6: + term3 = term2 * (t - 0.5) / 3 + result += term3 * (finite_diff_table[3][mid] + finite_diff_table[3][mid - 1]) / 2 + + return result diff --git "a/\320\2403213/yusupova_409938/lab5/plot.py" "b/\320\2403213/yusupova_409938/lab5/plot.py" new file mode 100644 index 0000000..fbfc677 --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab5/plot.py" @@ -0,0 +1,28 @@ +import numpy as np +import matplotlib.pyplot as plt +from methods import ( + lagrange_interpolation, + newton_divided_diff_interpolation +) + + +def plot_interpolation(x, y): + """Построение графиков интерполяции""" + if len(x) < 2: + print("Недостаточно точек для построения графика") + return + + x_vals = np.linspace(min(x), max(x), 100) + y_lagrange = [lagrange_interpolation(x, y, xi) for xi in x_vals] + y_newton = [newton_divided_diff_interpolation(x, y, xi) for xi in x_vals] + + plt.figure(figsize=(10, 6)) + plt.scatter(x, y, color='red', label='Узлы интерполяции') + plt.plot(x_vals, y_lagrange, label='Многочлен Лагранжа') + plt.plot(x_vals, y_newton, '--', label='Многочлен Ньютона') + plt.xlabel('x') + plt.ylabel('y') + plt.title('Интерполяция функции') + plt.legend() + plt.grid() + plt.show() \ No newline at end of file diff --git "a/\320\2403213/yusupova_409938/lab5/reports/\320\233\320\240\342\204\2265.pdf" "b/\320\2403213/yusupova_409938/lab5/reports/\320\233\320\240\342\204\2265.pdf" new file mode 100644 index 0000000..8ecf77c Binary files /dev/null and "b/\320\2403213/yusupova_409938/lab5/reports/\320\233\320\240\342\204\2265.pdf" differ diff --git "a/\320\2403213/yusupova_409938/lab6/input_output_handler.py" "b/\320\2403213/yusupova_409938/lab6/input_output_handler.py" new file mode 100644 index 0000000..6faa78f --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab6/input_output_handler.py" @@ -0,0 +1,95 @@ +# input_output_handler.py +import math + + +class InputOutputHandler: + def __init__(self): + self.equations = { + '1': { + 'text': "y' = x + y", + 'solution': lambda x0, y0, x: -x - 1 + (y0 + x0 + 1) * math.exp(x - x0) + }, + '2': { + 'text': "y' = x^2 + y^2", + 'solution': None + }, + '3': { + 'text': "y' = 2x - y", + 'solution': lambda x0, y0, x: 2 * x - 2 + (y0 - 2 * x0 + 2) * math.exp(-(x - x0)) + } + } + + def get_input(self): + """Получает входные данные от пользователя""" + print("Доступные дифференциальные уравнения:") + for num, eq in self.equations.items(): + print(f"{num}. {eq['text']}") + + while True: + choice = input("Выберите уравнение (1-3): ") + if choice in self.equations: + break + print("Неверный ввод. Попробуйте снова.") + + while True: + try: + x0 = float(input("Введите начальное значение x0: ")) + y0 = float(input(f"Введите начальное значение y0 = y({x0}): ")) + xn = float(input("Введите конечное значение xn: ")) + h = float(input("Введите шаг h: ")) + epsilon = float(input("Введите точность ε: ")) + + if xn <= x0: + print("xn должно быть больше x0. Попробуйте снова.") + continue + if h <= 0: + print("Шаг h должен быть положительным. Попробуйте снова.") + continue + if epsilon <= 0: + print("Точность ε должна быть положительной. Попробуйте снова.") + continue + + break + except ValueError: + print("Неверный формат числа. Попробуйте снова.") + + # Формируем точное решение, если оно доступно + exact_solution = None + if self.equations[choice]['solution'] is not None: + exact_solution = lambda x: self.equations[choice]['solution'](x0, y0, x) + + return choice, x0, y0, xn, h, epsilon, exact_solution + + def print_results_table(self, euler_results, rk4_results, adams_results, exact_results=None): + """Выводит таблицу результатов""" + x_euler, y_euler = euler_results + x_rk4, y_rk4 = rk4_results + x_adams, y_adams = adams_results + + print("\nРезультаты численного решения:") + header = "| {:^10} | {:^15} | {:^15} | {:^15} |".format( + "x", "Метод Эйлера", "Рунге-Кутта 4", "Метод Адамса") + if exact_results: + header = header[:-1] + "| {:^15} |".format("Точное решение") + print(header) + print("-" * len(header)) + + max_len = max(len(x_euler), len(x_rk4), len(x_adams)) + for i in range(max_len): + x = x_euler[i] if i < len(x_euler) else "-" + euler_val = y_euler[i] if i < len(y_euler) else "-" + rk4_val = y_rk4[i] if i < len(y_rk4) else "-" + adams_val = y_adams[i] if i < len(y_adams) else "-" + exact_val = exact_results[i] if exact_results and i < len(exact_results) else "-" + + row = "| {:^10.4f} | {:^15.6f} | {:^15.6f} | {:^15.6f} |".format( + x if x != "-" else "-", + euler_val if euler_val != "-" else "-", + rk4_val if rk4_val != "-" else "-", + adams_val if adams_val != "-" else "-") + + if exact_results: + row = row[:-1] + " {:^15.6f} |".format( + exact_val if exact_val != "-" else "-") + + print(row) \ No newline at end of file diff --git "a/\320\2403213/yusupova_409938/lab6/main.py" "b/\320\2403213/yusupova_409938/lab6/main.py" new file mode 100644 index 0000000..53c689d --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab6/main.py" @@ -0,0 +1,62 @@ +from methods import EulerMethod, RungeKutta4Method, AdamsMethod, Runge_rule +from input_output_handler import InputOutputHandler +from plot import Plotter + +def main(): + io_handler = InputOutputHandler() + plotter = Plotter() + + # Получение входных данных от пользователя + equation_choice, x0, y0, xn, h, epsilon, exact_solution = io_handler.get_input() + + # Инициализация методов + euler = EulerMethod() + rk4 = RungeKutta4Method() + adams = AdamsMethod() + + # Решение уравнения выбранными методами + methods = { + '1': ('Метод Эйлера', euler.solve, 1), + '2': ('Метод Рунге-Кутта 4 порядка', rk4.solve, 4), + '3': ('Метод Адамса', adams.solve, None) + } + + results = {} + for method_num, (method_name, solver, order) in methods.items(): + x_values, y_values = solver(equation_choice, x0, y0, xn, h) + results[method_name] = (x_values, y_values) + + # Оценка точности + if order is not None: # Для одношаговых методов используем правило Рунге + _, y_values_half = solver(equation_choice, x0, y0, xn, h / 2) + error = Runge_rule(y_values[-1], y_values_half[-1], order) + else: # Для многошаговых методов сравниваем с точным решением + if exact_solution: + exact_values = [exact_solution(x) for x in x_values] + error = max(abs(y - exact) for y, exact in zip(y_values, exact_values)) + else: + error = float('nan') + + print(f"\n{method_name}:") + print(f"Погрешность: {error:.6f}") + + # Вывод результатов в таблицу + exact_values = [exact_solution(x) for x in results['Метод Эйлера'][0]] if exact_solution else None + io_handler.print_results_table( + results['Метод Эйлера'], + results['Метод Рунге-Кутта 4 порядка'], + results['Метод Адамса'], + exact_values + ) + + # Построение графиков + plotter.plot_results( + results['Метод Эйлера'], + results['Метод Рунге-Кутта 4 порядка'], + results['Метод Адамса'], + exact_solution + ) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git "a/\320\2403213/yusupova_409938/lab6/methods.py" "b/\320\2403213/yusupova_409938/lab6/methods.py" new file mode 100644 index 0000000..80af3e4 --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab6/methods.py" @@ -0,0 +1,108 @@ +class EulerMethod: + def solve(self, equation_num, x0, y0, xn, h): + f = self._get_equation(equation_num) + x_values = [] + y_values = [] + + x = x0 + y = y0 + x_values.append(x) + y_values.append(y) + + while x < xn: + y += h * f(x, y) + x += h + x_values.append(x) + y_values.append(y) + + return x_values, y_values + + def _get_equation(self, num): + equations = { + '1': lambda x, y: x + y, + '2': lambda x, y: x**2 + y**2, + '3': lambda x, y: 2 * x - y + } + return equations.get(num, lambda x, y: x + y) + + +class RungeKutta4Method: + def solve(self, equation_num, x0, y0, xn, h): + f = self._get_equation(equation_num) + x_values = [] + y_values = [] + + x = x0 + y = y0 + x_values.append(x) + y_values.append(y) + + 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 += h + x_values.append(x) + y_values.append(y) + + return x_values, y_values + + def _get_equation(self, num): + equations = { + '1': lambda x, y: x + y, + '2': lambda x, y: x**2 + y**2, + '3': lambda x, y: 2*x - y + } + return equations.get(num, lambda x, y: x + y) + + +class AdamsMethod: + def solve(self, equation_num, x0, y0, xn, h): + f = self._get_equation(equation_num) + x_values = [] + y_values = [] + + # Используем Рунге-Кутта для получения первых 4 точек + rk4 = RungeKutta4Method() + start_x, start_y = rk4.solve(equation_num, x0, y0, x0 + 3*h, h) + + x_values.extend(start_x) + y_values.extend(start_y) + + x = x0 + 3*h + while x < xn: + # Предыдущие значения функции + f0 = f(x_values[-4], y_values[-4]) + f1 = f(x_values[-3], y_values[-3]) + f2 = f(x_values[-2], y_values[-2]) + f3 = f(x_values[-1], y_values[-1]) + + # Формула Адамса (предиктор) + y_next = y_values[-1] + h*(55*f3 - 59*f2 + 37*f1 - 9*f0)/24 + x_next = x + h + + # Корректор (одна итерация) + f_next = f(x_next, y_next) + y_next = y_values[-1] + h*(9*f_next + 19*f3 - 5*f2 + f1)/24 + + x_values.append(x_next) + y_values.append(y_next) + x = x_next + + return x_values, y_values + + def _get_equation(self, num): + """Возвращает выбранное уравнение""" + equations = { + '1': lambda x, y: x + y, + '2': lambda x, y: x**2 + y**2, + '3': lambda x, y: 2*x - y + } + return equations.get(num, lambda x, y: x + y) + + +def Runge_rule(y_h, y_h2, p): + return abs(y_h - y_h2) / (2 ** p - 1) \ No newline at end of file diff --git "a/\320\2403213/yusupova_409938/lab6/plot.py" "b/\320\2403213/yusupova_409938/lab6/plot.py" new file mode 100644 index 0000000..1884d47 --- /dev/null +++ "b/\320\2403213/yusupova_409938/lab6/plot.py" @@ -0,0 +1,28 @@ +import matplotlib.pyplot as plt + + +class Plotter: + def plot_results(self, euler_results, rk4_results, adams_results, exact_solution=None): + plt.figure(figsize=(12, 8)) + + x_euler, y_euler = euler_results + x_rk4, y_rk4 = rk4_results + x_adams, y_adams = adams_results + + plt.plot(x_euler, y_euler, 'b-', label='Метод Эйлера', linewidth=2) + plt.plot(x_rk4, y_rk4, 'g-', label='Рунге-Кутта 4 порядка', linewidth=2) + plt.plot(x_adams, y_adams, 'r-', label='Метод Адамса', linewidth=2) + + # Если есть точное решение, строим его + if exact_solution is not None: + x_exact = x_rk4 # Используем точки метода Рунге-Кутта как наиболее точные + y_exact = [exact_solution(x) for x in x_exact] + plt.plot(x_exact, y_exact, 'k--', label='Точное решение', linewidth=2) + + plt.title('Сравнение численных методов решения ОДУ') + plt.xlabel('x') + plt.ylabel('y(x)') + plt.legend() + plt.grid(True) + + plt.show() \ No newline at end of file diff --git "a/\320\2403213/yusupova_409938/lab6/reports/\320\233\320\240\342\204\2266.pdf" "b/\320\2403213/yusupova_409938/lab6/reports/\320\233\320\240\342\204\2266.pdf" new file mode 100644 index 0000000..e3e817a Binary files /dev/null and "b/\320\2403213/yusupova_409938/lab6/reports/\320\233\320\240\342\204\2266.pdf" differ