VeloGraphX
High-performance dynamic graph analytics in C++20
Loading...
Searching...
No Matches
weighted_dynamic_graph.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <cstdint>
5#include <limits>
6#include <map>
7#include <optional>
8#include <stdexcept>
9#include <utility>
10#include <vector>
11
13
14namespace velographx {
15
16using EdgeWeight = std::uint64_t;
18 std::numeric_limits<EdgeWeight>::max() / 4 - 1;
19
24 bool add{true};
25 std::uint64_t timestamp{0};
26};
27
29 std::vector<WeightedEdgeUpdate> updates;
30
31 void add(VertexId u, VertexId v, EdgeWeight w, std::uint64_t ts = 0) {
32 updates.push_back({u, v, w, true, ts});
33 }
34
35 void remove(VertexId u, VertexId v, std::uint64_t ts = 0) {
36 updates.push_back({u, v, 0, false, ts});
37 }
38
39 void update(VertexId u, VertexId v, EdgeWeight w, std::uint64_t ts = 0) {
40 updates.push_back({u, v, w, true, ts});
41 }
42
43 [[nodiscard]] bool empty() const noexcept { return updates.empty(); }
44};
45
47 public:
48 explicit WeightedDynamicGraph(std::size_t vertices = 0, bool directed = false)
49 : directed_(directed), adjacency_(vertices) {}
50
51 [[nodiscard]] std::size_t vertex_count() const noexcept { return adjacency_.size(); }
52 [[nodiscard]] std::uint64_t version() const noexcept { return version_; }
53 [[nodiscard]] bool directed() const noexcept { return directed_; }
54
56 const auto n = static_cast<std::size_t>(v) + 1;
57 if (n > adjacency_.size()) adjacency_.resize(n);
58 }
59
60 void apply(const WeightedUpdateBatch& batch) {
61 // Validate the complete batch before mutation so an invalid weight cannot
62 // leave a partially applied graph.
63 for (const auto& op : batch.updates) {
64 if (op.src == op.dst) continue; // VeloGraphX uses simple-graph semantics.
65 if (op.add && op.weight > kMaxFiniteWeightedDistance) {
66 throw std::invalid_argument(
67 "edge weight exceeds the representable finite-distance domain");
68 }
69 }
70
71 for (const auto& op : batch.updates) {
72 if (op.src == op.dst) continue;
73 ensure_vertex(std::max(op.src, op.dst));
74 apply_one(op);
75 if (!directed_) {
76 WeightedEdgeUpdate reverse{op.dst, op.src, op.weight, op.add, op.timestamp};
77 apply_one(reverse);
78 }
79 }
80 if (!batch.empty()) ++version_;
81 }
82
83 [[nodiscard]] std::optional<EdgeWeight> weight(VertexId u, VertexId v) const {
84 if (u >= adjacency_.size()) return std::nullopt;
85 const auto it = adjacency_[u].find(v);
86 if (it == adjacency_[u].end()) return std::nullopt;
87 return it->second;
88 }
89
90 [[nodiscard]] std::size_t degree(VertexId u) const noexcept {
91 return u < adjacency_.size() ? adjacency_[u].size() : 0;
92 }
93
94 template <class Fn>
95 void for_each_neighbor(VertexId u, Fn&& fn) const {
96 if (u >= adjacency_.size()) return;
97 for (const auto& [v, w] : adjacency_[u]) fn(v, w);
98 }
99
100 [[nodiscard]] std::vector<std::pair<VertexId, EdgeWeight>> neighbors(VertexId u) const {
101 if (u >= adjacency_.size()) return {};
102 std::vector<std::pair<VertexId, EdgeWeight>> out;
103 out.reserve(adjacency_[u].size());
104 for (const auto& [v, w] : adjacency_[u]) out.push_back({v, w});
105 return out;
106 }
107
108 private:
109 void apply_one(const WeightedEdgeUpdate& op) {
110 if (op.add) {
111 adjacency_[op.src][op.dst] = op.weight;
112 } else {
113 adjacency_[op.src].erase(op.dst);
114 }
115 }
116
117 bool directed_{false};
118 std::vector<std::map<VertexId, EdgeWeight>> adjacency_;
119 std::uint64_t version_{0};
120};
121
122} // namespace velographx
std::size_t vertex_count() const noexcept
void for_each_neighbor(VertexId u, Fn &&fn) const
std::optional< EdgeWeight > weight(VertexId u, VertexId v) const
std::uint64_t version() const noexcept
std::size_t degree(VertexId u) const noexcept
std::vector< std::pair< VertexId, EdgeWeight > > neighbors(VertexId u) const
void apply(const WeightedUpdateBatch &batch)
WeightedDynamicGraph(std::size_t vertices=0, bool directed=false)
constexpr EdgeWeight kMaxFiniteWeightedDistance
std::uint32_t VertexId
Definition frontier.hpp:6
std::uint64_t EdgeWeight
std::vector< WeightedEdgeUpdate > updates
void update(VertexId u, VertexId v, EdgeWeight w, std::uint64_t ts=0)
void remove(VertexId u, VertexId v, std::uint64_t ts=0)
void add(VertexId u, VertexId v, EdgeWeight w, std::uint64_t ts=0)