首页 > 解决方案 > 我的代码在超过 15500 次迭代时突然停止编写

问题描述

我正在研究如何用 Python 编写代码,并且正在尝试重新创建我在大学时编写的代码。

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

问题

我运行了脚本,除了执行时间太长外,计数停止在 15500。代码没有抛出任何错误,但它一直在继续。我等了大约 3 个小时才完成,但它仍然只能进行 15500 次迭代。

我尝试将写入 csv 块的内容注释掉,而是先打印值以观察它的发生情况,然后我看到,它再次停在 15500 处。

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

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

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

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

这部分初始化二维数组的大小。出于观察目的,我选择了一个 100 x 100 的格子。

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得到的内容。

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)

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

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

        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()

预期的输出是一个文本文件,其中包含每 500 次迭代的s次数i。看起来像这样的东西:

500,9736,264
1000,9472,528
1500,9197,803
2000,8913,1087
2500,8611,1389
3000,8292,1708
3500,7968,2032
4000,7643,2357
4500,7312,2688
5000,6960,3040
5500,6613,3387
6000,6257,3743
6500,5913,4087
7000,5570,4430
7500,5212,4788

我不知道从哪里开始解决方案。起初,我认为是对 csv 的写入导致了问题,但通过 print 函数进行探测证明并非如此。我尽量让它简洁。

我希望你们能帮忙!我真的很想学习这门语言并开始模拟很多东西,我认为这个迷你项目对我来说是一个很好的开始。

非常感谢!

标签: pythonpython-3.xwhile-loop

解决方案


@randomir 在评论中提供的答案:

您的代码可能是错误的。只要要翻转的旋转次数小于迭代次数,它就会阻塞在嵌套的 while 循环中。在您之前评论的示例中,人口规模为 10000,您想要翻转 15500 次旋转。请注意,一旦自旋向上翻转(概率为 100%),由于大都会采样,它将以较小的概率向下翻转。

作品。


推荐阅读