-
Notifications
You must be signed in to change notification settings - Fork 874
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
Collecting data from multiple differentiable classes of agents #1701
Conversation
…isjoint variables
pre-commit.ci autofix |
for more information, see https://pre-commit.ci
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #1701 +/- ##
==========================================
+ Coverage 81.49% 81.91% +0.42%
==========================================
Files 18 18
Lines 1405 1449 +44
Branches 273 289 +16
==========================================
+ Hits 1145 1187 +42
- Misses 214 215 +1
- Partials 46 47 +1
☔ View full report in Codecov by Sentry. |
# Conflicts: # mesa/datacollection.py # mesa/time.py
This gives me an idea for a much simpler solution. Basically, modify Line 163 in e3af2a5
to agent_records = []
for agent in model.schedule.agents:
record = get_reports(agent)
record = tuple(r for r in record if r is not None)
if len(record) == 0:
continue
agent_records.append(record) You do |
In my solution, you can have multiple different agent classes with the same attribute name to be collected together. |
Yea, but what about classes with different attributes, which is the sole reason for this PR? If you see possible changes in overall collection process, thats great, but for simplicity lets focus on the matter in hand. |
This is awesome!! This has been a big gap (#1419) and if we do a quick release to PyPI, I can incorporate into the Complexity Explorer tutorial for sugarscape. To @rht's point there may be a more elegant way to do this, but it has been brought up that Mesa needs to be easier to contribute to (Thank you @EwoutH for your candid feedback) and per open source etiquette we must be polite and positive (this is why @jackiekazil pinged me to get on the code of conduct) I say we merge and then release Mesa 1.2.2. What do you say @rht? |
The reason why I said my proposed solution in the first place is because it solves the problem brought up in this PR (classes with different attributes) in a much simpler way. I'd prefer to base on Occam's razor to have the codebase not contain complicated solution if possible. |
I don't think I have crossed any line regarding with the code of conduct. I was just pointing out a different way to solve the problem. |
I suppose I need to elaborate on why my solution solves classes with different attributes. With |
Okey, I might be missing something, but the get_report created from Even after your proposed change this code still results in an error from mesa import Agent, Model
from mesa.time import BaseScheduler
class MockAgent(Agent):
def __init__(self, unique_id, model, val=0):
super().__init__(unique_id, model)
self.val = val
class DifferentMockAgent(Agent):
def __init__(self, unique_id, model, val=0):
super().__init__(unique_id, model)
self.val2 = val
class MockModel(Model):
schedule = BaseScheduler(None)
def __init__(self):
self.schedule = BaseScheduler(self)
self.schedule.add(MockAgent(1, self))
self.schedule.add(DifferentMockAgent(2, self))
self.initialize_data_collector(
agent_reporters={"value": "val", "value2": "val2"}
)
def step(self):
self.schedule.step()
self.datacollector.collect(self)
model = MockModel()
model.step()
agent_vars = model.datacollector.get_agent_vars_dataframe() |
I just wanted to say that I love the semantics here. Using the agent classes directly as an identifier is just so explicit that it should be obvious for what it does. Awesome |
@GiveMeMoreData Take a look #1701. I believe this addresses your concerns but let us know. |
I think maybe it would be best to remove the performance optimization from if all(hasattr(rep, "attribute_name") for rep in rep_funcs):
# This branch is for performance optimization purpose.
prefix = ["model.schedule.steps", "unique_id"]
attributes = [func.attribute_name for func in rep_funcs]
get_reports = attrgetter(*prefix + attributes)` I think this would ease multi agent data collection, albeit with None values, which could be removed with the option added in #1701, if we find a way to fix it. Should i open such a PR? |
Yeah, the performance optimization is not worth the added opaqueness of the code. |
Curent version of mesa did allow for capturing data from multiple classes, but collected variables had to be present in all agents, which for large number of agent classes and variables, results in messy and unnecessary code. Modification present in this PR allows to write collection rules for specific class of agents. This changes the current code from
to
Agent specific variables are collected in separate dictionary, which can later be retrieved with
get_agent_specific_vars_dataframe
as dataframe copyting the bahaviour ofget_agent_vars_dataframe
, but with addition of one index column containg agent class info.