python - 构建捕获分子的晶格 - 无法正常工作

1 投票
2 回答
892 浏览
提问于 2025-04-17 05:48

我遇到了这样一个问题:

创建一个一维的网格,这个网格有100000个位置。在这个网格上随机放置一些“陷阱”分子,这些分子的浓度是c。然后在网格的一个随机位置放置一个粒子,让它进行随机漫步。在这个漫步过程中,不限制时间,也就是说,不会规定具体的步数。漫步会在粒子落到一个陷阱上时停止……要注意边界条件。当粒子到达网格的边缘时,它不能逃出网格,而是要留在网格内,要么返回到之前的位置,要么被放置到网格的另一边……

我的方法在我写的代码中有展示(代码里有注释)。

def steps1d(self,pos,c):
    #pos: number of positions
    #c:   concentration of trap-particles

    # array full of traps (zeros)
    myzeros = sc.zeros(self.c*self.pos)

    # grid full of available positions(ones)
    grid = sc.ones(self.pos)

    # distribute c*pos zeros(traps) in random positions (number of positions is pos)
    traps = sc.random.permutation(pos)[:c*pos]

    # the grid in which the particle is moving which has traps inside it 
    grid[traps] = myzeros
    steps_count = []    # list which holds the number of steps
    free = 0
    for i in range(pos):
        # the step of the particle can be 0 or 1
        step=sc.random.random_integers(0,1)
        for step in grid[:]:
            if step == 1:
                free += 1
                steps_count.append(free)
            else:
                break
    return steps_count

我有三个问题:

1) 比如说,当位置为10时,我得到的结果是这样的:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35...]

我本来期待每次运行(变量pos)能得到10个数字。

2) 我不太确定如何处理边界条件。我在考虑类似这样的方案:

if free > grid.size:
    free = free - 1

但我无法测试这个方案。而且,我也不确定这是否适用于网格的两个边界。

3) 如果我想让第一步从网格的中间开始,我该怎么做?

如果有人能给我一点提示,我会非常感激。

2 个回答

0

创建网格的部分是没问题的(不过你用了两次 traps - 我想你不需要第一行,第四行应该是 grid[traps]=0)。

接下来,根据问题的要求,你需要放一个分子并让它在网格上移动,但你程序的这一部分完全错了。你需要做的是为分子找到一个随机的起始点(可以用 sc.random.randint(pos)),然后计算分子在掉进陷阱之前走了多少步。在一维随机漫步中,步伐可以向左走(starting_point - 1)或向右走(starting_point + 1)。你需要在 [-1, +1] 之间随机选择,接着把这一步加到分子在网格上的位置上。如果这个新位置在网格上是空的,就把你的 free 变量加一。如果新位置碰到了陷阱,就把 free 变量的值添加到 steps_count 列表中。

至于你第二个问题,周期性边界条件可以很顺利地应用到网格上,只需用 index % pos 的余数作为分子的索引即可。

2

在一个较小的网格上,看看发生了什么:

import numpy

# Populate the lattice
lattice = numpy.concatenate([numpy.ones(90), numpy.zeros(10)])
numpy.random.shuffle(lattice)

# Intialize problem
in_trap = False
steps = 0
pos = int(numpy.random.randint(0,len(lattice),1))
history = []

while in_trap == False:
    # Step of -1 is backward, 1 is forward
    step = numpy.random.permutation([-1,1])[0]

    # Check position for edges and fix if required
    if pos + step > len(lattice) - 1:
        pos = 0
    elif pos + step < 0:
        pos = len(lattice) - 1
    else:
        pos += step

    # Keep track of random walk
    history.append(pos)

    # Check if it's a trap
    if lattice[pos] == 0:
        in_trap = True

    # If not, continue
    steps += 1


print steps
print history
print lattice

我建议你在代码中加入一些打印语句,这样可以查看每个变量的值。尝试在较小的网格上运行,这会帮助你理解这个过程是如何工作的。

编辑:

我会让你自己去弄清楚具体的细节,但我建议你把这个代码放在一个函数里,像下面这样。这样可以设置好函数,然后准备空的步骤和历史记录列表,用来保存每次运行的结果。我们运行这个函数,然后把结果添加到这些列表中。

def lattice():
    code
    return steps, history

steps = []
histories = []
for i in range(0,10):
    num_steps, history = lattice()
    steps.append(num_steps)
    histories.append(history)

撰写回答