A first update in C++#
This program builds a four-vertex graph, computes shortest paths from vertex 0, and then applies
a batch with sssp::update(), which changes the graph and brings the result up to date. It
is examples/cpp/first_update.cpp: the dev build compiles it, and CTest runs it on every
backend (the CPU backends, and cuda in a CUDA build with a GPU) and checks that it prints
exactly this:
invalidated 2, affected 2
distances 0 4 1 2
parents -1 0 0 2
#include <dyng/dyng.hpp>
#include <cstdint>
#include <cstdio>
#include <string>
#include <vector>
int main(int argc, char** argv) {
const std::string backend = argc > 1 ? argv[1] : "openmp";
if (backend == "cuda" && !dyng::backend_available(dyng::backend::cuda)) {
std::printf("no CUDA device visible\n");
return 77;
}
auto res = backend == "sequential" ? dyng::resources::sequential()
: backend == "cuda" ? dyng::resources::cuda()
: dyng::resources::openmp();
dyng::edge_list<std::int32_t, std::int32_t> edges;
edges.num_vertices = 4;
edges.num_weights = 1;
edges.add_edge(0, 1, {4});
edges.add_edge(0, 2, {1});
edges.add_edge(2, 1, {2});
edges.add_edge(1, 3, {1});
auto g = dyng::graph<>::from_edges(res, edges.view()); // int32 ids, offsets and weights
auto tree = dyng::sssp::compute(res, g, /*source=*/0); // canonical tree: lowest-id ties
dyng::edge_batch<std::int32_t, std::int32_t> batch;
batch.delete_edge(2, 1);
batch.insert_edge(2, 3, {1});
dyng::sssp::stats st = dyng::sssp::update(res, g, batch.view(), tree); // applies the batch
std::printf("invalidated %lld, affected %lld\n", static_cast<long long>(st.invalidated),
static_cast<long long>(st.affected));
// to_vector() copies a result to the host (from device memory on cuda).
const std::vector<std::int64_t> distances = dyng::to_vector(res, tree.distances());
const std::vector<std::int32_t> parents = dyng::to_vector(res, tree.parents());
std::printf("distances");
for (auto d : distances) std::printf(" %lld", static_cast<long long>(d));
std::printf("\nparents");
for (auto p : parents) std::printf(" %lld", static_cast<long long>(p));
std::printf("\n"); // distances 0 4 1 2, parents -1 0 0 2
}
What happened:
resourceschose the backend (Explanation: Backends and resources). Oncudathe graph and the tree live in device memory, so the program reads the result withto_vector(), which copies it to the host (on the CPU backends it is a plain copy).compute()produced the static result, the canonical shortest-path tree.update()applied the batch tog(its version went up by one) and repaired the tree: the deletion of the tree edge (2, 1) invalidated the subtree below vertex 1, and the insertion (2, 3) gave vertex 3 a shorter path. The result now matchesgagain, so a laterupdate()accepts it (Results and versions).
Build it against an installed dynG with find_package(dyng) (Install). The next step is
the tutorial Dynamic shortest paths on MOSP files (C++), which runs the same steps on the file formats
of the original research code.