Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mesa implementation of Ising Model #138

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

vitorfrois
Copy link

Ising Model (https://ccl.northwestern.edu/netlogo/models/Ising, https://en.wikipedia.org/wiki/Ising_model) implementation using new Visualization of Ising Model as issued at #136.
image

agents_list = list(self.agents)
self._steps += 1000
for i in range(1000):
random_spin = self.random.choice(agents_list)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having to create a new list of agents from scratch and selecting one is not ideal. I know this is a limitation of AgentSet. @EwoutH any idea to do this in a performant way via AgentSet? It seems to be a tower of abstractions, that it has slowed down the benchmark for mesa-frames as well: see https://github.com/adamamer20/mesa-frames/issues/25.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the comment. it does not feel right at all haha.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently I don’t think there is. @vitorfrois could you open a new issue on the main Mesa repo describing this lack of functionality and linking to this PR as example?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to suggest you can just do:

self.agents.select(n=1000)

But looking at our current implementation (here) that isn’t actually random.

What you can do though is:

self.agents.shuffle().select(n=1000)


What happens when the temperature slider is set very low? (This is called the "ferromagnetic" state.) Again, try this with different **Spin Up Probability** values.

Between these two very different behaviors is a transition point. On an infinite grid, the transition point can be proved to be $2 / ln (1 + sqrt 2)$, which is about 2.27. On a large enough finite toroidal grid, the transition point is near this number.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have means of aggregating various param sweep into a single plot of magnetization vs temperature. This is a homework for us developers to allow visualizing batch_run result easily.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rht
Copy link
Contributor

rht commented Jul 14, 2024

This model is very helpful in demonstrating phase transition. We have Epstein civil violence, but the Ising model is the bread and butter toy model for phase transition in statistical physics. We should aim towards being able to specify this model in code concisely.

examples/ising/ising/model.py Outdated Show resolved Hide resolved
@rht
Copy link
Contributor

rht commented Jul 21, 2024

Other than the 2 comments, this PR LGTM. Once you fix them, I will merge.

@vitorfrois
Copy link
Author

@rht comments fixed!

Copy link
Member

@EwoutH EwoutH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like a really clean and neat implementation! I already like it a lot, especially that it demonstrates some more recent Mesa functionality and comes with visualization.

I left some comments, but already like it a lot!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency is prefer this named app.py.

It might not be the best name, but it’s what we use now.

import solara
from ising.model import IsingModel
from ising.portrayal import portray_spin
from mesa.visualization import JupyterViz
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can now import SolaraViz

Suggested change
from mesa.visualization import JupyterViz
from mesa.visualization import SolaraViz


@solara.component
def Page():
JupyterViz(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
JupyterViz(
SolaraViz(

self.state = init_state

def neighbors(self):
return self.model.grid.iter_neighbors((self.x, self.y), True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make explicit for readability:

Suggested change
return self.model.grid.iter_neighbors((self.x, self.y), True)
return self.model.grid.iter_neighbors((self.x, self.y), moore=True)

"""
Create a cell, in the given state, at the given x, y position.
"""
super().__init__(pos, model)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn’t this map to unique_id, model?

If intended, please add a comment, if not, update

examples/ising/ising/portrayal.py Outdated Show resolved Hide resolved
for i in range(1000):
random_spin = self.random.choice(agents_list)
dE = self.get_energy_change(random_spin)
if dE < 0:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you can do here

Suggested change
if dE < 0:
if dE < 0 or self.random.random() < self.boltzmann_factor(dE):

If I understand Python correctly, the later part won’t be evaluated if the former is False already, making it just as fast, and more readable.


def step(self):
agents_list = list(self.agents)
self._steps += 1000
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand this correctly, you are using _step to count the number of agent activations (you use 1000, as in the for loop). Why use _step for this?

Co-authored-by: Ewout ter Hoeven <E.M.terHoeven@student.tudelft.nl>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants