SymPy + алгебраическое уравнение + числа с плавающей запятой => проблема.Математика с плавающей точкой не работает как обычная математика , и SymPy предназначен для последнего.Маленькие вещи, такие как 16 (целое число) против 16.0 (число с плавающей запятой) имеют большое значение при решении уравнений с помощью SymPy: в идеале у вас не должно быть чисел с плавающей запятой, вместо этого создаются точные рациональные числа , как здесь.
from sympy import S
one_x = S('-0.08')
Однако у вас есть данные с плавающей запятой и вы ищете решение с плавающей запятой.Это делает SymPy неподходящим инструментом для работы.SymPy предназначен для математических операций с символами, а не для вычисления чисел с плавающей запятой.Правильное решение - использовать соответствующее решение от SciPy, например brentq
.В качестве входных данных используется интервал брекетинга (где функция имеет разные знаки на обоих концах).Например:
from scipy.optimize import brentq
eq = lambda x: np.sqrt((x-second_x)**2 + (slope*x+intercept-second_y)**2) + second_r - one_r - np.sqrt((x-one_x)**2 + (slope*x + intercept - one_y)**2)
brentq(eq, -10, 10) # returns -0.049356742923277075
Если вы придерживаетесь SymPy, это означает, что ваше уравнение передается на аутсорсинг в библиотеку mpmath
, которая гораздо более ограничена в поиске и оптимизации числовых корней.Чтобы решение сходилось с его методами, вам понадобится действительно хорошая отправная точка: очевидно, one_x/2
- это такая точка.
from sympy import sqrt, Symbol, nsolve
# ... as in your code
nsolve(sqrt((x-second_x)**2+(slope*x+intercept-second_y)**2)+second_r-one_r-sqrt((x-one_x)**2+(slope*x+intercept-one_y)**2), one_x/2)
возвращает -0.0493567429232771
.
Используя sympy.solveset
, который предназначен для символического решения, вы лишаете себя не только мощных числовых решателей SciPy, но и возможности установить хорошее начальное значение для числового поиска, который обеспечивает sympy.nsolve
,Отсюда и отсутствие сходимости в этой численно сложной задаче.Кстати, это то, что делает его численно хитрым: функция почти постоянна в большинстве случаев с одним быстрым изменением.