Поддерживаемые типы и диспетчеризация в Symbolics
Существует противоречие между типами как представлением в виде деревьев выражений и типами, которые являются подтипом типов, уже присутствующих в Julia.
Нам требуется возможность единообразно работать с деревьями выражений и не ограничивать сами деревья выражений абстрактным типом в иерархии типов Julia. (Например, если бы мы сказали, что все деревья выражений являются подтипом Real, то мы не смогли бы представлять операции с массивами с помощью одного и того же дерева выражений.) Но мы также хотим передавать деревья выражений в те места существующего кода, где принимаются значения Real
.
Для этого деревья выражений следует заключить в простой тип-оболочку, который является подтипом желаемого абстрактного типа. Например, мы заключаем деревья выражений в тип Num
, который является подтипом Real
, чтобы он вел себя как вещественное число.
Методы для объектов Num
передаются в заключенное в оболочку дерево выражений. При этом необходимо следить за тем, чтобы в дереве выражений никогда не было Num
. Это делается как для повышения производительности, так и для разделения обязанностей.
Ориентированные на пользователя API в Symbolics всегда принимают заключенные в оболочку объекты типа Num
, которые затем внутренне разворачиваются для работы с деревом выражений.
Из-за того, что для этого требуются соответствующие оболочки, мы полностью поддерживаем только ограниченное количество типов как в качестве типов деревьев выражений, так и в качестве типов, как их видит Julia.
Вот эти типы:
-
вещественные числа (заключаются в оболочку с помощью
Num
) -
комплексные числа (хранятся как
Complex{Num}
, гдеComplex
берется из Base Julia) -
массивы вещественных и комплексных чисел (заключаются в оболочку с помощью
Arr
, поэтомуArr{Num}
илиArr{Complex{Num}}
)
@variables
и типы
Используйте синтаксис @variables x::T
для создания символа с именем x
символьного типа T
. Если T
является подтипом любого из перечисленных выше типов, поддерживающих оболочку, результирующая переменная будет заключена в этот тип. Как видно из приведенных ниже примеров, x, z, X, Z имеют подходящий тип оболочки. Поэтому показаны их типы. Однако s
, будучи символьным типом String
, не имеет соответствующей оболочки, поддерживаемой Symbolics, и, следовательно, возвращает объект Sym{String}
. Это тривиальное дерево выражений одной переменной без оболочки, и оно не является подтипом String или AbstractString.
using Symbolics
@variables x::Real z::Complex{Real} (X::Real)[1:10, 1:10] (Z::Complex{Real})[1:10] s::String
5-element Vector{Any}:
x
z
X[1:10,1:10]
Z[1:10]
s
typeof(x)
Num
typeof(z)
Complex{Num}
typeof(X)
Symbolics.Arr{Num, 2}
typeof(Z)
Symbolics.Arr{Complex{Num}, 1}
typeof(s)
SymbolicUtils.BasicSymbolic{String}