1 #ifndef PMPL_CC_TRACKER_H_
2 #define PMPL_CC_TRACKER_H_
6 #include "nonstd/call_on_destruct.h"
12 #include <unordered_map>
13 #include <unordered_set>
35 template <
typename RoadmapType>
43 typedef typename RoadmapType::VID
VID;
118 void SetRoadmap(RoadmapType*
const _r) noexcept;
182 void Print(std::ostream& _os, const std::
string& _indent = {})
const;
220 void RecomputeCCs() noexcept;
237 RoadmapType* m_roadmap{
nullptr};
239 std::unordered_map<VID, VertexSet*> m_vidToCC;
242 mutable std::function<void(
const std::string&)> m_clockStart;
243 mutable std::function<void(
const std::string&)> m_clockStop;
246 std::unordered_map<std::string, CreatedHook> m_createdHooks;
247 std::unordered_map<std::string, DeletedHook> m_deletedHooks;
248 std::unordered_map<std::string, BrokenHook> m_brokenHooks;
249 std::unordered_map<std::string, MergedHook> m_mergedHooks;
252 static constexpr
const bool s_debug =
false;
259 template <
typename RoadmapType>
261 CCTracker(RoadmapType*
const _r) : m_roadmap(_r) {
269 template <
typename RoadmapType>
278 template <
typename RoadmapType>
285 template <
typename RoadmapType>
288 *
this = std::move(_other);
292 template <
typename RoadmapType>
296 m_roadmap = _other.m_roadmap;
297 m_clockStart = _other.m_clockStart;
298 m_clockStop = _other.m_clockStop;
302 m_components.clear();
303 m_components.reserve(_other.m_components.size());
305 m_vidToCC.reserve(_other.m_vidToCC.size());
306 for(
const VertexSet*
const otherCC : _other.m_components) {
308 m_components.insert(myCC);
309 for(
const VID vid : *otherCC) {
311 m_vidToCC.emplace(vid, myCC);
319 template <
typename RoadmapType>
323 m_roadmap = _other.m_roadmap;
324 m_components = std::move(_other.m_components);
326 _other.m_components.clear();
327 m_vidToCC = std::move(_other.m_vidToCC);
328 m_clockStart = std::move(_other.m_clockStart);
329 m_clockStop = std::move(_other.m_clockStop);
336 template <
typename RoadmapType>
345 template <
typename RoadmapType>
352 m_clockStart = [](
const std::string&){};
353 m_clockStop = [](
const std::string&){};
357 m_clockStart = [_stats](
const std::string& _label) {
358 _stats->StartClock(_label);
360 m_clockStop = [_stats](
const std::string& _label) {
361 _stats->StopClock(_label);
367 template <
typename RoadmapType>
372 return m_components.size();
376 template <
typename RoadmapType>
379 GetCC(
const VID _vid)
const noexcept {
385 template <
typename RoadmapType>
390 for(
const VertexSet*
const cc : m_components)
391 representatives.insert(*cc->begin());
392 return representatives;
396 template <
typename RoadmapType>
401 return FindCC(_vid1) == FindCC(_vid2);
406 template <
typename RoadmapType>
410 begin() const noexcept {
411 return m_components.begin();
415 template <
typename RoadmapType>
419 end() const noexcept {
420 return m_components.end();
425 template <
template <
typename...>
class MapType,
typename ValueType,
429 const std::string& _label,
const ValueType& _value) noexcept {
430 if(_map.count(_label))
433 _map.emplace(_label, _value);
437 template <
typename RoadmapType>
445 template <
typename RoadmapType>
453 template <
typename RoadmapType>
461 template <
typename RoadmapType>
469 template <
typename RoadmapType>
477 template <
typename RoadmapType>
486 template <
typename RoadmapType>
489 Print(std::ostream& _os,
const std::string& _indent)
const {
490 _os << _indent <<
"There are " << GetNumCCs() <<
" CCs." << std::endl;
491 for(
const VertexSet*
const cc : m_components)
492 _os << _indent <<
" CC " << cc <<
": " << *cc << std::endl;
497 template <
typename RoadmapType>
504 m_clockStart(
"CCTracker::AddVertex");
505 nonstd::call_on_destruct stopper(m_clockStop,
"CCTracker::AddVertex");
508 const VID vid = _vi->descriptor();
509 if(m_vidToCC.count(vid))
514 m_components.emplace(cc);
515 m_vidToCC.emplace(vid, cc);
518 std::cout <<
"Added vertex " << vid <<
" to new CC " << cc <<
". "
519 <<
"There are now " << GetNumCCs() <<
" CCs."
522 for(
const auto& hook : m_createdHooks)
523 hook.second(
this, cc);
527 template <
typename RoadmapType>
534 m_clockStart(
"CCTracker::DeleteVertex");
535 nonstd::call_on_destruct stopper(m_clockStop,
"CCTracker::DeleteVertex");
539 if(_vi->begin() != _vi->end())
544 const VID vid = _vi->descriptor();
550 <<
" with " << cc->size()
551 <<
" != 1 vertices.";
555 <<
" is missing the query VID. Contents: "
558 for(
const auto& hook : m_deletedHooks)
559 hook.second(
this, cc);
562 m_components.erase(cc);
564 m_vidToCC.erase(vid);
567 std::cout <<
"Deleted vertex " << vid <<
" and CC " << cc <<
"."
569 Print(std::cout,
" ");
576 template <
typename RoadmapType>
585 m_clockStart(
"CCTracker::AddEdge");
586 nonstd::call_on_destruct stopper(m_clockStop,
"CCTracker::AddEdge");
589 const VID sourceVID = (*_ei).source(),
590 targetVID = (*_ei).target();
591 VertexSet*
const sourceCC = FindCC(sourceVID),
592 *
const targetCC = FindCC(targetVID);
595 std::cout <<
"Added edge (" << sourceVID <<
", " << targetVID <<
")."
599 if(sourceCC == targetCC) {
601 std::cout <<
" Vertices are already in the same CC."
608 if(sourceCC->size() < targetCC->size()) {
618 for(
const auto& hook : m_mergedHooks)
619 hook.second(
this, largeCC, smallCC);
622 std::copy(smallCC->begin(), smallCC->end(),
623 std::inserter(*largeCC, largeCC->begin()));
626 for(
const VID vid : *smallCC)
627 m_vidToCC[vid] = largeCC;
630 m_components.erase(smallCC);
634 std::cout <<
" Merged CC " << smallCC <<
" into " << largeCC <<
"."
636 Print(std::cout,
" ");
641 template <
typename RoadmapType>
648 m_clockStart(
"CCTracker::DeleteEdge");
649 nonstd::call_on_destruct stopper(m_clockStop,
"CCTracker::DeleteEdge");
652 const VID source = (*_ei).source(),
653 target = (*_ei).target();
656 std::cout <<
"Deleted edge (" << source <<
", " << target <<
")."
660 VertexSet*
const sourceCC = FindCC(source),
661 *
const targetCC = FindCC(target);
662 if(sourceCC != targetCC) {
664 std::cout <<
" Roadmap has " << m_roadmap->Size() <<
" vertices.\n"
665 <<
" CC from root has " << discovered.size() <<
" vertices:\n"
666 <<
"\t" << discovered
675 const bool exists = m_roadmap->GetEdge(target, source, ei);
678 std::cout <<
" Vertices are still connected (reverse edge exists)."
687 VertexSet discovered = BFS(target, {source});
690 if(discovered.count(source)) {
692 std::cout <<
" Vertices are still connected."
700 m_components.insert(newCC);
701 for(
const VID vid : discovered) {
702 sourceCC->erase(vid);
704 m_vidToCC[vid] = newCC;
708 std::cout <<
" Split off new CC " << newCC <<
" from "
709 << m_vidToCC.at(source) <<
"."
711 Print(std::cout,
" ");
714 for(
const auto& hook : m_brokenHooks)
715 hook.second(
this, sourceCC, newCC);
720 template <
typename RoadmapType>
723 FindCC(
const VID _vid)
const noexcept {
725 auto iter = m_vidToCC.find(_vid);
726 if(iter == m_vidToCC.end())
730 VertexSet*
const cc = iter->second;
731 if(!m_components.count(cc))
738 template <
typename RoadmapType>
742 FindCC(
const VID _vid) noexcept {
747 return const_cast<VertexSet*
>(cc);
751 template <
typename RoadmapType>
761 m_components.clear();
765 std::set<VID> unmappedDescriptors;
766 for(
auto iter = m_roadmap->begin(); iter != m_roadmap->end(); ++iter)
767 unmappedDescriptors.insert(iter->descriptor());
770 while(!unmappedDescriptors.empty()) {
772 const VID current = *unmappedDescriptors.
begin();
773 VertexSet*
const cc =
new VertexSet(BFS(current));
774 m_components.insert(cc);
777 for(
const VID vid : *cc) {
778 unmappedDescriptors.erase(vid);
779 m_vidToCC.emplace(vid, cc);
785 template <
typename RoadmapType>
788 BFS(
const VID _start, VertexSet _goals)
const noexcept {
792 const bool testGoals = !_goals.empty();
795 VertexSet discovered{_start};
796 std::queue<VID> queue;
800 while(!queue.empty()) {
802 const VID current = queue.front();
806 auto vi = m_roadmap->find_vertex(current);
807 for(
auto ei = vi->begin(); ei != vi->end(); ++ei) {
809 const VID child = ei->target();
812 if(discovered.count(child))
814 discovered.insert(child);
817 if(testGoals and _goals.count(child)) {
void MapUniqueInsert(MapType< std::string, ValueType, Rest... > &_map, const std::string &_label, const ValueType &_value) noexcept
Definition: CCTracker.h:428
#define WHERE
Macro for retrieving info about file, function, and line number.
Definition: RuntimeUtils.h:32
Definition: CCTracker.h:36
size_t GetNumCCs() const noexcept
Get the number of connected components in the graph.
Definition: CCTracker.h:371
ComponentSet::const_iterator end() const noexcept
Definition: CCTracker.h:419
void SetRoadmap(RoadmapType *const _r) noexcept
Set the roadmap object.
Definition: CCTracker.h:340
void InstallBrokenHook(const std::string &_label, const BrokenHook &_h)
Definition: CCTracker.h:456
void AddEdge(const edge_iterator _ei) noexcept
Definition: CCTracker.h:579
bool InSameCC(const VID _vid1, const VID _vid2) const noexcept
Definition: CCTracker.h:400
void InstallMergedHook(const std::string &_label, const MergedHook &_h)
Definition: CCTracker.h:464
~CCTracker()
Definition: CCTracker.h:271
void SetStatClass(StatClass *const _stats) const noexcept
Set the stat class pointer if we wish to do performance profiling.
Definition: CCTracker.h:349
std::function< void(const CCTrackerType *const, const VertexSet *const, const VertexSet *const)> MergedHook
Definition: CCTracker.h:85
void AddVertex(const vertex_iterator _vi) noexcept
Definition: CCTracker.h:500
RoadmapType::VID VID
Definition: CCTracker.h:43
void Enable()
Definition: CCTracker.h:480
void DeleteEdge(const edge_iterator _ei) noexcept
Definition: CCTracker.h:644
RoadmapType::adj_edge_iterator edge_iterator
Definition: CCTracker.h:45
std::function< void(const CCTrackerType *const, const VertexSet *const)> CreatedHook
Definition: CCTracker.h:60
std::function< void(const CCTrackerType *const, const VertexSet *const)> DeletedHook
Definition: CCTracker.h:67
ComponentSet::const_iterator begin() const noexcept
Definition: CCTracker.h:410
void InstallCreatedHook(const std::string &_label, const CreatedHook &_h)
Definition: CCTracker.h:440
VertexSet GetRepresentatives() const noexcept
Definition: CCTracker.h:388
std::function< void(const CCTrackerType *const, const VertexSet *const, const VertexSet *const)> BrokenHook
Definition: CCTracker.h:76
void DeleteVertex(const vertex_iterator _vi) noexcept
Definition: CCTracker.h:530
void Print(std::ostream &_os, const std::string &_indent={}) const
Definition: CCTracker.h:489
CCTracker & operator=(const CCTracker &)
Definition: CCTracker.h:295
RoadmapType::VertexSet VertexSet
Definition: CCTracker.h:46
const VertexSet * GetCC(const VID _vid) const noexcept
Definition: CCTracker.h:379
RoadmapType::vertex_iterator vertex_iterator
Definition: CCTracker.h:44
CCTracker< RoadmapType > CCTrackerType
Definition: CCTracker.h:52
void InstallDeletedHook(const std::string &_label, const DeletedHook &_h)
Definition: CCTracker.h:448
CCTracker(RoadmapType *const _r)
Definition: CCTracker.h:261
void Disable()
Definition: CCTracker.h:472
std::unordered_set< VertexSet * > ComponentSet
Definition: CCTracker.h:53
Definition: MetricUtils.h:29
Definition: PMPLExceptions.h:62