英文:
What is the best way to distingish between two structures with the same form in Julia?
问题
Here's the translated code portion:
所以我有面向对象编程的背景,所以下面的问题似乎非常简单。
class Hermitian:
def __init__(self, mat::np.ndarray):
self.mat::np.ndarray = mat
class Hamiltonian(Hermitian):
...
class Correlation(Hermitian):
...
对于了解一些物理学的人来说,哈密顿量和相关函数都可以用矩阵形式表示,但在我的上下文中,它们只是一个矩阵,因此它们可以是Hermitian
的子类。
我之所以要将它们分开,是因为有一些子例程必须对每个对象进行不同的处理。
例如,计算特征值的操作,它们可以共享为Hermitian
定义的操作,但对于像仅针对Correlation
的特定解缠缠积的情况,那么在Python中,我可以编写def ee(corr::Correlation)
来标记这仅适用于Correlation
,或者使用isinstance
方法进行显式断言。
然而,在Julia中,没有从抽象结构体继承的概念,我必须明确定义这两个结构体。
struct Hamiltonian
mat::Matrix{Complex}
end
struct Correlation
mat::Matrix{Complex}
end
这是真实的,现在我可以仅为特定类型定义函数,但共享的方法现在不可能存在,或者要为这些类型重载方法。
有人能提出一种构建这种问题的事实上的方法吗?
*我不想在通用结构Hermitian
内部放置一个specifier::Symbol
来标记对象类型,如下所示:
struct Hermitian
specifier::Symbol
mat::Matrix
end
hamiltonian::Hermitian = Hermitian(:hamiltonian, ...)
英文:
So I am from OOP background, so the following problem seems very easy.
class Hermitian:
def __init__(self, mat::np.ndarray):
self.mat::np.ndarray = mat
class Hamiltonian(Hermitian):
...
class Correlation(Hermitian):
...
So for people who knows a bit Physics Hamiltonian and Correlation function can both be expressed in matrix form, but since they really are just a matrix in my context, so they can be a subclass of a Hermitian
.
The reason I want to partition them is because they are some subroutines that have to handle differently for each of these objects.
Such as the operation to compute the eigenvalues, they can share the operation defined for Hermitian
, but for something else like resolving for entanglement entropy which is specific only for Correlation
, then in Python I can write def ee(corr::Correlation)
to label that this is for Correlation
only, or explicitly assert with the isinstance
method.
Yet in Julia, there are no such thing as inheriting from a abstract struct, I have to define the two structures explicitly.
struct Hamiltonian
mat::Matrix{Complex}
end
struct Correlation
mat::Matrix{Complex}
end
Which is true that now I can define functions only for a specific type, but the shared methods are now impossible or to overload the method for each of these types.
Can someone suggest a defacto way to structure this kind of problem?
*I don't want to put a specifier::Symbol
within a general struct Hermitian
to label the type of the object like:
struct Hermitian
specifier::Symbol
mat::Matrix
end
hamiltonian::Hermitian = Hermitian(:hamiltonian, ...)
答案1
得分: 1
这个问题的代码部分已经翻译完成,如果您有任何其他问题或需要进一步解释,请随时提出。
英文:
This could be handled in several different ways, but the one that is probably closest to what you want is:
julia> abstract type Hermitian end
julia> struct Hamiltonian{T} <: Hermitian
mat::Matrix{Complex{T}}
end
julia> struct Correlation{T} <: Hermitian
mat::Matrix{Complex{T}}
end
julia> getmat(::Hermitian) = error("getmat must be defined by concrete subtypes")
getmat (generic function with 1 method)
julia> getmat(x::Hamiltonian) = x.mat
getmat (generic function with 2 methods)
julia> getmat(x::Correlation) = x.mat
getmat (generic function with 3 methods)
julia> matsum(x::Hermitian) = sum(getmat(x)) # function common for all subtypes
matsum (generic function with 1 method)
julia> ee(corr::Correlation) = "defined only for Correlation"
ee (generic function with 1 method)
Things to note:
- Abstract type does not have fields. They can be only defined for concrete types.
- However, you can dispatch on abstract type, as in
matsum
definition. - The way I typically want to handle such things is to define a getter for a field, like
getmat
in our case. Note that this has an additional benefit that in generalHamiltonian
andCorrelation
do not have to sharemat
as their field. This matrix e.g. could be computed on the flight in one case, and stored in a struct in other case. Defining such getter allows for a level of abstraction that might be handy (i.e. not all subtypes ofHermitian
might want to storemat
matrix in general) - A small thing is that
Matrix{Complex}
is not a concrete type asComplex
can be complex of e.g. floats, or integers. Therefore, if you want performance it is usually better to make the type parametric. I usedT
as a parameter. In this way your code will be type stable. - When you use the pattern I described above, what is crucial is that you define the interface methods required to be defined by
Hermitian
abstract type subtypes (and make sure that such subtypes define this interface; in my example the interface requires that thegetmat
function is defined).
If something is not clear please comment and I can expand on this.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论