{
"cells": [
{
"cell_type": "markdown",
"id": "headed-amino",
"metadata": {},
"source": [
"# Randomness and reproducibility"
]
},
{
"cell_type": "markdown",
"id": "adverse-honolulu",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"Random numbers and [stochastic processes](http://www2.econ.iastate.edu/tesfatsi/ace.htm#Stochasticity)\n",
"are essential to most agent-based models.\n",
"[Pseudo-random number generators](https://en.wikipedia.org/wiki/Pseudorandom_number_generator)\n",
"can be used to create numbers in a sequence that appears \n",
"random but is actually a deterministic sequence based on an initial seed value.\n",
"In other words, the generator will produce the same pseudo-random sequence \n",
"over multiple runs if it is given the same seed at the beginning.\n",
"Note that is possible that the generators will draw the same number repeatedly, \n",
"as illustrated in this [comic strip](https://dilbert.com/strip/2001-10-25) from Scott Adams:\n",
"\n",
""
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "color-summit",
"metadata": {},
"outputs": [],
"source": [
"import agentpy as ap\n",
"import numpy as np\n",
"import random"
]
},
{
"cell_type": "markdown",
"id": "ambient-slovakia",
"metadata": {},
"source": [
"## Random number generators"
]
},
{
"cell_type": "markdown",
"id": "coordinated-release",
"metadata": {},
"source": [
"Agentpy models contain two internal pseudo-random number generators with different features:\n",
"\n",
"- `Model.random` is an instance of `random.Random` (more info [here](https://realpython.com/python-random/))\n",
"- `Model.nprandom` is an instance of `numpy.random.Generator` (more info [here](https://numpy.org/devdocs/reference/random/index.html))"
]
},
{
"cell_type": "markdown",
"id": "efficient-continent",
"metadata": {},
"source": [
"To illustrate, let us define a model that uses both generators to draw a random integer:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "organized-discretion",
"metadata": {},
"outputs": [],
"source": [
"class RandomModel(ap.Model):\n",
" \n",
" def setup(self):\n",
" self.x = self.random.randint(0, 99)\n",
" self.y = self.nprandom.integers(99)\n",
" self.report(['x', 'y'])\n",
" self.stop() "
]
},
{
"cell_type": "markdown",
"id": "greatest-satellite",
"metadata": {},
"source": [
"If we run this model multiple times, we will likely get a different series of numbers in each iteration:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "indirect-atlantic",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Scheduled runs: 5\n",
"Completed: 5, estimated time remaining: 0:00:00\n",
"Experiment finished\n",
"Run time: 0:00:00.027836\n"
]
}
],
"source": [
"exp = ap.Experiment(RandomModel, iterations=5)\n",
"results = exp.run()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "canadian-longitude",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" seed | \n",
" x | \n",
" y | \n",
"
\n",
" \n",
" iteration | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 163546198553218547629179155646693947592 | \n",
" 75 | \n",
" 1 | \n",
"
\n",
" \n",
" 1 | \n",
" 248413101981860191382115517400004092470 | \n",
" 57 | \n",
" 61 | \n",
"
\n",
" \n",
" 2 | \n",
" 71182126006424514048330534400698800795 | \n",
" 96 | \n",
" 37 | \n",
"
\n",
" \n",
" 3 | \n",
" 319505356893330694850769146666666339584 | \n",
" 89 | \n",
" 95 | \n",
"
\n",
" \n",
" 4 | \n",
" 64281825103124977892605409325092957646 | \n",
" 37 | \n",
" 84 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" seed x y\n",
"iteration \n",
"0 163546198553218547629179155646693947592 75 1\n",
"1 248413101981860191382115517400004092470 57 61\n",
"2 71182126006424514048330534400698800795 96 37\n",
"3 319505356893330694850769146666666339584 89 95\n",
"4 64281825103124977892605409325092957646 37 84"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results.reporters"
]
},
{
"cell_type": "markdown",
"id": "driven-values",
"metadata": {},
"source": [
"## Defining custom seeds"
]
},
{
"cell_type": "markdown",
"id": "mexican-radius",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"If we want the results to be reproducible, \n",
"we can define a parameter `seed` that \n",
"will be used automatically at the beginning of a simulation\n",
"to initialize both generators."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "opposite-cooper",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Scheduled runs: 5\n",
"Completed: 5, estimated time remaining: 0:00:00\n",
"Experiment finished\n",
"Run time: 0:00:00.039785\n"
]
}
],
"source": [
"parameters = {'seed': 42}\n",
"exp = ap.Experiment(RandomModel, parameters, iterations=5)\n",
"results = exp.run()"
]
},
{
"cell_type": "markdown",
"id": "ethical-equipment",
"metadata": {},
"source": [
"By default, the experiment will use this seed to generate different random seeds for each iteration:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "circular-pitch",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" seed | \n",
" x | \n",
" y | \n",
"
\n",
" \n",
" iteration | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 252336560693540533935881068298825202077 | \n",
" 26 | \n",
" 68 | \n",
"
\n",
" \n",
" 1 | \n",
" 47482295457342411543800303662309855831 | \n",
" 70 | \n",
" 9 | \n",
"
\n",
" \n",
" 2 | \n",
" 252036172554514852379917073716435574953 | \n",
" 58 | \n",
" 66 | \n",
"
\n",
" \n",
" 3 | \n",
" 200934189435493509245876840523779924304 | \n",
" 48 | \n",
" 77 | \n",
"
\n",
" \n",
" 4 | \n",
" 31882839497307630496007576300860674457 | \n",
" 94 | \n",
" 65 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" seed x y\n",
"iteration \n",
"0 252336560693540533935881068298825202077 26 68\n",
"1 47482295457342411543800303662309855831 70 9\n",
"2 252036172554514852379917073716435574953 58 66\n",
"3 200934189435493509245876840523779924304 48 77\n",
"4 31882839497307630496007576300860674457 94 65"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results.reporters"
]
},
{
"cell_type": "markdown",
"id": "stock-suggestion",
"metadata": {},
"source": [
"Repeating this experiment will yield the same results:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "grand-costume",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Scheduled runs: 5\n",
"Completed: 5, estimated time remaining: 0:00:00\n",
"Experiment finished\n",
"Run time: 0:00:00.047647\n"
]
}
],
"source": [
"exp2 = ap.Experiment(RandomModel, parameters, iterations=5)\n",
"results2 = exp2.run()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "necessary-relationship",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" seed | \n",
" x | \n",
" y | \n",
"
\n",
" \n",
" iteration | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 252336560693540533935881068298825202077 | \n",
" 26 | \n",
" 68 | \n",
"
\n",
" \n",
" 1 | \n",
" 47482295457342411543800303662309855831 | \n",
" 70 | \n",
" 9 | \n",
"
\n",
" \n",
" 2 | \n",
" 252036172554514852379917073716435574953 | \n",
" 58 | \n",
" 66 | \n",
"
\n",
" \n",
" 3 | \n",
" 200934189435493509245876840523779924304 | \n",
" 48 | \n",
" 77 | \n",
"
\n",
" \n",
" 4 | \n",
" 31882839497307630496007576300860674457 | \n",
" 94 | \n",
" 65 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" seed x y\n",
"iteration \n",
"0 252336560693540533935881068298825202077 26 68\n",
"1 47482295457342411543800303662309855831 70 9\n",
"2 252036172554514852379917073716435574953 58 66\n",
"3 200934189435493509245876840523779924304 48 77\n",
"4 31882839497307630496007576300860674457 94 65"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results2.reporters"
]
},
{
"cell_type": "markdown",
"id": "imposed-illinois",
"metadata": {},
"source": [
"Alternatively, we can set the argument `randomize=False` so that the experiment will use the same seed for each iteration:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "aggregate-farming",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Scheduled runs: 5\n",
"Completed: 5, estimated time remaining: 0:00:00\n",
"Experiment finished\n",
"Run time: 0:00:00.021621\n"
]
}
],
"source": [
"exp3 = ap.Experiment(RandomModel, parameters, iterations=5, randomize=False)\n",
"results3 = exp3.run()"
]
},
{
"cell_type": "markdown",
"id": "portable-hardwood",
"metadata": {},
"source": [
"Now, each iteration yields the same results:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "rocky-species",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" seed | \n",
" x | \n",
" y | \n",
"
\n",
" \n",
" iteration | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 42 | \n",
" 35 | \n",
" 39 | \n",
"
\n",
" \n",
" 1 | \n",
" 42 | \n",
" 35 | \n",
" 39 | \n",
"
\n",
" \n",
" 2 | \n",
" 42 | \n",
" 35 | \n",
" 39 | \n",
"
\n",
" \n",
" 3 | \n",
" 42 | \n",
" 35 | \n",
" 39 | \n",
"
\n",
" \n",
" 4 | \n",
" 42 | \n",
" 35 | \n",
" 39 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" seed x y\n",
"iteration \n",
"0 42 35 39\n",
"1 42 35 39\n",
"2 42 35 39\n",
"3 42 35 39\n",
"4 42 35 39"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results3.reporters"
]
},
{
"cell_type": "markdown",
"id": "educational-yield",
"metadata": {},
"source": [
"## Sampling seeds"
]
},
{
"cell_type": "markdown",
"id": "senior-particle",
"metadata": {},
"source": [
"For a sample with multiple parameter combinations, we can treat the seed like any other parameter.\n",
"The following example will use the same seed for each parameter combination:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "gothic-lunch",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'p': 0, 'seed': 0}, {'p': 1, 'seed': 0}]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"parameters = {'p': ap.Values(0, 1), 'seed': 0}\n",
"sample1 = ap.Sample(parameters, randomize=False)\n",
"list(sample1)"
]
},
{
"cell_type": "markdown",
"id": "found-macro",
"metadata": {},
"source": [
"If we run an experiment with this sample,\n",
"the same iteration of each parameter combination will have the same seed (remember that the experiment will generate different seeds for each iteration by default):"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "female-bahrain",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Scheduled runs: 4\n",
"Completed: 4, estimated time remaining: 0:00:00\n",
"Experiment finished\n",
"Run time: 0:00:00.052923\n"
]
}
],
"source": [
"exp = ap.Experiment(RandomModel, sample1, iterations=2)\n",
"results = exp.run()"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "noble-bridges",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" | \n",
" seed | \n",
" x | \n",
" y | \n",
"
\n",
" \n",
" sample_id | \n",
" iteration | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 0 | \n",
" 302934307671667531413257853548643485645 | \n",
" 68 | \n",
" 31 | \n",
"
\n",
" \n",
" 1 | \n",
" 328530677494498397859470651507255972949 | \n",
" 55 | \n",
" 30 | \n",
"
\n",
" \n",
" 1 | \n",
" 0 | \n",
" 302934307671667531413257853548643485645 | \n",
" 68 | \n",
" 31 | \n",
"
\n",
" \n",
" 1 | \n",
" 328530677494498397859470651507255972949 | \n",
" 55 | \n",
" 30 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" seed x y\n",
"sample_id iteration \n",
"0 0 302934307671667531413257853548643485645 68 31\n",
" 1 328530677494498397859470651507255972949 55 30\n",
"1 0 302934307671667531413257853548643485645 68 31\n",
" 1 328530677494498397859470651507255972949 55 30"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results.reporters"
]
},
{
"cell_type": "markdown",
"id": "binding-terminal",
"metadata": {},
"source": [
"Alternatively, we can use `Sample` with `randomize=True` (default)\n",
"to generate random seeds for each parameter combination in the sample."
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "endangered-pound",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'p': 0, 'seed': 302934307671667531413257853548643485645},\n",
" {'p': 1, 'seed': 328530677494498397859470651507255972949}]"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sample3 = ap.Sample(parameters, randomize=True)\n",
"list(sample3)"
]
},
{
"cell_type": "markdown",
"id": "chicken-brass",
"metadata": {},
"source": [
"This will always generate the same set of random seeds:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "induced-hughes",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[{'p': 0, 'seed': 302934307671667531413257853548643485645},\n",
" {'p': 1, 'seed': 328530677494498397859470651507255972949}]"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sample3 = ap.Sample(parameters)\n",
"list(sample3)"
]
},
{
"cell_type": "markdown",
"id": "agreed-current",
"metadata": {},
"source": [
"An experiment will now have different results for every parameter combination and iteration:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "expanded-spiritual",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Scheduled runs: 4\n",
"Completed: 4, estimated time remaining: 0:00:00\n",
"Experiment finished\n",
"Run time: 0:00:00.050806\n"
]
}
],
"source": [
"exp = ap.Experiment(RandomModel, sample3, iterations=2)\n",
"results = exp.run()"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "retained-edinburgh",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" | \n",
" seed | \n",
" x | \n",
" y | \n",
"
\n",
" \n",
" sample_id | \n",
" iteration | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 0 | \n",
" 189926022767640608296581374469671322148 | \n",
" 53 | \n",
" 18 | \n",
"
\n",
" \n",
" 1 | \n",
" 179917731653904247792112551705722901296 | \n",
" 3 | \n",
" 60 | \n",
"
\n",
" \n",
" 1 | \n",
" 0 | \n",
" 255437819654147499963378822313666594855 | \n",
" 83 | \n",
" 62 | \n",
"
\n",
" \n",
" 1 | \n",
" 68871684356256783618296489618877951982 | \n",
" 80 | \n",
" 68 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" seed x y\n",
"sample_id iteration \n",
"0 0 189926022767640608296581374469671322148 53 18\n",
" 1 179917731653904247792112551705722901296 3 60\n",
"1 0 255437819654147499963378822313666594855 83 62\n",
" 1 68871684356256783618296489618877951982 80 68"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results.reporters"
]
},
{
"cell_type": "markdown",
"id": "statutory-jones",
"metadata": {},
"source": [
"Repeating this experiment will yield the same results:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "running-affair",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Scheduled runs: 4\n",
"Completed: 4, estimated time remaining: 0:00:00\n",
"Experiment finished\n",
"Run time: 0:00:00.037482\n"
]
}
],
"source": [
"exp = ap.Experiment(RandomModel, sample3, iterations=2)\n",
"results = exp.run()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "middle-regard",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" | \n",
" seed | \n",
" x | \n",
" y | \n",
"
\n",
" \n",
" sample_id | \n",
" iteration | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 0 | \n",
" 189926022767640608296581374469671322148 | \n",
" 53 | \n",
" 18 | \n",
"
\n",
" \n",
" 1 | \n",
" 179917731653904247792112551705722901296 | \n",
" 3 | \n",
" 60 | \n",
"
\n",
" \n",
" 1 | \n",
" 0 | \n",
" 255437819654147499963378822313666594855 | \n",
" 83 | \n",
" 62 | \n",
"
\n",
" \n",
" 1 | \n",
" 68871684356256783618296489618877951982 | \n",
" 80 | \n",
" 68 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" seed x y\n",
"sample_id iteration \n",
"0 0 189926022767640608296581374469671322148 53 18\n",
" 1 179917731653904247792112551705722901296 3 60\n",
"1 0 255437819654147499963378822313666594855 83 62\n",
" 1 68871684356256783618296489618877951982 80 68"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results.reporters"
]
},
{
"cell_type": "markdown",
"id": "intensive-benjamin",
"metadata": {},
"source": [
"## Stochastic methods of AgentList"
]
},
{
"cell_type": "markdown",
"id": "primary-rendering",
"metadata": {},
"source": [
"Let us now look at some stochastic operations that are often used in agent-based models. \n",
"To start, we create a list of five agents:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "false-theorem",
"metadata": {},
"outputs": [],
"source": [
"model = ap.Model()\n",
"agents = ap.AgentList(model, 5)"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "fitted-flesh",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"AgentList (5 objects)"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"agents"
]
},
{
"cell_type": "markdown",
"id": "crucial-penny",
"metadata": {},
"source": [
"If we look at the agent's ids, we see that they have been created in order:"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "stone-fighter",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 2, 3, 4, 5]"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"agents.id"
]
},
{
"cell_type": "markdown",
"id": "parallel-gardening",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"To shuffle this list, we can use `AgentList.shuffle`:"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "satisfied-tongue",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[3, 2, 1, 4, 5]"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"agents.shuffle().id"
]
},
{
"cell_type": "markdown",
"id": "needed-spanish",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"To create a random subset, we can use `AgentList.random`:"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "collected-bumper",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[2, 1, 4]"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"agents.random(3).id"
]
},
{
"cell_type": "markdown",
"id": "palestinian-address",
"metadata": {},
"source": [
"And if we want it to be possible to select the same agent more than once:"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "attended-investor",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[5, 3, 2, 5, 2, 3]"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"agents.random(6, replace=True).id"
]
},
{
"cell_type": "markdown",
"id": "digital-johnson",
"metadata": {},
"source": [
"## Agent-specific generators"
]
},
{
"cell_type": "markdown",
"id": "illegal-wallace",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"For more advanced applications, we can create separate generators for each object.\n",
"We can ensure that the seeds of each object follow a controlled pseudo-random sequence by using the models' main generator to generate the seeds."
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "active-conducting",
"metadata": {},
"outputs": [],
"source": [
"class RandomAgent(ap.Agent):\n",
" \n",
" def setup(self):\n",
" seed = self.model.random.getrandbits(128) # Seed from model\n",
" self.random = random.Random(seed) # Create agent generator\n",
" self.x = self.random.random() # Create a random number\n",
" \n",
"class MultiRandomModel(ap.Model):\n",
" \n",
" def setup(self):\n",
" self.agents = ap.AgentList(self, 2, RandomAgent)\n",
" self.agents.record('x')\n",
" self.stop()"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "expressed-hospital",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Scheduled runs: 2\n",
"Completed: 2, estimated time remaining: 0:00:00\n",
"Experiment finished\n",
"Run time: 0:00:00.033219\n"
]
}
],
"source": [
"parameters = {'seed': 42}\n",
"exp = ap.Experiment(\n",
" MultiRandomModel, parameters, iterations=2, \n",
" record=True, randomize=False)\n",
"results = exp.run()"
]
},
{
"cell_type": "code",
"execution_count": 28,
"id": "intimate-logistics",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" | \n",
" | \n",
" x | \n",
"
\n",
" \n",
" iteration | \n",
" obj_id | \n",
" t | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 1 | \n",
" 0 | \n",
" 0.414688 | \n",
"
\n",
" \n",
" 2 | \n",
" 0 | \n",
" 0.591608 | \n",
"
\n",
" \n",
" 1 | \n",
" 1 | \n",
" 0 | \n",
" 0.414688 | \n",
"
\n",
" \n",
" 2 | \n",
" 0 | \n",
" 0.591608 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" x\n",
"iteration obj_id t \n",
"0 1 0 0.414688\n",
" 2 0 0.591608\n",
"1 1 0 0.414688\n",
" 2 0 0.591608"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results.variables.RandomAgent"
]
},
{
"cell_type": "markdown",
"id": "certified-worst",
"metadata": {},
"source": [
"Alternatively, we can also have each agent start from the same seed:"
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "facial-least",
"metadata": {},
"outputs": [],
"source": [
"class RandomAgent2(ap.Agent):\n",
" \n",
" def setup(self):\n",
" self.random = random.Random(self.p.agent_seed) # Create agent generator\n",
" self.x = self.random.random() # Create a random number\n",
" \n",
"class MultiRandomModel2(ap.Model):\n",
" \n",
" def setup(self):\n",
" self.agents = ap.AgentList(self, 2, RandomAgent2)\n",
" self.agents.record('x')\n",
" self.stop()"
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "quarterly-bacon",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Scheduled runs: 2\n",
"Completed: 2, estimated time remaining: 0:00:00\n",
"Experiment finished\n",
"Run time: 0:00:00.033855\n"
]
}
],
"source": [
"parameters = {'agent_seed': 42}\n",
"exp = ap.Experiment(\n",
" MultiRandomModel2, parameters, iterations=2, \n",
" record=True, randomize=False)\n",
"results = exp.run()"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "shared-trust",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" | \n",
" | \n",
" x | \n",
"
\n",
" \n",
" iteration | \n",
" obj_id | \n",
" t | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 1 | \n",
" 0 | \n",
" 0.639427 | \n",
"
\n",
" \n",
" 2 | \n",
" 0 | \n",
" 0.639427 | \n",
"
\n",
" \n",
" 1 | \n",
" 1 | \n",
" 0 | \n",
" 0.639427 | \n",
"
\n",
" \n",
" 2 | \n",
" 0 | \n",
" 0.639427 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" x\n",
"iteration obj_id t \n",
"0 1 0 0.639427\n",
" 2 0 0.639427\n",
"1 1 0 0.639427\n",
" 2 0 0.639427"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"results.variables.RandomAgent2"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.10"
},
"toc-autonumbering": false,
"toc-showcode": false,
"toc-showmarkdowntxt": false
},
"nbformat": 4,
"nbformat_minor": 5
}