Документация Engee

Поддерживаемые типы и диспетчеризация в 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}