Структуру с полем абстрактного типа или с Союзом бетонного типа в Юлии? - PullRequest
0 голосов
/ 24 октября 2019

У меня есть два конкретных типа с именами CreationOperator и AnnihilationOperator, и я хочу определить новый конкретный тип, который представляет собой строку операторов и реальный коэффициент, который умножает его.

Я нашел естественным определениеабстрактный тип FermionicOperator, от которого наследуются CreationOperator и AnnihilationOperator, то есть

abstract type FermionicOperator end

struct CreationOperator <: FermionicOperator
  ...
end

struct AnnihilationOperator <: FermionicOperator
  ...
end

, потому что я могу определить многие функции с сигнатурами типа function(op1::FermionicOperator, op2::FermionicOperator) = ..., например, арифметические операции (IЯ строю систему алгебры, поэтому я должен определить такие операции, как *, + и т. д. для операторов).
Тогда я бы продолжил и определил конкретный тип OperatorString

struct OperatorString
  coef::Float64
  ops::Vector{FermionicOperator}
end

Однако, согласно руководству Julia, я считаю, что OperatorString не идеален для производительности, потому что компилятор ничего не знает о FermionicOperator, и поэтому функции, включающие OperatorString, будут неэффективными (и я буду иметьмногие функции, манипулирующие строками операторов).

Я нашел следующее решение, однако я не уверен насчет его следствия и действительно ли оно имеет значение.
Вместо определения FermionicOperator как абстрактного типа, я определяю его как Union из CreationOperator и AnnihilationOperator, то есть

struct CreationOperator
  ...
end

struct AnnihilationOperator
  ...
end

FermionicOperator = Union{CreationOperator,AnnihilationOperator}

Это по-прежнему допускает функции вида function(op1::FermionicOperator, op2::FermionicOperator) = ..., но в то же время, насколько я понимаю, Union{CreationOperator,AnnihilationOperator} - это конкретный тип, такой, что OperatorString четко определен, и компиляторы могут оптимизировать вещи, если это так.

Я особеннопод вопросом, потому что я также решил использовать встроенную структуру Expr для определения моей строки операторов (на самом деле это было бы более общим), чье поле args является вектором с элементами абстрактного типа: очень похоже на мой первыйпопытка проектирования. Однако при реализации арифметических операций на Expr у меня было ощущение, что я делаю что-то «не так», и мне было лучше определять свои собственные типы.

1 Ответ

0 голосов
/ 24 октября 2019

Если ваше поле ops является вектором, который в любом конкретном случае является либо CreationOperators, либо всеми AnnihilationOperators, тогда рекомендуется использовать параметризованную структуру.

abstract type FermionicOperator end

struct CreationOperator <: FermionicOperator
    ...
end

struct AnnihilationOperator <: FermionicOperator
    ...
end

struct OperatorString{T<:FermionicOperator}
  coef::Float64
  ops::Vector{T}

  function OperatorString(coef::Float64, ops::Vector{T}) where {T<:FermionicOperator}
      return new{T}(coef, ops)
  end
end

Если ваше поле ops является вектором, который в любом конкретном случае может быть смесью CreationOperators и AnnihilationOperators, тогда вы можете использовать Union. Поскольку объединение является небольшим (2 типа), ваш код останется производительным.

struct CreationOperator
    value::Int
end

struct AnnihilationOperator
    value::Int
end

const Fermionic = Union{CreationOperator, AnnihilationOperator}

struct OperatorString
  coef::Float64
  ops::Vector{Fermionic}

  function OperatorString(coef::Float64, ops::Vector{Fermionic})
      return new(coef, ops)
  end
end

Хотя это и не показано, даже с подходом Union, вы можете использовать абстрактный тип также - только длябудущая простота и гибкость в распределении функций. Это полезно при разработке надежной логики, управляемой несколькими диспетчерами.

...