diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..981382c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Р3213/molchanov_413015/lab1/Qt-Math-App"] + path = Р3213/molchanov_413015/lab1/Qt-Math-App + url = https://github.com/fefumo/Qt-Math-App.git diff --git "a/\320\2403213/molchanov_413015/lab1/Qt-Math-App" "b/\320\2403213/molchanov_413015/lab1/Qt-Math-App" new file mode 160000 index 0000000..9d31400 --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab1/Qt-Math-App" @@ -0,0 +1 @@ +Subproject commit 9d314004e66c8c78ad97539620e500091ccbc4ab diff --git "a/\320\2403213/molchanov_413015/lab1/\320\262\321\213\321\207\320\274\320\260\321\202 \320\276\321\202\321\207\321\221\321\202 \320\273\320\260\320\2611.pdf" "b/\320\2403213/molchanov_413015/lab1/\320\262\321\213\321\207\320\274\320\260\321\202 \320\276\321\202\321\207\321\221\321\202 \320\273\320\260\320\2611.pdf" new file mode 100644 index 0000000..1bcc0a1 Binary files /dev/null and "b/\320\2403213/molchanov_413015/lab1/\320\262\321\213\321\207\320\274\320\260\321\202 \320\276\321\202\321\207\321\221\321\202 \320\273\320\260\320\2611.pdf" differ diff --git "a/\320\2403213/molchanov_413015/lab2/functions.py" "b/\320\2403213/molchanov_413015/lab2/functions.py" new file mode 100644 index 0000000..1f24244 --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab2/functions.py" @@ -0,0 +1,32 @@ +import math + +def f1(x): + return x**3 - x - 2 + +def f2(x): + return math.cos(x) - x + +def f3(x): + return math.exp(x) - 2 + +def f4(x): + return x**2 - 2 + +def f5(x): + return math.sin(x) - 0.5 + +def get_functions(): + return { + "1": ("x^3 - x - 2", f1), + "2": ("cos(x) - x", f2), + "3": ("exp(x) - 2", f3), + "4": ("x^2 - 2", f4), + "5": ("sin(x) - 0.5", f5), + } + +def get_function_choice(functions): + print("Доступные функции:") + for key, (desc, _) in functions.items(): + print(f"{key}: {desc}") + choice = input("Выберите номер функции: ").strip() + return functions[choice][1] \ No newline at end of file diff --git "a/\320\2403213/molchanov_413015/lab2/input_handler.py" "b/\320\2403213/molchanov_413015/lab2/input_handler.py" new file mode 100644 index 0000000..c7cfe7a --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab2/input_handler.py" @@ -0,0 +1,22 @@ +def get_user_input(): + source = input("Ввод из файла или с клавиатуры? (file/keyboard): ").strip().lower() + if source == "file": + filename = input("Введите имя файла: ").strip() + with open(filename, encoding="utf-8") as f: + parts = f.read().split() + a, b, eps = map(float, parts[:3]) + else: + a = float(input("Введите левую границу интервала a: ")) + b = float(input("Введите правую границу интервала b: ")) + eps = float(input("Введите точность вычисления eps: ")) + return a, b, eps + +def get_output_choice(): + return input("Вывести результат на экран или в файл? (screen/file): ").strip().lower() + +def get_function_choice(functions): + print("Доступные функции:") + for key, (desc, _) in functions.items(): + print(f"{key}: {desc}") + choice = input("Выберите номер функции: ").strip() + return functions[choice][1] \ No newline at end of file diff --git "a/\320\2403213/molchanov_413015/lab2/inputs.txt" "b/\320\2403213/molchanov_413015/lab2/inputs.txt" new file mode 100644 index 0000000..ee316e1 --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab2/inputs.txt" @@ -0,0 +1 @@ +-2 2 0.01 \ No newline at end of file diff --git "a/\320\2403213/molchanov_413015/lab2/main.py" "b/\320\2403213/molchanov_413015/lab2/main.py" new file mode 100644 index 0000000..f9f79bc --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab2/main.py" @@ -0,0 +1,121 @@ +import numpy as np +from functions import get_functions +from input_handler import get_user_input, get_function_choice, get_output_choice +from verification import verify_interval, find_initial_guess +from methods.chord import chord_method +from methods.secant import secant_method +from methods.simple_iteration import simple_iteration_method +from systems.systems import get_systems +from systems.newton_system import newton_system +import matplotlib.pyplot as plt + +def plot_scalar_function(func, a, b, root=None): + x_vals = np.linspace(a, b, 400) + y_vals = [func(x) for x in x_vals] + + plt.axhline(0, color='gray', linestyle='--') + plt.plot(x_vals, y_vals, label='f(x)') + if root is not None: + plt.scatter(root, func(root), color='red', label='Корень') + plt.xlabel('x') + plt.ylabel('f(x)') + plt.title('График функции') + plt.legend() + plt.grid(True) + plt.show() + +def main(): + mode = input("Выберите режим: 'scalar' (одно уравнение) или 'system' (система): ").strip().lower() + + if mode == "system": + systems = get_systems() + print("Доступные системы:") + for key, s in systems.items(): + print(f"{key}: {s['desc']}") + choice = input("Выберите номер системы: ").strip() + system = systems[choice] + F, J = system["func"], system["jacobian"] + default_guess = system["guess"] + + print(f"Рекомендуемое начальное приближение: {default_guess}") + use_default = input("Использовать рекомендованное? (y/n): ").strip().lower() + if use_default == "y": + x0 = default_guess + else: + x0 = list(map(float, input("Введите начальные приближения x1 и x2 через пробел: ").split())) + + eps = float(input("Введите точность eps: ")) + + result = newton_system(F, J, x0, eps) + + print(f"Решение: x = {result['x']}") + print(f"Итераций: {result['iterations']}") + print(f"Вектор невязки (норма): {result['residual']:.3e}") + + for i, e in enumerate(result['errors']): + print(f"Погрешности на итерации {i+1}: {e}") + + # График + x_vals = np.linspace(-3, 3, 400) + y_vals = np.linspace(-3, 3, 400) + X, Y = np.meshgrid(x_vals, y_vals) + + if choice == "1": + Z1 = X**2 + Y**2 - 4 + Z2 = X - Y + elif choice == "2": + Z1 = X**2 - Y - 1 + Z2 = X + Y**2 - 3 + elif choice == "3": + Z1 = X**2 + Y**2 - 1 + Z2 = X**3 - Y + 0.5 + else: + Z1 = Z2 = None + + if Z1 is not None and Z2 is not None: + plt.contour(X, Y, Z1, [0], colors='blue') + plt.contour(X, Y, Z2, [0], colors='red') + plt.scatter(*result['x'], color='green') + plt.title("Графики системы и найденный корень") + plt.xlabel("x1") + plt.ylabel("x2") + plt.grid(True) + plt.axis('equal') + plt.show() + + else: + functions = get_functions() + func = get_function_choice(functions) + method = input("Выберите метод (chord/secant/iteration): ").strip().lower() + a, b, eps = get_user_input() + + if not verify_interval(func, a, b): + print("На заданном интервале нет корней или их несколько.") + return + + x0 = find_initial_guess(func, a, b) + + if method == "chord": + result = chord_method(func, a, b, eps) + elif method == "secant": + result = secant_method(func, a, b, eps) + elif method == "iteration": + result = simple_iteration_method(func, a, b, eps) + else: + print("Неизвестный метод.") + return + + output_choice = get_output_choice() + if output_choice == "screen": + print("Результат:") + print(result) + else: + with open("result.txt", "w", encoding="utf-8") as f: + f.write(str(result)) + print("Результат записан в result.txt") + + # Показываем график после вывода + plot_scalar_function(func, a, b, root=result['root']) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git "a/\320\2403213/molchanov_413015/lab2/result.txt" "b/\320\2403213/molchanov_413015/lab2/result.txt" new file mode 100644 index 0000000..1f4c880 --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab2/result.txt" @@ -0,0 +1 @@ +{'method': 'Метод хорд', 'a': 1.5213797068045676, 'b': 2.0, 'epsilon': 0.01, 'root': 1.5213797068045676, 'f(root)': 0.0, 'iterations': 10000} \ No newline at end of file diff --git "a/\320\2403213/molchanov_413015/lab2/systems/__pycache__/newton_system.cpython-313.pyc" "b/\320\2403213/molchanov_413015/lab2/systems/__pycache__/newton_system.cpython-313.pyc" new file mode 100644 index 0000000..73d1093 Binary files /dev/null and "b/\320\2403213/molchanov_413015/lab2/systems/__pycache__/newton_system.cpython-313.pyc" differ diff --git "a/\320\2403213/molchanov_413015/lab2/systems/__pycache__/systems.cpython-313.pyc" "b/\320\2403213/molchanov_413015/lab2/systems/__pycache__/systems.cpython-313.pyc" new file mode 100644 index 0000000..24c9f8d Binary files /dev/null and "b/\320\2403213/molchanov_413015/lab2/systems/__pycache__/systems.cpython-313.pyc" differ diff --git "a/\320\2403213/molchanov_413015/lab2/systems/newton_system.py" "b/\320\2403213/molchanov_413015/lab2/systems/newton_system.py" new file mode 100644 index 0000000..02b1d24 --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab2/systems/newton_system.py" @@ -0,0 +1,38 @@ +import numpy as np + +def newton_system(F, J, x0, eps=1e-6, max_iter=100): + x = np.array(x0, dtype=float) + iter_count = 0 + errors = [] + + while iter_count < max_iter: + Fx = np.array(F(x)) + Jx = np.array(J(x)) + + norm_F = np.linalg.norm(Fx) + if norm_F < eps: + break + + try: + dx = np.linalg.solve(Jx, -Fx) + except np.linalg.LinAlgError: + print("Якобиан необратим.") + break + + x_new = x + dx + error = np.linalg.norm(dx) + errors.append(error) + + if error < eps: + x = x_new + break + + x = x_new + iter_count += 1 + + return { + "x": x.tolist(), + "iterations": iter_count, + "errors": errors, + "residual": np.linalg.norm(F(x)) + } \ No newline at end of file diff --git "a/\320\2403213/molchanov_413015/lab2/systems/systems.py" "b/\320\2403213/molchanov_413015/lab2/systems/systems.py" new file mode 100644 index 0000000..e7319bf --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab2/systems/systems.py" @@ -0,0 +1,63 @@ +def system1(x): + x1, x2 = x + return [ + x1**2 + x2**2 - 4, + x1 - x2 + ] + +def jacobian1(x): + x1, x2 = x + return [ + [2 * x1, 2 * x2], + [1, -1] + ] + +def system2(x): + x1, x2 = x + return [ + x1**2 - x2 - 1, + x1 + x2**2 - 3 + ] + +def jacobian2(x): + x1, x2 = x + return [ + [2 * x1, -1], + [1, 2 * x2] + ] + +def system3(x): + x1, x2 = x + return [ + x1**2 + x2**2 - 1, + x1**3 - x2 + 0.5 + ] + +def jacobian3(x): + x1, x2 = x + return [ + [2 * x1, 2 * x2], + [3 * x1**2, -1] + ] + +def get_systems(): + return { + "1": { + "desc": "x^2 + y^2 = 4; x = y", + "func": system1, + "jacobian": jacobian1, + "guess": [1.0, 1.0] + }, + "2": { + "desc": "x^2 - y = 1; x + y^2 = 3", + "func": system2, + "jacobian": jacobian2, + "guess": [1.0, 1.0] + }, + "3": { + "desc": "x^2 + y^2 = 1; x^3 - y = -0.5", + "func": system3, + "jacobian": jacobian3, + "guess": [0.5, 0.5] + } + } \ No newline at end of file diff --git "a/\320\2403213/molchanov_413015/lab2/verification.py" "b/\320\2403213/molchanov_413015/lab2/verification.py" new file mode 100644 index 0000000..1c67a70 --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab2/verification.py" @@ -0,0 +1,8 @@ +def verify_interval(func, a, b): + try: + return func(a) * func(b) < 0 + except: + return False + +def find_initial_guess(func, a, b): + return a if abs(func(a)) < abs(func(b)) else b \ No newline at end of file diff --git "a/\320\2403213/molchanov_413015/lab2/\320\236\321\202\321\207\321\221\321\202 \320\262\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\2612.pdf" "b/\320\2403213/molchanov_413015/lab2/\320\236\321\202\321\207\321\221\321\202 \320\262\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\2612.pdf" new file mode 100644 index 0000000..6026f06 Binary files /dev/null and "b/\320\2403213/molchanov_413015/lab2/\320\236\321\202\321\207\321\221\321\202 \320\262\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\2612.pdf" differ diff --git "a/\320\2403213/molchanov_413015/lab3/main.py" "b/\320\2403213/molchanov_413015/lab3/main.py" new file mode 100644 index 0000000..37a0228 --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab3/main.py" @@ -0,0 +1,108 @@ +import numpy as np + +def f1(x): return x ** 2 +def f2(x): return np.sin(x) +def f3(x): return np.exp(-x ** 2) +def f4(x): return 1 / (1 + x ** 2) +def f5(x): return np.log(x + 1) +def f6(x): return 4*x**3 - 5*x**2 + 6*x - 7 + +functions = { + 1: ("x^2", f1), + 2: ("sin(x)", f2), + 3: ("exp(-x^2)", f3), + 4: ("1 / (1 + x^2)", f4), + 5: ("ln(x + 1)", f5), + 6: ("4x^3 - 5x^2 + 6x - 7", f6) # из письменного задания +} + +# Методы численного интегрирования +def left_rect(f, a, b, n): + h = (b - a) / n + x = np.linspace(a, b - h, n) + return h * np.sum(f(x)) + +def right_rect(f, a, b, n): + h = (b - a) / n + x = np.linspace(a + h, b, n) + return h * np.sum(f(x)) + +def mid_rect(f, a, b, n): + h = (b - a) / n + x = np.linspace(a + h/2, b - h/2, n) + return h * np.sum(f(x)) + +def trapezoid(f, a, b, n): + h = (b - a) / n + x = np.linspace(a, b, n + 1) + return h * (0.5 * f(x[0]) + np.sum(f(x[1:-1])) + 0.5 * f(x[-1])) + +def simpson(f, a, b, n): + if n % 2: + n += 1 + h = (b - a) / n + x = np.linspace(a, b, n + 1) + return (h / 3) * (f(x[0]) + f(x[-1]) + + 4 * np.sum(f(x[1:-1:2])) + + 2 * np.sum(f(x[2:-2:2]))) + +# Правило Рунге +def runge_rule(I1, I2, k): + return abs(I1 - I2) / (2 ** k - 1) + +# Интегрирование с выводом шагов +def integrate_with_steps(method, f, a, b, eps, p): + n = 4 + step = 1 + I0 = method(f, a, b, n) + rows = [] + + while True: + n *= 2 + I1 = method(f, a, b, n) + diff = abs(I1 - I0) + rows.append((step, n, I0, I1, diff)) + if diff / (2**p - 1) < eps: + break + I0 = I1 + step += 1 + + return I1, n, rows + +# Ввод пользователя +def main(): + print("Выберите функцию для интегрирования:") + for k, (name, _) in functions.items(): + print(f"{k}: {name}") + choice = int(input("Введите номер функции (1-5): ")) + fname, f = functions[choice] + + print("\nВыберите метод численного интегрирования:") + methods = { + 1: ("Left Rectangles", left_rect, 1), + 2: ("Right Rectangles", right_rect, 1), + 3: ("Mid Rectangles", mid_rect, 2), + 4: ("Trapezoid", trapezoid, 2), + 5: ("Simpson", simpson, 4) + } + for k, (name, _, _) in methods.items(): + print(f"{k}: {name}") + method_choice = int(input("Введите номер метода (1-5): ")) + mname, mfunc, p = methods[method_choice] + + a = float(input("\nВведите нижний предел интегрирования a: ")) + b = float(input("Введите верхний предел интегрирования b: ")) + eps = float(input("Введите требуемую точность ε: ")) + + print(f"\nМетод: {mname}") + print(f"Функция: {fname} на интервале [{a}, {b}], точность ε = {eps}\n") + print(f"{'Step':<5} {'n':<8} {'I_0':<20} {'I_1':<20} {'|I_1 - I_0|':<20}") + print("-" * 75) + + result, final_n, table = integrate_with_steps(mfunc, f, a, b, eps, p) + for step, n, I0, I1, diff in table: + print(f"{step:<5} {n:<8} {I0:<20.10f} {I1:<20.10f} {diff:<20.10f}") + + print(f"\nПриближённое значение интеграла: {result:.10f} при n = {final_n}") + +main() diff --git "a/\320\2403213/molchanov_413015/lab3/\320\236\321\202\321\207\321\221\321\202 \320\262\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\2613.pdf" "b/\320\2403213/molchanov_413015/lab3/\320\236\321\202\321\207\321\221\321\202 \320\262\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\2613.pdf" new file mode 100644 index 0000000..02a74d7 Binary files /dev/null and "b/\320\2403213/molchanov_413015/lab3/\320\236\321\202\321\207\321\221\321\202 \320\262\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\2613.pdf" differ diff --git "a/\320\2403213/molchanov_413015/lab4/approximation_methods.py" "b/\320\2403213/molchanov_413015/lab4/approximation_methods.py" new file mode 100644 index 0000000..11877be --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab4/approximation_methods.py" @@ -0,0 +1,147 @@ +import math +import numpy as np +from math import exp, log + +def calculate_sums_1(n, X, Y): + sum_X = sum(X) + sum_Y = sum(Y) + sum_X2 = sum(map(lambda x: x ** 2, X)) + sum_XY = sum([X[i] * Y[i] for i in range(n)]) + return sum_X, sum_Y, sum_X2, sum_XY + + +def calculate_sums_2(n, X, Y): + sum_X3 = sum(map(lambda x: x ** 3, X)) + sum_X2Y = sum([X[i] ** 2 * Y[i] for i in range(n)]) + sum_X4 = sum(map(lambda x: x ** 4, X)) + return sum_X3, sum_X2Y, sum_X4 + + +def calculate_sums_3(n, X, Y): + sum_X5 = sum(map(lambda x: x ** 5, X)) + sum_X3Y = sum([X[i] ** 3 * Y[i] for i in range(n)]) + sum_X6 = sum(map(lambda x: x ** 6, X)) + return sum_X5, sum_X6, sum_X3Y + + +def linear_regression(n, X, Y) -> (float, float): # type: ignore + """ + :return: coefficients a, b for the linear function ax + b + """ + sum_X, sum_Y, sum_X2, sum_XY = calculate_sums_1(n, X, Y) + + # Solve the linear system using Cramer's rule + delta = sum_X2 * n - sum_X ** 2 + delta_1 = sum_XY * n - sum_X * sum_Y + delta_2 = sum_X2 * sum_Y - sum_X * sum_XY + + return delta_1 / delta, delta_2 / delta + + +def solve_linear_equation_system(A, B): + A = np.array(A) + B = np.array(B) + try: + solution = np.linalg.solve(A, B) + return solution + except np.linalg.LinAlgError: + return None, None + + +def quadratic_regression(n, X, Y) -> (float, float, float): # type: ignore + """ + :return: coefficients a, b, c for the quadratic function ax^2 + bx + c + """ + sum_X, sum_Y, sum_X2, sum_XY = calculate_sums_1(n, X, Y) + sum_X3, sum_X2Y, sum_X4 = calculate_sums_2(n, X, Y) + A = [[n, sum_X, sum_X2], + [sum_X, sum_X2, sum_X3], + [sum_X2, sum_X3, sum_X4]] + B = [sum_Y, sum_XY, sum_X2Y] + + a, b, c = solve_linear_equation_system(A, B)[::-1] + + return a, b, c + + +def cubic_regression(n, X, Y) -> (float, float, float, float): # type: ignore + """ + :return: coefficients a, b, c, d for the cubic function ax^3 + bx^2 + cx + d + """ + sum_X, sum_Y, sum_X2, sum_XY = calculate_sums_1(n, X, Y) + sum_X3, sum_X2Y, sum_X4 = calculate_sums_2(n, X, Y) + sum_X5, sum_X6, sum_X3Y = calculate_sums_3(n, X, Y) + A = [ + [sum_X6, sum_X5, sum_X4, sum_X3], + [sum_X5, sum_X4, sum_X3, sum_X2], + [sum_X4, sum_X3, sum_X2, sum_X], + [sum_X3, sum_X2, sum_X, n] + ] + + B = [sum_X3Y, sum_X2Y, sum_XY, sum_Y] + return solve_linear_equation_system(A, B) + + +def exponential_regression(n, X, Y): + """ + :return: coefficients a, b for the function ae^bx + """ + valid_X = [] + valid_Y = [] + + for x, y in zip(X, Y): + if y is not None and y > 0: # Check for validity + valid_X.append(x) + valid_Y.append(y) + + if len(valid_Y) < 2: # For linear regression, at least 2 points are required + return None, None, None, None + + try: + lnY = [math.log(y) for y in valid_Y] + B, A = linear_regression(len(lnY), valid_X, lnY) + return math.exp(A), B, valid_X, valid_Y + except (ValueError, TypeError): + return None, None, None, None + +def logarithmic_regression(n, X, Y): + valid_X = [] + valid_Y = [] + + for x, y in zip(X, Y): + if x is not None and y is not None and x > 0: # ln(x) is defined only for x > 0 + valid_X.append(x) + valid_Y.append(y) + + if len(valid_X) < 2: + return None, None, None, None + + try: + lnX = [math.log(x) for x in valid_X] + a, b = linear_regression(len(lnX), lnX, valid_Y) + return a, b, valid_X, valid_Y + except (ValueError, TypeError, ZeroDivisionError): + return None, None, None, None + + +def power_regression(n, X, Y): + valid_X = [] + valid_Y = [] + + for x, y in zip(X, Y): + if x is not None and y is not None and x > 0 and y > 0: + valid_X.append(x) + valid_Y.append(y) + + if len(valid_X) < 2: + return None, None, None, None + + try: + lnX = [math.log(x) for x in valid_X] + lnY = [math.log(y) for y in valid_Y] + b, ln_a = linear_regression(len(lnX), lnX, lnY) + a = math.exp(ln_a) + + return a, b, valid_X, valid_Y + except (ValueError, TypeError, ZeroDivisionError): + return None, None, None, None diff --git "a/\320\2403213/molchanov_413015/lab4/graphics/all_approximations.png" "b/\320\2403213/molchanov_413015/lab4/graphics/all_approximations.png" new file mode 100644 index 0000000..1b9af47 Binary files /dev/null and "b/\320\2403213/molchanov_413015/lab4/graphics/all_approximations.png" differ diff --git "a/\320\2403213/molchanov_413015/lab4/graphics/cubic_approximation.png" "b/\320\2403213/molchanov_413015/lab4/graphics/cubic_approximation.png" new file mode 100644 index 0000000..1d4ccf2 Binary files /dev/null and "b/\320\2403213/molchanov_413015/lab4/graphics/cubic_approximation.png" differ diff --git "a/\320\2403213/molchanov_413015/lab4/graphics/linear_approximation.png" "b/\320\2403213/molchanov_413015/lab4/graphics/linear_approximation.png" new file mode 100644 index 0000000..940abe6 Binary files /dev/null and "b/\320\2403213/molchanov_413015/lab4/graphics/linear_approximation.png" differ diff --git "a/\320\2403213/molchanov_413015/lab4/graphics/quadratic_approximation.png" "b/\320\2403213/molchanov_413015/lab4/graphics/quadratic_approximation.png" new file mode 100644 index 0000000..d03b34c Binary files /dev/null and "b/\320\2403213/molchanov_413015/lab4/graphics/quadratic_approximation.png" differ diff --git "a/\320\2403213/molchanov_413015/lab4/graphics_drawer.py" "b/\320\2403213/molchanov_413015/lab4/graphics_drawer.py" new file mode 100644 index 0000000..b823513 --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab4/graphics_drawer.py" @@ -0,0 +1,187 @@ +import numpy as np +import matplotlib.pyplot as plt +from math import exp + +def draw_linear_approximation(X, Y, a, b): + plt.figure(figsize=(10, 6)) + + # Plot original points + plt.scatter(X, Y, color='pink', label='Original points (X, Y)', zorder=5) + + # Plot linear approximation function + x_line = np.linspace(min(X) - 0.1, max(X) + 0.1, 100) + y_line = a * x_line + b + plt.plot(x_line, y_line, label=f'Approximating function: y = {round(a,3)}x + {round(b,3)}', color='darkcyan') + + plt.title('') + plt.xlabel('Ox') + plt.ylabel('Oy') + plt.grid(True, linestyle='--', alpha=0.7) + plt.legend() + plt.tight_layout() + + plt.savefig('graphics/linear_approximation.png') + plt.close() + + +def draw_quadratic_approximation(X, Y, a, b, c): + plt.figure(figsize=(10, 6)) + + # Plot original points + plt.scatter(X, Y, color='pink', label='Original points (X, Y)', zorder=5) + x_line = np.linspace(min(X) - 0.1, max(X) + 0.1, 100) + y_line = a * x_line**2 + b*x_line + c + plt.plot(x_line, y_line, label=f'Approximating function: y = {round(a,3)}x^2 + {round(b,3)}x + {round(c, 3)}', color='lightseagreen') + + plt.title('') + plt.xlabel('Ox') + plt.ylabel('Oy') + plt.grid(True, linestyle='--', alpha=0.7) + plt.legend() + plt.tight_layout() + plt.savefig('graphics/quadratic_approximation.png') + plt.close() + + +def draw_cubic_approximation(X, Y, a, b, c, d): + plt.figure(figsize=(10, 6)) + + # Plot original points + plt.scatter(X, Y, color='pink', label='Original points (X, Y)', zorder=5) + x_line = np.linspace(min(X) - 0.1, max(X) + 0.1, 100) + y_line = a * x_line ** 3 + b * x_line**2 + c*x_line + d + plt.plot(x_line, y_line, label=f'Approximating function: y = {round(a, 3)}x^3 + {round(b, 3)}x^2 + {round(c, 3)}x + {round(d, 3)}', color='lightseagreen') + + plt.title('') + plt.xlabel('Ox') + plt.ylabel('Oy') + plt.grid(True, linestyle='--', alpha=0.7) + plt.legend() + plt.tight_layout() + plt.savefig('graphics/cubic_approximation.png') + plt.close() + + +def draw_exponential_approximation(X, Y, acc_X, a, b): + plt.figure(figsize=(10, 6)) + + # Plot original points + plt.scatter(X, Y, color='pink', label='Original points (X, Y)', zorder=5) + x_line = np.linspace(min(acc_X) - 0.1, max(acc_X) + 0.1, 100) + y_line = a * np.exp(b * x_line) + plt.plot(x_line, y_line, label=f'Approximating function: y = {round(a, 3)} * e^{round(b, 3)}x', color='lightseagreen') + + plt.title('') + plt.xlabel('Ox') + plt.ylabel('Oy') + plt.grid(True, linestyle='--', alpha=0.7) + plt.legend() + plt.tight_layout() + plt.savefig('graphics/exp_approximation.png') + plt.close() + + +def draw_logarithmic_approximation(X, Y, acc_x, a, b): + plt.figure(figsize=(10, 6)) + + # Plot original points + plt.scatter(X, Y, color='pink', label='Original points (X, Y)', zorder=5) + x_line = np.linspace(min(acc_x) - 0.1, max(acc_x) + 0.1, 100) + y_line = a * np.log(x_line) + b + plt.plot(x_line, y_line, label=f'Approximating function: y = {round(a, 3)} * ln(x) + {round(b, 3)}', color='lightseagreen') + + plt.title('') + plt.xlabel('Ox') + plt.ylabel('Oy') + plt.grid(True, linestyle='--', alpha=0.7) + plt.legend() + plt.tight_layout() + plt.savefig('graphics/log_approximation.png') + plt.close() + + +def draw_power_approximation(X, Y, acc_x, a, b): + plt.figure(figsize=(10, 6)) + + # Plot original points + plt.scatter(X, Y, color='pink', label='Original points (X, Y)', zorder=5) + x_line = np.linspace(min(acc_x) - 0.1, max(acc_x) + 0.1, 100) + y_line = a * x_line**b + plt.plot(x_line, y_line, label=f'Approximating function: y = {round(a, 3)}x^{round(b, 3)}', color='lightseagreen') + + plt.title('') + plt.xlabel('Ox') + plt.ylabel('Oy') + plt.grid(True, linestyle='--', alpha=0.7) + plt.legend() + plt.tight_layout() + plt.savefig('graphics/pow_approximation.png') + plt.close() + + +def draw_all_approximations(X, Y, results): + linear_coeffs = results["linear"] + quadratic_coeffs = results["quadratic"] + cubic_coeffs = results["cubic"] + exp_coeffs = results["exp"][0:2] + log_coeffs = results["log"][0:2] + pow_coeffs = results["pow"][0:2] + acc_X = results["exp"][2] + + plt.figure(figsize=(12, 8)) + + # Plot original points + plt.scatter(X, Y, color='cyan', label='Original points (X, Y)', zorder=10) + + # Set the range for plotting + x_min = min(X) - 0.5 + x_max = max(X) + 0.5 + x_line = np.linspace(x_min, x_max, 500) + + # Plot linear approximation + if linear_coeffs and linear_coeffs[0] is not None: + a, b = linear_coeffs + y_linear = a * x_line + b + plt.plot(x_line, y_linear, label=f'Linear: y = {round(a, 3)}x + {round(b, 3)}', color='pink', linestyle='-') + + # Plot quadratic approximation + if quadratic_coeffs and all(c is not None for c in quadratic_coeffs): + a, b, c = quadratic_coeffs + y_quad = a * x_line ** 2 + b * x_line + c + plt.plot(x_line, y_quad, label=f'Quadratic: y = {round(a, 3)}x² + {round(b, 3)}x + {round(c, 3)}', color='hotpink', linestyle='-') + + # Plot cubic approximation + if cubic_coeffs and all(c is not None for c in cubic_coeffs): + a, b, c, d = cubic_coeffs + y_cubic = a * x_line ** 3 + b * x_line ** 2 + c * x_line + d + plt.plot(x_line, y_cubic, label=f'Cubic: y = {round(a, 3)}x³ + {round(b, 3)}x² + {round(c, 3)}x + {round(d, 3)}', color='Violet', linestyle='-') + + # Plot exponential approximation + if exp_coeffs and all(c is not None for c in exp_coeffs[:2]): + a, b = exp_coeffs[:2] + y_exp = a * np.exp(b * x_line) + plt.plot(x_line, y_exp, label=f'Exponential: y = {round(a, 3)}e^{round(b, 3)}x', color='grey', linestyle='--') + + # Plot logarithmic approximation + if log_coeffs and all(c is not None for c in log_coeffs[:2]): + a, b = log_coeffs[:2] + x_log = x_line[x_line > 0.01] # Avoid log(0) + y_log = a * np.log(x_log) + b + plt.plot(x_log, y_log, label=f'Logarithmic: y = {round(a, 3)}ln(x) + {round(b, 3)}', color='lightgrey', linestyle='--') + + # Plot power approximation + if pow_coeffs and all(c is not None for c in pow_coeffs[:2]): + a, b = pow_coeffs[:2] + x_pow = x_line[x_line > 0.01] # Avoid 0^b + y_pow = a * x_pow ** b + plt.plot(x_pow, y_pow, label=f'Power: y = {round(a, 3)}x^{round(b, 3)}', color='DarkSlateGrey', linestyle='--') + + plt.title('Comparison of Approximation Methods') + plt.xlabel('Ox') + plt.ylabel('Oy') + plt.grid(True, linestyle='--', alpha=0.5) + plt.legend(bbox_to_anchor=(1.05, 1), loc='upper right') + plt.tight_layout() + + plt.savefig('graphics/all_approximations.png', bbox_inches='tight', dpi=300) + plt.show() diff --git "a/\320\2403213/molchanov_413015/lab4/input.txt" "b/\320\2403213/molchanov_413015/lab4/input.txt" new file mode 100644 index 0000000..7d71c16 --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab4/input.txt" @@ -0,0 +1,3 @@ +11 +-2.000 -1.800 -1.600 -1.400 -1.200 -1.000 -0.800 -0.600 -0.400 -0.200 0.000 +-2.000 -2.366 -2.715 -2.970 -3.042 -2.875 -2.483 -1.936 -1.309 -0.657 0.000 \ No newline at end of file diff --git "a/\320\2403213/molchanov_413015/lab4/main.py" "b/\320\2403213/molchanov_413015/lab4/main.py" new file mode 100644 index 0000000..88785ac --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab4/main.py" @@ -0,0 +1,147 @@ +from approximation_methods import * +from graphics_drawer import * +from table_printer import * + +# Coefficients map for all methods +approximation_results = {"linear": [None, None], + "quadratic": [None] * 3, + "cubic": [None] * 4, + "exp": [None] * 4, + "log": [None] * 4, + "pow": [None] * 4 + } + +def validate_input(n, x_values, y_values): + if n < 8 or n > 12: + raise ValueError + X = [float(x) for x in x_values.split()] + if len(X) != n: + raise ValueError + Y = [float(y) for y in y_values.split()] + if len(Y) != n: + raise ValueError + return n, X, Y + +def input_data(): + while True: + try: + choice = input("Enter 'f' to read from a file or any other key to enter manually:") + if choice.strip() == "f": + with open(input("Enter filename:")) as f: + n = int(f.readline()) + x_values = f.readline().replace(",", ".") + y_values = f.readline().replace(",", ".") + else: + n = int(input("Enter the number of function nodes:")) + x_values = input("Enter x_i values separated by spaces:") + y_values = input("Enter y_i values separated by spaces:") + n, X, Y = validate_input(n, x_values, y_values) + return n, X, Y + + except ValueError: + print("Error: invalid input, please try again!") + continue + +def display_results(): + choice = input("Enter 'f' to save results to a file or any other key to display in console:") + if choice.strip() == "f": + with open("output.txt", mode="w") as f: + print("LINEAR REGRESSION METHOD:".center(90), file=f) + print_table(n, X, Y, lambda x: approximation_results["linear"][0] * x + approximation_results["linear"][1], f) + + print("QUADRATIC REGRESSION METHOD:".center(90), file=f) + print_table(n, X, Y, + lambda x: approximation_results["quadratic"][0] * x ** 2 + approximation_results["quadratic"][1] * x + approximation_results["quadratic"][2], f) + + print("CUBIC REGRESSION METHOD:".center(90), file=f) + print_table(n, X, Y, lambda x: + approximation_results["cubic"][0] * x ** 3 + approximation_results["cubic"][1] * x ** 2 + approximation_results["cubic"][2] * x + approximation_results["cubic"][3], f) + + if all(x is not None for x in approximation_results["exp"]): + print("EXPONENTIAL REGRESSION METHOD".center(90), file=f) + print_table(len(approximation_results["exp"][2]), approximation_results["exp"][2], approximation_results["exp"][3], + lambda x: approximation_results["exp"][0] * math.exp(approximation_results["exp"][1] * x), f) + + if all(x is not None for x in approximation_results["log"]): + print("LOGARITHMIC REGRESSION METHOD".center(90), file=f) + print_table(len(approximation_results["log"][2]), approximation_results["log"][2], approximation_results["log"][3], + lambda x: approximation_results["log"][0] * math.log(x) + approximation_results["log"][1], f) + + if all(x is not None for x in approximation_results["pow"]): + print("POWER REGRESSION METHOD".center(90), file=f) + print_table(len(approximation_results["pow"][2]), approximation_results["pow"][2], approximation_results["pow"][3], + lambda x: approximation_results["log"][0] * x ** approximation_results["log"][1], f) + + return + + print("LINEAR REGRESSION METHOD:".center(90)) + print_table(n, X, Y, lambda x: approximation_results["linear"][0] * x + approximation_results["linear"][1], None) + + print("QUADRATIC REGRESSION METHOD:".center(90)) + print_table(n, X, Y, + lambda x: approximation_results["quadratic"][0] * x ** 2 + approximation_results["quadratic"][1] * x + approximation_results["quadratic"][2], + None) + print("CUBIC REGRESSION METHOD:".center(90)) + print_table(n, X, Y, lambda x: + approximation_results["cubic"][0] * x ** 3 + approximation_results["cubic"][1] * x ** 2 + approximation_results["cubic"][2] * x + approximation_results["cubic"][3], None) + + if all(x is not None for x in approximation_results["exp"]): + print("EXPONENTIAL REGRESSION METHOD".center(90)) + print_table(len(approximation_results["exp"][2]), approximation_results["exp"][2], approximation_results["exp"][3], + lambda x: approximation_results["exp"][0] * math.exp(approximation_results["exp"][1] * x), + None) + + if all(x is not None for x in approximation_results["log"]): + print("LOGARITHMIC REGRESSION METHOD".center(90)) + print_table(len(approximation_results["log"][2]), approximation_results["log"][2], approximation_results["log"][3], + lambda x: approximation_results["log"][0] * math.log(x) + approximation_results["log"][1], None) + + if all(x is not None for x in approximation_results["pow"]): + print("POWER REGRESSION METHOD".center(90)) + print_table(len(approximation_results["pow"][2]), approximation_results["pow"][2], approximation_results["pow"][3], + lambda x: approximation_results["log"][0] * x ** approximation_results["log"][1], None) + + +if __name__ == "__main__": + n, X, Y = input_data() + + a, b = linear_regression(n, X, Y) + approximation_results["linear"] = a, b + draw_linear_approximation(X, Y, a, b) + + a, b, c = quadratic_regression(n, X, Y) + approximation_results["quadratic"] = float(a), float(b), float(c) + draw_quadratic_approximation(X, Y, a, b, c) + + a, b, c, d = cubic_regression(n, X, Y) + approximation_results["cubic"] = float(a), float(b), float(c), float(d) + draw_cubic_approximation(X, Y, a, b, c, d) + + try: + a, b, accepted_X, accepted_Y = exponential_regression(n, X, Y) + approximation_results["exp"] = float(a), float(b), accepted_X, accepted_Y + draw_exponential_approximation(X, Y, accepted_X, a, b) + except TypeError: + print( + "exponential approximation error: domain of definition for logarithm x>0 -> not enough points with positive function values for approximation using this method") + + try: + a, b, accepted_X, accepted_Y = logarithmic_regression(n, X, Y) + approximation_results["log"] = float(a), float(b), accepted_X, accepted_Y + draw_logarithmic_approximation(X, Y, accepted_X, a, b) + + except TypeError: + print( + "logarithmic approximation error: domain of definition for logarithm x>0 -> not enough points with positive function values for approximation using this method") + + try: + a, b, accepted_X, accepted_Y = power_regression(n, X, Y) + approximation_results["pow"] = float(a), float(b), accepted_X, accepted_Y + draw_power_approximation(X, Y, accepted_X, a, b) + + except TypeError: + print( + "power approximation error: domain of definition for logarithm x>0 -> not enough points with positive function values for approximation using this method") + + display_results() + draw_all_approximations(X, Y, approximation_results) diff --git "a/\320\2403213/molchanov_413015/lab4/output.txt" "b/\320\2403213/molchanov_413015/lab4/output.txt" new file mode 100644 index 0000000..ca0f085 --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab4/output.txt" @@ -0,0 +1,33 @@ + LINEAR REGRESSION METHOD: + X | -2.0 | -1.8 | -1.6 | -1.4 | -1.2 | -1.0 | -0.8 | -0.6 | -0.4 | -0.2 | 0.0 +------------------------------------------------------------------------------------------------------------------------------------------------------------ + Y | -2.0 | -2.366 | -2.715 | -2.97 | -3.042 | -2.875 | -2.483 | -1.936 | -1.309 | -0.657 | 0.0 +------------------------------------------------------------------------------------------------------------------------------------------------------------ + phi(X) | -3.1085 | -2.8932 | -2.6779 | -2.4627 | -2.2474 | -2.0321 | -1.8168 | -1.6015 | -1.3862 | -1.171 | -0.9557 +------------------------------------------------------------------------------------------------------------------------------------------------------------ + e_i | -1.1085 | -0.5272 | 0.0371 | 0.5073 | 0.7946 | 0.8429 | 0.6662 | 0.3345 | -0.0772 | -0.514 | -0.9557 +СРЕДНЕКВАДРАТИЧНОЕ ОТКЛОНЕНИЕ: 0.6638 + + + QUADRATIC REGRESSION METHOD: + X | -2.0 | -1.8 | -1.6 | -1.4 | -1.2 | -1.0 | -0.8 | -0.6 | -0.4 | -0.2 | 0.0 +------------------------------------------------------------------------------------------------------------------------------------------------------------ + Y | -2.0 | -2.366 | -2.715 | -2.97 | -3.042 | -2.875 | -2.483 | -1.936 | -1.309 | -0.657 | 0.0 +------------------------------------------------------------------------------------------------------------------------------------------------------------ + phi(X) | -1.9932 | -2.4471 | -2.7523 | -2.9088 | -2.9166 | -2.7756 | -2.486 | -2.0477 | -1.4606 | -0.7248 | 0.1597 +------------------------------------------------------------------------------------------------------------------------------------------------------------ + e_i | 0.0068 | -0.0811 | -0.0373 | 0.0612 | 0.1254 | 0.0994 | -0.003 | -0.1117 | -0.1516 | -0.0678 | 0.1597 +СРЕДНЕКВАДРАТИЧНОЕ ОТКЛОНЕНИЕ: 0.0967 + + + CUBIC REGRESSION METHOD: + X | -2.0 | -1.8 | -1.6 | -1.4 | -1.2 | -1.0 | -0.8 | -0.6 | -0.4 | -0.2 | 0.0 +------------------------------------------------------------------------------------------------------------------------------------------------------------ + Y | -2.0 | -2.366 | -2.715 | -2.97 | -3.042 | -2.875 | -2.483 | -1.936 | -1.309 | -0.657 | 0.0 +------------------------------------------------------------------------------------------------------------------------------------------------------------ + phi(X) | -1.9037 | -2.465 | -2.8179 | -2.9774 | -2.9583 | -2.7756 | -2.4443 | -1.9791 | -1.395 | -0.7069 | 0.0702 +------------------------------------------------------------------------------------------------------------------------------------------------------------ + e_i | 0.0963 | -0.099 | -0.1029 | -0.0074 | 0.0837 | 0.0994 | 0.0387 | -0.0431 | -0.086 | -0.0499 | 0.0702 +СРЕДНЕКВАДРАТИЧНОЕ ОТКЛОНЕНИЕ: 0.0767 + + diff --git "a/\320\2403213/molchanov_413015/lab4/table_printer.py" "b/\320\2403213/molchanov_413015/lab4/table_printer.py" new file mode 100644 index 0000000..a33444b --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab4/table_printer.py" @@ -0,0 +1,18 @@ +import math + + +def print_table(n, X, Y, phi, output_file): + print("X".center(10) + "|" + "|".join([str(round(x, 4)).center(12) for x in X]), file=output_file) + print("-" * (n + 1) * 13, file=output_file) + print("Y".center(10) + "|" + "|".join([str(round(y, 4)).center(12) for y in Y]), file=output_file) + print("-" * (n + 1) * 13, file=output_file) + + print("phi(X)".center(10) + "|" + "|".join([str(round(phi(x), 4)).center(12) for x in X]), file=output_file) + print("-" * (n + 1) * 13, file=output_file) + + e_i = [phi(X[i]) - Y[i] for i in range(n)] + print("e_i".center(10) + "|" + "|".join([str(round(e, 4)).center(12) for e in e_i]), file=output_file) + + e_i2 = list(map(lambda x: x ** 2, e_i)) + print(f"СРЕДНЕКВАДРАТИЧНОЕ ОТКЛОНЕНИЕ: {round(math.sqrt(sum(e_i2) / n), 4)}", file=output_file) + print("\n", file=output_file) \ No newline at end of file diff --git "a/\320\2403213/molchanov_413015/lab4/\320\236\321\202\321\207\321\221\321\202 \320\262\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\2614.pdf" "b/\320\2403213/molchanov_413015/lab4/\320\236\321\202\321\207\321\221\321\202 \320\262\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\2614.pdf" new file mode 100644 index 0000000..77bd096 Binary files /dev/null and "b/\320\2403213/molchanov_413015/lab4/\320\236\321\202\321\207\321\221\321\202 \320\262\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\2614.pdf" differ diff --git "a/\320\2403213/molchanov_413015/lab5/main.py" "b/\320\2403213/molchanov_413015/lab5/main.py" new file mode 100644 index 0000000..cfa5e4c --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab5/main.py" @@ -0,0 +1,164 @@ +import numpy as np +import matplotlib.pyplot as plt +from math import factorial, sin, cos + +def input_data(): + n = int(input("Enter the number of points: ")) + x = [] + y = [] + for i in range(n): + xi = float(input(f"x[{i}] = ")) + yi = float(input(f"y[{i}] = ")) + x.append(xi) + y.append(yi) + return np.array(x), np.array(y) + +def load_data_from_file(filename): + data = np.loadtxt(filename) + return data[:, 0], data[:, 1] + +def generate_function_data(): + funcs = {1: (np.sin, "sin(x)"), 2: (np.cos, "cos(x)")} + print("Choose a function:") + for k, (_, name) in funcs.items(): + print(f"{k} - {name}") + choice = int(input("Your choice: ")) + f, name = funcs[choice] + a = float(input("Enter interval start: ")) + b = float(input("Enter interval end: ")) + n = int(input("Number of points: ")) + x = np.linspace(a, b, n) + y = f(x) + return x, y + +def finite_differences(y): + n = len(y) + diffs = [y.copy()] + for i in range(1, n): + diffs.append(np.diff(diffs[-1])) + return diffs + +def print_difference_table(x, y): + diffs = finite_differences(y) + n = len(x) + headers = ["x", "y"] + [f"Δ^{i}y" for i in range(1, n)] + row_data = [] + for i in range(n): + row = [f"{x[i]:.4f}", f"{y[i]:.4f}"] + for order in range(1, n): + if i < len(diffs[order]): + row.append(f"{diffs[order][i]:.4f}") + else: + row.append("") + row_data.append(row) + print("\nFinite Difference Table:") + print(" ".join(f"{h:>8}" for h in headers)) + for row in row_data: + print(" ".join(f"{val:>8}" for val in row)) + return diffs + +def newton_finite_diff(x, y, x_val): + h = x[1] - x[0] + diffs = finite_differences(y) + t = (x_val - x[0]) / h + result = y[0] + t_product = 1 + for i in range(1, len(x)): + t_product *= (t - i + 1) + result += t_product / factorial(i) * diffs[i][0] + return result + +def divided_differences(x, y): + n = len(x) + coef = y.copy() + for j in range(1, n): + coef[j:] = (coef[j:] - coef[j-1:-1]) / (x[j:] - x[:n-j]) + return coef + +def newton_divided(x, coef, x_val): + result = coef[0] + product = 1 + for i in range(1, len(coef)): + product *= (x_val - x[i-1]) + result += coef[i] * product + return result + +def lagrange_interpolation(x, y, x_val): + total = 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]) + total += term + return total + +def plot_all_methods(x, y, x_val): + x_dense = np.linspace(min(x), max(x), 500) + + y_true = None + func_name = None + if np.allclose(y, np.sin(x), atol=1e-1): + y_true = np.sin(x_dense) + func_name = 'sin(x)' + elif np.allclose(y, np.cos(x), atol=1e-1): + y_true = np.cos(x_dense) + func_name = 'cos(x)' + + y_lagr_dense = np.array([lagrange_interpolation(x, y, xi) for xi in x_dense]) + coef_div = divided_differences(x, y) + y_newton_div_dense = np.array([newton_divided(x, coef_div, xi) for xi in x_dense]) + y_newton_fin_dense = np.array([newton_finite_diff(x, y, xi) for xi in x_dense]) + + if y_true is not None: + plt.plot(x_dense, y_true, label="Original Function", color='red', linestyle='solid', linewidth=2) + + plt.plot(x_dense, y_newton_div_dense, label="Newton Method (Divided)", color='orange', linestyle='--', linewidth=2) + plt.plot(x_dense, y_newton_fin_dense, label="Newton Method (Finite)", color='green', linestyle='-.', linewidth=2) + plt.plot(x_dense, y_lagr_dense, label="Lagrange Method", color='blue', linestyle=':', linewidth=2) + + plt.plot(x, y, 'o', label="Interpolation Nodes", color='black', markersize=6) + plt.axvline(x=x_val, color='gray', linestyle='--', label='Target x') + + plt.legend() + plt.grid(True, linestyle=':') + plt.title("Interpolation Methods Comparison") + plt.tight_layout() + plt.show() + +def check_duplicate_x(x): + unique, counts = np.unique(x, return_counts=True) + duplicates = unique[counts > 1] + if len(duplicates) > 0: + print("Error: duplicate x values found:", duplicates) + exit(1) + +def main(): + mode = int(input("Select input mode (1 - manual, 2 - from file, 3 - function): ")) + if mode == 1: + x, y = input_data() + elif mode == 2: + filename = input("Enter filename: ") + x, y = load_data_from_file(filename) + else: + x, y = generate_function_data() + + check_duplicate_x(x) + print_difference_table(x, y) + + x_val = float(input("\nEnter the value of x for interpolation: ")) + + y_lagr = lagrange_interpolation(x, y, x_val) + y_newton_div = newton_divided(x, divided_differences(x, y), x_val) + y_newton_fin = newton_finite_diff(x, y, x_val) + + print(f"\nInterpolated function values:") + print(f"Lagrange: {y_lagr:.6f}") + print(f"Newton (divided differences): {y_newton_div:.6f}") + print(f"Newton (finite differences): {y_newton_fin:.6f}") + + plot_all_methods(x, y, x_val) + +if __name__ == "__main__": + main() diff --git "a/\320\2403213/molchanov_413015/lab5/test_data_1.txt" "b/\320\2403213/molchanov_413015/lab5/test_data_1.txt" new file mode 100644 index 0000000..9636b71 --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab5/test_data_1.txt" @@ -0,0 +1,9 @@ +-5.0 0.0385 +-3.7 0.0681 +-2.5 0.1379 +-1.0 0.5000 + 0.0 1.0000 + 1.2 0.4098 + 2.7 0.1205 + 4.1 0.0563 + 5.0 0.0385 diff --git "a/\320\2403213/molchanov_413015/lab5/test_data_2.txt" "b/\320\2403213/molchanov_413015/lab5/test_data_2.txt" new file mode 100644 index 0000000..d82248c --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab5/test_data_2.txt" @@ -0,0 +1,5 @@ +0.0000 0.0000 +0.3000 0.2955 +0.6000 0.5646 +0.9000 0.7833 +1.2000 0.9320 diff --git "a/\320\2403213/molchanov_413015/lab5/test_data_3.txt" "b/\320\2403213/molchanov_413015/lab5/test_data_3.txt" new file mode 100644 index 0000000..13e50d1 --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab5/test_data_3.txt" @@ -0,0 +1,5 @@ +1.0000 0.8415 +1.5000 0.9975 +2.0000 0.9093 +2.5000 0.5985 +3.0000 0.1411 diff --git "a/\320\2403213/molchanov_413015/lab5/\320\236\321\202\321\207\321\221\321\202 \320\262\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\2615.pdf" "b/\320\2403213/molchanov_413015/lab5/\320\236\321\202\321\207\321\221\321\202 \320\262\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\2615.pdf" new file mode 100644 index 0000000..5e0af47 Binary files /dev/null and "b/\320\2403213/molchanov_413015/lab5/\320\236\321\202\321\207\321\221\321\202 \320\262\321\213\321\207\320\274\320\260\321\202 \320\273\320\260\320\2615.pdf" differ diff --git "a/\320\2403213/molchanov_413015/lab6/main.py" "b/\320\2403213/molchanov_413015/lab6/main.py" new file mode 100644 index 0000000..feae479 --- /dev/null +++ "b/\320\2403213/molchanov_413015/lab6/main.py" @@ -0,0 +1,135 @@ +import numpy as np +import matplotlib.pyplot as plt +from math import sin, cos, exp + +class ODESolver: + def __init__(self, f, y_exact=None): + self.f = f + self.y_exact = y_exact + + def euler(self, x0, y0, h, xn): + x_vals = [x0] + y_vals = [y0] + x, y = x0, y0 + while x < xn: + y += h * self.f(x, y) + x += h + x_vals.append(x) + y_vals.append(y) + return np.array(x_vals), np.array(y_vals) + + def improved_euler(self, x0, y0, h, xn): + x_vals = [x0] + y_vals = [y0] + x, y = x0, y0 + while x < xn: + k1 = self.f(x, y) + k2 = self.f(x + h, y + h * k1) + y += h / 2 * (k1 + k2) + x += h + x_vals.append(x) + y_vals.append(y) + return np.array(x_vals), np.array(y_vals) + + def runge_rule_generic(self, method, x0, y0, h, xn, p, eps=0.1): + x1, y1 = method(x0, y0, h, xn) + x2, y2 = method(x0, y0, h / 2, xn) + y2_interp = y2[::2] + min_len = min(len(y1), len(y2_interp)) + y1 = y1[:min_len] + y2_interp = y2_interp[:min_len] + x1 = x1[:min_len] + eps_arr = np.abs(y1 - y2_interp) / (2**p - 1) + return eps_arr, y1, x1 + + def milne(self, x0, y0, h, xn): + x_vals, y_vals = self.improved_euler(x0, y0, h, x0 + 3 * h) # 4 точки + f_vals = [self.f(x, y) for x, y in zip(x_vals, y_vals)] + + x = x_vals[-1] + while x + h <= xn: + y_pred = y_vals[-4] + (4 * h / 3) * (2 * f_vals[-3] - f_vals[-2] + 2 * f_vals[-1]) + f_pred = self.f(x + h, y_pred) + y_corr = y_vals[-2] + (h / 3) * (f_vals[-2] + 4 * f_vals[-1] + f_pred) + x += h + x_vals = np.append(x_vals, x) + y_vals = np.append(y_vals, y_corr) + f_vals.append(self.f(x, y_corr)) + + return x_vals, y_vals + +# --- Уравнения --- +def equation1(x, y): return x + y +def equation2(x, y): return y - x**2 + 1 +def equation3(x, y): return sin(x) - y + +print("Выберите уравнение y' = f(x, y):") +print("1. y' = x + y") +print("2. y' = y - x^2 + 1") +print("3. y' = sin(x) - y") +while True: + try: + choice = int(input("Ваш выбор (1-3): ")) + if choice in [1, 2, 3]: break + except ValueError: continue + +x0 = float(input("Введите x₀: ")) +y0 = float(input("Введите y₀: ")) +xn = float(input("Введите xₙ: ")) +h = float(input("Введите шаг h: ")) + +# --- Точные решения --- +def exact1(x): + C = (y0 + x0 + 1) / exp(x0) + return C * np.exp(x) - x - 1 + +def exact2(x): + return (x + 1)**2 - 0.5 * np.exp(x) + +def exact3(x): + C = (y0 - 0.5 * (sin(x0) - cos(x0))) * exp(x0) + return 0.5 * (np.sin(x) - np.cos(x)) + C * np.exp(-x) + +equations = {1: (equation1, exact1), 2: (equation2, exact2), 3: (equation3, exact3)} +f, y_exact = equations[choice] +solver = ODESolver(f, y_exact) + +# --- Решения и ошибки --- +eps_euler, y_euler, x_vals = solver.runge_rule_generic(solver.euler, x0, y0, h, xn, p=1) +eps_improved, y_improved, _ = solver.runge_rule_generic(solver.improved_euler, x0, y0, h, xn, p=2) +x_milne, y_milne = solver.milne(x0, y0, h, xn) + +# --- Глобальные ошибки --- +y_true = y_exact(np.array(x_vals)) +err_euler = np.max(np.abs(y_true - y_euler)) +err_improved = np.max(np.abs(y_true - y_improved)) +err_milne = np.max(np.abs(y_exact(x_milne) - y_milne)) + +print("\n{:>5} {:>12} {:>12} {:>16} {:>16} {:>16}".format("i", "x", "Euler", "Improved", "Milne", "ε (Euler)")) +print("-" * 90) +for i in range(len(x_vals)): + x = x_vals[i] + ye = y_euler[i] + yi = y_improved[i] + ym = y_milne[i] if i < len(y_milne) else float('nan') + ee = eps_euler[i] if i < len(eps_euler) else float('nan') + print("{:>5} {:>12.6f} {:>12.6f} {:>16.6f} {:>16.6f} {:>16.6f}".format(i, x, ye, yi, ym, ee)) + +print("\nГлобальная погрешность:") +print(f" Метод Эйлера: {err_euler:.6f}") +print(f" Усоверш. Эйлер: {err_improved:.6f}") +print(f" Метод Милна: {err_milne:.6f}") + +x_dense = np.linspace(x0, xn, 500) +y_dense = y_exact(x_dense) + +plt.plot(x_dense, y_dense, label="Точное решение", color="blue") +plt.plot(x_vals, y_euler, "o-", label="Эйлер", color="orange") +plt.plot(x_vals, y_improved, "s--", label="Усоверш. Эйлер", color="green") +plt.plot(x_milne, y_milne, "d-.", label="Метод Милна", color="red") +plt.xlabel("x") +plt.ylabel("y") +plt.title("Решение ОДУ: Эйлер, улучшенный и Милн") +plt.grid(True) +plt.legend() +plt.show()