FLAMEGPU/FLAMEGPU2

Mutable graphs/networks for on-graph communication

Opened this issue · 0 comments

#1089 will add support for host-device accessible graph data structures, which can be constructed from the host, then iterated from the device. Edge/Vertex attributes can be mutated from the host, but the graph structure itself cannot (i.e. no new vertices or edges)

This supports the messages-on-network-edges (and vertices) approach fundamental for road network simulation performance.

However, the graphs are intended to be static - once created the structure cannot be modified from the host nor the device. This is not useful for other types of model (i.e. social networks or even more complex road network simulations).

There are two forms of mutability for graphs we should consider:

  1. Mutable graphs for messages-on-network (#1120)
  2. Mutable graphs for relationships between agents (#1121)

This issue is for Option 1: Mutable graphs for messages-on-network


@todo - The following is not final / needs some refining / expansion / updating as #1089 changes


Within a simulation which uses host-device accessible graph data structures, for communication or just as part of the environment being modelled, such as a road network, it may be useful for the graph data structure to be changed throughout the lifespan of the simulation.

E.g. if a road is closed for a while (this could be done with properties, but checking an extra value for every access to any edge would be more expensive than the graph data structure being mutated).

This is semi-possible with #1089 in host functions, but requires a complete rebuild of the graph data structure (kill the old one, create a new one that is almost the same), which is obviously suboptimal.

E.g. with the current state of #1089 at the time of writing (2023-10-05) a graph can be constructed with (upto) 10 vertices and (upto) 20 edges via (taken from a test):

    HostEnvironmentDirectedGraph graph = FLAMEGPU->environment.getDirectedGraph("graph");
    graph.setVertexCount(10);
    for (unsigned int i = 0; i < 10; ++i) {
        graph.setVertexID(i, i + 1);
        graph.setVertexProperty<float>("vertex_float", i, static_cast<float>(i));
        // ... 
    }
    graph.setEdgeCount(20);
    for (unsigned int i = 0; i < 10; ++i) {
        graph.setEdgeSource(i, (i / 2) + 1);
        graph.setEdgeDestination(i, ((i + 2) % 10) + 1);
        // ... 
    }

It is not possible to add a new vertices nor edges, or remove vertices nor edges.

From the host, it should be relatively simple to extend the API to support this, by adding methods to the HostEnvironmentDirectedGraph class to add and remove vertices edges, which when called mark that the graph CSR/CSC needs a rebuild, which is triggered at the end of the host / device method (or maybe even dtor of graph, though prolly not.)

With the above index-based setEdgeSource() method, it would only work if the value is less than the size, then the same graph.set* methods should be usable, assuming the user can get the current size of the graph.

    size_t next_vidx = graph->currentVertexCount() + 1; // something like that 
    graph.setVertexID(next_vidx, 12);
    //... 

However it might be nicer to add a user-friendly method to add/append a vertex / edge

    size_t v_id = 12;
    auto new_vidx = graph.addVertex(12); // would throw if id is bad etc, doesn't have to return the index

This would need to invalidated any graph iterators etc, although the presence of the "rebuild-needed" flag would allow that, and either a throw could occur if used, or a rebuild could be triggered (which might murder performance if someone mutates, iterates, mutates again etc).

In some cases, it might be useful to have agents which can modify this type of graph, e.g. if you had an agent representing each road in a road network, that would remove / add itself to the environment graph, but that's a bit tenuous / I don't have a great use-case that couldn't just be done on the host for now.