这是我导入的内容:
import random
import matplotlib.pyplot as plt
from math import log, e, ceil, floor
import numpy as np
from numpy import arange,array
import pdb
from random import randint
这里我定义了函数矩阵(p,m)
def matrix(p,m): # A matrix with zeros everywhere, except in every entry in the middle of the row
v = [0]*m
v[(m+1)/2 - 1] = 1
vv = array([v,]*p)
return vv
ct = np.zeros(5) # Here, I choose 5 cause I wanted to work with an example, but should be p in general
这里我定义MHops,它基本上取矩阵,矩阵和向量ct的维度,并给我一个新的矩阵mm和一个新的向量ct
def MHops(p,m,mm,ct):
k = 0
while k < p : # This 'spans' the rows
i = 0
while i < m : # This 'spans' the columns
if mm[k][i] == 0 :
i+=1
else:
R = random.random()
t = -log(1-R,e) # Calculate time of the hopping
ct[k] = ct[k] + t
r = random.random()
if 0 <= r < 0.5 : # particle hops right
if 0 <= i < m-1:
mm[k][i] = 0
mm[k][i+1] = 1
break
else:
break # Because it is at the boundary
else: # particle hops left
if 0 < i <=m-1:
mm[k][i] = 0
mm[k][i-1] = 1
break
else: # Because it is at the boundary
break
break
k+=1
return (mm,ct) # Gives me the new matrix showing the new position of the particles and a new vector of times, showing the times taken by each particle to hop
现在我想做的是迭代这个过程,但我希望能够可视化列表中的每一步。简而言之,我所做的是: 1.创建一个表示晶格的矩阵,其中0表示该槽中没有粒子,1表示那里有粒子。 2.创建一个函数MHops,它模拟一步的随机游走并给我新的矩阵和一个向量ct,它显示粒子移动的时间。
现在我想要一个向量或数组,其中我有2 * n个对象,即矩阵mm和n次迭代的向量ct。我想要一个数组,列表或类似的东西,因为我需要稍后使用它们。
这里开始我的问题:
我创建了一个空列表,我使用append在while循环的每次迭代中追加项目。然而,我得到的结果是一个列表d,其中有来自上一次迭代的n个相等对象!
因此我的迭代函数如下:
def rep_MHops(n,p,m,mm,ct):
mat = mm
cct = ct
d = []
i = 0
while i < n :
y = MHops(p,m,mat,cct) # Calculate the hop, so y is a tuple y = (mm,ct)
mat = y[0] # I reset mat and cct so that for the next iteration, I go further
cct = y[1]
d.append(mat)
d.append(cct)
i+=1
return d
z = rep_MHops(3,5,5,matrix(5,5),ct) #If you check this, it doesn't work
print z
然而它不起作用,我不明白为什么。我正在做的是使用MHops,然后我想将新矩阵和新向量设置为MHops输出中的那些并再次执行此操作。但是,如果运行此代码,您将看到v工作,即时间向量增加并且晶格矩阵发生变化,但是当我将其附加到d时,d基本上是n个相等对象的列表,其中对象是最后一次迭代。
我的错误是什么? 此外,如果您对此代码有任何编码建议,他们将非常欢迎,我不确定这是一种有效的方式。
为了让你更好地理解,我想在另一个函数中使用最终向量d,首先我选择一个随机时间T,然后我基本上会检查每个奇数条目(每个ct)并因此检查每个条目每个ct,看看这些数字是否小于或等于T.如果发生这种情况,那么粒子的运动就会发生,否则就不会发生。 从这开始,我将尝试用matpotlibt用直方图或类似的东西来显示结果。
有没有人知道如何在matlab中运行这种模拟?你认为这会更容易吗?
答案 0 :(得分:0)
您通过引用传递和存储而不是副本,因此在循环的下一次迭代中
MHops
会改变您之前在d
中存储的版本。使用import copy; d.append(copy.deepcopy(mat))
代替存储以后不会更改的副本。
为什么呢?
Python通过引用传递列表,并且每个循环都存储对d中相同矩阵对象的引用。
我查看了python文档,我唯一能提到的是 "how do i write a function with output parameters (call by reference)"
以下是您的代码的简单示例:
def rep_MHops(mat_init):
mat = mat_init
d = []
for i in range(5):
mat = MHops(mat)
d.append(mat)
return d
def MHops(mat):
mat[0] += 1
return mat
mat_init = [10]
z = rep_MHops(mat_init)
print(z)
运行时给出:
[[15], [15], [15], [15], [15]]
Python仅通过引用传递可变对象(例如列表)。一个整数不是一个可变对象,这里是上面例子的略微修改版本,它对一个整数进行操作:
def rep_MHops_simple(mat_init):
mat = mat_init
d = []
for i in range(5):
mat = MHops_simple(mat)
d.append(mat)
return d
def MHops_simple(mat):
mat += 1
return mat
z = rep_MHops_simple(mat_init=10)
print(z)
运行时给出:
[11, 12, 13, 14, 15]
这是你期待的行为。
这个答案How do I pass a variable by reference?很好地解释了这一点。