mport sympy as sp
x = sp.symbols("x")
f_expr = 2 * sp.log(x) - x ** 2 + 5 # уравнение f(x) = 0
SEGMENTS = [(0.01, 0.1), (2, 3)] # отрезки изоляции корней (по графику)
ROOTS_COUNT = 2 # сколько корней найти
EPSILON = 0.0001 # точность
PARTS = 1000 # на сколько частей делим отрезок (для min и max)
if ROOTS_COUNT > len(SEGMENTS): # ошибка, если корней запрошено больше, чем есть
raise ValueError(f"В уравнении корней: {len(SEGMENTS)}, а запрошено {ROOTS_COUNT}")
PHI_EXPRS = [sp.exp((x ** 2 - 5) / 2), # x = phi(x) для корня на [0.01; 0.1]
sp.sqrt(2 * sp.log(x) + 5)] # x = phi(x) для корня на [2; 3]
for i in range(ROOTS_COUNT): # по одному отрезку на каждый корень
A, B = SEGMENTS[i] # границы отрезка
phi = sp.lambdify(x, PHI_EXPRS[i], "math") # phi(x)
phi1 = sp.lambdify(x, sp.diff(PHI_EXPRS[i], x), "math") # phi'(x)
points = [A + (B - A) * k / PARTS for k in range(PARTS + 1)] # точки разбиения отрезка
q = max(abs(phi1(p)) for p in points) # q = max |phi'(x)|
if q >= 1: # при q >= 1 метод не сходится
print(f"Корень {i + 1}: q = {q:.4f} >= 1, метод не сходится")
continue
x_prev = (A + B) / 2 # начальное приближение
iterations = 0 # счётчик итераций
while True:
x_new = phi(x_prev) # x(n) = phi(x(n-1))
iterations += 1
if q / (1 - q) * abs(x_new - x_prev) < EPSILON: # q/(1-q) * |x(n) - x(n-1)| < eps
break
x_prev = x_new # запоминаем для следующего шага
print(f"Корень {i + 1}: {x_new:.8f}, итераций: {iterations}, q = {q:.4f}")