Limi
antichain.h
1 /*
2  * Copyright 2016, IST Austria
3  *
4  * This file is part of Limi.
5  *
6  * Limi is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Limi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with Limi. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef LIMI_INTERNAL_ANTICHAIN_H
21 #define LIMI_INTERNAL_ANTICHAIN_H
22 
23 #include <vector>
24 #include <utility>
25 #include <unordered_map>
26 #include <unordered_set>
27 #include <algorithm>
28 #include <ostream>
29 #include "../generics.h"
30 #include "helpers.h"
31 
32 namespace Limi {
38  namespace internal {
39 
53 template <class A, class B, class HashA = std::hash<A>, class HashB = std::hash<B>, class CompareA = std::equal_to<A>, class CompareB = std::equal_to<B>>
54 class antichain
55 {
56 private:
57  typedef std::unordered_set<B, HashB, CompareB> b_set;
58  typedef std::shared_ptr<const b_set> pb_set;
59  // the datastore contais a list of sets for each element A. The list corresponds to sets
60  // of B's we saw with A. Further a dirty flag is stored for each set
61  std::unordered_map<A,std::vector<std::pair<pb_set,bool>>, HashA, CompareA> datastore;
62 
66  inline bool contained(const b_set& set1, const b_set& set2) const {
67  for(auto it=set1.begin(); it!=set1.end(); it++) {
68  if (set2.find(*it) == set2.end())
69  return false;
70  }
71  return true;
72  }
73 public:
74  antichain() = default;
75 
80  inline void add_unchecked(const A& a, const pb_set& b, bool dirty = false) {
81  datastore[a].push_back(std::make_pair(b, dirty));
82  }
83 
84 
92  void add(const A& a, const pb_set& b, bool dirty = false) {
93  std::vector<std::pair<pb_set,bool>>& b_sets = datastore[a];
94  bool found = false;
95  for (auto it = b_sets.begin(); it != b_sets.end();) {
96  // the smallest subset should stay in
97  if (contained(*it->first, *b)) {
98  found = true;
99  break;
100  }
101  if (contained(*b, *it->first)) {
102  it = b_sets.erase(it);
103  } else {
104  it++;
105  }
106  }
107  if (!found)
108  b_sets.push_back(std::make_pair(b,dirty));
109  }
110 
116  bool contains(const A& a, const pb_set& b) const {
117  auto b_sets = datastore.find(a);
118  if (b_sets == datastore.end())
119  return false;
120  for (auto it = b_sets->second.begin(); it != b_sets->second.end(); it++) {
121  if (contained(*it->first, *b))
122  return true;
123  }
124  return false;
125  }
126 
132  inline unsigned size() const {
133  return datastore.size();
134  }
135 
139  void clean_dirty() {
140  for(std::pair<const A,std::vector<std::pair<pb_set,bool>>>& ds : datastore) {
141  ds.second.erase(std::remove_if( ds.second.begin(), ds.second.end(), [](std::pair<pb_set,bool> el) { return el.second; } ), ds.second.end());
142  }
143  }
144 
145 
153  void print(std::ostream& out, const printer_base<A>& printerA = printer<A>(), const printer_base<B>& printerB = printer<B>()) const {
154  for(const std::pair<A,std::vector<std::pair<pb_set,bool>>>& ds : datastore) {
155  out << "For element " << printerA(ds.first) << std::endl;
156  for (const std::pair<pb_set,bool>& set1 : ds.second) {
157  out << " ";
158  print_set(*set1.first, out, printerB);
159  if (set1.second) out << "_d";
160  out << std::endl;
161  }
162  }
163  }
164 };
165 
166 
167 }
168 }
169 
170 #endif // LIMI_INTERNAL_ANTICHAIN_H
The printer base is what custom printers need to inherit from.
Definition: generics.h:81
The main namespace of the library.
Definition: antichain_algo.h:40
void clean_dirty()
Remove elements marked as dirty.
Definition: antichain.h:139
void print(std::ostream &out, const printer_base< A > &printerA=printer< A >(), const printer_base< B > &printerB=printer< B >()) const
Print the antichain on the screen.
Definition: antichain.h:153
void add_unchecked(const A &a, const pb_set &b, bool dirty=false)
Add to the antichain an element without checking if the invariant is preserved.
Definition: antichain.h:80
An Antichain of minimal elements.
Definition: antichain.h:54
bool contains(const A &a, const pb_set &b) const
Tests if the element (a,b) or a smaller element is already contained in the antichain.
Definition: antichain.h:116
The default implementation of Limi::printer_base.
Definition: generics.h:104
unsigned size() const
Returns the size of the antichain.
Definition: antichain.h:132
void add(const A &a, const pb_set &b, bool dirty=false)
Add element (a,b) to the antichain.
Definition: antichain.h:92