Changelog
0.1.5 (December 2021)
Experiment.run()
has a new argument ‘n_jobs’ that allows for parallel processing withjoblib.Parallel()
.Two new methods -
Grid.record_positions()
andSpace.record_positions()
- can be used to record agent positions.Model.run()
can now continue simulations that have already been run. The steps defined in the argument ‘steps’ now reflect additional steps, which will be added to the models current time-step. Random number generators will not be re-initialized in this case.animate()
has been improved. It used to stop the animation one step too early, which has been fixed. Two faulty import statements have been corrected. And, as above, the argument ‘steps’ now also reflects additional steps.Grid.add_field()
has been fixed. Single values can now be passed.
0.1.4 (September 2021)
AttrIter
now returns a newAttrIter
when called as a function.gridplot()
now returns anmatplotlib.image.AxesImage
DataDict.save()
now supports values of typenumpy.bool_
and can re-write to existing directories if an existing exp_id is passed.DataDict.load()
now supports the argument exp_id = 0.animate()
now supports more than 100 steps.AttrIter
now returns a newAttrIter
when called as a function.Model
can take a new parameter report_seed (default True) that indicates whether the seed of the current run should be reported.
0.1.3 (August 2021)
The
Grid
functionality track_empty has been fixed to work with multiple agents per cell.Getting and setting items in
AttrIter
has been fixed.Sequences like
AgentList
andAgentDList
no longer accept args, only kwargs. These keyword arguments are forwarded to the constructor of the new objects. Keyword arguments with sequences of typeAttrIter
will be broadcasted, meaning that the first value will be assigned to the first object, the second to the second, and so forth. Otherwise, the same value will be assigned to all objects.
0.1.2 (June 2021)
The property
Network.nodes
now returns anAttrIter
, so that network nodes can be assigned to agents as follows:self.nw = ap.Network(self) self.agents = ap.AgentList(self, 10) self.nw.add_agents(self.agents) self.agents.node = self.nw.nodes
AgentIter
now requires the model to be passed upon creation and has two new methodsAgentIter.to_list()
andAgentIter.to_dlist()
for conversion between sequence types.Syntax highlighting in the documentation has been fixed.
0.1.1 (June 2021)
Marked release for the upcoming JOSS publication of AgentPy.
Fixed
Grid.move_to()
: Agents can now move to their current position.
0.1.0 (May 2021)
This update contains major revisions of most classes and methods in the library, including new features, better performance, and a more coherent syntax. The most important API changes are described below.
Object creation
The methods add_agents()
, add_env()
, etc. have been removed.
Instead, new objects are now created directly or through Sequences.
This allows for more control over data structures (see next point) and attribute names.
For example:
class Model(ap.Model):
def setup(self):
self.single_agent = ap.Agent() # Create a single agent
self.agents = ap.AgentList(self, 10) # Create a sequence of 10 agents
self.grid = ap.Grid(self, (5, 5)) # Create a grid environment
Data structures
The new way of object creation makes it possible to choose specific data structures for different groups of agents.
In addition to AgentList
, there is a new sequence type
AgentDList
that provides increased performance
for the lookup and deletion of agents.
It also comes with a method AgentDList.buffer()
that allows for safe deletion of agents
from the list while it is iterated over
AttrList
has been replaced by AttrIter
.
This improves performance and makes it possible to change
agent attributes by setting new values to items in the attribute list (see
AgentList
for an example). In most other ways, the class still behaves like a normal list.
There are also two new classes AgentIter
and AgentDListIter
that are returned by some of the library’s methods.
Environments
The three environment classes have undergone a major revision.
The add_agents()
functions have been extended with new features
and are now more consistent between the three environment classes.
The method move_agents()
has been replaced by move_to()
and move_by()
.
Grid
is now defined as a structured numpy array
that can hold field attributes per position in addition to agents,
and can be customized with the arguments torus, track_empty, and check_border.
gridplot()
has been adapted to support this new numpy structure.
Network
now consists of AgentNode
nodes that can hold multiple agents per node, as well as node attributes.
Environment-agent interaction
The agents’ env attribute has been removed. Instead, environments are manually added as agent attributes, giving more control over the attribute name in the case of multiple environments. For example, agents in an environment can be set up as follows:
class Model(ap.Model):
def setup(self):
self.agents = ap.AgentList(self, 10)
self.grid = self.agents.mygrid = ap.Grid(self, (10, 10))
self.grid.add_agents(self.agents)
The agent methods move_to, move_by, and neighbors have also been removed. Instead, agents can access these methods through their environment. In the above example, a given agent a could for example access their position through a.mygrid.positions[a] or their neighbors through calling a.mygrid.neighbors(a).
Parameter samples
Variable parameters can now be defined with the three new classes
Range
(for continuous parameter ranges), IntRange
(for integer parameter ranges), and Values
(for pre-defined of discrete parameter values).
Parameter dictionaries with these classes can be used to create samples,
but can also be passed to a normal model, which will then use default values.
The sampling methods sample()
, sample_discrete()
, and sample_saltelli()
have been removed and integrated into the new class Sample
,
which comes with additional features to create new kinds of samples.
Random number generators
Model
now contains two random number generators Model.random and Model.nprandom
so that both standard and numpy random operations can be used.
The parameter seed can be used to initialize both generators.
Sample
has an argument randomize to vary seeds over parameter samples.
And Experiment
has a new argument randomize to control whether
to vary seeds over different iterations.
More on this can be found in Randomness and reproducibility.
Data analysis
The structure of output data in DataDict
has been changed.
The name of measures has been changed to reporters.
Parameters are now stored in the two categories constants and sample.
Variables are stored in separate dataframes based on the object type.
The dataframe’s index is now separated into sample_id and iteration.
The function sensitivity_sobol()
has been removed and is replaced
by the method DataDict.calc_sobol()
.
Interactive simulations
The method Experiment.interactive()
has been removed and is replaced
by an interactive simulation interface that is being developed in the separate
package ipysimulate.
This new package provides interactive javascript widgets with parameter sliders
and live plots similar to the traditional NetLogo interface.
Examples can be found in Interactive simulations.
0.0.7 (March 2021)
Continuous space environments
A new environment type Space
and method Model.add_space()
for agent-based models with continuous space topologies has been added.
There is a new demonstration model Flocking behavior in the model library,
which shows how to simulate the flocking behavior of animals
and demonstrates the use of the continuous space environment.
Random number generators
Model
has a new property Model.random
, which returns the
models’ random number generator of type numpy.random.Generator()
.
A custom seed can be set for Model.run()
and animate()
by either passing an argument or defining a parameter seed
.
All methods with stochastic elements like AgentList.shuffle()
or AgentList.random()
now take an optional argument generator,
with the model’s main generator being used if none is passed.
The function AgentList.random()
now uses numpy.random.Generator.choice()
and has three new arguments ‘replace’, ‘weights’, and ‘shuffle’.
More information with examples can be found in the API reference
and the new user guide Randomness and reproducibility.
Other changes
The function
sensitivity_sobol()
now has an argumentcalc_second_order
(default False). If True, the function will add second-order indices to the output.The default value of
calc_second_order
insample_saltelli()
has also been changed to False for consistency.For consistency with
Space
,Grid
no longer takes an integer as argument for ‘shape’. A tuple with the lengths of each spatial dimension has to be passed.The argument ‘agents’ has been removed from
Environment
. Agents have to be added throughEnvironment.add_agents()
.
Fixes
The step limit in
animate()
is now the same as inModel.run()
.A false error message in
DataDict.save()
has been removed.
0.0.6 (January 2021)
A new demonstration model Segregation has been added.
All model objects now have a unique id number of type
int
. Methods that take an agent or environment as an argument can now take either the instance or id of the object. Thekey
attribute of environments has been removed.Extra keyword arguments to
Model
andExperiment
are now forwarded toModel.setup()
.Model.run()
now takes an optional argument steps.EnvDict
has been replaced byEnvList
, which has the same functionalities asAgentList
.Model objects now have a property
env
that returns the first environment of the object.Revision of
Network
. The argument map_to_nodes has been removed fromNetwork.add_agents()
. Instead, agents can be mapped to nodes by passing an AgentList to the agents argument ofModel.add_network()
. Direct forwarding of attribute calls toNetwork.graph
has been removed to avoid confusion.New and revised methods for
Grid
:Agent.move_to()
andAgent.move_by()
can be used to move agents.Grid.items()
returns an iterator of position and agent tuples.Grid.get_agents()
returns agents in selected position or area.Grid.position()
returns the position coordinates for an agent.Grid.positions()
returns an iterator of position coordinates.Grid.attribute()
returns a nested list with values of agent attributes.Grid.apply()
returns nested list with return values of a custom function.Grid.neighbors()
has new arguments diagonal and distance.
gridplot()
now takes a grid of values as an input and can convert them to rgba.animate()
now takes a model instance as an input instead of a class and parameters.sample()
andsample_saltelli()
will now return integer values for parameters if parameter ranges are given as integers. For float values, a new argument digits can be passed to round parameter values.The function
interactive()
has been removed, and is replaced by the new methodExperiment.interactive()
.sobol_sensitivity()
has been changed tosensitivity_sobol()
.
0.0.5 (December 2020)
Experiment.run()
now supports parallel processing.New methods
DataDict.arrange_variables()
andDataDict.arrange_measures()
, which generate a dataframe of recorded variables or measures and varied parameters.Major revision of
DataDict.arrange()
, see new description in the documentation.New features for
AgentList
: Arithmethic operators can now be used withAttrList
.
0.0.4 (November 2020)
First documented release.