simulatingrisk 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- simulatingrisk/__init__.py +1 -0
- simulatingrisk/about_app.md +2 -0
- simulatingrisk/app.py +50 -0
- simulatingrisk/batch_run.py +145 -0
- simulatingrisk/charts/histogram.js +51 -0
- simulatingrisk/charts/histogram.py +72 -0
- simulatingrisk/hawkdove/README.md +106 -0
- simulatingrisk/hawkdove/app.py +90 -0
- simulatingrisk/hawkdove/model.py +391 -0
- simulatingrisk/hawkdove/run.py +31 -0
- simulatingrisk/hawkdove/server.py +189 -0
- simulatingrisk/hawkdovemulti/README.md +92 -0
- simulatingrisk/hawkdovemulti/analysis_utils.py +83 -0
- simulatingrisk/hawkdovemulti/app.py +242 -0
- simulatingrisk/hawkdovemulti/batch_run.py +328 -0
- simulatingrisk/hawkdovemulti/model.py +462 -0
- simulatingrisk/hawkdovemulti/run_simulation.ipynb +55 -0
- simulatingrisk/hawkdovemulti/simrisk_batch.slurm +44 -0
- simulatingrisk/risky_bet/README.md +45 -0
- simulatingrisk/risky_bet/app.py +17 -0
- simulatingrisk/risky_bet/model.py +237 -0
- simulatingrisk/risky_bet/run.py +46 -0
- simulatingrisk/risky_bet/server.py +102 -0
- simulatingrisk/risky_food/README.md +32 -0
- simulatingrisk/risky_food/__init__.py +0 -0
- simulatingrisk/risky_food/app.py +19 -0
- simulatingrisk/risky_food/model.py +250 -0
- simulatingrisk/risky_food/run.py +20 -0
- simulatingrisk/risky_food/server.py +78 -0
- simulatingrisk/stag_hunt/README.md +15 -0
- simulatingrisk/stag_hunt/__init__.py +0 -0
- simulatingrisk/stag_hunt/model.py +123 -0
- simulatingrisk/stag_hunt/run.py +45 -0
- simulatingrisk/utils.py +31 -0
- simulatingrisk-1.0.0.dist-info/METADATA +113 -0
- simulatingrisk-1.0.0.dist-info/RECORD +40 -0
- simulatingrisk-1.0.0.dist-info/WHEEL +5 -0
- simulatingrisk-1.0.0.dist-info/entry_points.txt +2 -0
- simulatingrisk-1.0.0.dist-info/licenses/LICENSE +201 -0
- simulatingrisk-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import mesa
|
|
2
|
+
|
|
3
|
+
from simulatingrisk.risky_food.model import RiskyFoodModel
|
|
4
|
+
from simulatingrisk.risky_food.server import (
|
|
5
|
+
chart,
|
|
6
|
+
risk_chart,
|
|
7
|
+
total_agent_chart,
|
|
8
|
+
histogram,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
server = mesa.visualization.ModularServer(
|
|
13
|
+
RiskyFoodModel,
|
|
14
|
+
# [chart, risk_chart, agent_risk_chart, total_agent_chart],
|
|
15
|
+
[chart, risk_chart, total_agent_chart, histogram],
|
|
16
|
+
"Risky Food",
|
|
17
|
+
{"n": 20, "mode": "types"},
|
|
18
|
+
)
|
|
19
|
+
server.port = 8521 # The default
|
|
20
|
+
server.launch()
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import mesa
|
|
2
|
+
import solara
|
|
3
|
+
from matplotlib.figure import Figure
|
|
4
|
+
|
|
5
|
+
from simulatingrisk.charts.histogram import RiskHistogramModule
|
|
6
|
+
from simulatingrisk.utils import labelLabel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
chart = mesa.visualization.ChartModule(
|
|
10
|
+
labelLabel(
|
|
11
|
+
[
|
|
12
|
+
{"Label": "prob_notcontaminated", "Color": "blue"},
|
|
13
|
+
{"Label": "contaminated", "Color": "red"},
|
|
14
|
+
]
|
|
15
|
+
),
|
|
16
|
+
data_collector_name="datacollector",
|
|
17
|
+
canvas_height=100, # default height is 200
|
|
18
|
+
)
|
|
19
|
+
risk_chart = mesa.visualization.ChartModule(
|
|
20
|
+
labelLabel(
|
|
21
|
+
[
|
|
22
|
+
{"Label": "average_risk_level", "Color": "blue"},
|
|
23
|
+
{"Label": "min_risk_level", "Color": "green"},
|
|
24
|
+
{"Label": "max_risk_level", "Color": "orange"},
|
|
25
|
+
]
|
|
26
|
+
),
|
|
27
|
+
data_collector_name="datacollector",
|
|
28
|
+
canvas_height=100,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
total_agent_chart = mesa.visualization.ChartModule(
|
|
32
|
+
labelLabel(
|
|
33
|
+
[
|
|
34
|
+
{"Label": "num_agents", "Color": "gray"},
|
|
35
|
+
]
|
|
36
|
+
),
|
|
37
|
+
data_collector_name="datacollector",
|
|
38
|
+
canvas_height=100,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# bins for risk levels to chart as histogram
|
|
43
|
+
# match types used in the class, i.e. 0, 0.1, 0.2, 0.3, ... 1.0
|
|
44
|
+
# NOTE: if we don't include 1.1, np.histogram groups 0.9 with 1.0
|
|
45
|
+
risk_bins = [r / 10 for r in range(12)]
|
|
46
|
+
histogram = RiskHistogramModule(risk_bins, 200, 500, "risk levels")
|
|
47
|
+
|
|
48
|
+
# server is initialized in run.py
|
|
49
|
+
# jupyterviz is initialized in app.py
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
jupyterviz_params = {
|
|
53
|
+
"n": {
|
|
54
|
+
"type": "SliderInt",
|
|
55
|
+
"value": 20,
|
|
56
|
+
"label": "Number of starting agents",
|
|
57
|
+
"min": 10,
|
|
58
|
+
"max": 50,
|
|
59
|
+
"step": 1,
|
|
60
|
+
},
|
|
61
|
+
"mode": {
|
|
62
|
+
"type": "Select",
|
|
63
|
+
"value": "types",
|
|
64
|
+
"values": ["types", "random"],
|
|
65
|
+
"description": "Risk types of random risk level distribution",
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def plot_total_agents(model):
|
|
71
|
+
"""plot total agents over time to provide an indicator of population size"""
|
|
72
|
+
fig = Figure()
|
|
73
|
+
ax = fig.subplots()
|
|
74
|
+
# generate a line plot of total number of agents
|
|
75
|
+
model_df = model.datacollector.get_model_vars_dataframe()
|
|
76
|
+
ax.plot(model_df.num_agents)
|
|
77
|
+
ax.set_title("total agents")
|
|
78
|
+
solara.FigureMatplotlib(fig)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Stag Hunt Simulation
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
This is a preliminary, incomplete implementation of the Stag Hunt game, drawing on Skyrms' _The stag hunt and the evolution of social structure_ (2004).
|
|
6
|
+
|
|
7
|
+
With the current implementation and payoff scheme, it converges to everyone hunting stag fairly quickly, and is probably not very interesting; but it may useful as a reference with mesa simulations, or for further refinement and experimentation.
|
|
8
|
+
|
|
9
|
+
## Running the simulation
|
|
10
|
+
|
|
11
|
+
- Install python dependencies as described in the main project readme (requires mesa)
|
|
12
|
+
- To run from the main `simulating-risk` project directory:
|
|
13
|
+
- Configure python to include the current directory in import path;
|
|
14
|
+
for C-based shells, run `setenv PYTHONPATH .` ; for bash, run `export $PYTHONPATH=.`
|
|
15
|
+
- To run interactively with mesa runserver: `mesa runserver simulatingrisk/stag_hunt/`
|
|
File without changes
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from functools import partial
|
|
3
|
+
|
|
4
|
+
import mesa
|
|
5
|
+
|
|
6
|
+
HuntChoice = Enum("Hunt", ["STAG", "HARE"])
|
|
7
|
+
choices = [HuntChoice.STAG, HuntChoice.HARE]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class StagHuntAgent(mesa.Agent):
|
|
11
|
+
"""An hunter agent who hunts stag or hare."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, unique_id, model):
|
|
14
|
+
super().__init__(unique_id, model)
|
|
15
|
+
# self.wealth = 1
|
|
16
|
+
# initialize hunt choice randomly for now
|
|
17
|
+
self.hunting = self.random.choices(list(HuntChoice), weights=[15, 85])[0]
|
|
18
|
+
# print("%s hunting %s" % (unique_id, self.hunting))
|
|
19
|
+
# self.hunting = self.random.choice(choices)
|
|
20
|
+
self.last_payoff = None
|
|
21
|
+
|
|
22
|
+
def payoff(self, other_agent):
|
|
23
|
+
# hunting hare has a payoff of 3 no matter what the other agent does
|
|
24
|
+
if self.hunting == HuntChoice.HARE:
|
|
25
|
+
return 3
|
|
26
|
+
|
|
27
|
+
# if both hunt stag, payoff is 4
|
|
28
|
+
if other_agent.hunting == HuntChoice.STAG:
|
|
29
|
+
return 4
|
|
30
|
+
|
|
31
|
+
# hunting stag alone payoff is zero
|
|
32
|
+
return 0
|
|
33
|
+
|
|
34
|
+
def get_neighbors(self):
|
|
35
|
+
# use moore neighborhood (include diagonals), don't include self
|
|
36
|
+
return self.model.grid.get_neighbors(self.pos, True, False)
|
|
37
|
+
|
|
38
|
+
def choose(self):
|
|
39
|
+
# decide on hunting strategy
|
|
40
|
+
# for first hunt, use initial strategy
|
|
41
|
+
|
|
42
|
+
# if this is not the first time hunting,
|
|
43
|
+
# compare our payoff to neighbors
|
|
44
|
+
if self.last_payoff is not None:
|
|
45
|
+
neighbors = self.get_neighbors()
|
|
46
|
+
# update strategy for next time based on neighbors
|
|
47
|
+
# sort neighbors by their last payoff
|
|
48
|
+
neighbor_success = sorted(
|
|
49
|
+
neighbors, key=lambda n: n.last_payoff, reverse=True
|
|
50
|
+
)
|
|
51
|
+
most_successful = neighbor_success[0]
|
|
52
|
+
if most_successful.last_payoff > self.last_payoff:
|
|
53
|
+
print(
|
|
54
|
+
"most successful neighbor: %s payoff=%s hunting=%s"
|
|
55
|
+
% (
|
|
56
|
+
most_successful.unique_id,
|
|
57
|
+
most_successful.last_payoff,
|
|
58
|
+
most_successful.hunting,
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
self.hunting = most_successful.hunting
|
|
62
|
+
|
|
63
|
+
def hunt(self):
|
|
64
|
+
# how to pair up agents? for now use random?
|
|
65
|
+
|
|
66
|
+
neighbors = self.get_neighbors()
|
|
67
|
+
# choose hunting partner from neighbors randomly
|
|
68
|
+
other_agent = self.random.choice(neighbors)
|
|
69
|
+
|
|
70
|
+
# other_agent = self.random.choice(self.model.schedule.agents)
|
|
71
|
+
self.last_payoff = self.payoff(other_agent)
|
|
72
|
+
# print("%s payoff %s" % (self.unique_id, self.last_payoff))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def count_stag_hunters(model):
|
|
76
|
+
return len(
|
|
77
|
+
[agent for agent in model.schedule.agents if agent.hunting == HuntChoice.STAG]
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def num_hunting_choice(model, hunting):
|
|
82
|
+
return len(
|
|
83
|
+
[hunter for hunter in model.schedule.agents if hunter.hunting == hunting]
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class StagHuntModel(mesa.Model):
|
|
88
|
+
"""A model with some number of stag-hunt agents."""
|
|
89
|
+
|
|
90
|
+
# def __init__(self, N):
|
|
91
|
+
# self.num_agents = N
|
|
92
|
+
def __init__(self, width, height):
|
|
93
|
+
self.num_agents = width * height
|
|
94
|
+
self.grid = mesa.space.SingleGrid(width, height, True)
|
|
95
|
+
self.schedule = mesa.time.StagedActivation(self, ["choose", "hunt"])
|
|
96
|
+
# Create agents
|
|
97
|
+
for i in range(self.num_agents):
|
|
98
|
+
a = StagHuntAgent(i, self)
|
|
99
|
+
self.schedule.add(a)
|
|
100
|
+
# place randomly in an empty spot
|
|
101
|
+
self.grid.move_to_empty(a)
|
|
102
|
+
|
|
103
|
+
# self.datacollector = mesa.DataCollector(
|
|
104
|
+
# model_reporters={"stag hunters": count_stag_hunters},
|
|
105
|
+
# agent_reporters={"Hunting": "hunting", "Payoff": "last_payoff"},
|
|
106
|
+
# )
|
|
107
|
+
|
|
108
|
+
self.datacollector = mesa.DataCollector(
|
|
109
|
+
model_reporters={
|
|
110
|
+
"stag_hunters": partial(
|
|
111
|
+
num_hunting_choice, self, hunting=HuntChoice.STAG
|
|
112
|
+
),
|
|
113
|
+
"hare_hunters": partial(
|
|
114
|
+
num_hunting_choice, self, hunting=HuntChoice.HARE
|
|
115
|
+
),
|
|
116
|
+
}
|
|
117
|
+
)
|
|
118
|
+
self.datacollector.collect(self)
|
|
119
|
+
|
|
120
|
+
def step(self):
|
|
121
|
+
"""Advance the model by one step."""
|
|
122
|
+
self.datacollector.collect(self)
|
|
123
|
+
self.schedule.step()
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import mesa
|
|
2
|
+
from simulatingrisk.stag_hunt.model import StagHuntModel
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def agent_portrayal(agent):
|
|
6
|
+
# TODO: figure out where Mesa wants this import to happen
|
|
7
|
+
# (expects model and server nested deeper than run?)
|
|
8
|
+
from simulatingrisk.stag_hunt.model import HuntChoice
|
|
9
|
+
|
|
10
|
+
portrayal = {
|
|
11
|
+
"Shape": "circle",
|
|
12
|
+
"Color": "gray",
|
|
13
|
+
"Filled": "true",
|
|
14
|
+
"Layer": 0,
|
|
15
|
+
"r": 0.2,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if agent.hunting == HuntChoice.STAG:
|
|
19
|
+
portrayal["Color"] = "green"
|
|
20
|
+
else:
|
|
21
|
+
portrayal["Color"] = "blue"
|
|
22
|
+
|
|
23
|
+
if agent.last_payoff == 0:
|
|
24
|
+
portrayal["r"] = 0.2
|
|
25
|
+
elif agent.last_payoff == 3:
|
|
26
|
+
portrayal["r"] = 0.4
|
|
27
|
+
elif agent.last_payoff == 4:
|
|
28
|
+
portrayal["r"] = 0.7
|
|
29
|
+
return portrayal
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
grid = mesa.visualization.CanvasGrid(agent_portrayal, 20, 20, 500, 500)
|
|
33
|
+
chart = mesa.visualization.ChartModule(
|
|
34
|
+
[
|
|
35
|
+
{"Label": "stag_hunters", "Color": "green"},
|
|
36
|
+
{"Label": "hare_hunters", "Color": "blue"},
|
|
37
|
+
],
|
|
38
|
+
data_collector_name="datacollector",
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
server = mesa.visualization.ModularServer(
|
|
42
|
+
StagHuntModel, [grid, chart], "Stag Hunt Model", {"width": 20, "height": 20}
|
|
43
|
+
)
|
|
44
|
+
server.port = 8521 # The default
|
|
45
|
+
server.launch()
|
simulatingrisk/utils.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import random
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def coinflip(choices: [any, any] = [0, 1], weight: float = 0.5) -> any:
|
|
5
|
+
"""Flip a coin with an optional weight between 0.0 and 1.0 for the
|
|
6
|
+
first choice. If no weight is specified, a choice is made with
|
|
7
|
+
equal probability.
|
|
8
|
+
|
|
9
|
+
:param choices: list of coin flip options, defaults to [0, 1]
|
|
10
|
+
:type choices: [any, any] (optional)
|
|
11
|
+
:param weight: optional weight between 0.0-1.0 for the first
|
|
12
|
+
choice, defaults to 0.5
|
|
13
|
+
:type weight: float (optional)
|
|
14
|
+
|
|
15
|
+
:return: selected choice
|
|
16
|
+
:rtype: any
|
|
17
|
+
"""
|
|
18
|
+
# adapted from https://stackoverflow.com/a/477248/9706217
|
|
19
|
+
# random.random is apparently faster than
|
|
20
|
+
selection = 0 if random.random() < weight else 1
|
|
21
|
+
return choices[selection]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def labelLabel(fields):
|
|
25
|
+
# some kind of a bug in current (forked) version of Mesa or
|
|
26
|
+
# a conflict with tornado version on field labels;
|
|
27
|
+
# display is undefined without lowercase but server requires uppercase
|
|
28
|
+
# for now, just copy them
|
|
29
|
+
for item in fields:
|
|
30
|
+
item["label"] = item["Label"]
|
|
31
|
+
return fields
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: simulatingrisk
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Agent-based modeling for simulations related to risk and rationality
|
|
5
|
+
License: Apache-2
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Requires-Python: >=3.7
|
|
8
|
+
Description-Content-Type: text/x-rst
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: mesa==2.1.5
|
|
11
|
+
Requires-Dist: matplotlib
|
|
12
|
+
Requires-Dist: altair>5.0.1
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
15
|
+
Requires-Dist: pytest; extra == "dev"
|
|
16
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
17
|
+
Provides-Extra: analysis
|
|
18
|
+
Requires-Dist: jupyterlab; extra == "analysis"
|
|
19
|
+
Requires-Dist: polars; extra == "analysis"
|
|
20
|
+
Requires-Dist: hvplot; extra == "analysis"
|
|
21
|
+
Requires-Dist: pyarrow; extra == "analysis"
|
|
22
|
+
Requires-Dist: altair; extra == "analysis"
|
|
23
|
+
Requires-Dist: scipy; extra == "analysis"
|
|
24
|
+
Requires-Dist: scikit-learn; extra == "analysis"
|
|
25
|
+
Requires-Dist: seaborn; extra == "analysis"
|
|
26
|
+
Requires-Dist: vegafusion[embed]>=1.5.0; extra == "analysis"
|
|
27
|
+
Requires-Dist: vl-convert-python; extra == "analysis"
|
|
28
|
+
Requires-Dist: great-tables; extra == "analysis"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# Simulating Risk
|
|
32
|
+
|
|
33
|
+
[](https://github.com/DHCodeReview/simulating-risk/pull/1) [](https://github.com/Princeton-CDH/simulating-risk/actions/workflows/unit_tests.yml)
|
|
34
|
+
|
|
35
|
+
The code in this repository is associated with the CDH project [Simulating risk, risking simulations](https://cdh.princeton.edu/projects/simulating-risk/).
|
|
36
|
+
|
|
37
|
+
Simulations are implemented with [Mesa](https://mesa.readthedocs.io/en/stable/), using Agent Based Modeling to explore risk attitudes within populations.
|
|
38
|
+
|
|
39
|
+
----
|
|
40
|
+
|
|
41
|
+
## Simulations with agent interaction
|
|
42
|
+
|
|
43
|
+
- [Hawk/Dove with risk attitudes](simulatingrisk/hawkdove)
|
|
44
|
+
- [Hawk/Dove with multiple risk attitudes and adjustment](simulatingrisk/hawkdovemulti)
|
|
45
|
+
|
|
46
|
+
The code for **Hawk/Dove with risk attitudes** and **Hawk/Dove with multiple risk attitudes** in this codebase was [reviewed](https://github.com/DHCodeReview/simulating-risk/pull/1) in June 2024 by [Scott Foster](https://github.com/sgfost) and [Malte Vogl](https://github.com/maltevogl) (Senior Research Fellow, Max Planck Institute of Geoanthropology) via [DHTech Community Code Review](https://dhcodereview.github.io/); review was faciliated by [Cole Crawford](https://github.com/ColeDCrawford) (Senior Software Engineer, Harvard Arts and Humanities Research Computing).
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
View an interactive version of the [Hawk/Dove with multiple risk attitudes](https://py.cafe/rlskoeser/simulatingrisk-hawk-dove-multirisk) simulation online.
|
|
50
|
+
|
|
51
|
+
The simulation can also be run in a Jupyter notebook: [](https://mybinder.org/v2/gh/Princeton-CDH/simulating-risk.git/HEAD?urlpath=%2Fdoc%2Ftree%2Fsimulatingrisk%2Fhawkdovemulti%2Frun_simulation.ipynb)
|
|
52
|
+
|
|
53
|
+
## Simulations with risky choices (environment)
|
|
54
|
+
|
|
55
|
+
- [Risky Food](simulatingrisk/risky_food)
|
|
56
|
+
- [Risky Bet](simulatingrisk/risky_bet)
|
|
57
|
+
|
|
58
|
+
## Risk attitude definitions
|
|
59
|
+
|
|
60
|
+
Across simulations, we define agents with risk attitudes tracked via a numeric `r` or `risk_level` 0.0 - 1.0, where `r` is that agent's minimum acceptable risk level for taking the risky bet. When the probability 'p' of the risky bet paying off is greater than an agent's 'r', that agent will take the bet. An agent with `r=1` will always take the safe option (no risk is acceptable); an agent with `r=0` will always take the risky choice (any risk is acceptable). Notice that the agent is never indifferent; allowing indifference would require introducing a tie-breaking rule, which would be a further parameter.
|
|
61
|
+
|
|
62
|
+
When the risky bet might be better or worse than the safe bet by the same amount (for example, the risky bet yields 3 or 1 and the safe bet yields 2), an agent who maximizes expected utility will prefer the risky bet when p > 0.5 and will prefer the safe bet when 'p < 0.5'; and they will be indifferent between the risky bet and the safe bet. Thus, r = 0.5 corresponds to expected utility maximization except in the case in which the probability is exactly 0.5 (or, we might say, a point epsilon units to the left of 0.5, where epsilon is smaller than the fineness of our random number generator, corresponds to expected utility maximization). These complications make no difference in practice, so we can simply say that r = 0.5 corresponds to expected utility maximization.
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
## Development instructions
|
|
66
|
+
|
|
67
|
+
Initial setup and installation:
|
|
68
|
+
|
|
69
|
+
- *Recommmended*: create and activate a Python 3.12 virtualenv:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
python3 -m venv simrisk
|
|
73
|
+
source simrisk/bin/activate
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- Install the package, dependencies, and development dependencies:
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
pip install -e .
|
|
80
|
+
pip install -e ".[dev]"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
To run the Solara app with tabs for all simulations that are available as Solara apps:
|
|
84
|
+
```sh
|
|
85
|
+
solara run simulatingrisk/app.py
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
To run a single simulation, run Solara with the model-specific app file:
|
|
89
|
+
```sh
|
|
90
|
+
solara run simulatingrisk/hawkdovemulti/app.py
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
An interactive version of the [Solara app with tabs for all simulations](https://py.cafe/app/rlskoeser/simulatingrisk)
|
|
94
|
+
is available online.
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
### Running the simulations (non-solara versions)
|
|
98
|
+
|
|
99
|
+
- Simulations can be run interactively with mesa runserver by specifying
|
|
100
|
+
the path to the model, e.g. `mesa runserver simulatingrisk/risky_bet/`
|
|
101
|
+
Refer to the readme for each model for more details.
|
|
102
|
+
- Simulations can be run in batches to aggregate data across multiple
|
|
103
|
+
runs and different parameters. For example,
|
|
104
|
+
`./simulatingrisk/batch_run.py riskyfood`
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
### Install pre-commit hooks
|
|
108
|
+
|
|
109
|
+
Install pre-commit hooks (currently [black](https://github.com/psf/black) and [ruff](https://beta.ruff.rs/docs/)):
|
|
110
|
+
|
|
111
|
+
```sh
|
|
112
|
+
pre-commit install
|
|
113
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
simulatingrisk/__init__.py,sha256=J-j-u0itpEFT6irdmWmixQqYMadNl1X91TxUmoiLHMI,22
|
|
2
|
+
simulatingrisk/about_app.md,sha256=wJIhaaiqiS5qn-_y7-tkYPhzmrLCGm3cuqTFppPRizY,148
|
|
3
|
+
simulatingrisk/app.py,sha256=yd5TVDbVUEyTQ38fAQYw5bnGaArE6gHJY0P7afdB0D0,1263
|
|
4
|
+
simulatingrisk/batch_run.py,sha256=ZB18m46wjkwwsMpMZmMh17F5ZxiONKUXB-OmSdVStJE,5113
|
|
5
|
+
simulatingrisk/utils.py,sha256=NfbKWkKdO8UksNpy9JmqtWCtQOcqVxztnMD7TzasUwI,1065
|
|
6
|
+
simulatingrisk/charts/histogram.js,sha256=fE_npwxCWMEs7tBpHaTAwi4C2kWSb-yhduHh5R2eZUw,1311
|
|
7
|
+
simulatingrisk/charts/histogram.py,sha256=m_v-imNd4nPrd-0H5DtlKpTcIGREwtquGX5ZHJ6HPbM,2499
|
|
8
|
+
simulatingrisk/hawkdove/README.md,sha256=G4gZsv8QTs9UMEJdBn76JKFh9qvO8gxf39e1r02rH9Y,6170
|
|
9
|
+
simulatingrisk/hawkdove/app.py,sha256=XjmP-ofdG4tpGQhIMghGWDc43ejoGwKpg0i0DHIPqqE,2702
|
|
10
|
+
simulatingrisk/hawkdove/model.py,sha256=jP8QGTQVSacFngD56vRf08HZ_X8srjQQ-MiXF4BiiEs,13734
|
|
11
|
+
simulatingrisk/hawkdove/run.py,sha256=5bNwwbthwhStOZlu9Frmd9nw--CyPw991QCUfziBAak,840
|
|
12
|
+
simulatingrisk/hawkdove/server.py,sha256=zBDM1lbjwUJJ6lmpudpqmO5iOO7nI1F5nKh5egRYvZ4,5784
|
|
13
|
+
simulatingrisk/hawkdovemulti/README.md,sha256=WCIHEPEsNVV9Z3cJsFjh6BgGZlrUS-TVHOTGsUWPj30,3672
|
|
14
|
+
simulatingrisk/hawkdovemulti/analysis_utils.py,sha256=mPHqhvTS3C79tbvcEyjkunfJcKHJtkdei4xra8xD66o,2774
|
|
15
|
+
simulatingrisk/hawkdovemulti/app.py,sha256=PXlfyyLSAqyQb0UDeVlUNdk3zYp2cZee3mkb5kPRIgU,8239
|
|
16
|
+
simulatingrisk/hawkdovemulti/batch_run.py,sha256=VsUoLkd-iyCqL1RvJEhWprbP3YnX6TRMWbfVDWXfVIU,11176
|
|
17
|
+
simulatingrisk/hawkdovemulti/model.py,sha256=lcDgPqT5tC9wYmc7jwPmb-hz6-YrZTpZ0oJ0q61MoKc,18429
|
|
18
|
+
simulatingrisk/hawkdovemulti/run_simulation.ipynb,sha256=a8YqveMmbVXVR1RUUsjZZp-aEFexJI_PSu7egF2XSzs,1224
|
|
19
|
+
simulatingrisk/hawkdovemulti/simrisk_batch.slurm,sha256=j7uCmMTK5xrDQgONWI6qU47YV2V6MCJuevi9BkYprZc,1922
|
|
20
|
+
simulatingrisk/risky_bet/README.md,sha256=BuSg7zaM1uu2AFFvMX33im_P-oQK0oVce0KRu40nwIk,2152
|
|
21
|
+
simulatingrisk/risky_bet/app.py,sha256=9n8i4XcbDRXVUzgNVe_mX6k_3dUUtY_brIQ1FgvEOtw,490
|
|
22
|
+
simulatingrisk/risky_bet/model.py,sha256=JD5JpIaSFNQ4cJtEKOrpPL-lcBRvwoCnnT6DYtUPSQA,8257
|
|
23
|
+
simulatingrisk/risky_bet/run.py,sha256=02KKzo_aqV6T0ZHeDySg3yAnZAFnSm3y8y5v0yzfbOE,1422
|
|
24
|
+
simulatingrisk/risky_bet/server.py,sha256=9XluBwI3XXR1qkrJY_VRSlcfO3b0m_8X64olxbIhDvs,3175
|
|
25
|
+
simulatingrisk/risky_food/README.md,sha256=tR3QvRDRmDo1X0HFz1Q-isD38AIbF5s2xOwrfzd8ztU,1344
|
|
26
|
+
simulatingrisk/risky_food/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
+
simulatingrisk/risky_food/app.py,sha256=z_ofGHX5UoU9fI93GovHH9p4IjYZJQWbth9MgFnLAGY,576
|
|
28
|
+
simulatingrisk/risky_food/model.py,sha256=zFjqa4ZFTJyQuGYzruXMw9uXtx-PUcbabhEXc2DzjR8,8776
|
|
29
|
+
simulatingrisk/risky_food/run.py,sha256=_5PYfNGa8NmDr-I0Obr6CdMH1S2pgBP639VpWz8KyxY,472
|
|
30
|
+
simulatingrisk/risky_food/server.py,sha256=RrO6GpAbMlsKbwguXcz9SqmLogszvnsJ9L4h0FXeH3c,2126
|
|
31
|
+
simulatingrisk/stag_hunt/README.md,sha256=hrxBs1wKuutZJNQMB-_cYWKBy52OTXsA9XZWkU1akyc,857
|
|
32
|
+
simulatingrisk/stag_hunt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
|
+
simulatingrisk/stag_hunt/model.py,sha256=HJGJOXcgLWnIpixFlx1PiZGI9I1G53MJn4g_AccaLMo,4202
|
|
34
|
+
simulatingrisk/stag_hunt/run.py,sha256=N-gC9FbkcEv23g98aGVliFSRSZr6c-rW24Rl4SbrIpg,1200
|
|
35
|
+
simulatingrisk-1.0.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
36
|
+
simulatingrisk-1.0.0.dist-info/METADATA,sha256=EPp7h1mVhvXTKyAtw9-tg0-Hxbd9HUGqQjewY9CZcvQ,5794
|
|
37
|
+
simulatingrisk-1.0.0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
38
|
+
simulatingrisk-1.0.0.dist-info/entry_points.txt,sha256=Wfr2ZZhtNf0-DKKXYJy45kUs_NEmFNqM0bP8c5fZuzE,95
|
|
39
|
+
simulatingrisk-1.0.0.dist-info/top_level.txt,sha256=73FkHL2uA7XLFVhk-vvXVyMnhBN6TW-oD944TY0vbo8,15
|
|
40
|
+
simulatingrisk-1.0.0.dist-info/RECORD,,
|