Utopia 2
Framework for studying models of complex & adaptive systems.
|
Algorithms for conveniently applying function objects on entities. More...
Namespaces | |
namespace | Utopia::GraphUtils |
Classes | |
class | Utopia::rule_invoke_result< State, Rule, Args > |
Helper class for checking rule signatures and return types. More... | |
class | Utopia::StateContainer< StateType, mode > |
Container for states. More... | |
class | Utopia::StateContainer< StateType, Update::manual > |
A very simple, default constructible container with public members. More... | |
class | Utopia::StateContainer< StateType, Update::async > |
State Container specialization for async states. More... | |
class | Utopia::StateContainer< StateType, Update::sync > |
State Container specialization for sync states. More... | |
Typedefs | |
template<typename State , typename Rule , typename... Args> | |
using | Utopia::rule_invoke_result_t = typename rule_invoke_result< State, Rule, Args... >::type |
Helper definition to query the rule result type. | |
Enumerations | |
enum class | Utopia::Shuffle { Utopia::Shuffle::on , Utopia::Shuffle::off } |
Switch for enabling/disabling shuffling the cells for asynchronous updates. More... | |
enum class | Utopia::Update { Utopia::Update::manual , Utopia::Update::sync , Utopia::Update::async } |
Update modes when applying rules. More... | |
Functions | |
template<typename State , typename Rule , typename... Args> | |
constexpr bool | Utopia::is_void_rule () |
Helper function to check if the rule returns void | |
template<class Tuple , std::size_t... I> | |
constexpr decltype(auto) | Utopia::make_tuple_from_tuple_impl (Tuple &&t, std::index_sequence< I... >) |
Helper function to create a tuple from a tuple using an index sequence. | |
template<class Tuple > | |
constexpr decltype(auto) | Utopia::make_tuple_from_tuple (Tuple &&t) |
Helper function to create a tuple from a tuple. | |
template<Update mode, class Rule , class ContTarget , class... ContArgs, typename std::enable_if_t< mode==Update::sync, int > = 0, typename std::enable_if_t< impl::entity_t< ContTarget >::mode==Update::manual, int > = 0> | |
void | Utopia::apply_rule (Rule &&rule, const ContTarget &cont_target, ContArgs &&... cont_args) |
Sequential overload. | |
template<Update mode, class Rule , class ContTarget , class... ContArgs, typename std::enable_if_t< mode==Update::sync, int > = 0, typename std::enable_if_t< impl::entity_t< ContTarget >::mode==Update::manual, int > = 0> | |
void | Utopia::apply_rule (const Utopia::ExecPolicy policy, Rule &&rule, const ContTarget &cont_target, ContArgs &&... cont_args) |
Apply a rule synchronously to manually updated states. | |
template<Update mode, Shuffle shuffle = Shuffle::on, class Rule , class ContTarget , class... ContArgs, typename std::enable_if_t< mode==Update::async, int > = 0, typename std::enable_if_t< impl::entity_t< ContTarget >::mode==Update::manual, int > = 0, typename std::enable_if_t< shuffle==Shuffle::off, int > = 0> | |
void | Utopia::apply_rule (Rule &&rule, const ContTarget &cont_target, ContArgs &&... cont_args) |
Sequential case overload. | |
template<Update mode, Shuffle shuffle = Shuffle::on, class Rule , class ContTarget , class... ContArgs, typename std::enable_if_t< mode==Update::async, int > = 0, typename std::enable_if_t< impl::entity_t< ContTarget >::mode==Update::manual, int > = 0, typename std::enable_if_t< shuffle==Shuffle::off, int > = 0> | |
void | Utopia::apply_rule (const Utopia::ExecPolicy policy, Rule &&rule, const ContTarget &cont_target, ContArgs &&... cont_args) |
Apply a rule asynchronously to manually updated states. | |
template<Update mode, Shuffle shuffle = Shuffle::on, class Rule , class ContTarget , class RNG , class... ContArgs, typename std::enable_if_t< mode==Update::async, int > = 0, typename std::enable_if_t< impl::entity_t< ContTarget >::mode==Update::manual, int > = 0, typename std::enable_if_t< shuffle==Shuffle::on, int > = 0> | |
void | Utopia::apply_rule (Rule &&rule, const ContTarget &cont_target, RNG &&rng, ContArgs &&... cont_args) |
Sequential case overload. | |
template<Update mode, Shuffle shuffle = Shuffle::on, class Rule , class ContTarget , class RNG , class... ContArgs, typename std::enable_if_t< mode==Update::async, int > = 0, typename std::enable_if_t< impl::entity_t< ContTarget >::mode==Update::manual, int > = 0, typename std::enable_if_t< shuffle==Shuffle::on, int > = 0> | |
void | Utopia::apply_rule (const Utopia::ExecPolicy policy, Rule &&rule, const ContTarget &cont_target, RNG &&rng, ContArgs &&... cont_args) |
Apply a rule asynchronously and shuffled to manually updated states. | |
template<class Rule , class Container , bool sync = impl::entity_t<Container>::is_sync()> | |
std::enable_if_t< sync, void > | Utopia::apply_rule (const Rule &rule, const Container &container) |
Apply a rule synchronously on the state of all entities of a container. | |
template<bool shuffle = true, class Rule , class Container , bool sync = impl::entity_t<Container>::is_sync()> | |
std::enable_if_t< not sync &¬ shuffle, void > | Utopia::apply_rule (const Rule &rule, const Container &container) |
Apply a rule on asynchronous states without prior shuffling. | |
template<bool shuffle = true, class Rule , class Container , class RNG , bool sync = impl::entity_t<Container>::is_sync()> | |
std::enable_if_t< not sync &&shuffle, void > | Utopia::apply_rule (const Rule &rule, const Container &container, RNG &&rng) |
Apply a rule on asynchronous states with prior shuffling. | |
template<IterateOver iterate_over, Update mode, typename Graph , typename Rule , typename std::enable_if_t< mode==Update::sync, int > = 0> | |
void | Utopia::apply_rule (Rule &&rule, Graph &&g) |
Synchronously apply a rule to graph entities. | |
template<IterateOver iterate_over, Update mode, Shuffle shuffle, typename Graph , typename Rule , typename std::enable_if_t< mode==Update::async, int > = 0> | |
void | Utopia::apply_rule (Rule &&rule, Graph &&g) |
Asynchronously apply a rule to graph entities, without shuffling. | |
template<IterateOver iterate_over, Update mode, Shuffle shuffle = Shuffle::on, typename Graph , typename Rule , typename RNG , typename std::enable_if_t< mode==Update::async, int > = 0, typename std::enable_if_t< shuffle==Shuffle::on, int > = 0> | |
void | Utopia::apply_rule (Rule &&rule, Graph &&g, RNG &&rng) |
Asynchronously, in shuffled order, apply a rule to graph entities. | |
template<IterateOver iterate_over, Update mode, typename Graph , typename Rule , typename VertexDesc = typename boost::graph_traits< std::remove_reference_t<Graph>>::vertex_descriptor, typename std::enable_if_t< mode==Update::sync, int > = 0> | |
void | Utopia::apply_rule (Rule &&rule, const VertexDesc ref_vertex, Graph &&g) |
Synchronously apply a rule to graph entities. | |
template<IterateOver iterate_over, Update mode, Shuffle shuffle = Shuffle::on, typename Graph , typename Rule , typename VertexDesc = typename boost::graph_traits< std::remove_reference_t<Graph>>::vertex_descriptor, typename std::enable_if_t< mode==Update::async, int > = 0, typename std::enable_if_t< shuffle==Shuffle::off, int > = 0> | |
void | Utopia::apply_rule (Rule &&rule, const VertexDesc ref_vertex, Graph &&g) |
Asynchronously apply a rule to graph entities, without shuffling. | |
template<IterateOver iterate_over, Update mode, Shuffle shuffle = Shuffle::on, typename Graph , typename Rule , typename RNG , typename VertexDesc = typename boost::graph_traits< std::remove_reference_t<Graph>>::vertex_descriptor> | |
void | Utopia::apply_rule (Rule &&rule, const VertexDesc ref_vertex, Graph &&g, RNG &&rng) |
Asynchronously, in shuffled order, apply a rule to graph entities. | |
Algorithms for conveniently applying function objects on entities.
A rule is a function that computes the new state of the entity it is applied to.
Applying a rule synchronously means that its result is applied to all entities simultaneously. In practice, one uses a cache for storing the intermediate states of the cells and then copies/moves the cache entries into the respective cell states.
Applying a rule asynchronously means that its result for a single entity is immediately imposed onto this entity. To avoid preferences in execution order, users may choose to use shuffling before iterating over the cells.
A rule must be implemented by the programmer as a function (object). The function it represents must take a pointer to the entity as first argument and any number of additional arguments, and may capture arbitrary objects. The function's return value is the new state of the entity it is applied to.
For asynchronously applied rules, no return value is required; the state may be changed directly.
Currently, rules may also alter other members (i.e., tags) of the entity they are applied to, and may even change states of other entities. Notice that this does not make sense if you intend to apply such a rule synchronously!
A rule is applied with the Utopia::apply_rule() function. All overloads of this function take the rule, a container of entities, and optionally additional containers as arguments. The latter two are iterated and their elements are applied to the rule in order of their occurance in the containers. The number of containers the function is called with must match the number of arguments of the rule. All containers must have the same size.
Defining a rule taking two arguments and passing an additional container with arguments to be applied can look like this:
Utopia::apply_rule() uses the Zip iteration utilities. The above function call is equivalent to the Python code:
Previously, the state cache for synchronous updates was implemented in the entity itself. Therefore, users had to opt for either sync or async updates when choosing the state data type. We now encourage the usage of the Utopia::StateContainer with the specialization for the Utopia::Update::manual tag (see Utopia::StateContainer<StateType, Update::manual>). This allows for choosing the update type via the Utopia::Update switch directly when calling Utopia::apply_rule.
Rules can also be applied in parallel, speeding up the entire computation. This requires the optional dependencies to be installed (consult the README.md
for further information). Overloads for manual state update of apply_rule() can take a Utopia::ExecPolicy as first argument. Omitting this policy argument has the same effect as using the Utopia::ExecPolicy::seq policy. Parallel execution of Utopia algorithms can be selected at runtime. See Multithreading for details.
{}
using Utopia::rule_invoke_result_t = typedef typename rule_invoke_result<State, Rule, Args...>::type |
Helper definition to query the rule result type.
|
strong |
|
strong |
Update modes when applying rules.
It is recommended to use Update::manual in the EntityTraits because this gives full flexibility when applying the rules.
Enumerator | |
---|---|
manual | User chooses update type when calling apply_rule() |
sync | Synchronous update. |
async | Asynchronous update. |
std::enable_if_t< sync, void > Utopia::apply_rule | ( | const Rule & | rule, |
const Container & | container | ||
) |
Apply a rule synchronously on the state of all entities of a container.
Applies the rule function to each of the entities' states and stores the result in a buffer. Afterwards, it iterates over all entities again and applies the buffer to the actual state.
rule | An application rule, see rule |
Container | A container with the entities upon whom rule is applied |
std::enable_if_t< not sync &¬ shuffle, void > Utopia::apply_rule | ( | const Rule & | rule, |
const Container & | container | ||
) |
Apply a rule on asynchronous states without prior shuffling.
rule | An application rule, see rule |
Container | A container with the entities upon whom rule is applied |
std::enable_if_t< not sync &&shuffle, void > Utopia::apply_rule | ( | const Rule & | rule, |
const Container & | container, | ||
RNG && | rng | ||
) |
Apply a rule on asynchronous states with prior shuffling.
rule | An application rule, see rule |
Container | A container with the entities upon whom rule is applied |
void Utopia::apply_rule | ( | const Utopia::ExecPolicy | policy, |
Rule && | rule, | ||
const ContTarget & | cont_target, | ||
ContArgs &&... | cont_args | ||
) |
Apply a rule synchronously to manually updated states.
This creates a cache for new states whose contents are moved into the respective state containers after all rules have been applied.
mode | Update mode for this rule. This is the overload for synchronous updates (Update::sync). |
Rule | The type of the rule function (object). |
ContTarget | The type of entity container. |
ContArgs | The types of argument containers. |
policy | Utopia::ExecPolicy for the rule when applied in parallel |
rule | The function (object) to apply to the entities |
cont_target | The container of entities the function will be applied to |
cont_args | The containers of additional argument for the function. |
void Utopia::apply_rule | ( | const Utopia::ExecPolicy | policy, |
Rule && | rule, | ||
const ContTarget & | cont_target, | ||
ContArgs &&... | cont_args | ||
) |
Apply a rule asynchronously to manually updated states.
Directly overwrite the states of the passed entities, according to the storage order inside the container.
mode | Update mode for this rule. This is the overload for asynchronous updates (Update::async). |
shuffle | Switch for enabling the shuffling of cells before applying the rule. This is the overload with shuffling disabled (Shuffle::off). |
Rule | The type of the rule function (object). |
Container | The type of entity container. |
ContArgs | The types of argument containers. |
policy | Utopia::ExecPolicy for the rule when applied in parallel |
rule | The function (object) to apply to the entities |
container | The container of entities the function will be applied to |
cont_args | The containers of additional argument for the function. |
void Utopia::apply_rule | ( | const Utopia::ExecPolicy | policy, |
Rule && | rule, | ||
const ContTarget & | cont_target, | ||
RNG && | rng, | ||
ContArgs &&... | cont_args | ||
) |
Apply a rule asynchronously and shuffled to manually updated states.
Copy the container of (pointers to) entities, shuffle it, and apply the rule sequentially to the shuffled container. The original container remains unchanged.
mode | Update mode for this rule. This is the overload for asynchronous updates (Update::async). |
shuffle | Switch for enabling the shuffling of containers before applying the rule. This is the overload with shuffling enabled (Shuffle::on). |
Rule | The type of the rule function (object). |
Container | The type of entity container. |
RNG | The type of the random number generator. |
ContArgs | The types of argument containers. |
policy | Utopia::ExecPolicy for the rule when applied in parallel |
rule | The function (object) to apply to the entities |
cont_target | The container of entities the function will be applied to |
rng | The random number generator used for shuffling the entities |
cont_args | The containers of additional argument for the function. |
cont_target
and all cont_args
simultaneously, guaranteeing that entity at index i
will be applied with additional arguments at index i
for all container indices i
. If you want to shuffle argument containers or entities independently from each other, you must do so yourself before applying this function. shuffle the arguments against the entities they are applied on, do so yourself before calling this function! void Utopia::apply_rule | ( | Rule && | rule, |
const ContTarget & | cont_target, | ||
ContArgs &&... | cont_args | ||
) |
Sequential overload.
void Utopia::apply_rule | ( | Rule && | rule, |
const ContTarget & | cont_target, | ||
ContArgs &&... | cont_args | ||
) |
Sequential case overload.
void Utopia::apply_rule | ( | Rule && | rule, |
const ContTarget & | cont_target, | ||
RNG && | rng, | ||
ContArgs &&... | cont_args | ||
) |
Sequential case overload.
void Utopia::apply_rule | ( | Rule && | rule, |
const VertexDesc | ref_vertex, | ||
Graph && | g | ||
) |
Synchronously apply a rule to graph entities.
This overload specified the apply_rule function for not shuffled entities where getting the correct iterator pair is dependent on a ref_vertex, for example if the rule should be applied to the neighbors, inv_neighbors, in_degree, out_degree or degree wrt. the ref_vertex.
iterate_over | Over which kind of graph entity to iterate over. See IterateOver |
mode | The update mode, see UpdateMode |
Shuffle | Whether to shuffle the container |
Graph | The graph type |
Rule | The rule type |
rule | The rule function, expecting (descriptor, graph) as arguments. For the synchronous update, the rule function needs to return the new state. |
ref_vertex | Reference vertex descriptor to create the iterator from |
g | The graph |
void Utopia::apply_rule | ( | Rule && | rule, |
const VertexDesc | ref_vertex, | ||
Graph && | g | ||
) |
Asynchronously apply a rule to graph entities, without shuffling.
This overload specifies the apply_rule function for an asynchronous update.
iterate_over | Over which kind of graph entity to iterate over. See IterateOver |
mode | The update mode, see UpdateMode |
Graph | The graph type |
Rule | The rule type |
rule | The rule function, expecting (descriptor, graph) as arguments. For an asynchronous update, returning the state is optional. |
ref_vertex | Reference vertex descriptor to create the iterator from |
g | The graph |
void Utopia::apply_rule | ( | Rule && | rule, |
const VertexDesc | ref_vertex, | ||
Graph && | g, | ||
RNG && | rng | ||
) |
Asynchronously, in shuffled order, apply a rule to graph entities.
This overload specified the apply_rule function for shuffled entities where getting the correct iterator pair is dependent on a ref_vertex, for example if the rule should be applied to the neighbors, inv_neighbors, in_degree, out_degree or degree wrt. the ref_vertex.
iterate_over | Over which kind of graph entity to iterate over. See IterateOver |
mode | The update mode, see UpdateMode |
Shuffle | Whether to shuffle the iteration |
Graph | The graph type |
Rule | The rule type |
RNG | The random number generator type |
rule | The rule function, expecting (descriptor, graph) as arguments. For an asynchronous update, returning the state is optional. |
ref_vertex | Reference vertex descriptor to create the iterator from |
g | The graph |
rng | The random number generator |
void Utopia::apply_rule | ( | Rule && | rule, |
Graph && | g | ||
) |
Synchronously apply a rule to graph entities.
This overload specifies the apply_rule function for a synchronous update. In such a case, it makes no sense to shuffle, so the shuffle option is not available here.
iterate_over | Over which kind of graph entity to iterate over. See IterateOver |
mode | The update mode, see UpdateMode |
Graph | The graph type |
Rule | The rule type |
rule | The rule function, expecting (descriptor, graph) as arguments. For the synchronous update, the rule function needs to return the new state. |
g | The graph |
void Utopia::apply_rule | ( | Rule && | rule, |
Graph && | g | ||
) |
Asynchronously apply a rule to graph entities, without shuffling.
This overload specifies the apply_rule function for an asynchronous update.
iterate_over | Over which kind of graph entity to iterate over. See IterateOver |
mode | The update mode, see UpdateMode |
Graph | The graph type |
Rule | The rule type |
rule | The rule function, expecting (descriptor, graph) as arguments. For an asynchronous update, returning the state is optional. |
g | The graph |
void Utopia::apply_rule | ( | Rule && | rule, |
Graph && | g, | ||
RNG && | rng | ||
) |
Asynchronously, in shuffled order, apply a rule to graph entities.
Using the given RNG, the iteration order is shuffled before the rule is applied sequentially to the specified entities.
iterate_over | Over which kind of graph entity to iterate over. See IterateOver |
mode | The update mode, see UpdateMode |
Shuffle | Whether to shuffle the container |
Graph | The graph type |
Rule | The rule type |
RNG | The random number generator type |
rule | The rule function, expecting (descriptor, graph) as arguments. For an asynchronous update, returning the state is optional. |
g | The graph |
rng | The random number generator |
Helper function to check if the rule returns void
|
constexpr |
Helper function to create a tuple from a tuple.
This seems silly, but calling std::make_tuple
decays objects of std::reference_wrapper<T> to
T&`, which is exactly what we use this function for.
This function creates a index sequence for the tuple and calls the implementation helper make_tuple_from_tuple_impl().
t | Tuple to create a tuple from |
|
constexpr |
Helper function to create a tuple from a tuple using an index sequence.
I | Index sequence to access the elements of the tuple |
t | Tuple to create a tuple from |