我的代码突然停止了15500次迭代的编写工作

时间:2019-05-26 07:12:02

标签: python python-3.x while-loop

我正在研究如何使用Python编写代码,并试图重新创建我在大学期间编写的代码。

该代码基于应用于流行病学的2D Ising模型。它的作用是:

  • 它使用numpy构造2D 100x100数组,并为每个元素分配值-1。
  • 根据以下脚本中的函数calc_h计算能量。
  • 然后,代码从晶格中随机选择一个单元,将值更改为1,然后再次计算系统的能量。
  • 然后,代码比较系统的能量是否小于或等于先前的配置。如果是这样,它将“接受”更改。如果不是,则将概率与随机数进行比较,以确定是否“接受”更改。这部分是在metropolis函数中完成的。
  • 代码使用while循环重复该过程,直到指定的最大迭代次数max_iterations。 -代码对{{1}中具有-1值的元素数量(即s变量)和具有1值的元素数量(即i变量)进行计数。 }函数。该脚本每500个iteratons追加到一个文本文件中。

问题

我运行了脚本,除了执行时间太长之外,计数在15500处停止。代码不会引发任何错误,但是它一直在继续。我等待了大约3个小时才能完成,但仍然最多只能进行15500次迭代。

我尝试注释掉对csv块的写操作,而是先打印值以观察它的发生,然后我看到它再次在15500处停止。

我不知道出什么问题了,因为它不会引发任何错误,并且代码也不会停止。

这是整个脚本。我在每个块下面都描述了该零件的作用:

countSI
  

此部分初始化2D数组的大小。出于观察目的,我选择了100 x 100格。

import numpy as np
import random as r
import math as m
import csv

init_size = input("Input array size: ")
size = int(init_size)

  

我将此函数用于def check_overflow(indx, size): if indx == size - 1: return -indx else: return 1 函数,以初始化圆形边界条件。简而言之,晶格的边缘相互连接。

calc_h
  

此函数通过将一个单元格的值与其顶部,底部,左侧和右侧邻居的乘积之和乘以常数def calc_h(pop, J1, size): h_sum = 0 r = 0 c = 0 while r < size: buffr = check_overflow(r, size) while c < size: buffc = check_overflow(c, size) h_sum = h_sum + J1*pop[r,c] * pop[r,c-1] * pop[r-1,c] * pop[r+buffr,c] * pop[r,c+buffc] c = c + 1 c = 0 r = r + 1 return h_sum 来计算系统的能量。

J
  

这取决于def metropolis(h, h0, T_): if h <= h0: return 1 else: rand_h = r.random() p = m.exp(-(h - h0)/T_) if rand_h <= p: return 1 else: return 0 得到什么来确定是否接受从-1到1的更改。

calc_h
  

这部分计算格子中-1和1的数量。

def countSI(pop, sz, iter):
    s = np.count_nonzero(pop == -1)
    i = np.count_nonzero(pop == 1)
    row = [iter, s, i]
    with open('data.txt', 'a') as si_csv:
        tally_data = csv.writer(si_csv)
        tally_data.writerow(row)
        si_csv.seek(0)
  

二维数组在def main(): J = 1 T = 4.0 max_iterations = 150000 population = np.full((size, size), -1, np.int8) #initialize population array 中初始化。

population
  

这是主循环,在其中选择了一个随机单元,并且是否接受更改由函数 h_0 = calc_h(population, J, size) turn = 1 while turn <= max_iterations: inf_x = r.randint(1,size) - 1 inf_y = r.randint(1,size) - 1 while population[inf_x,inf_y] == 1: inf_x = r.randint(1,size) - 1 inf_y = r.randint(1,size) - 1 population[inf_x, inf_y] = 1 h = calc_h(population, J, size) accept_i = metropolis(h,h_0,T) 确定。

metropolis
  

该脚本每500次迭代进行一次计数。

        if (accept_i == 0):
            population[inf_x, inf_y] = -1

        if turn%500 == 0 :
            countSI(population, size, turn)

预期输出是一个文本文件,该文本文件每进行500次迭代就记录一次 turn = turn + 1 h_0 = h main() s的数目。看起来像这样:

i

我不知道从哪里开始解决。起初,我以为引起csv的问题是导致该问题的原因,但通过print函数进行的研究证明并非如此。我试图使它尽可能简洁。

希望你们能提供帮助!我真的很想学习这种语言并开始模拟很多东西,我认为这个小型项目对我来说是一个很好的起点。

非常感谢!

1 个答案:

答案 0 :(得分:1)

@randomir in the comments提供的答案:

  

您的代码可能是错误的。每当要翻转的旋转次数小于迭代次数时,它将阻塞在嵌套的while循环中。在上一条注释的示例中,人口总数为10000,您想翻转15500次旋转。请注意,一旦旋转(具有100%概率)向上旋转,由于大都会采样,它将以较小的概率向下旋转。

有效。