Initialization

After we created a simulation by calling create_simulation, we must build the initial state of the simulation. As in Vahana the state of a model is represented as a graph, this means we must add the nodes (our agents) and edges to the graph.

Vahana.add_agent!Function
add_agent!(sim, agent::T)::AgentID

Add a single agent of type T to the simulation sim.

T must have been previously registered by calling register_agenttype!.

add_agent! returns a new AgentID, which can be used to create edges from or to this agent until finish_init! is called (in the case that add_agent! is called in the initialization phase), or until the transition funcion is finished (in the case that add_agent! is called in an apply! callback). Do not use the ID for other purposes, they are not guaranteed to be stable.

See also add_agents!, add_edge! and add_edges!

source
Vahana.add_agents!Function
add_agents!(sim, agents)::Vector{AgentID}

Add multiple agents at once to the simulation sim.

agents can be any iterable set of agents, or an arbitrary number of agents as arguments.

The types of the agents must have been previously registered by calling register_agenttype!.

add_agents! returns a vector of AgentIDs, which can be used to create edges from or to this agents before finish_init! is called (in the case that add_agents! is called in the initialization phase), or before the transition funcion is finished (in the case that add_agents! is called in an apply! callback). Do not use the ID for other purposes, they are not guaranteed to be stable.

See also add_agent!, register_agenttype!, add_edge! and add_edges!

source
Warning

The IDs created by add_agent(s)! contain Vahana internal information, that can change after an apply! or the finish_init! call. It is even possible that different agents have the same ID at different times. This has the implication, that the IDs can only be used temporary and should not be stored in the state of an agent or edge.

Vahana.EdgeType
struct Edge{T} 
    from::AgentID
    state::T
end

An edge between to agents with (optionally) additional state. T can be also a struct without any field.

The AgentID of the agent at the target of the edge is not a field of Edge itself, since this information is already part of the containers in which the edges are stored.

See also register_edgetype!

source
Vahana.add_edge!Function
add_edge!(sim, to::AgentID, edge::Edge{T})

Add a single edge to the simulation sim. The edges is directed from the agent with ID edge.from (the source) to the agent with ID to (the target).

add_edge!(sim, from::AgentID, to::AgentID, state::T)

Add a single edge to the simulation sim. The edge is directed from the agent with ID from (the source) to the agent with ID to (the target) and has the state state.

T must have been previously registered in the simulation by calling register_edgetype!.

See also Edge register_edgetype! and add_edges!

source
Vahana.add_edges!Function
add_edges!(sim, to::AgentID, edges)

Add multiple edges at once to the simulation sim, with all edges are directed to to.

edges can be any iterable set of agents, or an arbitrary number of edges as arguments.

See also Edge register_edgetype! and add_edge!

source

Graphs

It is also possible to use graph generators from the Graphs.jl package to construct the initial state. Or parts of it, since you can combine it with all the other functions described on this page. Since Graphs.jl has overlapping function names with Vahana, it is advisable to import only the SimpleGraphs module from Graphs.jl.

Vahana.add_graph!Function
add_graph!(sim::Simulation, graph, agent_constructor, edge_constructor) -> Vector{AgentID}

Adds a graph from the Graphs.jl package to sim, incl. all vertices of graph as new agents.

graph must be a Graphs.Graph or a Graphs.DiGraph.

For each vertix of graph the agent_constructor function is called, with the Graphs.vertix as argument. For each edge of graph the edge_constructor function is called, with the Graphs.edge as argument.

The agent types of agents created by the agent_constructor must be already registered via register_agenttype! and vis a vis the edge type via register_edgetype!.

Info

add_graph! is only available when the Graphs.jl package is imported by the model implementation.

Returns a vector with the IDs of the created agents.

source

There is also two function with works the other way and converts the underlying graph of an simulation (or a subset of this graph) to a structure that fulfills the AbstractGraph or AbstractSimpleGraph interface from the Graphs.jl package.

Vahana.vahanagraphFunction
vahanagraph(sim::Simulation; [agenttypes::Vector{DataType}, edgetypes::Vector{DataType}, show_ignorefrom_warning = true, drop_multiedges = false])

Creates a subgraph with nodes for all agents that have one of the agenttypes types, and all edges that have one of the edgetypes types and whose both adjacent agents have are of a type in agenttypes.

The default values for agenttypes and edgetypes are all registered agents/edgetypes (see register_agenttype! and register_edgetype!).

This subgraphs implements the AbstractGraph interface from the Graphs.jl package, so that e.g. GraphMakie can be used to visualize the subgraph. See also create_graphplot.

The AbstractGraph interface allows multiple edges between two nodes, but some functions (e.g. those that convert the graph to a binary (sparse) matrix) may produce undefined results for these graphs, e.g. when graphplot is called from GraphMakie.jl. If the keyword drop_multiedges is true and there are multiple edges, only the edge of the type that is first in the edgetypes vector is added to the generated graph.

The edge types must not have the :IgnoreFrom property. If there are edge types with this property in the edgetypes vector, a warning will be displayed and these edges will be ignored. The warning can be suppressed by setting show_ignorefrom_warning to false.

source
Vahana.vahanasimplegraphFunction
vahanasimplegraph(sim::Simulation; [agenttypes::Vector{DataType}, edgetypes::Vector{DataType}, show_ignorefrom_warning = true])

Creates a subgraph with nodes for all agents that have one of the agenttypes types, and all edges that have one of the edgetypes types and whose both adjacent node types are in agenttypes.

The default values for agenttypes and edgetypes are all registered agents/edgetypes (see register_agenttype! and register_edgetype!).

This subgraphs implements the AbstractSimpleGraph interface from the Graphs.jl package.

The edge types must not have the :IgnoreFrom property. If there are edge types with this property in the edgetypes vector, a warning will be displayed and these edges will be ignored. The warning can be suppressed by setting show_ignorefrom_warning to false.

Warning

The AbstractGraph interface allows multiple edges between two nodes, but some function (e.g. those that convert the graph into a binary (sparse)matrix can produce undefined results for those graphs. So use this function with care.

source

Raster

The process for adding raster data to a simulation is documented here.

Set Parameters

After creating a simulation, you can modify parameter values using set_param! until the simulation is initialized with finish_init!.

Vahana.set_param!Function
set_param!(sim::Simulation, param::Symbol, value)

Assign the specified value to the param parameter. This operation is only allowed prior to calling the finish_init! method.

A pipeable version of set_param! is also available.

source

Finish initialization

After all the initial state has been built using the functions described above, finish_init! must be called before the first call of apply!

Vahana.finish_init!Function
finish_init!(sim::Simulation; [distribute = true, 
             partition::Dict{AgentID, ProcessID}, 
             partition_algo = :Metis])

Finish the initialization phase of the simulation.

partition is an option keyword and allows to specify an assignment of the agents to the individual MPI ranks. The dictonary must contain all agentids created on the rank as key, the corresponding value is the rank on which the agent "lives" after finish_init!.

In the case that no partition is given and distribute is set to true, the Graph will be partitioned with the given partition_algo. Currently two algorithms are supported: - :Metis uses the Metis library for the graph partitioning. - :EqualAgentNumbers just ensures that per agent type more or less the same number of agents are distributed to each process.

finish_init! must be called before applying a transition function.

Info

When a simulation is run on multiple PEs, per default the graph found on rank 0 will be partitioned using Metis, and distributed to the different ranks. Which means that it's allowed to run the initialization phase on all ranks (there is no need for a mpi.isroot check), but then all added agents and edges on other ranks then 0 will be discarded. If this is not intended distribute must be set to false.

See also register_agenttype!, register_edgetype!, apply! and finish_simulation!

source