Часто задаваемые вопросы
Ограничения символьных вычислений
Не удалось преобразовать функцию в символьное уравнение. Что делать?
Если отображается следующее сообщение об ошибке:
ERROR: TypeError: non-boolean (Num) used in boolean context
скорее всего, причина в алгоритме, который невозможно отследить в чисто символьном алгоритме. Этим характеризуются, например, многие численные решатели. Ошибка появляется, когда вы делаете что-то вроде: если x < tol
. Если x — число, то значение верно или неверно. Если x — символ, то это x < tol
, поэтому Julia просто не может знать, сколько итераций нужно сделать, и возникает ошибка.
Это проявляется, например, в адаптивных алгоритмах:
function factorial(x)
out = x
while x > 1
x -= 1
out *= x
end
out
end
factorial (generic function with 1 method)
Количество итераций этого алгоритма зависит от значения x
, поэтому статического представления алгоритма не существует. Если x
равен 5, то это out = x*(x-1)(x-2)(x-3)(x-4)
, а если x
равен 3, то это out = x(x-1)*(x-2)
. Поэтому не стоит удивляться тому, что:
using Symbolics
@variables x
try
factorial(x)
catch e
e
end
TypeError(:if, "", Bool, x > 1)
завершается сбоем. Не то чтобы с этим кодом было что-то не так, но он не будет работать, потому что в своей основе это не является символически представимым алгоритмом.
Пространство алгоритмов, которые можно преобразовать в символьные алгоритмы, называют квазистатическим, то есть существует способ представления алгоритма как статического. Разрешены циклы, но количество итераций цикла не должно требовать от вас знание значения символа x
. Если алгоритм является квазистатическим, трассировка Symbolics.jl создаст статическую форму кода, развертывая операции и генерируя плоское представление алгоритма.
Что можно сделать?
Если вам нужно представить эту функцию f
символически, следует убедиться, что она не трассируется, а напрямую представлена в базовом вычислительном графе. Точно так же как sqrt(x)
символически не пытается представить базовый алгоритм, это должно быть сделано и с вашей функцией f
. Для этого нужно выполнить @register_symbolic f(x)
. Если вам нужно определить такие объекты, как производные функции f
, см. документацию по регистрации функций.
Тесты на равенство и принадлежность множеству
Сравнение символов с помощью ==
дает символьное уравнение, а не Bool
. Чтобы получить Bool
, вызовите isequal
.
Чтобы проверить, является ли символ частью коллекции символов, то есть вектора, создайте Set
и используйте in
, например:
try
x in [x]
catch e
e
end
TypeError(:if, "", Bool, x == x)
x in Set([x])
true
any(isequal(x), [x])
true