提问人:Mephistopheles Faust 提问时间:10/8/2023 最后编辑:Mephistopheles Faust 更新时间:10/8/2023 访问量:68
是否有表示排列的数组中 1 的位置的解析公式?
is there an analytic formula for the position of 1 in an array representing permutations?
问:
例如,假设我们有一个有 N 个站点的州。这些站点中的每一个都可以包含 0 或 1(其中没有粒子或有粒子)。
例如,当 N = 3 时,可能的状态为 |0,0,0>; |1,0,0>; |0,1,0>; |0,0,1>; |1,1,0>; |1,0,1>; |0,1,1>; |1,1,1>
由于与这个问题无关的原因,这些是物理学中粒子状态的表示。更具体地说,这些是无自旋费米子的排列。因此,它们是通过在单个状态之间执行张量积来构造的。 例如
|0,1,0> = |0> ⊗ |1> ⊗ |0> (在 2 号位点有 1 个费米子。站点 1 和 3 为空)
其中每个状态都可以在其自己的空间中显式表示为向量。
|0> = (1,0) (费米子不存在于这种|k>状态) 这也称为真空状态
|1> = (0,1) (费米子存在于此|k>状态)
这允许我们以数字方式进行乘积,输出将是维度为 2^(N) 的最终状态向量
所以:
|0,1,0> = |0> ⊗ |1> ⊗ |0> = (1,0) ⊗ (0,1) ⊗ (1,0) = (0, 0, 1, 0, 0, 0, 0, 0, 0) 作为向量
或
|0,1,1> = |0> ⊗ |1> ⊗ |1> = (1,0) ⊗ (0,1) ⊗ (0,1) = (0, 0, 0, 0, 0, 0, 0, 1, 0) 作为向量
问题是,对于大量站点来说,执行所有这些张量产品可能非常耗时。但需要注意的是,无论处于何种状态,最终的显式 Vector 都是稀疏的。它总是在某个位置有一个“1”,其余的将保证为零。
我现在的问题是,是否有一种分析表达式可以先知道唯一的“1”将落在何处,以便我可以避免做产品?
需要注意的一件有趣的事情是,通过采用我上面列举的 8 种状态,对于它们中的每一个,“1”只是在我们排列组合时在向量中向下移动 1 个索引。而且顺序很明显。我们首先沿 N 个位置移动“1”元素。然后,我们将第一个元素保持在 0 处,并将 1 沿着抽象状态的剩余尾部移动。我们重复这样做,直到达到我们的状态。
因此,这里我们以向量形式对 8 个枚举状态进行排序:
(1, 0, 0, 0, 0, 0, 0, 0) = |0,0,0>
(0, 1, 0, 0, 0, 0, 0, 0) = |1,0,0>
(0, 0, 1, 0, 0, 0, 0, 0) = |0,1,0>
(0, 0, 0, 1, 0, 0, 0, 0) = |1,1,0>
(0, 0, 0, 0, 1, 0, 0, 0) = |0,0,1>
(0, 0, 0, 0, 0, 1, 0, 0) = |1,0,1>
(0, 0, 0, 0, 0, 0, 1, 0) = |0,1,1>
(0, 0, 0, 0, 0, 0, 0, 1) = |1,1,1>
看到这一点的一种方式是,这条规则需要多少排列才能实现我们的?如果我们知道这一点,我们就知道唯一的“1”元素将具有索引 = 到这个排列数
对于 N=3 个站点,这很容易做到。但是对于14个粒子来说,这是肉眼无法做到的。
答:
感谢所有评论者,尤其是@Bergi,感谢他们启发了答案。
不幸的是,我不确定我是否完全同意,因为例如,在 10010 -> 10010000 等状态下添加 0 将代表更大的二进制数(更大的索引),但执行 1⊗0 和 1⊗0⊗0⊗0 之间的显式张量积不会改变索引
同样,其中 1 是向量 (0,1),0 是 (1,0)。虽然它确实改变了整体维度。
话虽如此,我是这样处理的。我采用输入字符串中的第一个状态 0 或 1,对应于它自己的向量。如果状态为 0,则最终索引 = 0,如果 1,则索引 = 1。我在字符串上向右移动,如果下一个条目是 0 状态,我只需将维度加倍并保持索引不变。但是,如果下一个状态是 1,我会将维度加倍并将其添加到当前索引中。这表示如果用 (0,1) 对向量进行张量乘积,则正在完成的移位。代码如下:
create_fermions创建了f_state结构,它只是二进制字符串(这些是整数的原因是因为它们稍后将用于直接对角化。 事实上,它们应该是双精度,但这目前不是问题)。此函数旨在方便用户输入状态
create_explicit_fermion 采用上一个函数的输出,并使用上面描述的技术返回指向显式向量/数组表示的指针。“1”元素的索引似乎位于正确的位置。
%%cython
cimport cython
from libc.stdlib cimport malloc, free
from cython cimport sizeof
#import numpy as np
#cimport numpy as np
ctypedef struct f_state:
int* state
int size
cdef void free_fermions(f_state fstate) nogil:
free(fstate.state)
cdef f_state create_fermions(str state, int space_size):
cdef int* state_array = <int*>malloc(space_size*sizeof(int))
if state_array is NULL:
raise MemoryError("Failed to allocate memory for state_array")
for i in range(space_size):
if state[i] not in ('0', '1'):
raise ValueError("spinless fermion states can only have 1 occupation or none 0")
state_array[i] = <int>state[i]-48 #minus 48 because of ascii encoding from str to int. 0 is 48 in ascii. 1 is 49
cdef f_state fstate
fstate.state = state_array
fstate.size = space_size
return fstate
cdef int* create_explicit_fermions(f_state in_state):
#start by allocating the vector
cdef int total_size = 2**in_state.size
#malloc this to mem
#....to be completed
cdef int tmp_dimension
cdef int index
if in_state.state[0] == 0:
index = 0
elif in_state.state[0] == 1:
index = 1
if (in_state.size > 1):
for i in range(in_state.size):
tmp_dimension = 2**(i+1)
if (in_state.state[i+1] == 0):
index = index
elif (in_state.state[i+1] == 1):
index = index + tmp_dimension
cdef int* result = <int*>malloc(total_size*sizeof(int))
for i in range(total_size):
result[i] = 0
result[index] = 1
return result
#test unit 2
cdef str fermions = "001"
cdef int fsize = 3
cdef f_state fermion_state = create_fermions(fermions, fsize)
for i in range(fsize):
print(fermion_state.state[i])
print("\nnow the explicit vector\n")
cdef int* fermion_vector = create_explicit_fermions(fermion_state)
for i in range(2**fsize):
print(fermion_vector[i])
free_fermions(fermion_state)
free(fermion_vector)
以下测试单元给出
the state in diract notation
0
0
1
the state in an explicit Fock space vector
0
0
0
0
1
0
0
0
如果您手动执行张量积,这是正确的结果
更复杂的示例:
费米子 = “010010” fsize = 6
给
the state in diract notation
0
1
0
0
1
0
the state in an explicit Fock space vector
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
在索引 18
多亏了这些,我现在可以计算创建-编年运算符的完整矩阵
@Bergi是否有办法按照您的建议或更有效地完成,请随时提供代码。感谢您的帮助
评论
0b010010