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
|
import numpy as np
|
||||||
from numba import jit
|
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):
|
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:])
|
E = -np.sum(state[:-1, :] * state[1:, :]) - np.sum(state[:, :-1] * state[:, 1:])
|
||||||
return 2 * E / np.product(state.shape)
|
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()):
|
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
|
assert N == M
|
||||||
|
|
||||||
current_state = initial_state.copy()
|
current_state = initial_state.copy()
|
||||||
E = N**2 * energy(state)
|
E = N**2 * energy(initial_state)
|
||||||
for i in range(steps):
|
for i in range(steps):
|
||||||
i, j = rng.integers(N, size=2)
|
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
|
E = new_E
|
||||||
|
|
||||||
return current_state
|
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