Adiar  2.1.0
An External Memory Decision Diagram Library
dd.h
1 #ifndef ADIAR_INTERNAL_DD_H
2 #define ADIAR_INTERNAL_DD_H
3 
4 #include <variant>
5 
6 #include <adiar/exec_policy.h>
7 
8 #include <adiar/internal/cut.h>
9 #include <adiar/internal/data_types/arc.h>
10 #include <adiar/internal/data_types/node.h>
11 #include <adiar/internal/io/arc_file.h>
12 #include <adiar/internal/io/node_file.h>
13 
14 namespace adiar::internal
15 {
16  // TODO (MDD):
17  // TODO (QMDD):
18  // TODO (ADD (64-bit)):
19  // template both 'dd' and '__dd' with the node type (and derive the
20  // corresponding arc type).
21 
22  class dd;
23 
28  using no_file = std::monostate;
29 
44  class __dd
45  {
46  public:
50  using node_type = node;
51 
55  using shared_node_file_type = shared_levelized_file<node_type>;
56 
60  using pointer_type = node_type::pointer_type;
61 
65  using label_type = node_type::label_type;
66 
70  using signed_label_type = node_type::signed_label_type;
71 
75  using arc_type = arc;
76 
80  using shared_arc_file_type = shared_levelized_file<arc_type>;
81 
86  std::variant<no_file, shared_node_file_type, shared_arc_file_type> _union;
87 
91  bool _negate = false;
92 
97 
102 
104  // Constructors
105 
109  __dd() = default;
110 
115  : _union(f)
116  {}
117 
121  __dd(const shared_arc_file_type& f, const exec_policy& ep)
122  : _union(f)
123  , _policy(ep)
124  {}
125 
130  __dd(const dd& dd);
131 
133  // Accessors
134  // TODO: change from 'file_t' to 'file::value_type'.
135 
139  template <typename file_t>
140  bool
141  has() const
142  {
143  return std::holds_alternative<file_t>(_union);
144  }
145 
151  template <typename file_t>
152  const file_t&
153  get() const
154  {
155  return std::get<file_t>(_union);
156  }
157 
163  bool
164  empty() const
165  {
166  return has<no_file>();
167  }
168 
169  // TODO (optimisation):
170  // Add precondition to be with 'arcs' only?
171 
175  size_t
176  size() const
177  {
178  if (has<shared_arc_file_type>()) {
179  // TODO (QMDD): Divide by node::outdegree instead of 2u
180  return get<shared_arc_file_type>()->size() / 2u;
181  }
182  if (has<shared_node_file_type>()) { return get<shared_node_file_type>()->size(); }
183  return 0u;
184  }
185 
192  cut::size_type
193  max_1level_cut(const cut ct) const
194  {
195  if (has<shared_arc_file_type>()) {
196  const shared_arc_file_type& af = get<shared_arc_file_type>();
197  return af->max_1level_cut + (ct.includes(false) ? af->number_of_terminals[false] : 0u)
198  + (ct.includes(true) ? af->number_of_terminals[true] : 0u);
199  }
200  if (has<shared_node_file_type>()) { return get<shared_node_file_type>()->max_1level_cut[ct]; }
201  return 0u;
202  }
203 
210  cut::size_type
211  max_2level_cut(const cut ct) const
212  {
213  if (has<shared_arc_file_type>()) {
214  const shared_arc_file_type& af = get<shared_arc_file_type>();
215  return std::min( // 3/2 times the 1-level cut
216  (3 * af->max_1level_cut) / 2 + (ct.includes(false) ? af->number_of_terminals[false] : 0u)
217  + (ct.includes(true) ? af->number_of_terminals[true] : 0u),
218  // At most the number of nodes + 1
219  (af->size() / 2u) + 1);
220  }
221  if (has<shared_node_file_type>()) { return get<shared_node_file_type>()->max_2level_cut[ct]; }
222  return 0u;
223  }
224 
228  size_t
229  number_of_terminals(const bool value) const
230  {
231  if (has<shared_arc_file_type>()) {
232  return get<shared_arc_file_type>()->number_of_terminals[this->_negate ^ value];
233  }
234  if (has<shared_node_file_type>()) {
235  return get<shared_node_file_type>()->number_of_terminals[this->_negate ^ value];
236  }
237  return 0u;
238  }
239 
243  size_t
245  {
246  if (has<shared_arc_file_type>()) {
247  const shared_arc_file_type& af = get<shared_arc_file_type>();
248  return af->number_of_terminals[false] + af->number_of_terminals[true];
249  }
250  if (has<shared_node_file_type>()) {
251  const shared_node_file_type& nf = get<shared_node_file_type>();
252  return nf->number_of_terminals[false] + nf->number_of_terminals[true];
253  }
254  return 0u;
255  }
256  };
257 
264  class dd
265  {
267  // Constants
268  public:
272  using node_type = node;
273 
277  using pointer_type = node_type::pointer_type;
278 
282  using label_type = node_type::label_type;
283 
287  using signed_label_type = node_type::signed_label_type;
288 
292  static constexpr label_type max_label = node_type::max_label;
293 
297  using id_type = node_type::id_type;
298 
302  static constexpr id_type max_id = node_type::max_id;
303 
307  using terminal_type = typename node_type::terminal_type;
308 
312  using node_file_type = levelized_file<node_type>;
313 
317  using shared_node_file_type = shared_file_ptr<node_file_type>;
318 
320  // Internal state
321  protected:
326 
332  void
334  {
335  this->_file.reset();
336  }
337 
340  //
341  // TODO: move to 'bdd' or generalize to 'attribute'?
343  bool _negate = false;
344 
349 
351  // Constructors
352  public:
356  dd(const shared_node_file_type& f, bool negate = false, signed_label_type shift = 0)
357  : _file(f)
358  , _negate(negate)
359  , _shift(shift)
360  {}
361 
366  dd(const dd& dd) = default;
367 
371  dd(dd&& dd) = default;
372 
374  // NOTE:
375  //
376  // To implement the specific DD, add the following move-conversion that runs the Reduce
377  // algorithm.
378  //
379  // dd(__dd &&dd)
381 
382  public:
387  file_ptr() const
388  {
389  return this->_file;
390  }
391 
396  const node_file_type*
397  operator->() const
398  {
399  return this->_file.get();
400  }
401 
405  bool
406  is_negated() const
407  {
408  return this->_negate;
409  }
410 
415  shift() const
416  {
417  return this->_shift;
418  }
419 
427  cut::size_type
428  max_1level_cut(const cut ct) const
429  {
430  return this->_file->max_1level_cut[negate_cut_type(ct)];
431  }
432 
439  cut::size_type
440  max_2level_cut(const cut ct) const
441  {
442  return this->_file->max_2level_cut[negate_cut_type(ct)];
443  }
444 
446 
450  size_t
451  size() const
452  {
453  return this->_file->size();
454  }
455 
459  size_t
460  width() const
461  {
462  return this->_file->width;
463  }
464 
468  size_t
469  number_of_terminals(const bool value) const
470  {
471  return this->_file->number_of_terminals[this->_negate ^ value];
472  }
473 
477  size_t
479  {
480  return this->number_of_terminals(false) + this->number_of_terminals(true);
481  }
482 
483  private:
488  cut
489  negate_cut_type(const cut ct) const
490  {
491  if (!this->_negate) { return ct; }
492 
493  switch (ct) {
494  case cut::Internal_False: return cut::Internal_True;
495  case cut::Internal_True: return cut::Internal_False;
496  default: return ct;
497  }
498  }
499 
501  // Friends
502  friend class __dd;
503  };
504 
505  inline __dd::__dd(const dd& dd)
506  : _union(dd._file)
507  , _negate(dd._negate)
508  , _shift(dd._shift)
509  {}
510 
512  template <typename DD, typename __DD>
513  class dd_policy
514  {
517  public:
521  using dd_type = DD;
522 
526  using __dd_type = __DD;
527 
531  using node_type = typename dd_type::node_type;
532 
536  using pointer_type = typename dd_type::pointer_type;
537 
541  using children_type = typename node_type::children_type;
542 
546  using label_type = typename dd_type::label_type;
547 
551  using signed_label_type = typename dd_type::label_type;
552 
556  static constexpr label_type max_label = dd_type::max_label;
557 
561  using id_type = typename dd_type::id_type;
562 
566  static constexpr id_type max_id = dd_type::max_id;
567 
571  using terminal_type = typename dd_type::terminal_type;
572 
576  using shared_node_file_type = typename __dd_type::shared_node_file_type;
577 
581  using shared_arc_file_type = typename __dd_type::shared_arc_file_type;
582 
585  public:
591  static inline pointer_type
592  reduction_rule(const node_type& n);
593 
600  static inline children_type
601  reduction_rule_inv(const pointer_type& child);
602  };
603 
605 }
606 
607 #endif // ADIAR_INTERNAL_DD_H
Settings to dictate the execution of Adiar's algorithms.
Definition: exec_policy.h:35
Definition: dd.h:45
exec_policy _policy
Copy of the execution policy given to the top-down algorithm.
Definition: dd.h:101
shared_levelized_file< arc_type > shared_arc_file_type
Type of the file object arc-based representation of a diagram.
Definition: dd.h:80
shared_levelized_file< node_type > shared_node_file_type
Type of the file object node-based representation of a diagram.
Definition: dd.h:55
node_type::signed_label_type signed_label_type
Type for difference between variable labels.
Definition: dd.h:70
__dd()=default
Default construction to nothing.
arc arc_type
Type of nodes of this diagram.
Definition: dd.h:75
__dd(const shared_arc_file_type &f, const exec_policy &ep)
Conversion for algorithms returning to-be reduced arcs.
Definition: dd.h:121
const file_t & get() const
Get the content of a certain type.
Definition: dd.h:153
std::variant< no_file, shared_node_file_type, shared_arc_file_type > _union
Union of levelized node or arc files to reflect the possible return types of a function and a 'no_fil...
Definition: dd.h:86
bool has() const
Whether the union currently holds a certain file type.
Definition: dd.h:141
__dd(const shared_node_file_type &f)
Conversion for algorithms returning already-reduced nodes.
Definition: dd.h:114
cut::size_type max_2level_cut(const cut ct) const
Obtain the 2-level cut of the desired type, i.e. of the sub-graph including the desired type of arcs.
Definition: dd.h:211
size_t number_of_terminals() const
Number of terminals.
Definition: dd.h:244
bool _negate
Propagation of the dd.negate flag.
Definition: dd.h:91
node node_type
Type of nodes of this diagram.
Definition: dd.h:50
node_type::pointer_type pointer_type
Type of pointers of this diagram.
Definition: dd.h:60
size_t size() const
Number of nodes.
Definition: dd.h:176
cut::size_type max_1level_cut(const cut ct) const
Obtain the 1-level cut of the desired type, i.e. of the sub-graph including the desired type of arcs.
Definition: dd.h:193
bool empty() const
Whether it currently holds no content.
Definition: dd.h:164
node_type::label_type label_type
Type of this node's variable label.
Definition: dd.h:65
signed_label_type _shift
Propagation of the dd.negate flag.
Definition: dd.h:96
size_t number_of_terminals(const bool value) const
Number of terminals of a certain value.
Definition: dd.h:229
Container for the files that represent a Decision Diagram.
Definition: dd.h:265
static constexpr id_type max_id
The maximal possible value for this nodes level identifier.
Definition: dd.h:302
const node_file_type * operator->() const
Read-only access to the members of the raw files and meta information, i.e. this is similar to writin...
Definition: dd.h:397
levelized_file< node_type > node_file_type
File type for the file object representing the diagram.
Definition: dd.h:312
bool _negate
Whether to negate the leaves when reading nodes from the file.
Definition: dd.h:343
bool is_negated() const
Read-only access to the negation flag.
Definition: dd.h:406
signed_label_type _shift
Number of levels to shift by.
Definition: dd.h:348
const shared_node_file_type file_ptr() const
Read-only access to the raw files and meta information.
Definition: dd.h:387
dd(const shared_node_file_type &f, bool negate=false, signed_label_type shift=0)
Constructor to wrap the node-based result of an algorithm.
Definition: dd.h:356
shared_file_ptr< node_file_type > shared_node_file_type
File type for the shared file object representing the diagram.
Definition: dd.h:317
static constexpr label_type max_label
The maximal possible value for a unique identifier's label.
Definition: dd.h:292
node_type::signed_label_type signed_label_type
Type for difference between variable labels.
Definition: dd.h:287
node_type::label_type label_type
Type of this node's variable label.
Definition: dd.h:282
node_type::pointer_type pointer_type
Type of pointers of this diagram.
Definition: dd.h:277
void deref()
Release the claim on the underlying file, thereby decreasing its reference counter....
Definition: dd.h:333
signed_label_type shift() const
Read-only access to the number of levels to shift.
Definition: dd.h:415
dd(dd &&dd)=default
Move construction, taking over ownership of the files underneath.
shared_node_file_type _file
The file describing the actual DAG of the decision diagram.
Definition: dd.h:325
size_t number_of_terminals(const bool value) const
Number of terminals of a certain value.
Definition: dd.h:469
typename node_type::terminal_type terminal_type
Type of a terminal value.
Definition: dd.h:307
node_type::id_type id_type
Type of this node's level identifier.
Definition: dd.h:297
size_t size() const
The number of elements in the node file.
Definition: dd.h:451
dd(const dd &dd)=default
Copy construction, incrementing the reference count on the file underneath.
size_t width() const
The number of nodes on the widest level.
Definition: dd.h:460
node node_type
Type of nodes of this diagram.
Definition: dd.h:272
size_t number_of_terminals() const
Number of terminals.
Definition: dd.h:478