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

feat: Implement experimental DataCollector API 2 #2024

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions mesa/experimental/measure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from collections import defaultdict


class Group:
def __init__(self, model, fn):
self.model = model
self.fn = fn

@property
def value(self):
return self.fn(self.model)


class Measure:
def __init__(self, group, measurer):
self.group = group
self.measurer = measurer

def _measure_group(self, group, measurer):
# get an attribute
if isinstance(measurer, str):
return getattr(group, measurer)
# apply
return measurer(group)

@property
def value(self):
group_object = self.group
if isinstance(self.group, Group):
group_object = self.group.value
return self._measure_group(group_object, self.measurer)


class DataCollector:
"""
Example: a model consisting of a hybrid of Boltzmann wealth model and
Epstein civil violence.

class EpsteinBoltzmannModel:
def __init__(self):
# Groups
self.quiescents = Group(
lambda model: model.agents.select(
agent_type=Citizen, filter_func=lambda a: a.condition == "Quiescent"
)
)
self.citizens = Group(lambda model: model.get_agents_of_type(Citizen))

# Measurements
self.num_quiescents = Measure(self.quiescents, len)
self.gini = Measure(
self.agents, lambda agents: calculate_gini(agents.get("wealth"))
)
self.gini_quiescents = Measure(
self.quiescents, lambda agents: calculate_gini(agents.get("wealth"))
)
self.condition = Measure(self.citizens, "condition")
self.wealth = Measure(self.agents, "wealth")


def run():
model = EpsteinBoltzmannModel()
datacollector = DataCollector(
model, ["num_quiescents", "gini_quiescents", "wealth"]
)

for _ in range(10):
model.step()
datacollector.collect()
"""

def __init__(self, model, attributes):
self.model = model
self.attributes = attributes
self.data_collection = defaultdict(lambda: defaultdict(list))

def collect(self):
for name in self.attributes:
attribute = getattr(self.model, name)
group = "model"
if isinstance(attribute, Measure):
group = attribute.group
attribute = attribute.value
self.data_collection[group][name].append(attribute)
Loading