Добавление информации о методах (№1) #2
							
								
								
									
										236
									
								
								code/main.py
									
									
									
									
									
								
							
							
						
						
									
										236
									
								
								code/main.py
									
									
									
									
									
								
							| @ -16,16 +16,16 @@ def plt_append(sp, x: list[float], y: list[float], label: str, format: str): | ||||
|    sp.plot(x, y, format, label=label) | ||||
| 
 | ||||
| 
 | ||||
| def generate_array(min, max, density=10): | ||||
|    point_count = int(m.fabs(max-min)*density) | ||||
|    x = np.linspace(min, max, point_count) | ||||
|    return list(x.tolist()) | ||||
| 
 | ||||
| 
 | ||||
| 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): | ||||
| @ -54,7 +54,7 @@ class NonLinear: | ||||
|    def plot_bisect(): | ||||
|       bounds = 0, 6 | ||||
|       split_val = 1 | ||||
|       x1 = NonLinear.generate_array(bounds[0], bounds[1]) | ||||
|       x1 = generate_array(bounds[0], bounds[1]) | ||||
|       x2 = NonLinear.slice_array(x1, split_val, None) | ||||
| 
 | ||||
|       sp = create_subplot() | ||||
| @ -65,9 +65,9 @@ class NonLinear: | ||||
|       plt_append( | ||||
|           sp, x1, sol1[0], f"Исходные данные (y={NonLinear.bisect_exp})", "-b") | ||||
|       plt_append( | ||||
|           sp, *(sol1[1]), f"bisect at [{bounds[0]},{bounds[1]}]", "or") | ||||
|           sp, *(sol1[1]), f"bisect на [{bounds[0]},{bounds[1]}]", "or") | ||||
|       plt_append( | ||||
|           sp, *(sol2[1]), f"bisect at [{split_val},{bounds[1]}]", "og") | ||||
|           sp, *(sol2[1]), f"bisect на [{split_val},{bounds[1]}]", "og") | ||||
| 
 | ||||
|       sp.set_title("scipy.optimize.bisect") | ||||
|       sp.legend(loc='lower left') | ||||
| @ -84,7 +84,7 @@ class NonLinear: | ||||
|    def plot_newton(): | ||||
|       bounds = -2, 7 | ||||
|       split_l, split_r = 2, 5 | ||||
|       x1 = NonLinear.generate_array(bounds[0], bounds[1]) | ||||
|       x1 = 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() | ||||
| @ -95,9 +95,9 @@ class NonLinear: | ||||
|       plt_append( | ||||
|           sp, x1, sol1[0], f"Исходные данные (y={NonLinear.newton_exp})", "-b") | ||||
|       plt_append( | ||||
|           sp, *(sol1[1]), f"newton at [{bounds[0]},{bounds[1]}]", "or") | ||||
|           sp, *(sol1[1]), f"newton на отрезке [{bounds[0]},{bounds[1]}]", "or") | ||||
|       plt_append( | ||||
|           sp, *(sol2[1]), f"newton at [{split_l},{bounds[1]}]", "og") | ||||
|           sp, *(sol2[1]), f"newton на отрезке [{split_l},{bounds[1]}]", "og") | ||||
| 
 | ||||
|       sp.set_title("scipy.optimize.newton") | ||||
|       sp.legend(loc='lower left') | ||||
| @ -137,7 +137,8 @@ class SLE: | ||||
|          new_data = [] | ||||
|          new_len = len(data[0][0]) | ||||
|          zipped = list(zip(*tuple(data[0]))) | ||||
|          zipped[len(zipped)-1] = (zipped[len(zipped)-1][0],zipped[len(zipped)-2][1]) | ||||
|          zipped[len(zipped)-1] = (zipped[len(zipped)-1] | ||||
|                                   [0], zipped[len(zipped)-2][1]) | ||||
|          complement_to = new_len - len(zipped[0]) | ||||
|          for i, val in enumerate(zipped): | ||||
|             zero_r = complement_to - i | ||||
| @ -159,7 +160,7 @@ class SLE: | ||||
|             if coef != 0: | ||||
|                print(f"({coef}{SLE.var_str(i_coef)}) + ", end='') | ||||
|             else: | ||||
|                print(f"  {coef}   + ",end='') | ||||
|                print(f"  {coef}   + ", end='') | ||||
|          print(f"({val[-1]}{SLE.var_str(len(val)-1)})", end='') | ||||
|          print(f" = {data[1][i]}") | ||||
| 
 | ||||
| @ -213,12 +214,215 @@ class SLE: | ||||
|       if method in ["banded", "all"]: | ||||
|          SLE.print_tridiagonal() | ||||
| 
 | ||||
| 
 | ||||
| class Approx: | ||||
|    function = "np.sin(x) * np.sqrt(np.abs(x))" | ||||
|    function_exp = "np.sin(x) * np.sqrt(np.abs(x))" | ||||
|    least_sq_exp = "np.sin(x) * np.abs(x)" | ||||
| 
 | ||||
|    @staticmethod | ||||
|    def get_function_exp_der(*args): | ||||
|       function_der_exp = "(x * np.sin(x) + 2 * x**2 * np.cos(x)) / (2 * np.sqrt(np.abs(x)) ** 3)" | ||||
|       result = () | ||||
|       for i in args: | ||||
|          array = [] | ||||
|          for x in i: | ||||
|             array.append(eval(function_der_exp)) | ||||
| 
 | ||||
|          result = result + (array,) | ||||
|       return result | ||||
| 
 | ||||
|    @staticmethod | ||||
|    def generate_y(x_array, function): | ||||
|       result = [] | ||||
|       for x in x_array: | ||||
|          result.append(eval(function)) | ||||
|       return result | ||||
| 
 | ||||
|    @staticmethod | ||||
|    def lagrange(x, y): | ||||
|       return sitp.lagrange(x, y) | ||||
| 
 | ||||
|    @staticmethod | ||||
|    def get_approx_data(function=function_exp, bounds=[-6, 6]): | ||||
|       x1 = generate_array(bounds[0], bounds[1], 1/2) | ||||
|       x2 = generate_array(bounds[0], bounds[1], 1) | ||||
|       y1 = Approx.generate_y(x1, function) | ||||
|       y2 = Approx.generate_y(x2, function) | ||||
|       x_real = generate_array(bounds[0], bounds[1]) | ||||
|       y_real = Approx.generate_y(x_real, function) | ||||
|       return x1, x2, y1, y2, x_real, y_real | ||||
| 
 | ||||
|    @staticmethod | ||||
|    def plot_lagrange(): | ||||
|       x1, x2, y1, y2, x_real, y_real = Approx.get_approx_data() | ||||
| 
 | ||||
|       sp = create_subplot() | ||||
|       sol1 = np.polynomial.polynomial.Polynomial( | ||||
|           Approx.lagrange(x1, y1).coef[::-1]) | ||||
|       sol2 = np.polynomial.polynomial.Polynomial( | ||||
|           Approx.lagrange(x2, y2).coef[::-1]) | ||||
| 
 | ||||
|       plt_append( | ||||
|           sp, x_real, y_real, f"Исходные данные (y={Approx.function_exp})", "--b") | ||||
|       plt_append( | ||||
|           sp, x_real, sol1(np.array(x_real)), f"f1 = lagrange, кол-во точек = {len(x1)}", "-m") | ||||
|       plt_append( | ||||
|           sp, x_real, sol2(np.array(x_real)), f"f2 = lagrange, кол-во точек = {len(x2)}", "-r") | ||||
|       plt_append( | ||||
|           sp, x1, y1, f"Исходные точки для f1", ".m") | ||||
|       plt_append( | ||||
|           sp, x2, y2, f"Исходные точки для f2", ".r") | ||||
| 
 | ||||
|       sp.set_title("scipy.interpolate.lagrange") | ||||
|       sp.legend(loc='lower left') | ||||
| 
 | ||||
|    @staticmethod | ||||
|    def plot_spline(): | ||||
|       x1, x2, y1, y2, x_real, y_real = Approx.get_approx_data() | ||||
|       d1, d2 = Approx.get_function_exp_der(x1, x2) | ||||
| 
 | ||||
|       for interpolator in [sitp.CubicSpline, | ||||
|                            sitp.PchipInterpolator, | ||||
|                            sitp.CubicHermiteSpline, | ||||
|                            sitp.Akima1DInterpolator]: | ||||
|          sp = create_subplot() | ||||
| 
 | ||||
|          if interpolator.__name__ != "CubicHermiteSpline": | ||||
|             args1 = x1, y1 | ||||
|             args2 = x2, y2 | ||||
|          else: | ||||
|             args1 = x1, y1, d1 | ||||
|             args2 = x2, y2, d2 | ||||
| 
 | ||||
|          sol1 = interpolator(*args1) | ||||
|          sol2 = interpolator(*args2) | ||||
|          plt_append( | ||||
|              sp, x_real, y_real, f"Исходные данные (y={Approx.function_exp})", "--b") | ||||
|          plt_append( | ||||
|              sp, x_real, sol1(np.array(x_real)), f"f1 = {interpolator.__name__}, кол-во точек = {len(x1)}", "-m") | ||||
|          plt_append( | ||||
|              sp, x_real, sol2(np.array(x_real)), f"f2 = {interpolator.__name__}, кол-во точек = {len(x2)}", "-r") | ||||
|          plt_append( | ||||
|              sp, x1, y1, f"Исходные точки для f1", ".m") | ||||
|          plt_append( | ||||
|              sp, x2, y2, f"Исходные точки для f2", ".r") | ||||
| 
 | ||||
|          sp.set_title(f"scipy.interpolate.{interpolator.__name__}") | ||||
|          sp.legend(loc='lower left') | ||||
| 
 | ||||
|    @staticmethod | ||||
|    def linear(x, a, b): | ||||
|       return a*x + b | ||||
| 
 | ||||
|    @staticmethod | ||||
|    def quadratic(x, a, b, c): | ||||
|       return a * (x**2) + (b*x) + c | ||||
| 
 | ||||
|    @staticmethod | ||||
|    def fract(x, a, b, c): | ||||
|       return x / (a * x + b) - c | ||||
| 
 | ||||
|    @staticmethod | ||||
|    def noise_y(y, rng): | ||||
|       diff = max(y) - min(y) | ||||
|       noise_coeff = diff*(10/100) | ||||
|       return y + (noise_coeff * rng.normal(size=len(y))) | ||||
| 
 | ||||
|    @staticmethod | ||||
|    def plot_least_squares_curvefit(): | ||||
|       rng = np.random.default_rng() | ||||
|       bounds = [3, 6] | ||||
|       x1, x2, y1, y2, x_real, y_real = Approx.get_approx_data( | ||||
|           Approx.least_sq_exp, bounds) | ||||
|       x_real = np.array(x_real) | ||||
| 
 | ||||
|       y_real = Approx.noise_y(y_real, rng) | ||||
|       base_functions = [Approx.linear, | ||||
|                         Approx.quadratic, (Approx.fract, "x/(ax+b)")] | ||||
| 
 | ||||
|       sp = create_subplot() | ||||
|       plt_append( | ||||
|           sp, x_real, y_real, f"y={Approx.least_sq_exp} на [{bounds[0]};{bounds[1]}], с шумом", ".b") | ||||
|       for bf in base_functions: | ||||
|          if isinstance(bf, tuple): | ||||
|             bf, desc = bf[0], bf[1] | ||||
|          else: | ||||
|             bf, desc = bf, None | ||||
|          optimal_params, _ = sopt.curve_fit(bf, x_real, y_real) | ||||
|          desc_str = f" ({desc}) " if desc is not None else "" | ||||
|          plt_append( | ||||
|              sp, x_real, bf(np.array(x_real), *optimal_params), | ||||
|              f"МНК, вид функции - {bf.__name__}{desc_str}", "-") | ||||
|       sp.set_title(f"scipy.optimize.curve_fit") | ||||
|       sp.legend(loc='lower left') | ||||
| 
 | ||||
|    @staticmethod | ||||
|    def plot_least_squares(): | ||||
|       rng = np.random.default_rng() | ||||
| 
 | ||||
|       def exponential(x, a, b, c): | ||||
|          return np.sin(x) * np.sqrt(np.abs(x)) | ||||
|       exponential.str = "np.sin(x) * np.sqrt(np.abs(x))" | ||||
| 
 | ||||
|       def gen_y(x, a, b, c, noise=0., n_outliers=0): | ||||
|          y = exponential(x, a, b, c) | ||||
|          error = noise * rng.standard_normal(x.size) | ||||
|          outliers = rng.integers(0, x.size, n_outliers) | ||||
|          error[outliers] *= 10 | ||||
|          return y + error | ||||
| 
 | ||||
|       def loss(params, x, y): | ||||
|          return (exponential(x, params[0], params[1], params[2])) - y | ||||
|       params0 = np.array([0.1, 1, 0]) | ||||
|       bounds = [-5, 3] | ||||
|       params_real = (3, 1, 5) | ||||
|       x_approx = np.array(generate_array(bounds[0], bounds[1], 4)) | ||||
|       y_approx = np.array(gen_y(x_approx, *params_real, | ||||
|                                 noise=0.3, n_outliers=4)) | ||||
| 
 | ||||
|       params_lsq = sopt.least_squares( | ||||
|           loss, params0, loss='linear', args=(x_approx, y_approx)).x | ||||
|       params_soft_l1 = sopt.least_squares( | ||||
|           loss, params0, loss='soft_l1', args=(x_approx, y_approx),f_scale=0.1).x | ||||
|       params_cauchy = sopt.least_squares( | ||||
|           loss, params0, loss='cauchy', args=(x_approx, y_approx), f_scale=2).x | ||||
| 
 | ||||
|       x_real = np.array(generate_array(bounds[0], bounds[1])) | ||||
|       y_real = np.array(gen_y(x_real, *params_real, 0, 0)) | ||||
| 
 | ||||
|       sp = create_subplot() | ||||
|       sp.plot(x_real, y_real, "-b", | ||||
|               label=f"y={exponential.str} на [{bounds[0]};{bounds[1]}]") | ||||
|       sp.plot(x_approx, y_approx, ".r", label=f"Табличные значения с шумом") | ||||
|       sp.plot(x_real, gen_y(x_real, *params_lsq), color="green", | ||||
|               label=f"loss=\"linear\"", linestyle=(0, (5, 10))) | ||||
|       sp.plot(x_real, gen_y(x_real, *params_soft_l1), color="magenta", | ||||
|               label=f"loss=\"soft_l1\"", linestyle=(5, (5, 10))) | ||||
|       sp.plot(x_real, gen_y(x_real, *params_cauchy), color="black", | ||||
|               label=f"loss=\"cauchy\"", linestyle=(7, (5, 10))) | ||||
| 
 | ||||
|       sp.set_title(f"scipy.optimize.least_squares") | ||||
|       sp.legend(loc='lower left') | ||||
| 
 | ||||
|    @staticmethod | ||||
|    def plot(method: str = "all"): | ||||
|       if method in ["lagrange", "all"]: | ||||
|          Approx.plot_lagrange() | ||||
|       if method in ["spline", "all"]: | ||||
|          Approx.plot_spline() | ||||
|       if method in ["least_squares_curvefit", "all"]: | ||||
|          Approx.plot_least_squares_curvefit() | ||||
|       if method in ["least_squares", "all"]: | ||||
|          Approx.plot_least_squares() | ||||
|       plt.ylabel("y") | ||||
|       plt.xlabel("x") | ||||
|       plt.show() | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
|    # NonLinear.plot() | ||||
|    NonLinear.plot() | ||||
|    SLE.print() | ||||
|    Approx.plot() | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user