-
Notifications
You must be signed in to change notification settings - Fork 1
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
Hawk/dove updating risk attitudes #36
Conversation
Codecov Report
@@ Coverage Diff @@
## main #36 +/- ##
==========================================
+ Coverage 48.58% 53.64% +5.05%
==========================================
Files 15 16 +1
Lines 566 645 +79
==========================================
+ Hits 275 346 +71
- Misses 291 299 +8 |
e50342b
to
0d5980c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fantastic!
simulatingrisk/charts/histogram.py
Outdated
# You have to specify the dependencies as follows, so that the figure | ||
# auto-updates when viz.model or viz.df is changed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this comment outdated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ooh, yes, thanks for catching
simulatingrisk/hawkdovevar/app.py
Outdated
jupyterviz_params_var = jupyterviz_params.copy() | ||
# remove parameter for agent risk level; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this removed? not clear from immediate context but perhaps clear elsewhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point, I should clarify that in the comment at least - it's a parameter that's only relevant for the single-risk level simulation because in the variable simulation risk attitudes are generated randomly; I don't currently have base/common parameters (common params would probably be clearer)
@@ -13,18 +17,94 @@ def set_risk_level(self): | |||
# generate a random risk level | |||
self.risk_level = self.random.randint(0, num_neighbors) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.random
presumably comes from the base mesa class? Otherwise wondering what it refers to
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, mesa provides access to built-in random methods that works just like the main python library random module
It's in mentioned in their documentation best practices, it would allow using a random seed at model instantiation: https://mesa.readthedocs.io/en/stable/best-practices.html#randomization
def adjust_risk(self): | ||
# look at neighbors | ||
# if anyone has more points | ||
# either adopt their risk attitude or average theirs with yours | ||
|
||
best = self.most_successful_neighbor | ||
# if most successful neighbor has more points and a different | ||
# risk attitude, adjust | ||
if best.points > self.points and best.risk_level != self.risk_level: | ||
# adjust risk based on model configuration | ||
if self.model.risk_adjustment == "adopt": | ||
# adopt neighbor's risk level | ||
self.risk_level = best.risk_level | ||
elif self.model.risk_adjustment == "average": | ||
# average theirs with mine, then round to a whole number | ||
# since this model uses discrete risk levels | ||
self.risk_level = round( | ||
statistics.mean([self.risk_level, best.risk_level]) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very, very cool, and slick. I remember talking about this and/or similar strategies of risk adjustment with David and Lara and you.
assert ( | ||
repr(agent) | ||
== f"<HawkDoveSingleRiskAgent id={agent_id} r={risk_level} points=0>" | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice test
assert model.risk_adjustment == "adopt" | ||
assert model.adjust_round_n == 5 | ||
assert model.hawk_odds == 0.2 | ||
assert model.include_diagonals is False | ||
|
||
# handle string none for solara app parameters | ||
model = HawkDoveVariableRiskModel(5, risk_adjustment="none") | ||
assert model.risk_adjustment is None | ||
|
||
# complain about invalid adjustment type | ||
with pytest.raises(ValueError, match="Unsupported risk adjustment 'bogus'"): | ||
HawkDoveVariableRiskModel(3, risk_adjustment="bogus") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These easy access object property-methods really make using and testing quite easy and legible.
] | ||
|
||
|
||
@pytest.mark.parametrize("params,expect_adjust_step", adjustment_testdata) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is nice, so it runs the test 4 times according to the number of tuples in the adjustment_testdata
list?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, isn't that cool? very useful sometimes
neighbor = Mock(points=1500, risk_level=3) | ||
with patch.object(HawkDoveVariableRiskAgent, "most_successful_neighbor", neighbor): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very elegant patching
* Preliminary work for hawk/dove adaptive risk attitudes #20 * Clean up duplicate code; add comments about adjusting parameters * Add tests for variable hawk/dove; improve error handling * Add a label for round-adjustment parameter * Fix typo in app about placeholder content * Load about app content relative to app file * Remove model dependency in matplotlib histogram (prevents from updating) * Remove unused requirements text files/directories * Clean up outdated comments and refactor common hawk/dove params
modify variable-risk hawk/dove game to add logic for updating risk levels based on neighbors
adjustment logic is adapted from previous implementation in the risk bet simulation