TdZdd  1.1
A top-down/breadth-first decision diagram manipulation framework
DdSpec.hpp
1 /*
2  * TdZdd: a Top-down/Breadth-first Decision Diagram Manipulation Framework
3  * by Hiroaki Iwashita <iwashita@erato.ist.hokudai.ac.jp>
4  * Copyright (c) 2014 ERATO MINATO Project
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #pragma once
26 
27 #include <cassert>
28 #include <iostream>
29 #include <stdexcept>
30 
31 #include "dd/DdBuilder.hpp"
32 #include "dd/DepthFirstSearcher.hpp"
33 #include "util/demangle.hpp"
34 #include "util/MessageHandler.hpp"
35 
36 namespace tdzdd {
37 
67 template<typename S, int AR>
68 class DdSpecBase {
69 public:
70  static int const ARITY = AR;
71 
72  S& entity() {
73  return *static_cast<S*>(this);
74  }
75 
76  S const& entity() const {
77  return *static_cast<S const*>(this);
78  }
79 
80  void printLevel(std::ostream& os, int level) const {
81  os << level;
82  }
83 
92  std::vector<std::pair<int,int> > findOneInstance() const {
93  return DepthFirstSearcher<S>(entity()).findOneInstance();
94  }
95 
101  void dumpDot(std::ostream& os = std::cout,
102  std::string title = typenameof<S>()) const {
103  DdDumper<S> dumper(entity());
104  dumper.dump(os, title);
105  }
106 
112  std::string dot(std::string title = typenameof<S>()) const {
113  std::stringstream s;
114  dumpDot(s, title);
115  return s.str();
116  }
117 
124  friend std::ostream& operator<<(std::ostream& os, DdSpecBase const& o) {
125  o.dumpDot(os);
126  return os;
127  }
128 
129 private:
130  template<typename T, typename I>
131  static size_t rawHashCode_(void const* p) {
132  size_t h = 0;
133  I const* a = static_cast<I const*>(p);
134  for (size_t i = 0; i < sizeof(T) / sizeof(I); ++i) {
135  h += a[i];
136  h *= 314159257;
137  }
138  return h;
139  }
140 
141  template<typename T, typename I>
142  static size_t rawEqualTo_(void const* p1, void const* p2) {
143  I const* a1 = static_cast<I const*>(p1);
144  I const* a2 = static_cast<I const*>(p2);
145  for (size_t i = 0; i < sizeof(T) / sizeof(I); ++i) {
146  if (a1[i] != a2[i]) return false;
147  }
148  return true;
149  }
150 
151 protected:
152  template<typename T>
153  static size_t rawHashCode(T const& o) {
154  if (sizeof(T) % sizeof(size_t) == 0) {
155  return rawHashCode_<T,size_t>(&o);
156  }
157  if (sizeof(T) % sizeof(unsigned int) == 0) {
158  return rawHashCode_<T,unsigned int>(&o);
159  }
160  if (sizeof(T) % sizeof(unsigned short) == 0) {
161  return rawHashCode_<T,unsigned short>(&o);
162  }
163  return rawHashCode_<T,unsigned char>(&o);
164  }
165 
166  template<typename T>
167  static size_t rawEqualTo(T const& o1, T const& o2) {
168  if (sizeof(T) % sizeof(size_t) == 0) {
169  return rawEqualTo_<T,size_t>(&o1, &o2);
170  }
171  if (sizeof(T) % sizeof(unsigned int) == 0) {
172  return rawEqualTo_<T,unsigned int>(&o1, &o2);
173  }
174  if (sizeof(T) % sizeof(unsigned short) == 0) {
175  return rawEqualTo_<T,unsigned short>(&o1, &o2);
176  }
177  return rawEqualTo_<T,unsigned char>(&o1, &o2);
178  }
179 };
180 
194 template<typename S, int AR>
195 class StatelessDdSpec: public DdSpecBase<S,AR> {
196 public:
197  int datasize() const {
198  return 0;
199  }
200 
201  int get_root(void* p) {
202  return this->entity().getRoot();
203  }
204 
205  int get_child(void* p, int level, int value) {
206  assert(0 <= value && value < S::ARITY);
207  return this->entity().getChild(level, value);
208  }
209 
210  void get_copy(void* to, void const* from) {
211  }
212 
213  int merge_states(void* p1, void* p2) {
214  return 0;
215  }
216 
217  void destruct(void* p) {
218  }
219 
220  void destructLevel(int level) {
221  }
222 
223  size_t hash_code(void const* p, int level) const {
224  return 0;
225  }
226 
227  bool equal_to(void const* p, void const* q, int level) const {
228  return true;
229  }
230 
231  void print_state(std::ostream& os, void const* p, int level) const {
232  os << "*";
233  }
234 };
235 
256 template<typename S, typename T, int AR>
257 class DdSpec: public DdSpecBase<S,AR> {
258 public:
259  typedef T State;
260 
261 private:
262  static State& state(void* p) {
263  return *static_cast<State*>(p);
264  }
265 
266  static State const& state(void const* p) {
267  return *static_cast<State const*>(p);
268  }
269 
270 public:
271  int datasize() const {
272  return sizeof(State);
273  }
274 
275  void construct(void* p) {
276  new (p) State();
277  }
278 
279  int get_root(void* p) {
280  this->entity().construct(p);
281  return this->entity().getRoot(state(p));
282  }
283 
284  int get_child(void* p, int level, int value) {
285  assert(0 <= value && value < S::ARITY);
286  return this->entity().getChild(state(p), level, value);
287  }
288 
289  void getCopy(void* p, State const& s) {
290  new (p) State(s);
291  }
292 
293  void get_copy(void* to, void const* from) {
294  this->entity().getCopy(to, state(from));
295  }
296 
297  int mergeStates(State& s1, State& s2) {
298  return 0;
299  }
300 
301  int merge_states(void* p1, void* p2) {
302  return this->entity().mergeStates(state(p1), state(p2));
303  }
304 
305  void destruct(void* p) {
306  state(p).~State();
307  }
308 
309  void destructLevel(int level) {
310  }
311 
312  size_t hashCode(State const& s) const {
313  return this->rawHashCode(s);
314  }
315 
316  size_t hashCodeAtLevel(State const& s, int level) const {
317  return this->entity().hashCode(s);
318  }
319 
320  size_t hash_code(void const* p, int level) const {
321  return this->entity().hashCodeAtLevel(state(p), level);
322  }
323 
324  bool equalTo(State const& s1, State const& s2) const {
325  //return this->rawEqualTo(s1, s2);
326  return s1 == s2;
327  }
328 
329  bool equalToAtLevel(State const& s1, State const& s2, int level) const {
330  return this->entity().equalTo(s1, s2);
331  }
332 
333  bool equal_to(void const* p, void const* q, int level) const {
334  return this->entity().equalToAtLevel(state(p), state(q), level);
335  }
336 
337  void printState(std::ostream& os, State const& s) const {
338  os << s;
339  }
340 
341  void printStateAtLevel(std::ostream& os, State const& s, int level) const {
342  this->entity().printState(os, s);
343  }
344 
345  void print_state(std::ostream& os, void const* p, int level) const {
346  this->entity().printStateAtLevel(os, state(p), level);
347  }
348 };
349 
372 template<typename S, typename T, int AR>
373 class PodArrayDdSpec: public DdSpecBase<S,AR> {
374 public:
375  typedef T State;
376 
377 private:
378  typedef size_t Word;
379 
380  int arraySize;
381  int dataWords;
382 
383  static State* state(void* p) {
384  return static_cast<State*>(p);
385  }
386 
387  static State const* state(void const* p) {
388  return static_cast<State const*>(p);
389  }
390 
391 protected:
392  void setArraySize(int n) {
393  assert(0 <= n);
394  if (arraySize >= 0)
395  throw std::runtime_error(
396  "Cannot set array size twice; use setArraySize(int) only once in the constructor of DD spec.");
397  arraySize = n;
398  dataWords = (n * sizeof(State) + sizeof(Word) - 1) / sizeof(Word);
399  }
400 
401  int getArraySize() const {
402  return arraySize;
403  }
404 
405 public:
406  PodArrayDdSpec() :
407  arraySize(-1), dataWords(-1) {
408  }
409 
410  int datasize() const {
411  if (dataWords < 0)
412  throw std::runtime_error(
413  "Array size is unknown; please set it by setArraySize(int) in the constructor of DD spec.");
414  return dataWords * sizeof(Word);
415  }
416 
417  int get_root(void* p) {
418  return this->entity().getRoot(state(p));
419  }
420 
421  int get_child(void* p, int level, int value) {
422  assert(0 <= value && value < S::ARITY);
423  return this->entity().getChild(state(p), level, value);
424  }
425 
426  void get_copy(void* to, void const* from) {
427  Word const* pa = static_cast<Word const*>(from);
428  Word const* pz = pa + dataWords;
429  Word* qa = static_cast<Word*>(to);
430  while (pa != pz) {
431  *qa++ = *pa++;
432  }
433  }
434 
435  int mergeStates(T* a1, T* a2) {
436  return 0;
437  }
438 
439  int merge_states(void* p1, void* p2) {
440  return this->entity().mergeStates(state(p1), state(p2));
441  }
442 
443  void destruct(void* p) {
444  }
445 
446  void destructLevel(int level) {
447  }
448 
449  size_t hashCode(State const* s) const {
450  Word const* pa = reinterpret_cast<Word const*>(s);
451  Word const* pz = pa + dataWords;
452  size_t h = 0;
453  while (pa != pz) {
454  h += *pa++;
455  h *= 314159257;
456  }
457  return h;
458  }
459 
460  size_t hashCodeAtLevel(State const* s, int level) const {
461  return this->entity().hashCode(s);
462  }
463 
464  size_t hash_code(void const* p, int level) const {
465  return this->entity().hashCodeAtLevel(state(p), level);
466  }
467 
468  bool equalTo(State const* s1, State const* s2) const {
469  Word const* pa = reinterpret_cast<Word const*>(s1);
470  Word const* qa = reinterpret_cast<Word const*>(s1);
471  Word const* pz = pa + dataWords;
472  while (pa != pz) {
473  if (*pa++ != *qa++) return false;
474  }
475  return true;
476  }
477 
478  bool equalToAtLevel(State const* s1, State const* s2, int level) const {
479  return this->entity().equalTo(s1, s2);
480  }
481 
482  bool equal_to(void const* p, void const* q, int level) const {
483  return this->entity().equalToAtLevel(state(p), state(q), level);
484  }
485 
486  void printState(std::ostream& os, State const* a) const {
487  os << "[";
488  for (int i = 0; i < arraySize; ++i) {
489  if (i > 0) os << ",";
490  os << a[i];
491  }
492  os << "]";
493  }
494 
495  void printStateAtLevel(std::ostream& os, State const* a, int level) const {
496  this->entity().printState(os, a);
497  }
498 
499  void print_state(std::ostream& os, void const* p, int level) const {
500  this->entity().printStateAtLevel(os, state(p), level);
501  }
502 };
503 
525 template<typename S, typename TS, typename TA, int AR>
526 class HybridDdSpec: public DdSpecBase<S,AR> {
527 public:
528  typedef TS S_State;
529  typedef TA A_State;
530 
531 private:
532  typedef size_t Word;
533  static int const S_WORDS = (sizeof(S_State) + sizeof(Word) - 1)
534  / sizeof(Word);
535 
536  int arraySize;
537  int dataWords;
538 
539  static S_State& s_state(void* p) {
540  return *static_cast<S_State*>(p);
541  }
542 
543  static S_State const& s_state(void const* p) {
544  return *static_cast<S_State const*>(p);
545  }
546 
547  static A_State* a_state(void* p) {
548  return reinterpret_cast<A_State*>(static_cast<Word*>(p) + S_WORDS);
549  }
550 
551  static A_State const* a_state(void const* p) {
552  return reinterpret_cast<A_State const*>(static_cast<Word const*>(p)
553  + S_WORDS);
554  }
555 
556 protected:
557  void setArraySize(int n) {
558  assert(0 <= n);
559  arraySize = n;
560  dataWords = S_WORDS
561  + (n * sizeof(A_State) + sizeof(Word) - 1) / sizeof(Word);
562  }
563 
564  int getArraySize() const {
565  return arraySize;
566  }
567 
568 public:
569  HybridDdSpec() :
570  arraySize(-1), dataWords(-1) {
571  }
572 
573  int datasize() const {
574  return dataWords * sizeof(Word);
575  }
576 
577  void construct(void* p) {
578  new (p) S_State();
579  }
580 
581  int get_root(void* p) {
582  this->entity().construct(p);
583  return this->entity().getRoot(s_state(p), a_state(p));
584  }
585 
586  int get_child(void* p, int level, int value) {
587  assert(0 <= value && value < S::ARITY);
588  return this->entity().getChild(s_state(p), a_state(p), level, value);
589  }
590 
591  void getCopy(void* p, S_State const& s) {
592  new (p) S_State(s);
593  }
594 
595  void get_copy(void* to, void const* from) {
596  this->entity().getCopy(to, s_state(from));
597  Word const* pa = static_cast<Word const*>(from);
598  Word const* pz = pa + dataWords;
599  Word* qa = static_cast<Word*>(to);
600  pa += S_WORDS;
601  qa += S_WORDS;
602  while (pa != pz) {
603  *qa++ = *pa++;
604  }
605  }
606 
607  int mergeStates(S_State& s1, A_State* a1, S_State& s2, A_State* a2) {
608  return 0;
609  }
610 
611  int merge_states(void* p1, void* p2) {
612  return this->entity().mergeStates(s_state(p1), a_state(p1), s_state(p2),
613  a_state(p2));
614  }
615 
616  void destruct(void* p) {
617  }
618 
619  void destructLevel(int level) {
620  }
621 
622  size_t hashCode(S_State const& s) const {
623  return this->rawHashCode(s);
624  }
625 
626  size_t hashCodeAtLevel(S_State const& s, int level) const {
627  return this->entity().hashCode(s);
628  }
629 
630  size_t hash_code(void const* p, int level) const {
631  size_t h = this->entity().hashCodeAtLevel(s_state(p), level);
632  h *= 271828171;
633  Word const* pa = static_cast<Word const*>(p);
634  Word const* pz = pa + dataWords;
635  pa += S_WORDS;
636  while (pa != pz) {
637  h += *pa++;
638  h *= 314159257;
639  }
640  return h;
641  }
642 
643  bool equalTo(S_State const& s1, S_State const& s2) const {
644  return this->rawEqualTo(s1, s2);
645  }
646 
647  bool equalToAtLevel(S_State const& s1, S_State const& s2, int level) const {
648  return this->entity().equalTo(s1, s2);
649  }
650 
651  bool equal_to(void const* p, void const* q, int level) const {
652  if (!this->entity().equalToAtLevel(s_state(p), s_state(q), level))
653  return false;
654  Word const* pa = static_cast<Word const*>(p);
655  Word const* qa = static_cast<Word const*>(q);
656  Word const* pz = pa + dataWords;
657  pa += S_WORDS;
658  qa += S_WORDS;
659  while (pa != pz) {
660  if (*pa++ != *qa++) return false;
661  }
662  return true;
663  }
664 
665  void printState(std::ostream& os,
666  S_State const& s,
667  A_State const* a) const {
668  os << "[" << s << ":";
669  for (int i = 0; i < arraySize; ++i) {
670  if (i > 0) os << ",";
671  os << a[i];
672  }
673  os << "]";
674  }
675 
676  void printStateAtLevel(std::ostream& os,
677  S_State const& s,
678  A_State const* a,
679  int level) const {
680  this->entity().printState(os, s, a);
681  }
682 
683  void print_state(std::ostream& os, void const* p, int level) const {
684  this->entity().printStateAtLevel(os, s_state(p), a_state(p), level);
685  }
686 };
687 
688 /* for backward compatibility */
689 template<typename S, typename TS, typename TA, int AR>
690 class PodHybridDdSpec: public HybridDdSpec<S,TS,TA,AR> {
691 };
692 
693 } // namespace tdzdd
DD dumper.
Definition: DdBuilder.hpp:1248
friend std::ostream & operator<<(std::ostream &os, DdSpecBase const &o)
Dumps the node table in Graphviz (dot) format.
Definition: DdSpec.hpp:124
Base class of DD specs.
Definition: DdSpec.hpp:68
void dumpDot(std::ostream &os=std::cout, std::string title=typenameof< S >()) const
Dumps the diagram in Graphviz (DOT) format.
Definition: DdSpec.hpp:101
std::vector< std::pair< int, int > > findOneInstance() const
Returns a random instance using simple depth-first search without caching.
Definition: DdSpec.hpp:92
void dump(std::ostream &os, std::string title)
Dumps the node table in Graphviz (dot) format.
Definition: DdBuilder.hpp:1333
Abstract class of DD specifications using POD array states.
Definition: DdSpec.hpp:373
Abstract class of DD specifications using scalar states.
Definition: DdSpec.hpp:257
Abstract class of DD specifications using both scalar and POD array states.
Definition: DdSpec.hpp:526
Abstract class of DD specifications without states.
Definition: DdSpec.hpp:195
std::string dot(std::string title=typenameof< S >()) const
Makes an input code for Graphviz.
Definition: DdSpec.hpp:112