You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Canvas模拟伊辛模型时动态图像无法显示的技术求助

Hey Louise, let's work through the issues in your code step by step—there are a few bugs in the class implementation and plotting logic that are causing your dynamic visualization to fail, plus syntax errors breaking the Ising model behavior.


1. Critical Syntax & Class Implementation Bugs

These issues are preventing your model from working correctly, which indirectly breaks the plotting too.

a. __init__ Method Shape Error

In your Ising constructor, np.ones(N,N) is invalid—np.ones expects a tuple for the shape. Also, you should use the passed nx/ny parameters instead of hardcoding N to keep the class flexible:

def __init__(self, nx, ny, random=False):
    if random:
        self._lattice = np.random.choice([-1, 1], size=(nx, ny))
    else:
        self._lattice = np.ones((nx, ny))  # Fixed shape tuple

b. Broken flipspin Method

You used equality checks (==) instead of assignment (=) here—this means spins never actually flip! A simpler way to toggle between 1 and -1 is:

def flipspin(self, x, y):
    self._lattice[x, y] *= -1

c. nearestneighbours Method Fixes

  • Your class doesn't have a shape() method—access the lattice's shape directly with self._lattice.shape.
  • Periodic boundary conditions are cleaner with modulo arithmetic (no messy conditionals):
def nearestneighbours(self, x, y):
    nx, ny = self._lattice.shape
    # Auto-wrap boundaries using modulo
    return [
        ((x + 1) % nx, y),
        ((x - 1) % nx, y),
        (x, (y + 1) % ny),
        (x, (y - 1) % ny)
    ]

d. Incorrect Hamiltonianenergy Function

Your function was passing wrong parameters to nearestneighbours and not summing neighbor spins properly. Here's the corrected version to calculate the energy change for a spin flip:

def Hamiltonianenergy(lattice, x, y):
    # Sum the spins of all nearest neighbors
    neighbor_spins = sum(lattice._lattice[coord] for coord in lattice.nearestneighbours(x, y))
    # Energy change for flipping spin (x,y) (J=1)
    return 2 * lattice._lattice[x, y] * neighbor_spins

2. Fixing Dynamic Plotting

Your plotting logic had multiple issues preventing updates:

  • You passed the Ising class instance to plt.imshow() instead of the actual lattice array (lattice._lattice).
  • Calling plt.show() inside the loop creates a new window every time—initialize the plot once and update its data instead.

Here's the corrected metropolis function:

def metropolis(temperature, sweeps, nx, ny):
    beta = 1 / temperature
    # Initialize Ising lattice
    lattice = Ising(nx, ny, random=True)
    
    # Set up the plot once
    fig, ax = plt.subplots()
    im = ax.imshow(lattice._lattice, cmap='viridis', vmin=-1, vmax=1)
    plt.colorbar(im)
    plt.show(block=False)  # Keep the window open for updates
    
    energycount = []
    energies = 0  # Track total energy (initialize properly if needed)
    
    for t in range(sweeps):
        i = np.random.randint(nx)
        j = np.random.randint(ny)
        
        dH = Hamiltonianenergy(lattice, i, j)
        
        # Metropolis acceptance rule
        if dH <= 0 or np.random.uniform() < np.exp(-beta * dH):
            lattice.flipspin(i, j)
            energies += dH
        
        energycount.append(energies)
        
        # Update the plot data
        im.set_data(lattice._lattice)
        fig.canvas.draw()
        fig.canvas.flush_events()  # Force the plot to update
        plt.pause(0.01)
        
        print(f"Iteration: {t}, Total Energy: {energies}")
    
    plt.close(fig)
    return energycount

3. Other Minor Fixes
  • Removed the redundant lattice = Ising(...) line inside metropolis (you were overwriting the input parameter unnecessarily).
  • Fixed the spin flip call from lattice.flip(i,j) to lattice.flipspin(i,j) to match the method name.
  • Removed unused variables like switch and res, and the unnecessary t +=1 (the loop already increments t via range(sweeps)).

4. Run the Corrected Code

Call the function with your parameters to see the dynamic plot:

if __name__ == "__main__":
    T = 1.0
    N = 5
    sweeps = 50
    energy_history = metropolis(T, sweeps, N, N)

The "local variable image is assigned to but never used" warning doesn't appear in the code you shared, but if you had an unused image variable elsewhere, just remove it to resolve the warning.

After these fixes, the dynamic plot should update with each sweep, showing your Ising lattice evolving over time.

内容的提问来源于stack exchange,提问作者Louise

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:56:26