附加不断附加相同的项目,不附加正确的项目,Python

时间:2016-06-10 15:23:35

标签: python matlab list loops montecarlo

这是我导入的内容:

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中运行这种模拟?你认为这会更容易吗?

1 个答案:

答案 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?很好地解释了这一点。