python - 构建捕获分子的晶格 - 无法正常工作
我遇到了这样一个问题:
创建一个一维的网格,这个网格有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 个回答
创建网格的部分是没问题的(不过你用了两次 traps
- 我想你不需要第一行,第四行应该是 grid[traps]=0
)。
接下来,根据问题的要求,你需要放一个分子并让它在网格上移动,但你程序的这一部分完全错了。你需要做的是为分子找到一个随机的起始点(可以用 sc.random.randint(pos)
),然后计算分子在掉进陷阱之前走了多少步。在一维随机漫步中,步伐可以向左走(starting_point - 1
)或向右走(starting_point + 1
)。你需要在 [-1, +1]
之间随机选择,接着把这一步加到分子在网格上的位置上。如果这个新位置在网格上是空的,就把你的 free
变量加一。如果新位置碰到了陷阱,就把 free
变量的值添加到 steps_count
列表中。
至于你第二个问题,周期性边界条件可以很顺利地应用到网格上,只需用 index % pos
的余数作为分子的索引即可。
在一个较小的网格上,看看发生了什么:
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)