2025, Oct 31 23:46
Почему plot_implicit в SymPy падает на Abs и And и как это исправить
Разбираемся, почему plot_implicit в SymPy падает на булевых неравенствах с Abs и And, и как решить проблему с помощью SymPy Plotting Backends (spb). Советы.
Построение булевых неявных областей в SymPy: почему это ломается и как это исправить
Объединять неравенства в единую неявную область в SymPy на первый взгляд просто — пока внезапно не перестает работать. Типичный пример — построение неравенства, где логическое выражение сочетается с Abs. Пример ниже по отдельности выполняется без проблем, однако совместный график через стандартный plot_implicit приводит к исключению.
Проблемный пример
from sympy import *
u, v = symbols('u v')
rule_a = v + 2*Abs(u) > 0
rule_b = u > 0
rule_c = v < 0
fig_a = plot_implicit(rule_a)
fig_b = plot_implicit(rule_b)
fig_c = plot_implicit(And(rule_b, rule_c))
try:
fig_d = plot_implicit(And(rule_a, rule_b))
except:
print("Why is this not working")
Последний вызов и есть источник ошибки: построение And(rule_a, rule_b) падает, тогда как предыдущие одиночные графики строятся без проблем.
Что на самом деле происходит
Использование SymPy Plotting Backends (spb) решает проблему. Разработчик SymPy Plotting Backends исправил баг и выпустил новый релиз с исправлением. Пакет уже доступен на PyPI, а в Conda ожидается в ближайшее время. С обновленным spb то же булево выражение, где смешиваются And и Abs, строится успешно.
Есть небольшой алгоритмический нюанс, о котором полезно знать. В spb функция plot_implicit может вычислять выражения двумя способами. Обычно она берёт равномерную сетку точек. Когда на вход поступает булево выражение (например, с And или Or), автоматически включается адаптивный алгоритм на базе интервальной арифметики, поскольку он обычно даёт лучший результат. Однако выражение, содержащее Abs, такой адаптивный режим не поддерживает. В этой ситуации код обнаруживает ограничение и откатывается к равномерной выборке. Во время работы вы увидите предупреждения, поясняющие смену стратегии:
UserWarning: Переданное выражение содержит булевы функции. Для его построения алгоритм автоматически переключился на адаптивное семплирование.
UserWarning: К выражению не удалось применить адаптивную разметку. Используется равномерная разметка.
Практическое решение с SymPy Plotting Backends
Ниже приведена рабочая конфигурация с spb. Порядок символов определяет оси, а пара небольших настроек делает вывод чище. Если диапазоны не заданы, plot_implicit ограничивает обе оси отрезком [-10, 10]. Выбор нечетного n размещает точки выборки ровно на u=0 и v=0, что улучшает вид границ. Для объединённой булевой области увеличение n дополнительно сглаживает результат.
from sympy import *
from spb import *
var("u v")
rule_a = v + 2*Abs(u) > 0
rule_b = u > 0
rule_c = v < 0
combo = And(rule_a, rule_b)
fig1 = plot_implicit(rule_a, u, v, n=101, grid=False, title=str(rule_a))
fig2 = plot_implicit(rule_b, u, v, grid=False, title=str(rule_b))
fig3 = plot_implicit(combo, u, v, n=1001, grid=False, title=str(combo))
Запустите это с обновлённым spb — получите ожидаемые графики. Предупреждения носят информативный характер и отражают автоматическое переключение с адаптивной на равномерную сетку из‑за Abs.
Зачем это важно
Неявное построение логических комбинаций неравенств — распространённый способ визуализации допустимых областей и ограничений. Без устойчивой обработки булевых выражений, особенно с Abs, можно столкнуться с исключениями или вводящими в заблуждение графиками. Знание того, что spb сначала пытается адаптивный проход, а затем корректно откатывается к равномерному семплированию, даёт предсказуемый результат даже для сложных выражений.
Вывод и практические советы
Если неявный график с булевой логикой падает при стандартном подходе, попробуйте plot_implicit из SymPy Plotting Backends. Следите за консолью: предупреждения подскажут, когда алгоритм меняет режим. Явно задавайте порядок переменных, чтобы оси не перепутались, и используйте нечетное n, чтобы узлы попадали на оси; для более сложных объединений увеличивайте n, чтобы повысить качество визуализации. Обновлённый пакет с исправлением уже доступен на PyPI и в ближайшее время ожидается в Conda. Если столкнётесь с другими проблемами, сообщите о них в репозитории проекта: https://github.com/Davide-sd/sympy-plot-backends/issues. Подробности по использованию смотрите в документации: https://sympy-plot-backends.readthedocs.io.