FCT
载入中...
搜索中...
未找到
TokenGraph.h
浏览该文件的文档.
1//
2// Created by Administrator on 2025/7/23.
3//
4
5#ifndef TOKENGRAPH_H
6#define TOKENGRAPH_H
7#include "../ThirdParty.h"
8#include "Noncopyable.h"
9namespace FCT {
10 template<typename Token,typename Value>
11 class TokenGraph : public Noncopyable
12 {
13 private:
14 class NodeProbe;
15 struct NodeInfo
16 {
17 private:
18 Token token;
19 NodeInfo(Token token,Value value, std::vector<Token> predecessors, std::vector<Token> successors)
20 {
21 this->token = token;
22 this->value = value;
23 this->predecessors = predecessors;
24 this->successors = successors;
25 }
26 public:
27 friend class TokenGraph;
28 friend class NodeProbe;
29 NodeInfo(Value value, std::vector<Token> predecessors, std::vector<Token> successors)
30 {
31 this->value = value;
32 this->predecessors = predecessors;
33 this->successors = successors;
34 }
36 {
37 this->predecessors = std::vector<Token>();
38 this->successors = std::vector<Token>();
39 }
40 Value value;
41 std::vector<Token> predecessors;
42 std::vector<Token> successors;
43 };
45 boost::adjacency_list<
46 boost::listS,
47 boost::listS,
48 boost::bidirectionalS,
49 int, //weak ref
50 int //weak ref
51 >;
52 using BoostVertex = typename TokenGraphSavedBoostGraph::vertex_descriptor;
53 void addVertex(Token token,int weak_ref = 0)
54 {
55 if (m_vertex.left.count(token))
56 return;
57 BoostVertex vertex = boost::add_vertex(weak_ref, m_graph);
58 m_vertex.insert({token, vertex});
59 }
60 void removeVertex(Token token)
61 {
62 auto it = m_vertex.left.find(token);
63 if (it != m_vertex.left.end()) {
64 BoostVertex vertex = it->second;
65 boost::remove_vertex(vertex, m_graph);
66 m_vertex.left.erase(it);
67 }
68 }
69 bool hasVertex(Token token) const
70 {
71 return m_vertex.left.count(token);
72 }
73 void addWeakRef(Token token)
74 {
75 auto it = m_vertex.left.find(token);
76 if (it != m_vertex.left.end()) {
77 ++m_graph[it->second];
78 }
79 }
80 void removeWeakRef(Token token)
81 {
82 auto it = m_vertex.left.find(token);
83 if (it!= m_vertex.left.end()) {
84 --m_graph[it->second];
85 }
86 }
87 void addWeakRef(Token from, Token to)
88 {
89 auto from_it = m_vertex.left.find(from);
90 auto to_it = m_vertex.left.find(to);
91
92 if (from_it != m_vertex.left.end() && to_it != m_vertex.left.end()) {
93 auto edge_pair = boost::edge(from_it->second, to_it->second, m_graph);
94 if (edge_pair.second) {
95 ++m_graph[edge_pair.first];
96 }
97 }
98 }
99 void removeWeakRef(Token from, Token to)
100 {
101 auto from_it = m_vertex.left.find(from);
102 auto to_it = m_vertex.left.find(to);
103
104 if (from_it != m_vertex.left.end() && to_it != m_vertex.left.end()) {
105 auto edge_pair = boost::edge(from_it->second, to_it->second, m_graph);
106 if (edge_pair.second) {
107 --m_graph[edge_pair.first];
108 if (m_graph[edge_pair.first])
109 return;
110 removeBoostEdge(from,to);
111 }
112 }
113 }
114 bool hasEdge(Token from, Token to) const
115 {
116 auto from_it = m_vertex.left.find(from);
117 auto to_it = m_vertex.left.find(to);
118
119 if (from_it != m_vertex.left.end() && to_it != m_vertex.left.end()) {
120 auto edge_pair = boost::edge(from_it->second, to_it->second, m_graph);
121 return edge_pair.second;
122 }
123 return false;
124 }
125 bool hasNode(Token token) const
126 {
127 return m_nodeMap.count(token);
128 }
129 void addBoostEdge(Token from, Token to)
130 {
131 boost::add_edge(m_vertex.left.at(from), m_vertex.left.at(to), 1, m_graph);
132 }
133 void removeBoostEdge(Token from, Token to)
134 {
135 auto from_it = m_vertex.left.find(from);
136 auto to_it = m_vertex.left.find(to);
137 if (from_it!= m_vertex.left.end() && to_it!= m_vertex.left.end())
138 {
139 auto edge_pair = boost::edge(from_it->second, to_it->second, m_graph);
140 if (edge_pair.second)
141 {
142 boost::remove_edge(edge_pair.first, m_graph);
143 }
144 //boost::remove_edge(from_it->second, to_it->second, m_graph);
145 }
146 }
147 void addEdge(Token node, Token rhs,bool isSuccessor)
148 {
149 if (hasVertex(rhs))
150 {
151 addWeakRef(rhs);
152 } else
153 {
154 addVertex(rhs,1);
155 }
156 if (isSuccessor)
157 {
158 if (hasEdge(node, rhs))
159 {
160 addWeakRef(node,rhs);
161 } else
162 {
163 addBoostEdge(node, rhs);
164 }
165 } else
166 {
167 if (hasEdge(rhs, node))
168 {
169 addWeakRef(rhs, node);
170 } else
171 {
172 addBoostEdge(rhs, node);
173 }
174 }
175 }
176
177
178 template<typename Visitor>
179 class TokenGraphBFSVisitor : public boost::default_bfs_visitor
180 {
181 private:
183 Visitor visitor;
186
187 public:
188 TokenGraphBFSVisitor(const TokenGraph* g, Visitor v, Token start, bool include)
189 : graph(g), visitor(v), startToken(start), includeStart(include) {}
190
191 template<typename VertexDescriptor, typename Graph>
192 void discover_vertex(VertexDescriptor v, const Graph& g) const
193 {
194 auto vertex_token_it = graph->m_vertex.right.find(v);
195 if (vertex_token_it != graph->m_vertex.right.end()) {
196 Token token = vertex_token_it->second;
197 if (graph->hasNode(token)) {
198 if (!includeStart && token == startToken) {
199 return;
200 }
201 visitor(graph->m_nodeMap.at(token).value);
202 }
203 }
204 }
205 };
206 bool isZeroRefVertex(Token token) const
207 {
208 auto it = m_vertex.left.find(token);
209 return m_graph[it->second] == 0;
210 }
211
212 void removeEdge(Token node, Token rhs,bool isSuccessor)
213 {
214 if (isSuccessor)
215 {
216 if (hasEdge(node, rhs))
217 {
218 removeWeakRef(node, rhs);
219 }
220 } else
221 {
222 if (hasEdge(rhs, node))
223 {
224 removeWeakRef(rhs, node);
225 }
226 }
227 removeWeakRef(rhs);
228 if (isZeroRefVertex(rhs) && !hasNode(rhs))
229 {
230 removeVertex(rhs);
231 }
232 }
233 public:
234
243 template<typename Visitor>
244 void visitBFS(Token startToken, Visitor visitor, bool includeStart = true) const
245 {
246 auto start_vertex_it = m_vertex.left.find(startToken);
247 if (start_vertex_it == m_vertex.left.end()) {
248 return;
249 }
250
251 std::map<BoostVertex, boost::default_color_type> vertex_color_map;
252 auto color_pmap = boost::make_assoc_property_map(vertex_color_map);
253
254 TokenGraphBFSVisitor<Visitor> bfs_visitor(this, visitor, startToken, includeStart);
255
256 boost::breadth_first_search(m_graph, start_vertex_it->second,
257 boost::visitor(bfs_visitor).color_map(color_pmap));
258 }
259 void addNode(NodeInfo info)
260 {
261 addVertex(info.token);
262 m_nodeMap[info.token] = info;
263 for (const auto& predecessor : info.predecessors) {
264 addEdge( info.token,predecessor, false);
265 }
266
267 for (const auto& successor : info.successors) {
268 addEdge(info.token, successor, true);
269 }
270 }
271 void addNode(Token token,
272 Value value,
273 std::vector<Token> predecessors,
274 std::vector<Token> successors)
275 {
276 NodeInfo info = { token, value, predecessors, successors };
277 addNode(info);
278 }
279 void removeNode(const Token& token)
280 {
281 for (const auto& predecessor : m_nodeMap[token].predecessors)
282 {
283 removeEdge(predecessor, token, false);
284 }
285 for (const auto& successor : m_nodeMap[token].successors)
286 {
287 removeEdge(token, successor, true);
288 }
289 m_nodeMap.erase(token);
290 if (isZeroRefVertex(token))
291 {
292 removeVertex(token);
293 }
294 }
295 void update()
296 {
297 std::deque<BoostVertex> sortedVertices;
298
299 std::map<BoostVertex, std::size_t> vertex_index_map;
300 std::size_t index = 0;
301 for (auto [v_iter, v_end] = boost::vertices(m_graph); v_iter != v_end; ++v_iter) {
302 vertex_index_map[*v_iter] = index++;
303 }
304 auto index_pmap = boost::make_assoc_property_map(vertex_index_map);
305
306 std::map<BoostVertex, boost::default_color_type> vertex_color_map;
307 auto color_pmap = boost::make_assoc_property_map(vertex_color_map);
308
309 boost::topological_sort(m_graph, std::front_inserter(sortedVertices),
310 boost::vertex_index_map(index_pmap).color_map(color_pmap));
311
312 m_order.clear();
313
314 for (auto vertex : sortedVertices) {
315 auto it = m_vertex.right.find(vertex);
316 if (it != m_vertex.right.end()) {
317 Token token = it->second;
318 if (hasNode(token)) {
319 m_order.push_back(m_nodeMap[token].value);
320 }
321 }
322 }
323 }
325 {
326 private:
328 : m_graph(graph), m_token(token), m_modified(false)
329 {
330 if (m_graph.m_nodeMap.find(token)!= m_graph.m_nodeMap.end())
331 {
332 m_nodeInfo = m_graph.m_nodeMap[token];
333 m_exists = true;
334 } else
335 {
336 m_nodeInfo = {};
337 m_exists = false;
338 }
339 }
340 public:
341 friend class TokenGraph;
343 {
344 if (!m_exists)
345 {
346 if (m_modified)
347 {
348 m_nodeInfo.token = m_token;
349 m_graph.addNode(m_nodeInfo);
350 }
351 return;
352 }
353 if (m_modified) {
354 m_graph.updateNode(m_nodeInfo);
355 }
356 }
357 NodeProbe(const NodeProbe&) = delete;
358 NodeProbe& operator=(const NodeProbe&) = delete;
359 NodeProbe(NodeProbe&& other) noexcept
360 : m_graph(other.m_graph), m_token(std::move(other.m_token)),
361 m_nodeInfo(std::move(other.m_nodeInfo)), m_modified(other.m_modified),
362 m_exists(other.m_exists)
363 {
364 other.m_modified = false;
365 }
367 {
368 m_nodeInfo = info;
369 m_nodeInfo.token = m_token;
370 m_modified = true;
371 return *this;
372 }
373
375 {
376 m_modified = true;
377 return &m_nodeInfo;
378 }
379
380 const NodeInfo* operator->() const
381 {
382 return &m_nodeInfo;
383 }
384
386 {
387 m_modified = true;
388 return m_nodeInfo;
389 }
390
391 const NodeInfo& operator*() const
392 {
393 return m_nodeInfo;
394 }
395
396 bool exists() const { return m_exists; }
397
398 const Token& token() const { return m_token; }
399
400 NodeProbe& addPredecessor(const Token& pred)
401 {
402 auto& preds = m_nodeInfo.predecessors;
403 if (std::find(preds.begin(), preds.end(), pred) == preds.end()) {
404 preds.push_back(pred);
405 m_modified = true;
406 }
407 return *this;
408 }
409
410 NodeProbe& removePredecessor(const Token& pred)
411 {
412 auto& preds = m_nodeInfo.predecessors;
413 auto it = std::find(preds.begin(), preds.end(), pred);
414 if (it != preds.end()) {
415 preds.erase(it);
416 m_modified = true;
417 }
418 return *this;
419 }
420
421 NodeProbe& addSuccessor(const Token& succ)
422 {
423 auto& succs = m_nodeInfo.successors;
424 if (std::find(succs.begin(), succs.end(), succ) == succs.end()) {
425 succs.push_back(succ);
426 m_modified = true;
427 }
428 return *this;
429 }
430
431 NodeProbe& removeSuccessor(const Token& succ)
432 {
433 auto& succs = m_nodeInfo.successors;
434 auto it = std::find(succs.begin(), succs.end(), succ);
435 if (it != succs.end()) {
436 succs.erase(it);
437 m_modified = true;
438 }
439 return *this;
440 }
441
442 private:
444 Token m_token;
448 };
450 {
451 return NodeProbe(*this, token);
452 }
453 std::vector<Value> order() const
454 {
455 return m_order;
456 }
457 void updateNode(const NodeInfo& info)
458 {
459 removeNode(info.token);
460 addNode(info);
461 }
462 std::vector<Value> computeOrder(std::function<bool(const Value&)> canVisit)
463 {
464 std::deque<BoostVertex> sortedVertices;
465
466 std::map<BoostVertex, std::size_t> vertex_index_map;
467 std::size_t index = 0;
468 for (auto [v_iter, v_end] = boost::vertices(m_graph); v_iter != v_end; ++v_iter) {
469 vertex_index_map[*v_iter] = index++;
470 }
471 auto index_pmap = boost::make_assoc_property_map(vertex_index_map);
472
473 std::map<BoostVertex, boost::default_color_type> vertex_color_map;
474 auto color_pmap = boost::make_assoc_property_map(vertex_color_map);
475
476 boost::topological_sort(m_graph, std::front_inserter(sortedVertices),
477 boost::vertex_index_map(index_pmap).color_map(color_pmap));
478
479 std::vector<Value> ret;
480
481 for (auto vertex : sortedVertices) {
482 auto it = m_vertex.right.find(vertex);
483 if (it != m_vertex.right.end()) {
484 Token token = it->second;
485 if (hasNode(token) && canVisit(m_nodeMap[token].value)) {
486 ret.push_back(m_nodeMap[token].value);
487 }
488 }
489 }
490 return ret;
491 }
492
493 public:
497 template<typename Visitor>
498 class TokenGraphDFSVisitor : public boost::default_dfs_visitor
499 {
500 private:
502 Visitor visitor;
503 mutable std::set<Token> visitedTokens;
504
505 public:
506 TokenGraphDFSVisitor(const TokenGraph* g, Visitor v)
507 : graph(g), visitor(v) {}
508
509 template<typename VertexDescriptor, typename Graph>
510 void discover_vertex(VertexDescriptor v, const Graph& g) const
511 {
512 auto vertex_token_it = graph->m_vertex.right.find(v);
513 if (vertex_token_it != graph->m_vertex.right.end()) {
514 Token token = vertex_token_it->second;
515 if (graph->hasNode(token) && visitedTokens.find(token) == visitedTokens.end()) {
516 visitedTokens.insert(token);
517 visitor(graph->m_nodeMap.at(token).value);
518 }
519 }
520 }
521 };
522 template<typename Visitor>
523 void visitDFSFromRoots(Visitor visitor) const
524 {
525 std::vector<BoostVertex> rootVertices;
526
527 for (auto [v_iter, v_end] = boost::vertices(m_graph); v_iter != v_end; ++v_iter) {
528 if (boost::in_degree(*v_iter, m_graph) == 0) {
529 auto vertex_token_it = m_vertex.right.find(*v_iter);
530 if (vertex_token_it != m_vertex.right.end() && hasNode(vertex_token_it->second)) {
531 rootVertices.push_back(*v_iter);
532 }
533 }
534 }
535
536 std::map<BoostVertex, boost::default_color_type> vertex_color_map;
537 auto color_pmap = boost::make_assoc_property_map(vertex_color_map);
538
539 TokenGraphDFSVisitor<Visitor> dfs_visitor(this, visitor);
540
541 for (BoostVertex root : rootVertices) {
542 boost::depth_first_visit(m_graph, root,
543 boost::visitor(dfs_visitor).color_map(color_pmap));
544 }
545 }
546 std::vector<Token> getActivePredecessors(const Token& token) const
547 {
548 std::vector<Token> activePredecessors;
549
550 auto token_it = m_vertex.left.find(token);
551 if (token_it == m_vertex.left.end()) {
552 return activePredecessors;
553 }
554
555 BoostVertex vertex = token_it->second;
556
557 auto [in_edge_iter, in_edge_end] = boost::in_edges(vertex, m_graph);
558 for (auto edge_iter = in_edge_iter; edge_iter != in_edge_end; ++edge_iter) {
559 BoostVertex source_vertex = boost::source(*edge_iter, m_graph);
560
561 auto vertex_token_it = m_vertex.right.find(source_vertex);
562 if (vertex_token_it != m_vertex.right.end()) {
563 Token predecessor_token = vertex_token_it->second;
564
565 if (hasNode(predecessor_token)) {
566 activePredecessors.push_back(predecessor_token);
567 } else {
568 auto subPredecessors = getActivePredecessors(predecessor_token);
569 activePredecessors.insert(activePredecessors.end(), subPredecessors.begin(), subPredecessors.end());
570 }
571 }
572 }
573
574 return activePredecessors;
575 }
576 std::vector<Token> getActiveSuccessors(const Token& token) const
577 {
578 std::vector<Token> activeSuccessors;
579
580 auto token_it = m_vertex.left.find(token);
581 if (token_it == m_vertex.left.end()) {
582 return activeSuccessors;
583 }
584
585 BoostVertex vertex = token_it->second;
586
587 auto [out_edge_iter, out_edge_end] = boost::out_edges(vertex, m_graph);
588 for (auto edge_iter = out_edge_iter; edge_iter != out_edge_end; ++edge_iter) {
589 BoostVertex target_vertex = boost::target(*edge_iter, m_graph);
590
591 auto vertex_token_it = m_vertex.right.find(target_vertex);
592 if (vertex_token_it != m_vertex.right.end()) {
593 Token successor_token = vertex_token_it->second;
594
595 if (hasNode(successor_token)) {
596 activeSuccessors.push_back(successor_token);
597 } else {
598 auto subSuccessors = getActiveSuccessors(successor_token);
599 activeSuccessors.insert(activeSuccessors.end(), subSuccessors.begin(), subSuccessors.end());
600 }
601 }
602 }
603
604 return activeSuccessors;
605 }
606 private:
608 boost::bimap<
609 boost::bimaps::unordered_set_of<Token>,
612 //std::unordered_map<Token,BoostVertex> m_vertex;
613 std::unordered_map<Token, NodeInfo> m_nodeMap;
614 std::vector<Value> m_order;
615 };
616}
617#endif //TOKENGRAPH_H
Noncopyable()=default
NodeProbe(TokenGraph &graph, Token token)
NodeProbe & operator=(const NodeInfo &info)
NodeProbe(const NodeProbe &)=delete
NodeProbe & addSuccessor(const Token &succ)
NodeProbe & addPredecessor(const Token &pred)
NodeProbe & operator=(const NodeProbe &)=delete
const NodeInfo & operator*() const
const NodeInfo * operator->() const
NodeProbe(NodeProbe &&other) noexcept
const Token & token() const
NodeProbe & removePredecessor(const Token &pred)
NodeProbe & removeSuccessor(const Token &succ)
void discover_vertex(VertexDescriptor v, const Graph &g) const
TokenGraphBFSVisitor(const TokenGraph *g, Visitor v, Token start, bool include)
TokenGraphDFSVisitor(const TokenGraph *g, Visitor v)
void discover_vertex(VertexDescriptor v, const Graph &g) const
void addBoostEdge(Token from, Token to)
void addVertex(Token token, int weak_ref=0)
bool hasEdge(Token from, Token to) const
bool hasVertex(Token token) const
void addWeakRef(Token token)
typename TokenGraphSavedBoostGraph::vertex_descriptor BoostVertex
bool isZeroRefVertex(Token token) const
std::vector< Value > m_order
void visitDFSFromRoots(Visitor visitor) const
TokenGraphSavedBoostGraph m_graph
std::unordered_map< Token, NodeInfo > m_nodeMap
NodeProbe operator[](Token token)
void removeEdge(Token node, Token rhs, bool isSuccessor)
std::vector< Token > getActivePredecessors(const Token &token) const
void removeWeakRef(Token token)
void removeWeakRef(Token from, Token to)
std::vector< Value > computeOrder(std::function< bool(const Value &)> canVisit)
void removeNode(const Token &token)
void visitBFS(Token startToken, Visitor visitor, bool includeStart=true) const
void addWeakRef(Token from, Token to)
void addNode(Token token, Value value, std::vector< Token > predecessors, std::vector< Token > successors)
std::vector< Value > order() const
void removeBoostEdge(Token from, Token to)
boost::bimap< boost::bimaps::unordered_set_of< Token >, BoostVertex > m_vertex
boost::adjacency_list< boost::listS, boost::listS, boost::bidirectionalS, int, int > TokenGraphSavedBoostGraph
void addEdge(Token node, Token rhs, bool isSuccessor)
std::vector< Token > getActiveSuccessors(const Token &token) const
bool hasNode(Token token) const
void removeVertex(Token token)
void addNode(NodeInfo info)
void updateNode(const NodeInfo &info)
NodeInfo(Token token, Value value, std::vector< Token > predecessors, std::vector< Token > successors)
NodeInfo(Value value, std::vector< Token > predecessors, std::vector< Token > successors)
std::vector< Token > successors
std::vector< Token > predecessors