Загрузка данных


from scipy import optimize
import numpy as np
import matplotlib.pyplot as plt

# Коэффициенты варианта 16
B, C, D = -0.205, -10.880, 1.469

def f(x): return x**3 - B*x**2 + C*x - D
def fp(x): return 3*x**2 - 2*B*x + C

# ----- Поиск корней -----
# Корень 1: на интервале [-4, -2.5] (примерно -3.179)
x1 = optimize.root_scalar(f, bracket=[-4, -2.5], method='bisect')

# Корень 2: метод Ньютона, начальное приближение 0 (корень ~0.1345)
x2 = optimize.root_scalar(f, x0=0, method='newton', fprime=fp)

# Корень 3: обычный root, начальное приближение 3.2 (корень ~3.265)
x3 = optimize.root(f, 3.2)

# ----- Аналитические точки экстремумов (из производной) -----
a_fp, b_fp, c_fp = 3, -2*B, C
discriminant = b_fp**2 - 4*a_fp*c_fp   # всегда >0 для кубического многочлена с тремя корнями
x_max_analyt = (-b_fp - np.sqrt(discriminant)) / (2*a_fp)   # локальный максимум
x_min_analyt = (-b_fp + np.sqrt(discriminant)) / (2*a_fp)   # локальный минимум

print("Аналитически (из производной):")
print(f"  Точка максимума: x = {x_max_analyt:.6f}, f(x) = {f(x_max_analyt):.6f}")
print(f"  Точка минимума:  x = {x_min_analyt:.6f}, f(x) = {f(x_min_analyt):.6f}")

# ----- Численное уточнение экстремумов с помощью SciPy -----
# Минимум (метод bounded, сужаем интервал вокруг аналитического минимума)
min_res = optimize.minimize_scalar(f, bounds=(x_min_analyt-0.5, x_min_analyt+0.5), method='bounded')
# Максимум (минимизируем -f(x))
max_res = optimize.minimize(lambda x: -f(x), x_max_analyt)

print("\nРешатели SciPy:")
print(f"  Корни: x1 = {x1.root:.6f}, x2 = {x2.root:.6f}, x3 = {x3.x[0]:.6f}")
print(f"  Минимум: x = {min_res.x:.6f}, f = {min_res.fun:.6f}")
print(f"  Максимум: x = {max_res.x[0]:.6f}, f = {-max_res.fun:.6f}")

# ----- Построение графика -----
x_vals = np.linspace(-5.5, 5.0, 500)   # расширенный диапазон для 16 варианта
plt.figure(figsize=(12, 6))
plt.plot(x_vals, f(x_vals), 'b-', linewidth=2, label='f(x)')
plt.axhline(0, color='black', lw=1)

# Отмечаем корни
plt.scatter([x1.root, x2.root, x3.x[0]], [0, 0, 0], color='red', s=80, zorder=5, label='Корни')

# Отмечаем экстремумы
plt.scatter(min_res.x, min_res.fun, color='green', s=100, zorder=5, marker='^',
            label=f'Минимум ({min_res.x:.3f}, {min_res.fun:.1f})')
plt.scatter(max_res.x[0], -max_res.fun, color='orange', s=100, zorder=5, marker='v',
            label=f'Максимум ({max_res.x[0]:.3f}, {-max_res.fun:.1f})')

# Аннотация для максимума
plt.annotate(f'{-max_res.fun:.1f}', xy=(max_res.x[0], -max_res.fun),
             xytext=(max_res.x[0]+0.3, -max_res.fun+2), fontsize=10)

plt.title("Исследование функции (Вариант 16)")
plt.xlabel("x")
plt.ylabel("f(x)")
plt.grid(True, alpha=0.3)
plt.legend()
plt.tight_layout()
plt.show()