python – 逐个运行时效果很好,使用循环时出错

python – 逐个运行时效果很好,使用循环时出错,第1张

概述我有一个零和1的零网格.簇被定义为相邻的非对角集.例如,如果我们看一个网格: [[0 0 0 0 0] [1 1 1 1 1] [1 0 0 0 1] [0 1 0 0 1] [1 1 1 1 0]] 一个集群将是一组坐标(实际上我使用列表,但它并不重要): c1=[[1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [2, 1], [2, 4], [3, 4] @H_403_6@ 我有一个零和1的零网格.簇被定义为相邻的非对角集.例如,如果我们看一个网格:

[[0 0 0 0 0] [1 1 1 1 1] [1 0 0 0 1] [0 1 0 0 1] [1 1 1 1 0]]

一个集群将是一组坐标(实际上我使用列表,但它并不重要):

c1=[[1,0],[1,1],2],3],4],[2,[3,4]]

此网格中的另一个群集由下式给出:

c2=[[3,[4,3]]

现在,我已经制定了一个方法,对于给定的起始坐标(如果它的值为1),返回该点所属的簇(例如,如果我选择[1,1]坐标,它将返回c1).
为了测试,我将选择一个点(1,1)和一个小网格.这是结果良好时的输出:

Number of recursions: 10Length of cluster: 10[[1 1 1 0 1] [1 1 0 1 1] [0 1 0 0 1] [1 1 1 0 0] [0 1 0 1 1]][[1 1 1 0 0] [1 1 0 0 0] [0 1 0 0 0] [1 1 1 0 0] [0 1 0 0 0]]

我想知道当簇大小越来越大时我的算法有多快.如果我运行该程序然后重新运行它并多次执行,它总是会产生良好的结果.如果我使用循环,它会开始给出错误的结果.这是一个可能的输出测试场景:

Number of recursions: 10Length of cluster: 10[[1 1 1 0 1] [1 1 0 1 1] [0 1 0 0 1] [1 1 1 0 0] [0 1 0 1 1]][[1 1 1 0 0] [1 1 0 0 0] [0 1 0 0 0] [1 1 1 0 0] [0 1 0 0 0]]Number of recursions: 8Length of cluster: 8[[0 1 1 1 0] [1 1 1 0 0] [1 0 0 0 0] [1 1 1 0 1] [1 1 0 0 0]][[0 0 0 0 0] - the first one is always good,this one already has an error [1 1 0 0 0] [1 0 0 0 0] [1 1 1 0 0] [1 1 0 0 0]]Number of recursions: 1Length of cluster: 1[[1 1 1 1 1] [0 1 0 1 0] [0 1 0 0 0] [0 1 0 0 0] [0 1 1 0 1]][[0 0 0 0 0] - till end [0 1 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]Number of recursions: 1Length of cluster: 1[[1 1 1 1 1] [0 1 1 0 0] [1 0 1 1 1] [1 1 0 1 0] [0 1 1 1 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]]... till end

我将给出循环代码(给你所有代码都没问题,但它太大了,错误可能是由于我在循环中做的事情):

import numpy as npfrom time import timedef test(N,p,testTime,length):    assert N>0    x=1    y=1    a=PercolationGrID(N) #this is a class that creates a grID    a.useFixedProbability(p) #the probability that given point will be 1    a.grID[x,y]=1 #I put the starting point as 1 manually    cluster=Cluster(a)    t0=time()    cluster.getCluster(x,y)  #this is what I'm testing how fast is it    t1=time()    stats=cluster.getStats() #get the length of cluster and some other data    testTime.append(t1-t0)    testTime.sort()    length.append(stats[1]) #[1] is the length stat that interests me    length.sort()  #both sorts are so I can use plot later    print a.getGrID()  #show whole grID    clusterGrID=np.zeros(N*N,dtype='int8').reshape(N,N) #create zero grID where I'll "put" the cluster of interest    c1=cluster.getClusterCoordinates() #this is recursive method (if it has any importance)    for xy in c1:         k=xy[0]        m=xy[1]        clusterGrID[k,m]=1    print clusterGrID    del a,cluster,clusterGrIDtestTime=[]length=[]p=0.59N=35np.set_printoptions(threshold='nan') #so the output doesn't shrinkfor i in range(10):    test(N,length)

我假设我在释放内存或其他东西时做错了(如果它不是循环中的一些微不足道的错误我看不到)?我在64位linux上使用python 2.7.3.

编辑:
我知道这里的人不应该检查整个代码,而是具体的问题,但是我找不到正在发生的事情,唯一的建议是我可能有一些静态变量,但在我看来情况并非如此.所以,如果有人有良好的意志和精力,你可以浏览代码,也许你会看到一些东西.我不是在不久前开始使用课程,所以要为很多不好的东西做好准备.

import numpy as npimport matplotlib as mplimport matplotlib.pyplot as pltimport timeclass ProbabilityGrID(object):    """    This class gives 2D quadratic array (a grID) which is filled with    float values from 0-1,which in many cases represent probabilitIEs    """    def __init__(self,size=2,dataType='float16'):        """initialization of a grID with 0. values"""        assert size>1        assert dataType=='float64' or dataType=='float32' or dataType=='float16'        self.n=size        self.dataType=dataType        self.grID=np.zeros((size,size),dtype=dataType)    def getGrID(self):        """returns a 2D probability array"""        return self.grID    def getSize(self):            """returns a size of a 2D array"""        return self.size    def fillRandom(self):        """fills the grID with uniformly random values from 0 to 1"""        n=self.n        self.grID=np.random.rand(n,n)    def fixedProbabilitIEs(self,p):        """fills the grID with fixed value from 0 to 1"""        assert p<1.0        self.grID=P*np.ones((self.n,self.n))class PercolationGrID(object):    """    percolation quadratic grID filled with 1 and 0,int8    which represent a state.    Percolation grID is closly connected to probabilIEs grID.    ProbabilityGrID gives the starting probabilitIEs will the [i,j] spot    be filled or not. All functions change the PercolationGrID.grID when    ProbabilityGrID.grID changes,so in a way their values are connected    """    def __init__(self,dataType='int8'):        """        initialization of PercolationGrID,sets uniformly 0 and 1 to grID        """        assert size>1        assert dataType=='int64' or dataType=='int32' or dataType=='int8'        self.n=size        self.dataType=dataType        self.grID=np.zeros((size,dtype=dataType)        self.pGrID=ProbabilityGrID(self.n)        self.pGrID.fillRandom()        self.useProbabilityGrID()    #def fillRandom(self,min=0,max=1,distribution='uniform'):     #   n=self.n      #  self.grID=np.random.random_integers(min,max,n*n).reshape(n,n)    def getGrID(self):        """returns a 2D percolation array"""        return self.grID    def useProbabilityGrID(self): #use probability grID to get Percolation grID of 0s and 1es        """        this method fills the PercolationGrID.grID according to probabilitIEs        from Probability.grID        """        comparisonGrID=np.random.rand(self.n,self.n)        self.grID=np.array(np.floor(self.pGrID.grID-comparisonGrID)+1,dtype=self.dataType)      # Here I used a trick. To simulate whether 1 will apear with probability p,# we can use uniform random generator which returns values from 0 to 1. If       # the value<p then we get 1,if value>p it's 0.      # But instead looPing over each element,it's much faster to make same sized      # grID of random,uniform values from 0 to 1,calculate the difference,add 1      # and use floor function which round everything larger than 1 to 1,and lower      # to 0. Then value-p+1 will give 0 if value<p,1 if value>p. The result is      # converted to data type of percolation array.    def useFixedProbability(self,p):        """        this method fills the PercolationGrID according to fixed probabilitIEs        of being filled,for example,a large grID with parameter p set to 0.33        should,aproximatly have one third of places filed with ones and 2/3 with 0        """        self.pGrID.fixedProbabilitIEs(p)        self.useProbabilityGrID()    def probabilityCheck(self):        """ this method checks the number of ones vs number of elements,good for checking if the filling of a grID was close to probability        we had in mind. Of course,the accuracy is larger as grID size grows.        For smaller grID sizes you can still check the probability by         running the test multiple times.        """        sum=self.grID.sum()        print float(sum)/float(self.n*self.n)        #this works because values can only be 0 or 1,so the sum/size gives        #the ratio of ones vs size    def setGrID(self,grID):        shape=grID.shape        i,j=shape[0],shape[1]        assert i>1 and j>1        if i!=j:            print ("The grID needs to be NxN shape,N>1")        self.grID=grID    def setProbabilitIEs(self,N>1")        self.pGrID.grID=grID        self.useProbabilityGrID()    def showPercolations(self):        fig1=plt.figure()        fig2=plt.figure()        ax1=fig1.add_subplot(111)        ax2=fig2.add_subplot(111)        mycolors=[(1.0,1.0,1.0),(1.0,0.0,1.0)]        mycmap=mpl.colors.Listedcolormap(mycolors)        subplt1=ax1.matshow(self.pGrID.grID,cmap='jet')        cbar1=fig1.colorbar(subplt1)        subplt2=ax2.matshow(self.grID,cmap=mycmap)        cbar2=fig2.colorbar(subplt2,ticks=[0.25,0.75])        cbar2.ax.set_yticklabels(['None','Percolated'],rotation='vertical')class Cluster(object):    """This is a class of percolation clusters"""    def __init__(self,array):        self.grID=array.getGrID()        self.N=len(self.grID[0,])        self.cluster={}        self.numOfSteps=0    #next 4 functions return True if fIEld next to given fIEld is 1 or False if it's 0    def moveleft(self,i,j):        moveleft=False        assert i<self.N        assert j<self.N        if j>0 and self.grID[i,j-1]==1:            moveleft=True        return moveleft    def moveRight(self,j):        moveRight=False        assert i<self.N        assert j<self.N        if j<N-1 and self.grID[i,j+1]==1:            moveRight=True        return moveRight    def moveDown(self,j):        moveDown=False        assert i<self.N        assert j<self.N        if i<N-1 and self.grID[i+1,j]==1:            moveDown=True        return moveDown    def moveUp(self,j):        moveUp=False        assert i<self.N        assert j<self.N        if i>0 and self.grID[i-1,j]==1:            moveUp=True        return moveUp    def listofOnes(self):        """nested List of connected ones in each row"""        outList=[]        for i in xrange(self.N):            outList.append([])            helpList=[]            for j in xrange(self.N):                if self.grID[i,j]==0:                    if (j>0 and self.grID[i,j-1]==0) or (j==0 and self.grID[i,j]==0):                        continue # condition needed because of edges                    outList[i].append(helpList)                    helpList=[]                    continue                helpList.append((i,j))                if self.grID[i,j]==1 and j==self.N-1:                    outList[i].append(helpList)        return outList    def getCluster(self,i=0,j=0,moveD=[1,1,1]):        #(left,right,up,down)        #moveD short for moveDirections,1 means that it trIEs to move it to that sIDe,0 so it doesn't try        self.numOfSteps=self.numOfSteps+1        if self.grID[i,j]==1:            self.cluster[(i,j)]=True        else:            print "the starting coordinate is not in any cluster"            return        if moveD[0]==1:            try: #if it comes to same point from different directions we'd get an infinite recursion,checking if it already been on that point prevents that                self.cluster[(i,j-1)]                moveD[0]=0            except:                if self.moveleft(i,j)==False: #check if 0 or 1 is left to (i,j)                    moveD[0]=0                else:                   self.getCluster(i,j-1,1]) #right is 0,because we came from left        if moveD[1]==1:            try:                self.cluster[(i,j+1)]                moveD[1]=0            except:                if self.moveRight(i,j)==False:                    moveD[1]=0                else:                    self.getCluster(i,j+1,[0,1])        if moveD[2]==1:            try:                self.cluster[(i-1,j)]                moveD[2]=0            except:                if self.moveUp(i,j)==False:                    moveD[2]=0                else:                    self.getCluster(i-1,j,0])        if moveD[3]==1:            try:                self.cluster[(i+1,j)]                moveD[3]=0            except:                if self.moveDown(i,j)==False:                    moveD[3]=0                else:                    self.getCluster(i+1,1])        if moveD==(0,0):            return    def getClusterCoordinates(self):        return self.cluster    def getStats(self):        print "Number of recursions:",self.numOfSteps        print "Length of cluster:",len(self.cluster)        return (self.numOfSteps,len(self.cluster))
解决方法 您的错误来自getCluster方法.将moveD设置为[1,1]时,实际上是设置一个静态变量(不要在此引用我).这导致先前执行的信息继续存在.

Here is a link to a blog post that shows an example of this.

下面是getCluster方法的一个工作版本,它既修复了默认的争论问题,又删除了表现出有问题的行为的无关的moveD赋值.

def getCluster(self,moveD=None):    #(left,down)    #moveD short for moveDirections,0 so it doesn't try    if moveD == None: moveD = [1,1]    self.numOfSteps=self.numOfSteps+1    if self.grID[i,j]==1:        self.cluster[(i,j)]=True    else:        print "the starting coordinate is not in any cluster"        return    if moveD[0]==1:        try: #if it comes to same point from different directions we'd get an infinite recursion,checking if it already been on that point prevents that            self.cluster[(i,j-1)]        except:            if self.moveleft(i,j)==True: #check if 0 or 1 is left to (i,j)               self.getCluster(i,because we came from left    if moveD[1]==1:        try:            self.cluster[(i,j+1)]        except:            if self.moveRight(i,j)==True:                self.getCluster(i,1])    if moveD[2]==1:        try:            self.cluster[(i-1,j)]        except:            if self.moveUp(i,j)==True:                self.getCluster(i-1,0])    if moveD[3]==1:        try:            self.cluster[(i+1,j)]        except:            if self.moveDown(i,j)==True:                self.getCluster(i+1,1])
总结

以上是内存溢出为你收集整理的python – 逐个运行时效果很好,使用循环时出错全部内容,希望文章能够帮你解决python – 逐个运行时效果很好,使用循环时出错所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1196623.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存