LeviLamina
Loading...
Searching...
No Matches
DependencyGraph.h
1#pragma once
2
3#include <cstddef>
4#include <vector>
5
6#include "ll/api/base/Containers.h"
7
8namespace ll::data {
9template <class T>
11 struct Data {
12 SmallDenseSet<T> dependBy;
13 SmallDenseSet<T> dependOn;
14 };
15 DenseMap<T, Data> data;
16
17public:
18 struct SortResult {
19 std::vector<T> sorted;
20 std::vector<T> unsorted;
21
22 [[nodiscard]] constexpr bool hasCycles() const { return !unsorted.empty(); }
23 };
24 void clear() { data.clear(); }
25
26 [[nodiscard]] bool contains(T const& node) const { return data.contains(node); }
27 [[nodiscard]] bool contains(T const& node, T const& dependency) const {
28 if (!contains(dependency)) {
29 return false;
30 }
31 return data.at(dependency).dependBy.contains(node);
32 }
33 bool emplace(T const& node) {
34 if (contains(node)) {
35 return false;
36 }
37 data[node] = {};
38 return true;
39 }
40 bool erase(T const& node) {
41 if (contains(node)) {
42 auto& deps = data.at(node);
43 if (deps.dependBy.size() == 0) {
44 for (auto& dependency : SmallDenseSet<T>{deps.dependOn}) {
45 eraseDependency(node, dependency);
46 }
47 data.erase(node);
48 return true;
49 }
50 }
51 return false;
52 }
53 bool emplaceDependency(T const& node, T const& dependency) {
54 if (dependency != node) {
55 auto& deps = data[dependency];
56 if (!deps.dependBy.contains(node)) {
57 deps.dependBy.emplace(node);
58 data[node].dependOn.emplace(dependency);
59 return true;
60 }
61 }
62 return false;
63 }
64 bool emplaceDependencies(T const& node, std::vector<T> const& dependencies) {
65 for (auto& dependency : dependencies) {
66 if (!emplaceDependency(node, dependency)) {
67 return false;
68 }
69 }
70 return true;
71 }
72 bool eraseDependency(T const& node, T const& dependency) {
73 if (dependency != node && data.contains(dependency)) {
74 auto& deps = data.at(dependency);
75 if (deps.dependBy.contains(node)) {
76 deps.dependBy.erase(node);
77 data[node].dependOn.erase(dependency);
78 return true;
79 }
80 }
81 return false;
82 }
83 SmallDenseSet<T> dependentBy(T const& node) const {
84 if (!contains(node)) {
85 return {};
86 }
87 return data.at(node).dependBy;
88 }
89 SmallDenseSet<T> dependentOn(T const& node) const {
90 if (!contains(node)) {
91 return {};
92 }
93 return data.at(node).dependOn;
94 }
95 [[nodiscard]] SortResult sort() const {
96 std::vector<T> sorted;
97 std::vector<T> unsorted;
98
99 DenseMap<T, size_t> csize;
100 for (auto& [node, deps] : data) {
101 csize[node] = deps.dependOn.size();
102 }
103
104 for (auto& [node, count] : csize) {
105 if (count == 0) {
106 sorted.push_back(node);
107 }
108 }
109 for (size_t i = 0; i < sorted.size(); i++) {
110 for (auto const& node : data.at(sorted[i]).dependBy) {
111 if (--csize[node] == 0) {
112 sorted.push_back(node);
113 }
114 }
115 }
116 for (auto& [node, size] : csize) {
117 if (size != 0) {
118 unsorted.push_back(node);
119 }
120 }
121 return {sorted, unsorted};
122 }
123};
124} // namespace ll::data
Definition DependencyGraph.h:10
Definition DependencyGraph.h:18