mirror of
https://github.com/ImperialCollegeLondon/ReCoDE_MCMCFF.git
synced 2025-06-26 08:51:16 +02:00
Add improved versions to the MCFF package
This commit is contained in:
parent
99974d506b
commit
a772b43fa7
@ -6,6 +6,15 @@ States are represented by NxM numpy arrays with values +/-1. These functions are
|
||||
|
||||
import numpy as np
|
||||
from numba import jit
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
|
||||
def show_state(state, ax=None):
|
||||
"Plot an Ising state to axis or make a new figure to plot to"
|
||||
if ax is None:
|
||||
f, ax = plt.subplots()
|
||||
ax.matshow(state, cmap="Greys", vmin=-1, vmax=1)
|
||||
ax.set(xticks=[], yticks=[])
|
||||
|
||||
|
||||
def all_up_state(N):
|
||||
@ -85,3 +94,18 @@ def energy_numpy(state):
|
||||
"""
|
||||
E = -np.sum(state[:-1, :] * state[1:, :]) - np.sum(state[:, :-1] * state[:, 1:])
|
||||
return 2 * E / np.product(state.shape)
|
||||
|
||||
|
||||
@jit(nopython=True, nogil=True)
|
||||
def energy_difference(state, site):
|
||||
"The change in energy if we flipped site of state"
|
||||
# loop over the four neighbours of the site, skipping if the site is near an edge
|
||||
N, M = state.shape
|
||||
i, j = site
|
||||
h = 0
|
||||
for di, dj in [[-1, 0], [1, 0], [0, -1], [0, 1]]: # loop over N,E,S,W neighbours
|
||||
if (0 <= (i + di) < N) and (
|
||||
0 <= (j + dj) < M
|
||||
): # ignore neighbours not in the NxN grid
|
||||
h += state[i + di, j + dj]
|
||||
return 4 * state[i, j] * h / (N * M)
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
|
||||
"""
|
||||
import numpy as np
|
||||
from numba import jit
|
||||
from .ising_model import energy, energy_difference
|
||||
|
||||
|
||||
def mcmc(initial_state, steps, T, rng=np.random.default_rng()):
|
||||
@ -27,7 +30,7 @@ def mcmc(initial_state, steps, T, rng=np.random.default_rng()):
|
||||
assert N == M
|
||||
|
||||
current_state = initial_state.copy()
|
||||
E = N**2 * energy(state)
|
||||
E = N**2 * energy(initial_state)
|
||||
for i in range(steps):
|
||||
i, j = rng.integers(N, size=2)
|
||||
|
||||
@ -40,3 +43,25 @@ def mcmc(initial_state, steps, T, rng=np.random.default_rng()):
|
||||
E = new_E
|
||||
|
||||
return current_state
|
||||
|
||||
|
||||
@jit(nopython=True, nogil=True)
|
||||
def mcmc_generator(
|
||||
initial_state, steps, T, stepsize=1000, energy_difference=energy_difference
|
||||
):
|
||||
N, M = initial_state.shape
|
||||
assert N == M
|
||||
|
||||
current_state = initial_state.copy()
|
||||
for _ in range(steps):
|
||||
for _ in range(stepsize):
|
||||
i, j = np.random.randint(N), np.random.randint(N)
|
||||
|
||||
# calculate the energy change if we were to flip this pixel but don't actually do it
|
||||
change_in_E = N**2 * energy_difference(current_state, (i, j))
|
||||
|
||||
if change_in_E < 0 or np.exp(-change_in_E / T) > np.random.random():
|
||||
current_state[i, j] *= -1 # accept the change!
|
||||
|
||||
yield current_state.copy()
|
||||
return
|
||||
|
Loading…
x
Reference in New Issue
Block a user