mc2lib
sets.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014-2016, Marco Elver
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the
15  * distribution.
16  *
17  * * Neither the name of the software nor the names of its contributors
18  * may be used to endorse or promote products derived from this
19  * software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 #ifndef MC2LIB_SETS_HPP_
35 #define MC2LIB_SETS_HPP_
36 
37 #include <cassert>
38 #include <cstddef>
39 #include <unordered_map>
40 #include <unordered_set>
41 #include <utility>
42 #include <vector>
43 
44 namespace mc2lib {
45 
50 namespace sets {
51 
59 template <class T>
60 inline bool AllBitmask(T mask, T all) {
61  assert(all != 0);
62  return (mask & all) == all;
63 }
64 
72 template <class T>
73 inline bool AnyBitmask(T mask, T any) {
74  assert(any != 0);
75  return (mask & any) != 0;
76 }
77 
84 template <class Ts>
85 class Set {
86  public:
87  typedef typename Ts::Element Element;
88  typedef typename Ts::SetContainer Container;
89 
90  Set() {}
91 
92  explicit Set(Container s) : set_(std::move(s)) {}
93 
99  const Container& get() const { return set_; }
100 
101  bool operator==(const Set& rhs) const { return set_ == rhs.set_; }
102 
103  bool operator!=(const Set& rhs) const { return set_ != rhs.set_; }
104 
112  const Element& Insert(const Element& e, bool assert_unique = false) {
113  auto result = set_.insert(e);
114  assert(!assert_unique || result.second);
115  return *result.first;
116  }
117 
125  const Element& Insert(Element&& e, bool assert_unique = false) {
126  auto result = set_.emplace(std::move(e));
127  assert(!assert_unique || result.second);
128  return *result.first;
129  }
130 
137  bool Erase(const Element& e, bool assert_exists = false) {
138  auto result = set_.erase(e);
139  assert(!assert_exists || result != 0);
140  return result != 0;
141  }
142 
143  template <class FilterFunc>
144  Set Filter(FilterFunc filterFunc) const {
145  Set res;
146 
147  for (const auto& e : set_) {
148  if (filterFunc(e)) {
149  res.Insert(e);
150  }
151  }
152 
153  return res;
154  }
155 
156  void Clear() { set_.clear(); }
157 
158  bool Contains(const Element& e) const { return set_.find(e) != set_.end(); }
159 
163  Set& operator|=(const Set& rhs) {
164  if (this != &rhs) {
165  set_.insert(rhs.set_.begin(), rhs.set_.end());
166  }
167 
168  return *this;
169  }
170 
171  Set& operator|=(Set&& rhs) {
172  if (empty()) {
173  set_ = std::move(rhs.set_);
174  } else {
175  set_.insert(rhs.set_.begin(), rhs.set_.end());
176  }
177 
178  return *this;
179  }
180 
184  Set& operator-=(const Set& rhs) {
185  if (this == &rhs) {
186  Clear();
187  } else {
188  // Cannot use set_.erase with iterator, as rhs may contain elements
189  // that do not exist in this set. In such a case, the erase
190  // implementation of current GCC segfaults.
191  for (const auto& e : rhs.get()) {
192  Erase(e);
193  }
194  }
195 
196  return *this;
197  }
198 
202  Set& operator&=(const Set& rhs) {
203  if (this != &rhs) {
204  for (auto it = set_.begin(); it != set_.end();) {
205  if (!rhs.Contains(*it)) {
206  it = set_.erase(it);
207  continue;
208  }
209 
210  it++;
211  }
212  }
213 
214  return *this;
215  }
216 
217  std::size_t size() const { return set_.size(); }
218 
219  bool empty() const { return set_.empty(); }
220 
221  bool SubsetEq(const Set& s) const {
222  if (size() > s.size()) return false;
223 
224  for (const auto& e : set_) {
225  if (!s.Contains(e)) {
226  return false;
227  }
228  }
229 
230  return true;
231  }
232 
233  bool Subset(const Set& s) const { return size() < s.size() && SubsetEq(s); }
234 
235  protected:
236  Container set_;
237 };
238 
239 template <class Ts>
240 inline Set<Ts> operator|(const Set<Ts>& lhs, const Set<Ts>& rhs) {
241  Set<Ts> res = lhs;
242  return res |= rhs;
243 }
244 
245 template <class Ts>
246 inline Set<Ts> operator|(Set<Ts>&& lhs, const Set<Ts>& rhs) {
247  lhs |= rhs;
248  return std::move(lhs);
249 }
250 
251 template <class Ts>
252 inline Set<Ts> operator|(const Set<Ts>& lhs, Set<Ts>&& rhs) {
253  rhs |= lhs;
254  return std::move(rhs);
255 }
256 
257 template <class Ts>
258 inline Set<Ts> operator|(Set<Ts>&& lhs, Set<Ts>&& rhs) {
259  lhs |= rhs;
260  return std::move(lhs);
261 }
262 
263 template <class Ts>
264 inline Set<Ts> operator-(const Set<Ts>& lhs, const Set<Ts>& rhs) {
265  Set<Ts> res = lhs;
266  return res -= rhs;
267 }
268 
269 template <class Ts>
270 inline Set<Ts> operator-(Set<Ts>&& lhs, const Set<Ts>& rhs) {
271  lhs -= rhs;
272  return std::move(lhs);
273 }
274 
275 template <class Ts>
276 inline Set<Ts> operator-(const Set<Ts>& lhs, Set<Ts>&& rhs) {
277  Set<Ts> res = lhs;
278  return res -= rhs;
279 }
280 
281 template <class Ts>
282 inline Set<Ts> operator-(Set<Ts>&& lhs, Set<Ts>&& rhs) {
283  lhs -= rhs;
284  return std::move(lhs);
285 }
286 
287 template <class Ts>
288 inline Set<Ts> operator&(const Set<Ts>& lhs, const Set<Ts>& rhs) {
289  Set<Ts> res;
290 
291  for (const auto& e : rhs.get()) {
292  if (lhs.Contains(e)) {
293  res.Insert(e);
294  }
295  }
296 
297  return res;
298 }
299 
300 template <class Ts>
301 inline Set<Ts> operator&(Set<Ts>&& lhs, const Set<Ts>& rhs) {
302  lhs &= rhs;
303  return std::move(lhs);
304 }
305 
306 template <class Ts>
307 inline Set<Ts> operator&(const Set<Ts>& lhs, Set<Ts>&& rhs) {
308  rhs &= lhs;
309  return std::move(rhs);
310 }
311 
312 template <class Ts>
313 inline Set<Ts> operator&(Set<Ts>&& lhs, Set<Ts>&& rhs) {
314  lhs &= rhs;
315  return std::move(lhs);
316 }
317 
318 template <class Ts>
319 class Relation {
320  public:
321  typedef typename Ts::Element Element;
322 
323  typedef typename Ts::template MapContainer<Set<Ts>> Container;
324 
325  typedef std::pair<Element, Element> Tuple;
326 
327  typedef std::vector<Element> Path;
328 
335  typedef unsigned Properties;
336 
337  // Properties {{{
338 
339  static constexpr Properties kNone = 0x0;
340  static constexpr Properties kTransitiveClosure = 0x1;
341  static constexpr Properties kReflexiveClosure = 0x2;
342  static constexpr Properties kReflexiveTransitiveClosure =
343  kTransitiveClosure | kReflexiveClosure;
344 
345  // }}}
346 
347  Relation() : props_(kNone) {}
348 
349  explicit Relation(Container r) : props_(kNone), rel_(std::move(r)) {}
350 
355  const Container& get() const { return rel_; }
356 
357  Properties props() const { return props_; }
358 
359  Relation& set_props(Properties props) {
360  props_ = props;
361  return *this;
362  }
363 
364  Relation& add_props(Properties props) {
365  props_ |= props;
366  return *this;
367  }
368 
369  Relation& unset_props(Properties props) {
370  props_ &= ~props;
371  return *this;
372  }
373 
374  bool all_props(Properties all) const { return AllBitmask(props_, all); }
375 
376  bool any_props(Properties any) const { return AnyBitmask(props_, any); }
377 
378  Properties clear_props() {
379  const auto props = props_;
380  props_ = kNone;
381  return props;
382  }
383 
384  void Insert(const Element& e1, const Element& e2,
385  bool assert_unique = false) {
386  rel_[e1].Insert(e2, assert_unique);
387  }
388 
389  void Insert(const Element& e1, Element&& e2, bool assert_unique = false) {
390  rel_[e1].Insert(std::move(e2), assert_unique);
391  }
392 
393  void Insert(const Element& e1, const Set<Ts>& e2s) {
394  if (e2s.empty()) return;
395  rel_[e1] |= e2s;
396  }
397 
398  void Insert(const Element& e1, Set<Ts>&& e2s) {
399  if (e2s.empty()) return;
400  rel_[e1] |= std::move(e2s);
401  }
402 
403  bool Erase(const Element& e1, const Element& e2, bool assert_exists = false) {
404  // May not work as expect if kReflexiveClosure is set.
405  if (Contains__(e1)) {
406  bool result = rel_[e1].Erase(e2, assert_exists);
407 
408  if (rel_[e1].empty()) {
409  rel_.erase(e1);
410  }
411 
412  return result;
413  }
414 
415  return false;
416  }
417 
418  void Erase(const Element& e1, const Set<Ts>& e2s) {
419  if (Contains__(e1)) {
420  rel_[e1] -= e2s;
421 
422  if (rel_[e1].empty()) {
423  rel_.erase(e1);
424  }
425  }
426  }
427 
434  std::size_t size() const {
435  std::size_t total = 0;
436 
437  if (props()) {
438  const auto dom = Domain();
439  for (const auto& e : dom.get()) {
440  total += Reachable(e).size();
441  }
442  } else {
443  for (const auto& tuples : rel_) {
444  total += tuples.second.size();
445  }
446  }
447 
448  return total;
449  }
450 
456  template <class Func>
457  Func for_each(Func func) const {
458  const auto dom = Domain();
459 
460  for (const auto& e1 : dom.get()) {
461  const auto reach = Reachable(e1);
462  for (const auto& e2 : reach.get()) {
463  func(e1, e2);
464  }
465  }
466 
467  return std::move(func);
468  }
469 
475  Relation Eval() const {
476  if (props() == kNone) {
477  return *this;
478  }
479 
480  Relation result;
481 
482  for_each([&result](const Element& e1, const Element& e2) {
483  result.Insert(e1, e2);
484  });
485 
486  return result;
487  }
488 
495  if (props() == kNone) {
496  return *this;
497  }
498 
499  Relation result;
500 
501  for_each([&result](const Element& e1, const Element& e2) {
502  result.Insert(e1, e2);
503  });
504 
505  clear_props();
506  rel_ = std::move(result.rel_);
507  return *this;
508  }
509 
510  template <class FilterFunc>
511  Relation Filter(FilterFunc filterFunc) const {
512  Relation result;
513 
514  for_each([&filterFunc, &result](const Element& e1, const Element& e2) {
515  if (filterFunc(e1, e2)) {
516  result.Insert(e1, e2);
517  }
518  });
519 
520  return result;
521  }
522 
526  Relation Inverse() const {
527  Relation result;
528 
529  for_each([&result](const Element& e1, const Element& e2) {
530  result.Insert(e2, e1);
531  });
532 
533  return result;
534  }
535 
539  Relation& operator|=(const Relation& rhs) {
540  EvalInplace();
541 
542  if (rhs.props()) {
543  const auto rhs_domain = rhs.Domain();
544  for (const auto& e : rhs_domain.get()) {
545  rel_[e] |= rhs.Reachable(e);
546  }
547  } else {
548  for (const auto& tuples : rhs.get()) {
549  rel_[tuples.first] |= tuples.second;
550  }
551  }
552 
553  return *this;
554  }
555 
559  Relation& operator-=(const Relation& rhs) {
560  EvalInplace();
561 
562  if (rhs.props()) {
563  const auto rhs_domain = rhs.Domain();
564  for (const auto& e : rhs_domain.get()) {
565  Erase(e, rhs.Reachable(e));
566  }
567  } else {
568  for (const auto& tuples : rhs.get()) {
569  Erase(tuples.first, tuples.second);
570  }
571  }
572 
573  return *this;
574  }
575 
579  Relation& operator&=(const Relation& rhs) {
580  EvalInplace();
581 
582  for (auto it = rel_.begin(); it != rel_.end();) {
583  it->second &= rhs.Reachable(it->first);
584 
585  if (it->second.empty()) {
586  it = rel_.erase(it);
587  continue;
588  }
589 
590  it++;
591  }
592 
593  return *this;
594  }
595 
596  void Clear() { rel_.clear(); }
597 
598  bool empty() const {
599  // Upon erasure, we ensure that an element is not related to an empty
600  // set, i.e. in that case it is deleted.
601  return rel_.empty();
602  }
603 
604  bool operator==(const Relation& rhs) const {
605  return (props() ? Eval() : *this).rel_ ==
606  (rhs.props() ? rhs.Eval() : rhs).rel_;
607  }
608 
609  bool operator!=(const Relation& rhs) const { return !((*this) == rhs); }
610 
620  bool R(const Element& e1, const Element& e2, Path* path = nullptr) const {
621  if (e1 == e2 && all_props(kReflexiveClosure)) {
622  if (InOn(e1)) {
623  if (path != nullptr) {
624  path->push_back(e1);
625  path->push_back(e1);
626  }
627 
628  return true;
629  }
630  }
631 
632  Set<Ts> visited;
633 
634  if (path != nullptr) {
635  FlagSet visiting;
636 
637  bool result = R_search(e1, &e2, &visited, &visiting);
638  if (result) {
639  GetPath(path, &e1, &e2, &visiting);
640  }
641 
642  return result;
643  }
644 
645  return R_search(e1, &e2, &visited);
646  }
647 
656  Set<Ts> Reachable(const Element& e) const {
657  Set<Ts> visited;
658 
659  if (all_props(kReflexiveClosure) && InOn(e)) {
660  visited.Insert(e);
661  }
662 
663  if (!all_props(kTransitiveClosure)) {
664  const auto tuples = rel_.find(e);
665  if (tuples != rel_.end()) {
666  visited |= tuples->second;
667  }
668 
669  return visited;
670  }
671 
672  if (!R_search(e, &e, &visited, nullptr, kNone,
673  SearchMode::kRelatedVisitAll)) {
674  if (!all_props(kReflexiveClosure)) {
675  visited.Erase(e);
676  }
677  }
678 
679  return visited;
680  }
681 
682  bool Irreflexive(Path* cyclic = nullptr) const {
683  return Irreflexive(kNone, cyclic);
684  }
685 
686  bool Acyclic(Path* cyclic = nullptr) const {
687  return Irreflexive(kTransitiveClosure, cyclic);
688  }
689 
693  bool Transitive() const {
694  if (all_props(kTransitiveClosure)) {
695  return true;
696  }
697 
698  for (const auto& tuples1 : rel_) {
699  for (const auto& e1 : tuples1.second.get()) {
700  const auto tuples2 = rel_.find(e1);
701  if (tuples2 != rel_.end()) {
702  for (const auto& e2 : tuples2->second.get()) {
703  if (!R(tuples1.first, e2)) {
704  return false;
705  }
706  }
707  }
708  }
709  }
710 
711  return true;
712  }
713 
717  bool TotalOn(const Set<Ts>& on) const {
718  for (const auto& e1 : on.get()) {
719  for (const auto& e2 : on.get()) {
720  if (!R(e1, e2) && !R(e2, e1)) {
721  return false;
722  }
723  }
724  }
725 
726  return true;
727  }
728 
732  bool ConnexOn(const Set<Ts>& on) const {
733  for (const auto& e1 : on.get()) {
734  for (const auto& e2 : on.get()) {
735  if (e1 != e2 && !R(e1, e2) && !R(e2, e1)) {
736  return false;
737  }
738  }
739  }
740 
741  return true;
742  }
743 
744  bool WeakPartialOrder(const Set<Ts>& on) const {
745  // (domain ∪ range) in on
746  for (const auto& tuples : rel_) {
747  if (!on.Contains(tuples.first) && !tuples.second.SubsetEq(on)) {
748  return false;
749  }
750  }
751 
752  return Transitive() && !Irreflexive();
753  }
754 
755  bool WeakTotalOrder(const Set<Ts>& on) const {
756  return WeakPartialOrder(on) && TotalOn(on);
757  }
758 
759  bool StrictPartialOrder(const Set<Ts>& on) const {
760  // (domain ∪ range) in on
761  for (const auto& tuples : rel_) {
762  if (!on.Contains(tuples.first) && !tuples.second.SubsetEq(on)) {
763  return false;
764  }
765  }
766 
767  return Transitive() && Irreflexive();
768  }
769 
770  bool StrictTotalOrder(const Set<Ts>& on) const {
771  return StrictPartialOrder(on) && ConnexOn(on);
772  }
773 
774  bool InOn(const Element& e) const {
775  if (Contains__(e)) {
776  return true;
777  } else {
778  for (const auto& tuples : rel_) {
779  if (tuples.second.Contains(e)) {
780  return true;
781  }
782  }
783  }
784 
785  return false;
786  }
787 
788  bool InDomain(const Element& e) const {
789  if (all_props(kReflexiveClosure)) {
790  return InOn(e);
791  }
792 
793  return Contains__(e);
794  }
795 
796  bool InRange(const Element& e) const {
797  if (all_props(kReflexiveClosure)) {
798  return InOn(e);
799  }
800 
801  for (const auto& tuples : rel_) {
802  if (Reachable(tuples.first).Contains(e)) {
803  return true;
804  }
805  }
806 
807  return false;
808  }
809 
810  Set<Ts> On() const {
811  Set<Ts> res;
812  for (const auto& tuples : rel_) {
813  res.Insert(tuples.first);
814  res |= tuples.second;
815  }
816  return res;
817  }
818 
819  Set<Ts> Domain() const {
820  if (all_props(kReflexiveClosure)) {
821  // By the fact that the reflexive closure is
822  // R ∪ {(x,x). x ∈ S}, where S is the set the relation is on, and
823  // thus S contains both the range and domain, constructing the
824  // above will yield domain = range = S under the reflexive closure.
825  return On();
826  }
827 
828  Set<Ts> res;
829  for (const auto& tuples : rel_) {
830  res.Insert(tuples.first);
831  }
832 
833  return res;
834  }
835 
836  Set<Ts> Range() const {
837  if (all_props(kReflexiveClosure)) {
838  // See above.
839  return On();
840  }
841 
842  Set<Ts> res;
843  for (const auto& tuples : rel_) {
844  res |= Reachable(tuples.first);
845  }
846 
847  return res;
848  }
849 
850  bool SubsetEq(const Relation& rhs) const {
851  const Relation diff = (*this - rhs);
852  return diff.empty();
853  }
854 
855  bool Subset(const Relation& rhs) const {
856  return size() < rhs.size() && SubsetEq(rhs);
857  }
858 
859  protected:
860  typedef typename Ts::template MapContainer<bool> FlagSet;
861 
865  enum class SearchMode {
869  kRelated,
870 
874  kRelatedVisitAll,
875 
879  kFindCycle
880  };
881 
885  bool Contains__(const Element& e) const { return rel_.find(e) != rel_.end(); }
886 
890  void GetPath(Path* out, const Element* start, const Element* end,
891  FlagSet* visiting,
892  SearchMode mode = SearchMode::kRelated) const {
893  assert(out != nullptr && start != nullptr && visiting != nullptr);
894 
895  out->push_back(*start);
896  (*visiting)[*start] = false;
897 
898  while (start != nullptr) {
899  const Set<Ts>& next = rel_.find(*start)->second;
900  start = nullptr;
901 
902  for (const auto& e : next.get()) {
903  const auto se = visiting->find(e);
904  if (se != visiting->end() && se->second) {
905  out->push_back(e);
906  se->second = false;
907  start = &e;
908  break;
909  }
910  }
911  }
912 
913  const Set<Ts>& next = rel_.find(out->back())->second;
914  if (mode == SearchMode::kFindCycle) {
915  assert(end == nullptr);
916 
917  for (const auto& e : *out) {
918  if (next.Contains(e)) {
919  // Final edge
920  out->push_back(e);
921  break;
922  }
923  }
924  } else {
925  assert(end != nullptr);
926 
927  // This function should only be called if search established there
928  // is a path between start->end.
929  assert(next.Contains(*end));
930 
931  out->push_back(*end);
932  }
933  }
934 
943  bool Irreflexive(Properties local_props, Path* cyclic) const {
944  local_props |= props_;
945 
946  if (AllBitmask(local_props, kReflexiveClosure) && !empty()) {
947  if (cyclic != nullptr) {
948  // Pick arbitrary.
949  cyclic->push_back(rel_.begin()->first);
950  cyclic->push_back(rel_.begin()->first);
951  }
952 
953  return false;
954  }
955 
956  Set<Ts> visited;
957  FlagSet visiting;
958 
959  for (const auto& tuples : rel_) {
960  if (R_search(tuples.first, nullptr, &visited, &visiting, local_props,
961  SearchMode::kFindCycle)) {
962  if (cyclic != nullptr) {
963  GetPath(cyclic, &tuples.first, nullptr, &visiting,
964  SearchMode::kFindCycle);
965  }
966 
967  return false;
968  }
969  }
970 
971  return true;
972  }
973 
987  bool R_search(const Element& e1, const Element* e2, Set<Ts>* visited,
988  FlagSet* visiting = nullptr, Properties local_props = kNone,
989  SearchMode mode = SearchMode::kRelated) const {
990  // We always require visited to be set.
991  assert(visited != nullptr);
992 
993  // Merge call-specific props with global props.
994  local_props |= props_;
995 
996  const bool is_tran_cl = AllBitmask(local_props, kTransitiveClosure);
997 
998  R_impl search(this, visited, visiting, is_tran_cl, mode);
999 
1000  if (e2 == nullptr) {
1001  // For the purpose of cycle detection, we are looking for e1->*e1.
1002  // In addition, if the transitive property is set, we require that
1003  // visiting is provided, as we cannot make assumptions on if visited
1004  // is reset before every call -- and for performance reasons, this
1005  // usage is discouraged.
1006 
1007  assert(mode == SearchMode::kFindCycle);
1008 
1009  e2 = &e1;
1010 
1011  if (is_tran_cl) {
1012  assert(visiting != nullptr);
1013  return search.DfsRecFindCycle(e1);
1014  }
1015  } else {
1016  assert(mode != SearchMode::kFindCycle);
1017  }
1018 
1019  return search.DfsRec(e1, *e2);
1020  }
1021 
1025  class R_impl {
1026  public:
1027  R_impl(const Relation* src, Set<Ts>* visited, FlagSet* visiting,
1028  bool is_tran_cl, SearchMode mode)
1029  : src_(src),
1030  visited_(visited),
1031  visiting_(visiting),
1032  is_tran_cl_(is_tran_cl),
1033  mode_(mode) {}
1034 
1039  bool DfsRec(const Element& e1, const Element& e2) const {
1040  const auto tuples = src_->get().find(e1);
1041 
1042  if (tuples == src_->get().end()) {
1043  return false;
1044  }
1045 
1046  if (visiting_ != nullptr) {
1047  (*visiting_)[e1] = true;
1048  }
1049 
1050  bool result = false;
1051  visited_->Insert(e1);
1052 
1053  for (const auto& e : tuples->second.get()) {
1054  if (e == e2) {
1055  if (mode_ == SearchMode::kRelatedVisitAll) {
1056  result = true;
1057  } else {
1058  return true;
1059  }
1060  }
1061 
1062  if (is_tran_cl_) {
1063  if (!visited_->Contains(e)) {
1064  if (DfsRec(e, e2)) {
1065  if (mode_ == SearchMode::kRelatedVisitAll) {
1066  result = true;
1067  } else {
1068  return true;
1069  }
1070  }
1071 
1072  // There might not be an edge e -> e2, but we must update
1073  // the visited set regardless -- this is only relevant, as
1074  // the caller might expect the complete set of visited
1075  // nodes if mode == RelatedVisitAll.
1076  visited_->Insert(e);
1077  } else {
1078  // assert(mode_ != SearchMode::kFindCycle);
1079  }
1080  }
1081  }
1082 
1083  if (visiting_ != nullptr) {
1084  (*visiting_)[e1] = false;
1085  }
1086 
1087  return result;
1088  }
1089 
1094  bool DfsRecFindCycle(const Element& start) const {
1095  // assert(is_tran_cl_);
1096  // assert(mode_ == SearchMode::kFindCycle);
1097  // assert(visiting_ != nullptr);
1098 
1099  const auto tuples = src_->get().find(start);
1100 
1101  if (tuples == src_->get().end()) {
1102  return false;
1103  }
1104 
1105  (*visiting_)[start] = true;
1106  visited_->Insert(start);
1107 
1108  for (const auto& e : tuples->second.get()) {
1109  if (!visited_->Contains(e)) {
1110  if (DfsRecFindCycle(e)) {
1111  return true;
1112  }
1113  } else {
1114  const auto se = visiting_->find(e);
1115  if (se != visiting_->end() && se->second) {
1116  // Found a backedge --> cycle!
1117  return true;
1118  }
1119  }
1120  }
1121 
1122  (*visiting_)[start] = false;
1123  return false;
1124  }
1125 
1126  private:
1127  const Relation* src_;
1129  FlagSet* visiting_;
1132  };
1133 
1134  protected:
1135  Properties props_;
1136  Container rel_;
1137 };
1138 
1139 template <class Ts>
1140 inline Relation<Ts> operator*(const Set<Ts>& lhs, const Set<Ts>& rhs) {
1141  Relation<Ts> res;
1142 
1143  for (const auto& e1 : lhs.get()) {
1144  for (const auto& e2 : rhs.get()) {
1145  res.Insert(e1, e2);
1146  }
1147  }
1148 
1149  return res;
1150 }
1151 
1152 template <class Ts>
1154  const Relation<Ts>& rhs) {
1155  Relation<Ts> res = lhs;
1156  return res |= rhs;
1157 }
1158 
1159 template <class Ts>
1161  lhs |= rhs;
1162  return std::move(lhs);
1163 }
1164 
1165 template <class Ts>
1167  rhs |= lhs;
1168  return std::move(rhs);
1169 }
1170 
1171 template <class Ts>
1173  lhs |= rhs;
1174  return std::move(lhs);
1175 }
1176 
1177 template <class Ts>
1179  const Relation<Ts>& rhs) {
1180  Relation<Ts> res = lhs;
1181  return res -= rhs;
1182 }
1183 
1184 template <class Ts>
1186  lhs -= rhs;
1187  return std::move(lhs);
1188 }
1189 
1190 template <class Ts>
1192  Relation<Ts> res = lhs;
1193  return res -= rhs;
1194 }
1195 
1196 template <class Ts>
1198  lhs -= rhs;
1199  return std::move(lhs);
1200 }
1201 
1202 template <class Ts>
1204  const Relation<Ts>& rhs) {
1205  Relation<Ts> res;
1206 
1207  const auto lhs_domain = lhs.Domain();
1208  for (const auto& e : lhs_domain.get()) {
1209  Set<Ts> intersect = lhs.Reachable(e) & rhs.Reachable(e);
1210  // insert checks if empty or not
1211  res.Insert(e, std::move(intersect));
1212  }
1213 
1214  return res;
1215 }
1216 
1217 template <class Ts>
1219  lhs &= rhs;
1220  return std::move(lhs);
1221 }
1222 
1223 template <class Ts>
1225  rhs &= lhs;
1226  return std::move(rhs);
1227 }
1228 
1229 template <class Ts>
1231  lhs &= rhs;
1232  return std::move(lhs);
1233 }
1234 
1239 template <class Ts>
1240 class RelationOp {
1241  public:
1243 
1244  explicit RelationOp(std::vector<Relation<Ts>> rels)
1245  : rels_(std::move(rels)) {}
1246 
1247  /*//virtual ~RelationOp()
1248  *
1249  * No destructor, so compiler can implicitly create move constructor and
1250  * assignment operators.
1251  */
1252 
1260  virtual RelationOp& EvalInplace() = 0;
1261 
1267  virtual Relation<Ts> Eval() const = 0;
1268 
1269  void Clear() { rels_.clear(); }
1270 
1279  if (rels_.empty()) {
1280  // Already cleared
1281  return Relation<Ts>();
1282  }
1283 
1284  EvalInplace();
1285  assert(rels_.size() == 1);
1286 
1287  Relation<Ts> result = std::move(rels_.back());
1288  rels_.clear();
1289  return result; // NRVO
1290  }
1291 
1292  protected:
1293  void Add(const Relation<Ts>& er) { rels_.push_back(er); }
1294 
1295  void Add(Relation<Ts>&& er) { rels_.push_back(std::move(er)); }
1296 
1297  void Add(const std::vector<Relation<Ts>>& rels) {
1298  rels_.reserve(rels_.size() + rels.size());
1299  rels_.insert(rels_.end(), rels.begin(), rels.end());
1300  }
1301 
1302  protected:
1303  std::vector<Relation<Ts>> rels_;
1304 };
1305 
1309 template <class Ts>
1310 class RelationSeq : public RelationOp<Ts> {
1311  public:
1312  typedef typename Ts::Element Element;
1313 
1315 
1316  explicit RelationSeq(std::vector<Relation<Ts>> v)
1317  : RelationOp<Ts>(std::move(v)) {}
1318 
1320  this->Add(rhs);
1321  return *this;
1322  }
1323 
1325  this->Add(std::move(rhs));
1326  return *this;
1327  }
1328 
1330  this->Add(rhs.rels_);
1331  return *this;
1332  }
1333 
1335  while (this->rels_.size() > 1) {
1336  std::size_t from_idx = this->rels_.size() - 2;
1337  const auto& first = this->rels_[from_idx];
1338  const auto& last = this->rels_.back();
1339 
1340  Relation<Ts> er;
1341 
1342  first.for_each([&er, &last](const Element& e1, const Element& e2) {
1343  if (last.InDomain(e2)) {
1344  er.Insert(e1, last.Reachable(e2));
1345  }
1346  });
1347 
1348  this->rels_.erase(this->rels_.end() - 2, this->rels_.end());
1349  this->rels_.push_back(std::move(er));
1350  }
1351 
1352  return *this;
1353  }
1354 
1355  Relation<Ts> Eval() const override {
1356  Relation<Ts> er;
1357 
1358  if (this->rels_.empty()) {
1359  return Relation<Ts>();
1360  } else if (this->rels_.size() == 1) {
1361  return this->rels_.back();
1362  }
1363 
1364  const auto potential_domain = this->rels_.front().Domain();
1365  const auto potential_range = this->rels_.back().Range();
1366 
1367  for (const auto& e1 : potential_domain.get()) {
1368  for (const auto& e2 : potential_range.get()) {
1369  if (R(e1, e2)) {
1370  er.Insert(e1, e2);
1371  }
1372  }
1373  }
1374 
1375  return er;
1376  }
1377 
1387  bool R(const Element& e1, const Element& e2,
1388  typename Relation<Ts>::Path* path = nullptr,
1389  std::size_t seq = 0) const {
1390  if (this->rels_.empty()) {
1391  return false;
1392  }
1393 
1394  assert(seq < this->rels_.size());
1395 
1396  if (seq + 1 < this->rels_.size()) {
1397  const auto& rel = this->rels_[seq];
1398  std::size_t path_size = 0;
1399 
1400  const Set<Ts> reach = rel.Reachable(e1);
1401  for (const auto& e : reach.get()) {
1402  if (path != nullptr) {
1403  path_size = path->size();
1404  rel.R(e1, e, path); // true
1405  path->pop_back(); // remove e
1406  }
1407 
1408  if (R(e, e2, path, seq + 1)) {
1409  return true;
1410  }
1411 
1412  if (path != nullptr) {
1413  // e not connected to e2, remove all up to e1 (inclusive).
1414  assert(path_size < path->size());
1415  path->erase(path->begin() + path_size, path->end());
1416  }
1417  }
1418 
1419  return false;
1420  }
1421 
1422  return this->rels_[seq].R(e1, e2, path);
1423  }
1424 
1432  bool Irreflexive(typename Relation<Ts>::Path* cyclic = nullptr) const {
1433  if (this->rels_.empty()) {
1434  return true;
1435  }
1436 
1437  const auto domain = this->rels_.front().Domain();
1438  for (const auto& e : domain.get()) {
1439  if (R(e, e, cyclic)) {
1440  return false;
1441  }
1442  }
1443 
1444  return true;
1445  }
1446 };
1447 
1448 template <class Ts>
1450  const Relation<Ts>& rhs) {
1451  RelationSeq<Ts> res = lhs;
1452  return res += rhs;
1453 }
1454 
1455 template <class Ts>
1457  const Relation<Ts>& rhs) {
1458  lhs += rhs;
1459  return std::move(lhs);
1460 }
1461 
1462 template <class Ts>
1464  Relation<Ts>&& rhs) {
1465  RelationSeq<Ts> res = lhs;
1466  return res += std::move(rhs);
1467 }
1468 
1469 template <class Ts>
1471  lhs += std::move(rhs);
1472  return std::move(lhs);
1473 }
1474 
1475 template <class Ts>
1477  const RelationSeq<Ts>& rhs) {
1478  RelationSeq<Ts> res = lhs;
1479  return res += rhs;
1480 }
1481 
1482 template <class Ts>
1484  const RelationSeq<Ts>& rhs) {
1485  lhs += rhs;
1486  return std::move(lhs);
1487 }
1488 
1489 template <class Ts>
1491  RelationSeq<Ts>&& rhs) {
1492  RelationSeq<Ts> res = lhs;
1493  return res += rhs;
1494 }
1495 
1496 template <class Ts>
1498  lhs += rhs;
1499  return std::move(lhs);
1500 }
1501 
1509 template <class E, class Hash = typename E::Hash>
1510 struct Types {
1511  typedef E Element;
1512 
1513  typedef std::unordered_set<Element, Hash> SetContainer;
1514 
1515  template <class T>
1516  using MapContainer = std::unordered_map<Element, T, Hash>;
1517 };
1518 
1519 } // namespace sets
1520 } // namespace mc2lib
1521 
1522 #endif /* MC2LIB_SETS_HPP_ */
1523 
1524 /* vim: set ts=2 sts=2 sw=2 et : */
bool StrictPartialOrder(const Set< Ts > &on) const
Definition: sets.hpp:759
std::unordered_map< Element, T, std::hash< types::Addr > > MapContainer
Definition: sets.hpp:1516
bool AnyBitmask(T mask, T any)
Definition: sets.hpp:73
Set< Ts > operator &(const Set< Ts > &lhs, const Set< Ts > &rhs)
Definition: sets.hpp:288
bool InDomain(const Element &e) const
Definition: sets.hpp:788
RelationOp< Ts > & EvalInplace() override
Definition: sets.hpp:1334
bool Transitive() const
Definition: sets.hpp:693
bool operator==(const Set &rhs) const
Definition: sets.hpp:101
Helper class to instantiate types used by Set, Relation, etc.
Definition: sets.hpp:1510
bool Irreflexive(Path *cyclic=nullptr) const
Definition: sets.hpp:682
const Relation * src_
Definition: sets.hpp:1127
bool DfsRecFindCycle(const Element &start) const
Definition: sets.hpp:1094
bool WeakTotalOrder(const Set< Ts > &on) const
Definition: sets.hpp:755
Set< Ts > operator|(const Set< Ts > &lhs, const Set< Ts > &rhs)
Definition: sets.hpp:240
bool operator==(const Relation &rhs) const
Definition: sets.hpp:604
void Add(const Relation< Ts > &er)
Definition: sets.hpp:1293
void Insert(const Element &e1, Set< Ts > &&e2s)
Definition: sets.hpp:398
RelationOp()
Definition: sets.hpp:1242
std::unordered_set< Element, Hash > SetContainer
Definition: sets.hpp:1513
Set< Ts > Range() const
Definition: sets.hpp:836
Set< Ts > Reachable(const Element &e) const
Definition: sets.hpp:656
Properties clear_props()
Definition: sets.hpp:378
bool InOn(const Element &e) const
Definition: sets.hpp:774
Ts::SetContainer Container
Definition: sets.hpp:88
Definition: cats.hpp:47
bool SubsetEq(const Relation &rhs) const
Definition: sets.hpp:850
Set & operator &=(const Set &rhs)
Definition: sets.hpp:202
std::size_t size() const
Definition: sets.hpp:217
Set & operator-=(const Set &rhs)
Definition: sets.hpp:184
Relation Inverse() const
Definition: sets.hpp:526
Set< Ts > operator-(const Set< Ts > &lhs, const Set< Ts > &rhs)
Definition: sets.hpp:264
bool operator!=(const Relation &rhs) const
Definition: sets.hpp:609
Container rel_
Definition: sets.hpp:1136
Relation< Ts > operator*(const Set< Ts > &lhs, const Set< Ts > &rhs)
Definition: sets.hpp:1140
RelationOp(std::vector< Relation< Ts >> rels)
Definition: sets.hpp:1244
bool R_search(const Element &e1, const Element *e2, Set< Ts > *visited, FlagSet *visiting=nullptr, Properties local_props=kNone, SearchMode mode=SearchMode::kRelated) const
Definition: sets.hpp:987
Properties props() const
Definition: sets.hpp:357
void Add(Relation< Ts > &&er)
Definition: sets.hpp:1295
void Erase(const Element &e1, const Set< Ts > &e2s)
Definition: sets.hpp:418
RelationSeq< Ts > operator+(const RelationSeq< Ts > &lhs, const Relation< Ts > &rhs)
Definition: sets.hpp:1449
const Element & Insert(const Element &e, bool assert_unique=false)
Definition: sets.hpp:112
bool Erase(const Element &e1, const Element &e2, bool assert_exists=false)
Definition: sets.hpp:403
Set & operator|=(Set &&rhs)
Definition: sets.hpp:171
bool Irreflexive(typename Relation< Ts >::Path *cyclic=nullptr) const
Definition: sets.hpp:1432
Set & operator|=(const Set &rhs)
Definition: sets.hpp:163
std::vector< Element > Path
Definition: sets.hpp:327
Set< Ts > On() const
Definition: sets.hpp:810
bool AllBitmask(T mask, T all)
Definition: sets.hpp:60
std::pair< Element, Element > Tuple
Definition: sets.hpp:325
bool empty() const
Definition: sets.hpp:598
Definition: sets.hpp:1240
bool ConnexOn(const Set< Ts > &on) const
Definition: sets.hpp:732
Ts::template MapContainer< Set< Ts > > Container
Definition: sets.hpp:323
RelationSeq()
Definition: sets.hpp:1314
unsigned Properties
Definition: sets.hpp:335
Relation & operator &=(const Relation &rhs)
Definition: sets.hpp:579
Set< Ts > * visited_
Definition: sets.hpp:1128
RelationSeq & operator+=(const Relation< Ts > &rhs)
Definition: sets.hpp:1319
bool Irreflexive(Properties local_props, Path *cyclic) const
Definition: sets.hpp:943
std::size_t size() const
Definition: sets.hpp:434
RelationSeq(std::vector< Relation< Ts >> v)
Definition: sets.hpp:1316
Func for_each(Func func) const
Definition: sets.hpp:457
Relation & EvalInplace()
Definition: sets.hpp:494
const Container & get() const
Definition: sets.hpp:99
void Clear()
Definition: sets.hpp:156
Definition: sets.hpp:319
bool Contains(const Element &e) const
Definition: sets.hpp:158
Relation Eval() const
Definition: sets.hpp:475
Container set_
Definition: sets.hpp:236
Properties props_
Definition: sets.hpp:1135
void Clear()
Definition: sets.hpp:1269
Set()
Definition: sets.hpp:90
Set< Ts > Domain() const
Definition: sets.hpp:819
Abstracts over container library&#39;s set implementation.
Definition: sets.hpp:85
bool WeakPartialOrder(const Set< Ts > &on) const
Definition: sets.hpp:744
void Insert(const Element &e1, Element &&e2, bool assert_unique=false)
Definition: sets.hpp:389
bool operator!=(const Set &rhs) const
Definition: sets.hpp:103
bool TotalOn(const Set< Ts > &on) const
Definition: sets.hpp:717
Ts::Element Element
Definition: sets.hpp:1312
const Container & get() const
Definition: sets.hpp:355
bool StrictTotalOrder(const Set< Ts > &on) const
Definition: sets.hpp:770
Relation & unset_props(Properties props)
Definition: sets.hpp:369
FlagSet * visiting_
Definition: sets.hpp:1129
Definition: sets.hpp:1025
Relation()
Definition: sets.hpp:347
bool Erase(const Element &e, bool assert_exists=false)
Definition: sets.hpp:137
Set Filter(FilterFunc filterFunc) const
Definition: sets.hpp:144
bool R(const Element &e1, const Element &e2, Path *path=nullptr) const
Definition: sets.hpp:620
bool DfsRec(const Element &e1, const Element &e2) const
Definition: sets.hpp:1039
bool any_props(Properties any) const
Definition: sets.hpp:376
const Element & Insert(Element &&e, bool assert_unique=false)
Definition: sets.hpp:125
Relation< Ts > Eval() const override
Definition: sets.hpp:1355
SearchMode mode_
Definition: sets.hpp:1131
std::vector< Relation< Ts > > rels_
Definition: sets.hpp:1303
Relation & operator|=(const Relation &rhs)
Definition: sets.hpp:539
Relation Filter(FilterFunc filterFunc) const
Definition: sets.hpp:511
void Insert(const Element &e1, const Element &e2, bool assert_unique=false)
Definition: sets.hpp:384
Relation< Ts > EvalClear()
Definition: sets.hpp:1278
Relation(Container r)
Definition: sets.hpp:349
Relation & operator-=(const Relation &rhs)
Definition: sets.hpp:559
Ts::Element Element
Definition: sets.hpp:87
void GetPath(Path *out, const Element *start, const Element *end, FlagSet *visiting, SearchMode mode=SearchMode::kRelated) const
Definition: sets.hpp:890
Definition: sets.hpp:1310
Relation & add_props(Properties props)
Definition: sets.hpp:364
R_impl(const Relation *src, Set< Ts > *visited, FlagSet *visiting, bool is_tran_cl, SearchMode mode)
Definition: sets.hpp:1027
bool Subset(const Set &s) const
Definition: sets.hpp:233
RelationSeq & operator+=(const RelationSeq &rhs)
Definition: sets.hpp:1329
bool Subset(const Relation &rhs) const
Definition: sets.hpp:855
bool InRange(const Element &e) const
Definition: sets.hpp:796
bool SubsetEq(const Set &s) const
Definition: sets.hpp:221
void Add(const std::vector< Relation< Ts >> &rels)
Definition: sets.hpp:1297
bool R(const Element &e1, const Element &e2, typename Relation< Ts >::Path *path=nullptr, std::size_t seq=0) const
Definition: sets.hpp:1387
bool Acyclic(Path *cyclic=nullptr) const
Definition: sets.hpp:686
E Element
Definition: sets.hpp:1511
Set(Container s)
Definition: sets.hpp:92
bool Contains__(const Element &e) const
Definition: sets.hpp:885
bool empty() const
Definition: sets.hpp:219
RelationSeq & operator+=(Relation< Ts > &&rhs)
Definition: sets.hpp:1324
Ts::Element Element
Definition: sets.hpp:321
sets::Types< Event > ::template MapContainer< bool > FlagSet
Definition: sets.hpp:860
void Clear()
Definition: sets.hpp:596
void Insert(const Element &e1, const Set< Ts > &e2s)
Definition: sets.hpp:393
bool is_tran_cl_
Definition: sets.hpp:1130
bool all_props(Properties all) const
Definition: sets.hpp:374
Relation & set_props(Properties props)
Definition: sets.hpp:359