是否有表示排列的数组中 1 的位置的解析公式?

is there an analytic formula for the position of 1 in an array representing permutations?

提问人:Mephistopheles Faust 提问时间:10/8/2023 最后编辑:Mephistopheles Faust 更新时间:10/8/2023 访问量:68

问:

例如,假设我们有一个有 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个粒子来说,这是肉眼无法做到的。

算法 排列

评论

3赞 Bergi 10/8/2023
这看起来只是索引的二进制表示?
1赞 Bergi 10/8/2023
您能否提供一些示例代码来处理这些值,您如何表示它们?你得到什么作为输入,你期望什么作为输出?请编辑您的问题,以您最喜欢的语言包含一个最小的可重复示例,然后我可以写出具体的答案
1赞 Dave 10/8/2023
如果把它看作是费米子/物理问题,并使用大多数人不熟悉的符号,你会失去很多人。我建议将问题重铸为输入、操作和输出。如果做不到这一点,至少定义什么是“⊗”,并解释“|”和“>”在“|0,1,0”等表达式中传达的信息价值(如果有的话>
0赞 Mephistopheles Faust 10/8/2023
@Bergi这是非常准系统的 github.com/dcthecook/Many_Body_Theory/blob/main/......因此,我想如何使用它,我希望有一个用于状态的结构,例如|0,1,0>用户将其输入为字符串。create_fermion将返回结构。函数“create_explicit_fermions”应该返回一个数组(向量),该数组只有一个 1,其余的零都放在帖子中。必须有一种方法可以在不执行所有张量积的情况下在正确的索引中获取 1
1赞 Bergi 10/8/2023
基本上索引将是 .只需将状态视为整数的位 - little endian0b010010

答:

0赞 Mephistopheles Faust 10/8/2023 #1

感谢所有评论者,尤其是@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是否有办法按照您的建议或更有效地完成,请随时提供代码。感谢您的帮助