Skip to content

update intro tutorial discrete space#2731

Merged
tpike3 merged 10 commits intomesa:mainfrom
tpike3:update_intro
Apr 7, 2025
Merged

update intro tutorial discrete space#2731
tpike3 merged 10 commits intomesa:mainfrom
tpike3:update_intro

Conversation

@tpike3
Copy link
Copy Markdown
Member

@tpike3 tpike3 commented Mar 20, 2025

Summary

Updated tutorials to use discrete space

Motive

To ensure tutorials align with current direction of Mesa

Implementation

  • Updated Markdown description of Moving in Mesa and associated code
  • I feel the tutorial is to wordy and repetitive so for Moving in Mesa this time I overviewed the structure, previewed the changes, and then commented on each line change
  • I also added a graphic

Usage Examples

N/A

If you're modifying the visualisation, add before/after screenshots. -->

Additional Notes

You can view the rendered version of this tutorial on: https://mesa--2731.org.readthedocs.build/2731/tutorials/intro_tutorial.html#adding-space

@tpike3 tpike3 requested review from EwoutH and quaquel March 20, 2025 18:05
@github-actions
Copy link
Copy Markdown

Performance benchmarks:

Model Size Init time [95% CI] Run time [95% CI]
BoltzmannWealth small 🔵 -0.8% [-1.3%, -0.3%] 🔵 -0.2% [-0.4%, -0.0%]
BoltzmannWealth large 🔵 +17.6% [-1.6%, +54.6%] 🔵 -2.7% [-4.3%, -1.2%]
Schelling small 🔵 -0.2% [-0.5%, +0.1%] 🔵 -1.2% [-2.1%, -0.3%]
Schelling large 🔵 +0.4% [-0.2%, +1.0%] 🔵 -1.4% [-4.7%, +1.8%]
WolfSheep small 🔵 -0.3% [-0.7%, +0.1%] 🔵 -1.0% [-1.3%, -0.5%]
WolfSheep large 🔵 +2.0% [+0.5%, +3.6%] 🔵 -0.4% [-1.3%, +0.6%]
BoidFlockers small 🔵 +1.6% [+0.8%, +2.6%] 🔵 -1.2% [-1.5%, -0.9%]
BoidFlockers large 🔵 +1.2% [+0.2%, +2.1%] 🔵 -0.8% [-1.2%, -0.3%]

@EwoutH EwoutH added the docs Release notes label label Mar 21, 2025
@Spartan-71
Copy link
Copy Markdown
Contributor

The Moving in MESA section is well-written, with changes clearly illustrated in a point-wise manner.

However, as a beginner, I find the introductory tutorial a bit lengthy. Additionally, the Moving in MESA section modifies the initial code that users have been following from the start, which makes it somewhat challenging. A tutorial that gradually builds upon the existing code without altering it would be more beginner-friendly.

@tpike3
Copy link
Copy Markdown
Member Author

tpike3 commented Mar 24, 2025

The Moving in MESA section is well-written, with changes clearly illustrated in a point-wise manner.

However, as a beginner, I find the introductory tutorial a bit lengthy. Additionally, the Moving in MESA section modifies the initial code that users have been following from the start, which makes it somewhat challenging. A tutorial that gradually builds upon the existing code without altering it would be more beginner-friendly.

Thanks @Spartan-71

tpike3 added 2 commits March 26, 2025 05:56
- update "Moving in Mesa"
- remove FutureWarning property layer
- add visual of space layout
-change cell magic to see if that fixes execution issue
@tpike3 tpike3 marked this pull request as draft March 27, 2025 12:35
@tpike3
Copy link
Copy Markdown
Member Author

tpike3 commented Mar 27, 2025

@quaquel Please pause on the review. I am completely redoing the intro

Some key changes will be more bit size chunks and some different formatting approaches

Copy link
Copy Markdown
Member

@quaquel quaquel left a comment

Choose a reason for hiding this comment

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

I left a few small textual changes and a question. Once those are addressed this is good to go.

@tpike3
Copy link
Copy Markdown
Member Author

tpike3 commented Mar 27, 2025

I left a few small textual changes and a question. Once those are addressed this is good to go.

Thanks, I tried to stop you when I saw the comments, base don some comment from the chat, i am doing larger structural changes. However, I will still take a look at the comments and make sure I capture your intent in the new approach.

@EwoutH EwoutH requested a review from jackiekazil March 29, 2025 13:46
@EwoutH
Copy link
Copy Markdown
Member

EwoutH commented Mar 29, 2025

Awesome work Tom! I will try to review later today or tomorrow.

@tpike3 tpike3 marked this pull request as ready for review March 30, 2025 10:40
@tpike3 tpike3 requested a review from quaquel March 30, 2025 10:43
@github-actions
Copy link
Copy Markdown

Performance benchmarks:

Model Size Init time [95% CI] Run time [95% CI]
BoltzmannWealth small 🔴 +4.9% [+3.9%, +5.8%] 🔴 +5.7% [+5.4%, +6.0%]
BoltzmannWealth large 🔵 +18.7% [+2.0%, +53.7%] 🔵 +3.9% [+2.0%, +6.4%]
Schelling small 🔵 +2.1% [+1.9%, +2.2%] 🔵 +2.1% [+2.0%, +2.2%]
Schelling large 🔵 +2.5% [+2.2%, +2.8%] 🔴 +5.4% [+4.6%, +6.2%]
WolfSheep small 🔴 +3.3% [+3.0%, +3.6%] 🔴 +4.5% [+4.3%, +4.6%]
WolfSheep large 🔴 +3.9% [+3.4%, +4.4%] 🔴 +3.9% [+3.2%, +4.7%]
BoidFlockers small 🔵 -1.1% [-1.5%, -0.6%] 🔵 +0.2% [-0.1%, +0.4%]
BoidFlockers large 🔵 -0.4% [-0.8%, +0.0%] 🔵 +0.3% [+0.0%, +0.5%]

Copy link
Copy Markdown
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.

This is excellent work Tom, thanks very much.

I think the AgentSet tutorial can be extended. Several additional features could be covered:

  1. agg() - Quickly compute statistics (avg wealth: model.agents.agg("wealth", np.mean))
  2. map() - Return results from method calls (collect data: results = model.agents.map("calculate_utility"))
  3. set() - Modify attributes in bulk (reset state: model.agents.set("active", True))

And a little advanced usage:

  1. Chaining operations - Combine methods for complex operations (model.agents.select(lambda a: a.wealth > 10).shuffle().do("invest"))
  2. model.agents_by_type - Access agents by class type

However, this can be done is a separate PR, and could also be an excellent issue to work on for a less experienced contributor.

@EwoutH
Copy link
Copy Markdown
Member

EwoutH commented Mar 30, 2025

I was also thinking about the need to ever time repeat the full Agent and Model in the tutorial.

Maybe that can be done more elegantly for demonstration purposes, like:

# Define core model components once
def compute_gini(model):
    agent_wealths = [agent.wealth for agent in model.agents]
    x = sorted(agent_wealths)
    n = model.num_agents
    B = sum(xi * (n - i) for i, xi in enumerate(x)) / (n * sum(x))
    return 1 + (1 / n) - 2 * B

class MoneyAgent(mesa.Agent):
    """An agent with fixed initial wealth."""
    
    def __init__(self, model, ethnicity=None):
        super().__init__(model)
        self.wealth = 1
        self.ethnicity = ethnicity
        
    def give_money(self, recipients):
        if self.wealth > 0:
            other_agent = self.random.choice(recipients)
            other_agent.wealth += 1
            self.wealth -= 1

class MoneyModel(mesa.Model):
    """A model with some number of agents."""
    
    def __init__(self, n, agent_type="basic"):
        super().__init__()
        self.num_agents = n
        self.agent_type = agent_type
        
        if agent_type == "basic":
            # Create basic agents
            MoneyAgent.create_agents(model=self, n=n)
        elif agent_type == "ethnic":
            # Create agents with ethnicity
            ethnicities = ["Green", "Blue", "Mixed"]
            MoneyAgent.create_agents(
                model=self,
                n=self.num_agents,
                ethnicity=self.random.choices(ethnicities, k=self.num_agents),
            )
            
        self.datacollector = mesa.DataCollector(
            model_reporters={"Gini": compute_gini},
            agent_reporters={"Wealth": "wealth", "Ethnicity": "ethnicity"} 
            if agent_type == "ethnic" else {"Wealth": "wealth"}
        )
    
    def step(self):
        # This will be overridden in each example
        pass
# Then for each demonstration, just define a new step method and assign it:

# Example 1: Selection
def selection_step(model):
    model.datacollector.collect(model)
    rich_agents = model.agents.select(lambda a: a.wealth >= 3)
    poor_agents = model.agents.select(lambda a: a.wealth < 3)
    
    if len(rich_agents) > 0:
        rich_agents.shuffle_do("give_money", poor_agents)
    else:
        poor_agents.shuffle_do("give_money", poor_agents)

# Create and run the model with selection step
model = MoneyModel(100)
model.step = selection_step.__get__(model)  # Bind the method to the model
# Example 2: GroupBy
def groupby_step(model):
    model.datacollector.collect(model)
    grouped_agents = model.agents.groupby("ethnicity")
    
    for ethnic, similars in grouped_agents:
        if ethnic != "Mixed":
            similars.shuffle_do("give_money", similars)
        else:
            similars.shuffle_do("give_money", model.agents)

# Create and run the model with groupby step
model = MoneyModel(100, agent_type="ethnic")
model.step = groupby_step.__get__(model)  # Bind the method to the model

@tpike3
Copy link
Copy Markdown
Member Author

tpike3 commented Mar 30, 2025

This is excellent work Tom, thanks very much.

I think the AgentSet tutorial can be extended. Several additional features could be covered:

  1. agg() - Quickly compute statistics (avg wealth: model.agents.agg("wealth", np.mean))
  2. map() - Return results from method calls (collect data: results = model.agents.map("calculate_utility"))
  3. set() - Modify attributes in bulk (reset state: model.agents.set("active", True))

And a little advanced usage:

  1. Chaining operations - Combine methods for complex operations (model.agents.select(lambda a: a.wealth > 10).shuffle().do("invest"))
  2. model.agents_by_type - Access agents by class type

However, this can be done is a separate PR, and could also be an excellent issue to work on for a less experienced contributor.

Concur! I think this is the benefit of the modular approach is that it is much easier to extend or add in a new section

@EwoutH
Copy link
Copy Markdown
Member

EwoutH commented Mar 30, 2025

I don't think the More Mesa en Happy Modeling! sections do need to repeat every time. Maybe only in the first and last tutorial part.

@tpike3
Copy link
Copy Markdown
Member Author

tpike3 commented Mar 30, 2025

I was also thinking about the need to ever time repeat the full Agent and Model in the tutorial.

Maybe that can be done more elegantly for demonstration purposes, like:

# Define core model components once
def compute_gini(model):
    agent_wealths = [agent.wealth for agent in model.agents]
    x = sorted(agent_wealths)
    n = model.num_agents
    B = sum(xi * (n - i) for i, xi in enumerate(x)) / (n * sum(x))
    return 1 + (1 / n) - 2 * B

class MoneyAgent(mesa.Agent):
    """An agent with fixed initial wealth."""
    
    def __init__(self, model, ethnicity=None):
        super().__init__(model)
        self.wealth = 1
        self.ethnicity = ethnicity
        
    def give_money(self, recipients):
        if self.wealth > 0:
            other_agent = self.random.choice(recipients)
            other_agent.wealth += 1
            self.wealth -= 1

class MoneyModel(mesa.Model):
    """A model with some number of agents."""
    
    def __init__(self, n, agent_type="basic"):
        super().__init__()
        self.num_agents = n
        self.agent_type = agent_type
        
        if agent_type == "basic":
            # Create basic agents
            MoneyAgent.create_agents(model=self, n=n)
        elif agent_type == "ethnic":
            # Create agents with ethnicity
            ethnicities = ["Green", "Blue", "Mixed"]
            MoneyAgent.create_agents(
                model=self,
                n=self.num_agents,
                ethnicity=self.random.choices(ethnicities, k=self.num_agents),
            )
            
        self.datacollector = mesa.DataCollector(
            model_reporters={"Gini": compute_gini},
            agent_reporters={"Wealth": "wealth", "Ethnicity": "ethnicity"} 
            if agent_type == "ethnic" else {"Wealth": "wealth"}
        )
    
    def step(self):
        # This will be overridden in each example
        pass
# Then for each demonstration, just define a new step method and assign it:

# Example 1: Selection
def selection_step(model):
    model.datacollector.collect(model)
    rich_agents = model.agents.select(lambda a: a.wealth >= 3)
    poor_agents = model.agents.select(lambda a: a.wealth < 3)
    
    if len(rich_agents) > 0:
        rich_agents.shuffle_do("give_money", poor_agents)
    else:
        poor_agents.shuffle_do("give_money", poor_agents)

# Create and run the model with selection step
model = MoneyModel(100)
model.step = selection_step.__get__(model)  # Bind the method to the model
# Example 2: GroupBy
def groupby_step(model):
    model.datacollector.collect(model)
    grouped_agents = model.agents.groupby("ethnicity")
    
    for ethnic, similars in grouped_agents:
        if ethnic != "Mixed":
            similars.shuffle_do("give_money", similars)
        else:
            similars.shuffle_do("give_money", model.agents)

# Create and run the model with groupby step
model = MoneyModel(100, agent_type="ethnic")
model.step = groupby_step.__get__(model)  # Bind the method to the model

That's a good point, I didn't even think about that.. The other bit I learned, which I didn't expect, is each module has its own dynamic I was thinking I could just repeat what I did in adding space so there was a common template and I learned that was not the best approach for each one.

Happy to co-author this if you want to make any of these changes, I am out of time for major updates as I am helping a fiend with his ML book review. Let me know.

Copy link
Copy Markdown
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.

Any of my comments can be addressed in a follow-up PR, it's great the tutorial is now so modular. Overall a great improvement!

Curious what everyone else thinks!

@tpike3
Copy link
Copy Markdown
Member Author

tpike3 commented Mar 30, 2025

I don't think the More Mesa en Happy Modeling! sections do need to repeat every time. Maybe only in the first and last tutorial part.

That's easy I will make that change.

@tpike3
Copy link
Copy Markdown
Member Author

tpike3 commented Mar 30, 2025

I don't think the More Mesa en Happy Modeling! sections do need to repeat every time. Maybe only in the first and last tutorial part.

Removed!

@Ben-geo
Copy link
Copy Markdown
Collaborator

Ben-geo commented Mar 30, 2025

I feel this is more intuitive and easier to navigate, also I am guessing easier to maintain as we can easily add/ remove components

here the title should be Adding space right
agent space

also when learning I tend to switch between overview of mesa library and specific component ( might just be my preference ) so it would be nice if overview was present in section navigation ( overview is there on top bar but switching between overview and specific section requires users to go back to getting started)

Update overview.md

Updates based on feedback
@tpike3
Copy link
Copy Markdown
Member Author

tpike3 commented Mar 30, 2025

I feel this is more intuitive and easier to navigate, also I am guessing easier to maintain as we can easily add/ remove components

here the title should be Adding space right agent space

also when learning I tend to switch between overview of mesa library and specific component ( might just be my preference ) so it would be nice if overview was present in section navigation ( overview is there on top bar but switching between overview and specific section requires users to go back to getting started)

Recommendations incorporated, thanks!

@Sahil-Chhoker
Copy link
Copy Markdown
Collaborator

@tpike3 Does this tutorial contain the tutorial for property layer visualizing? If no, I think it would be helpful if it could be added.

@tpike3
Copy link
Copy Markdown
Member Author

tpike3 commented Mar 30, 2025

@tpike3 Does this tutorial contain the tutorial for property layer visualizing? If no, I think it would be helpful if it could be added.

@Sahil-Chhoker It does not, but with this set up once it is merged, then it will be much easier to to add that module.

@Spartan-71
Copy link
Copy Markdown
Contributor

I personally found the updated tutorial much cleaner and easier to navigate, thanks to the newly added modules.
Moreover, it provides beginners an overview of different components like AgentSet, Discrete Space, and Customizing the visualization, all in one place.

I struggled a lot with customizing the visualization since there wasn’t good documentation for it in a single location. I had to go through the visualization sections of different examples to figure out what I wanted to achieve.

Good to see this improvement! Hope this helps newbies to learn and use Mesa more easily.

Great work, @tpike3! :)

@EwoutH
Copy link
Copy Markdown
Member

EwoutH commented Apr 1, 2025

@quaquel you're review status is still "Requested changes", which is blocking the merge of this review. Is that still the current status of your review?

@quaquel
Copy link
Copy Markdown
Member

quaquel commented Apr 1, 2025

@quaquel you're review status is still "Requested changes", which is blocking the merge of this review. Is that still the current status of your review?

it's based on the old version. I haven't gotten the chance to review this version yet.

@tpike3 tpike3 dismissed quaquel’s stale review April 7, 2025 11:18

Concerns addressed in major refactor of tutorial. Merging just to keep it moving. Any other concerns can be addressed in future PRs.

@tpike3 tpike3 merged commit b490a66 into mesa:main Apr 7, 2025
11 checks passed
@tpike3 tpike3 deleted the update_intro branch April 7, 2025 11:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Release notes label

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants