diff --git a/code/main.py b/code/main.py new file mode 100644 index 0000000..cb64fc1 --- /dev/null +++ b/code/main.py @@ -0,0 +1,121 @@ +import scipy.integrate as sitg +import scipy.interpolate as sitp +import scipy.optimize as sopt +import scipy.linalg as salg +import math as m +import numpy as np + +import matplotlib.pyplot as plt + + +def create_subplot(): + return plt.subplots(layout='constrained')[1] + + +class NonLinear: + bisect_exp = "x**2 * np.sin(x)" + newton_exp = "np.sin(x) * np.sqrt(np.abs(x))" + + @staticmethod + def generate_array(min, max): + point_count = int(m.fabs(max-min))*10 + x = np.linspace(min, max, point_count) + return list(x.tolist()) + + @staticmethod + def slice_array(range: list[float], val_min, val_max): + def index_search(range: list[float], val): + i = 0 + for v in range: + if v >= val: + return i + i += 1 + return -1 + + index_l = index_search( + range, val_min) if val_min is not None else range.index(min(range)) + index_r = index_search( + range, val_max) if val_max is not None else range.index(max(range)) + return range[index_l:index_r+1] + + @staticmethod + def plt_append(sp, x: list[float], y: list[float], label: str, format: str): + sp.plot(x, y, format, label=label) + + @staticmethod + def bisect(x, x_min, x_max): + def f(x): return eval(NonLinear.bisect_exp) + y = f(np.array(x)) + root = sopt.bisect(f, x_min, x_max) + solution = root[0] if root is tuple else root + return list(y), (float(solution), float(f(solution))) + + @staticmethod + def plot_bisect(): + bounds = 0, 6 + split_val = 1 + x1 = NonLinear.generate_array(bounds[0], bounds[1]) + x2 = NonLinear.slice_array(x1, split_val, None) + + sp = create_subplot() + + sol1 = NonLinear.bisect(x1, bounds[0], bounds[1]) + sol2 = NonLinear.bisect(x2, split_val, bounds[1]) + + NonLinear.plt_append( + sp, x1, sol1[0], f"Исходные данные (y={NonLinear.bisect_exp})", "-b") + NonLinear.plt_append( + sp, *(sol1[1]), f"bisect at [{bounds[0]},{bounds[1]}]", "or") + NonLinear.plt_append( + sp, *(sol2[1]), f"bisect at [{split_val},{bounds[1]}]", "og") + + sp.set_title("scipy.optimize.bisect") + sp.legend(loc='lower left') + + @staticmethod + def newton(x, x0): + def f(x): return eval(NonLinear.bisect_exp) + y = f(np.array(x)) + root = sopt.newton(f, x0) + solution = root[0] if root is tuple else root + return list(y), (float(solution), float(f(solution))) + + @staticmethod + def plot_newton(): + bounds = -2, 7 + split_l, split_r = 2, 5 + x1 = NonLinear.generate_array(bounds[0], bounds[1]) + x2 = NonLinear.slice_array(x1, split_l, split_r) + x0_1, x0_2 = 1/100, 4 + sp = create_subplot() + + sol1 = NonLinear.newton(x1, x0_1) + sol2 = NonLinear.newton(x2, x0_2) + + NonLinear.plt_append( + sp, x1, sol1[0], f"Исходные данные (y={NonLinear.newton_exp})", "-b") + NonLinear.plt_append( + sp, *(sol1[1]), f"newton at [{bounds[0]},{bounds[1]}]", "or") + NonLinear.plt_append( + sp, *(sol2[1]), f"newton at [{split_l},{bounds[1]}]", "og") + + sp.set_title("scipy.optimize.newton") + sp.legend(loc='lower left') + + @staticmethod + def plot(method: str = "all"): + if method in ["bisect", "all"]: + NonLinear.plot_bisect() + if method in ["newton", "all"]: + NonLinear.plot_newton() + plt.ylabel("y") + plt.xlabel("x") + plt.show() + + +def main(): + NonLinear.plot() + + +if __name__ == "__main__": + main()