libboloq
A library to replesent binary functions using Binary Decision Diagram.
 全て クラス 名前空間 関数 型定義 ページ
combination_cache.h
1 #pragma once
2 
3 namespace boloq {
4 
8 template<class N>
10 public:
12  using node_type = N;
14  using node_ptr = typename node_type::node_ptr;
15 
16 private:
18 
19  using index_type = typename node_type::index_type;
20  using label_type = typename node_type::label_type;
21 
22  using unique_key_type = const std::tuple<label_type, index_type, index_type>;
23  using change_key_type = const std::tuple<index_type, label_type>;
24  using bin_op_key_type = const std::tuple<index_type, index_type>;
25 
26  using cache_ptr = std::weak_ptr<typename node_ptr::element_type>;
27 
29 
30  std::unordered_map<unique_key_type, cache_ptr> unique_table;
31  std::unordered_map<change_key_type, cache_ptr> change_table;
32  std::unordered_map<bin_op_key_type, cache_ptr> union_table;
33  std::unordered_map<bin_op_key_type, cache_ptr> intersection_table;
34 
35  const node_type __terminal_false, __terminal_true;
36  const node_ptr terminal_false, terminal_true;
37 
41  static unique_key_type make_unique_key(const label_type& l, const node_ptr& t, const node_ptr& e) {
42  return std::make_tuple(l, t->index(), e->index());
43  }
44 
48  static change_key_type make_change_key(const node_ptr& n, const label_type& l) {
49  return std::make_tuple(n->index(), l);
50  }
51 
52  static bin_op_key_type make_bin_op_key(const node_ptr& p, const node_ptr& q) {
53  return std::make_tuple(p->index(), q->index());
54  }
55 
56 public:
57 
62  __terminal_false(0), __terminal_true(1),
63  terminal_false(&__terminal_false, null_deleter()),
64  terminal_true(&__terminal_true, null_deleter())
65  {}
66 
71 
75  const node_ptr& zero() const {return terminal_false;}
79  const node_ptr& one() const {return terminal_true;}
80 
84  const node_ptr new_var(const label_type& _label, const node_ptr& t, const node_ptr& e) {
85  if (t == zero()) return e;
86  // もうすでに存在するなら既存のノードを返す
87  const unique_key_type key = make_unique_key(_label, t, e);
88  const auto it = unique_table.find(key);
89  if (it != unique_table.end() && !it->second.expired()) {
90  return it->second.lock();
91  }
92  // 存在しなければ新しく生成
93  const node_ptr pf(new node(igen.get_index(key) + 2, _label, t, e));
94  unique_table[key] = pf; // 登録
95  return pf;
96  }
97 
101  const node_ptr new_var(const label_type& _label) {
102  return new_var(_label, one(), zero());
103  }
104 
108  const node_ptr apply_change(const node_ptr& _root, const label_type& v) {
109  if (_root->label() == v) return new_var(v, _root->else_node(), _root->then_node());
110  if (_root->label() > v) return new_var(v, _root, zero());
111  const auto key = make_change_key(_root, v);
112  const auto it = change_table.find(key);
113  if (it != change_table.end() && !it->second.expired()) {
114  return it->second.lock();
115  }
116  const node_ptr& r = new_var(_root->label(),
117  apply_change(_root->then_node(), v),
118  apply_change(_root->else_node(), v));
119  change_table[key] = r;
120  return r;
121  }
122 
126  const node_ptr apply_union(const node_ptr& p, const node_ptr& q) {
127  if (p == zero()) return q;
128  if (q == zero() || p == q) return p;
129  const auto key = make_bin_op_key(p, q);
130  const auto it = union_table.find(key);
131  if (it != union_table.end() && !it->second.expired()) {
132  return it->second.lock();
133  }
134 
135  node_ptr r;
136  if (p->label() < q->label()) {
137  r = new_var(p->label(),
138  p->then_node(),
139  apply_union(p->else_node(), q));
140  }
141  else if (p->label() > q->label()) {
142  r = new_var(q->label(),
143  q->then_node(),
144  apply_union(p, q->else_node()));
145  }
146  else {
147  r = new_var(p->label(),
148  apply_union(p->then_node(), q->then_node()) ,
149  apply_union(p->else_node(), q->else_node()));
150  }
151 
152  union_table[key] = r;
153  return r;
154  }
155 
159  const node_ptr apply_intersection(const node_ptr& p, const node_ptr& q) {
160  if (p == zero() || q == zero()) return zero();
161  if (p == q) return p;
162  const auto key = make_bin_op_key(p, q);
163  const auto it = intersection_table.find(key);
164  if (it != intersection_table.end() && !it->second.expired()) {
165  return it->second.lock();
166  }
167 
168  node_ptr r;
169  if (p->label() < q->label()) {
170  r = apply_intersection(p->else_node(), q);
171  }
172  else if (p->label() > q->label()) {
173  r = apply_intersection(q->else_node(), p);
174  }
175  else {
176  r = new_var(p->label(),
177  apply_intersection(p->then_node(), q->then_node()),
178  apply_intersection(p->else_node(), q->else_node()));
179  }
180 
181  intersection_table[key] = r;
182  return r;
183  }
184 
185 };
186 
191 
192 }
N node_type
このクラスが扱うノードの型
Definition: combination_cache.h:12
boloq の名前空間
Definition: boolean_function.h:3
basic_combination_cache & operator=(const basic_combination_cache &)=delete
代入は禁止されています
const node_ptr new_var(const label_type &_label)
新しいノードを生成します
Definition: combination_cache.h:101
index_type get_index(const key_type &key)
インデックスを生成します
Definition: index_generator.h:25
const node_ptr new_var(const label_type &_label, const node_ptr &t, const node_ptr &e)
新しいノードを生成します
Definition: combination_cache.h:84
basic_combination_cache()
コンストラクタ
Definition: combination_cache.h:61
const node_ptr apply_union(const node_ptr &p, const node_ptr &q)
和集合を返します
Definition: combination_cache.h:126
const node_ptr apply_intersection(const node_ptr &p, const node_ptr &q)
積集合を返します
Definition: combination_cache.h:159
basic_node< size_t, size_t > node
標準的なノードのクラス
Definition: node.h:94
const node_ptr & zero() const
0定節点を返します
Definition: combination_cache.h:75
const node_ptr & one() const
1定節点を返します
Definition: combination_cache.h:79
const node_ptr apply_change(const node_ptr &_root, const label_type &v)
特定のアイテムの存在を反転させた結果を返します
Definition: combination_cache.h:108
typename node_type::node_ptr node_ptr
このクラスが扱うノードのポインタ型
Definition: combination_cache.h:14
基本的な演算キャッシュのテーブルです
Definition: combination_cache.h:9