libboloq
A library to replesent binary functions using Binary Decision Diagram.
 全て クラス 名前空間 関数 型定義 ページ
boolean_function_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 compute_key_type = const std::tuple<index_type, index_type, index_type>;
24 
25  using cache_ptr = std::weak_ptr<const typename node_ptr::element_type>;
26 
27  using unique_table_type = std::unordered_map<unique_key_type, cache_ptr>;
28  using compute_table_type = std::unordered_map<compute_key_type, cache_ptr>;
29  using index_table_type = std::unordered_map<unique_key_type, index_type>;
30 
31  const node_type __terminal_false, __terminal_true;
32  const node_ptr terminal_false, terminal_true;
33 
35 
36  unique_table_type unique_table;
37  compute_table_type compute_table;
38 
39  const node_ptr next_then_node(const node_ptr& n, const label_type& label) const {
40  if (n->label() != label) return n;
41  return n->then_node();
42  }
43 
44  const node_ptr next_else_node(const node_ptr& n, const label_type& label) const {
45  if (n->label() != label) return n;
46  return n->else_node();
47  }
48 
52  static unique_key_type make_unique_key(const label_type& l, const node_ptr& t, const node_ptr& e) {
53  return unique_key_type(l, t->index(), e->index());
54  }
55 
59  static compute_key_type make_compute_key(const node_ptr& i, const node_ptr& t, const node_ptr& e) {
60  return compute_key_type(i->index(), t->index(), e->index());
61  }
62 
63 public:
64 
69  __terminal_false(0), __terminal_true(1),
70  terminal_false(&__terminal_false, null_deleter()),
71  terminal_true(&__terminal_true, null_deleter())
72  {}
73 
78 
82  const node_ptr& zero() const {return terminal_false;}
86  const node_ptr& one() const {return terminal_true;}
87 
91  const node_ptr new_var(const label_type& _label, const node_ptr& t, const node_ptr& e) {
92  // もうすでに存在するなら既存のノードを返す
93  const unique_key_type key = make_unique_key(_label, t, e);
94  const auto it = unique_table.find(key);
95  if (it != unique_table.end() && !it->second.expired()) {
96  return it->second.lock();
97  }
98  // 存在しなければ新しく生成
99  const node_ptr pf(new node(igen.get_index(key) + 2, _label, t, e));
100  unique_table[key] = pf; // 登録
101  return pf;
102  }
103 
107  const node_ptr new_var(const label_type& _label) {
108  return new_var(_label, one(), zero());
109  }
110 
114  const node_ptr ite(const node_ptr& if_node, const node_ptr& then_node, const node_ptr& else_node) {
115  // if_node が終端なら then_node もしくは else_node を定義どおりに返す
116  if (if_node->is_terminal()) {
117  return (if_node->index()) ? then_node : else_node;
118  }
119 
120  // 計算済みなら計算結果を返す
121  const compute_key_type compute_key = make_compute_key(if_node, then_node, else_node);
122  const auto it = compute_table.find(compute_key);
123  if (it != compute_table.end() && !it->second.expired()) {
124  return it->second.lock();
125  }
126 
127  const label_type& v = std::min(if_node->label(),
128  std::min(then_node->label(),
129  else_node->label()));
130 
131  // 子を計算
132  const node_ptr then_child = ite(next_then_node(if_node, v),
133  next_then_node(then_node, v),
134  next_then_node(else_node, v));
135  const node_ptr else_child = ite(next_else_node(if_node, v),
136  next_else_node(then_node, v),
137  next_else_node(else_node, v));
138 
139  // ルールに従ってノードをスキップする
140  if (then_child == else_child) return then_child;
141 
142  // ノード (v, T, E) が存在しないなら新しいノードを生成
143  const node_ptr unique = new_var(v, then_child, else_child);
144  // 計算結果を登録
145  compute_table[compute_key] = unique;
146  return unique;
147  }
148 
152  const node_ptr apply_not(const node_ptr& a) {
153  return ite(a, zero(), one());
154  }
155 
159  const node_ptr apply_and(const node_ptr& a, const node_ptr& b) {
160  return ite(a, b, zero());
161  }
162 
166  const node_ptr apply_or(const node_ptr& a, const node_ptr& b) {
167  return ite(a, one(), b);
168  }
169 
173  const node_ptr apply_xor(const node_ptr& a, const node_ptr& b) {
174  return ite(a, apply_not(b), b);
175  }
176 };
177 
182 
183 }
const node_ptr & one() const
1定節点を返します
Definition: boolean_function_cache.h:86
const node_ptr apply_and(const node_ptr &a, const node_ptr &b)
and を適用した結果を返します
Definition: boolean_function_cache.h:159
boloq の名前空間
Definition: boolean_function.h:3
const node_ptr apply_xor(const node_ptr &a, const node_ptr &b)
or を適用した結果を返します
Definition: boolean_function_cache.h:173
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: boolean_function_cache.h:91
const node_ptr apply_not(const node_ptr &a)
not を適用した結果を返します
Definition: boolean_function_cache.h:152
N node_type
このクラスが扱うノードの型
Definition: boolean_function_cache.h:12
const node_ptr & zero() const
0定節点を返します
Definition: boolean_function_cache.h:82
basic_node< size_t, size_t > node
標準的なノードのクラス
Definition: node.h:94
基本的な演算キャッシュのテーブルです
Definition: boolean_function_cache.h:9
constexpr basic_boolean_function_cache()
コンストラクタ
Definition: boolean_function_cache.h:68
const node_ptr new_var(const label_type &_label)
新しいノードを生成します
Definition: boolean_function_cache.h:107
const node_ptr ite(const node_ptr &if_node, const node_ptr &then_node, const node_ptr &else_node)
Definition: boolean_function_cache.h:114
typename node_type::node_ptr node_ptr
このクラスが扱うノードのポインタ型
Definition: boolean_function_cache.h:14
basic_boolean_function_cache & operator=(const basic_boolean_function_cache &)=delete
代入は禁止されています
const node_ptr apply_or(const node_ptr &a, const node_ptr &b)
or を適用した結果を返します
Definition: boolean_function_cache.h:166