37 #include "dd/DdBuilder.hpp" 38 #include "dd/DdReducer.hpp" 39 #include "dd/Node.hpp" 40 #include "dd/NodeTable.hpp" 41 #include "eval/Cardinality.hpp" 42 #include "op/Lookahead.hpp" 43 #include "op/Unreduction.hpp" 44 #include "util/demangle.hpp" 45 #include "util/MessageHandler.hpp" 46 #include "util/MyHashTable.hpp" 47 #include "util/MyVector.hpp" 57 NodeTableHandler<ARITY> diagram;
66 root_(0), useMP(false) {
83 diagram(n + 1), root_(1), useMP(useMP) {
85 NodeTableEntity<ARITY>& table = diagram.privateEntity();
88 for (
int i = 1; i <= n; ++i) {
90 for (
int b = 0; b < ARITY; ++b) {
91 table[i][0].branch[b] = f;
104 template<
typename SPEC>
108 if (useMP) constructMP_(spec.entity());
111 construct_(spec.entity());
115 template<
typename SPEC>
116 void construct_(SPEC
const& spec) {
118 mh.begin(typenameof(spec));
124 for (
int i = n; i > 0; --i) {
136 template<
typename SPEC>
137 void constructMP_(SPEC
const& spec) {
139 mh.begin(typenameof(spec));
145 mh <<
" " << omp_get_max_threads() <<
"x";
148 for (
int i = n; i > 0; --i) {
165 template<
typename SPEC>
168 if (useMP) zddSubsetMP_(spec.entity());
171 zddSubset_(spec.entity());
175 template<
typename SPEC>
176 void zddSubset_(SPEC
const& spec) {
178 mh.begin(typenameof(spec));
179 NodeTableHandler<ARITY> tmpTable;
185 for (
int i = n; i > 0; --i) {
187 diagram.derefLevel(i);
199 template<
typename SPEC>
200 void zddSubsetMP_(SPEC
const& spec) {
202 mh.begin(typenameof(spec));
203 NodeTableHandler<ARITY> tmpTable;
209 mh <<
" " << omp_get_max_threads() <<
"x";
212 for (
int i = n; i > 0; --i) {
214 diagram.derefLevel(i);
260 NodeId
child(NodeId f,
int b)
const {
261 return diagram->child(f, b);
293 return diagram->size();
310 if (n != o.root_.row())
return false;
311 if (n == 0)
return root_ == o.root_;
312 if (root_ == o.root_ && &*diagram == &*o.diagram)
return true;
313 if (
size() > o.
size())
return o.operator==(*
this);
316 DataTable<NodeId> equiv(n + 1);
318 size_t om = (*o.diagram)[0].
size();
320 for (
size_t j = 0; j < om; ++j) {
325 for (
int i = 1; i <= n; ++i) {
326 size_t m = (*diagram)[i].size();
329 for (
size_t j = 0; j < m; ++j) {
330 uniq[(*diagram)[i][j]] = j;
333 size_t om = (*o.diagram)[i].
size();
336 for (
size_t j = 0; j < om; ++j) {
337 InitializedNode<ARITY> node;
339 for (
int b = 0; b < ARITY; ++b) {
340 NodeId f = (*o.diagram)[i][j].branch[b];
341 node.branch[b] = equiv[f.row()][f.col()];
345 equiv[i][j] = NodeId(i, (p != 0) ? *p : m);
349 return root_ == equiv[o.root_.row()][o.root_.col()];
365 reduce<false,false>();
373 reduce<true,false>();
381 reduce<false,true>();
389 template<
bool BDD,
bool ZDD>
392 mh.begin(
"reduction");
396 if (useMP) mh <<
" " << omp_get_max_threads() <<
"x";
399 DdReducer<ARITY,BDD,ZDD> zr(diagram, useMP);
403 for (
int i = 1; i <= n; ++i) {
418 ZddLookahead<BddUnreduction<DdStructure> >(
419 BddUnreduction<DdStructure>(*
this, numVars)), useMP);
428 BddLookahead<ZddUnreduction<DdStructure> >(
429 ZddUnreduction<DdStructure>(*
this, numVars)), useMP);
454 template<
typename S,
typename T,
typename R>
456 S eval(evaluator.entity());
458 bool useMP = this->useMP && eval.isThreadSafe();
460 bool msg = eval.showMessages();
465 mh.begin(typenameof(eval));
467 if (useMP) mh <<
" " << omp_get_max_threads() <<
"x";
473 int threads = useMP ? omp_get_max_threads() : 0;
474 MyVector<S> evals(threads, eval);
481 int k = omp_get_thread_num();
482 evals[k].initialize(n);
486 DataTable<T> work(diagram->numRows());
488 size_t const m = (*diagram)[0].size();
491 for (
size_t j = 0; j < m; ++j) {
492 eval.evalTerminal(work[0][j], j);
496 for (
int i = 1; i <= n; ++i) {
497 MyVector<Node<ARITY> >
const& node = (*diagram)[i];
498 size_t const m = node.size();
505 int k = omp_get_thread_num();
507 #pragma omp for schedule(static) 508 for (intmax_t j = 0; j < intmax_t(m); ++j) {
510 for (
int b = 0; b < ARITY; ++b) {
511 NodeId f = node[j].branch[b];
512 values.setReference(b, work[f.row()][f.col()]);
513 values.setLevel(b, f.row());
515 evals[k].evalNode(work[i][j], i, values);
520 for (
size_t j = 0; j < m; ++j) {
522 for (
int b = 0; b < ARITY; ++b) {
523 NodeId f = node[j].branch[b];
524 values.setReference(b, work[f.row()][f.col()]);
525 values.setLevel(b, f.row());
527 eval.evalNode(work[i][j], i, values);
530 MyVector<int>
const& levels = diagram->lowerLevels(i);
531 for (
int const* t = levels.begin(); t != levels.end(); ++t) {
533 eval.destructLevel(*t);
539 int k = omp_get_thread_num();
540 for (
int const* t = levels.begin(); t != levels.end(); ++t) {
541 evals[k].destructLevel(*t);
548 R retval = eval.getValue(work[root_.row()][root_.col()]);
565 Selection(NodeId node,
bool val) :
566 node(node), val(val) {
569 bool operator==(Selection
const& o)
const {
570 return node == o.node && val == o.val;
576 std::vector<Selection> path;
577 std::set<int> itemset;
581 dd(dd), cursor(begin ? -1 : -2), path(), itemset() {
582 if (begin) next(dd.root_);
590 std::set<int>
const& operator*()
const {
594 std::set<int>
const* operator->()
const {
599 return cursor == o.cursor && path == o.path;
603 return !operator==(o);
607 void next(NodeId f) {
612 Node<ARITY>
const& s = (*dd.diagram)[f.row()][f.col()];
614 if (s.branch[0] != 0) {
615 cursor = path.size();
616 path.push_back(Selection(f,
false));
620 path.push_back(Selection(f,
true));
627 for (; cursor >= 0; --cursor) {
628 Selection& sel = path[cursor];
629 Node<ARITY>
const& ss =
630 (*dd.diagram)[sel.node.row()][sel.node.col()];
631 if (sel.val ==
false && ss.branch[1] != 0) {
634 path.resize(cursor + 1);
635 f = dd.diagram->child(f, 1);
647 for (
size_t i = 0; i < path.size(); ++i) {
649 itemset.insert(path[i].node.row());
679 return (f == 1) ? -1 : f.row();
685 int getChild(NodeId& f,
int level,
int value)
const {
686 assert(level > 0 && level == f.row());
687 assert(0 <= value && value < ARITY);
689 return (f.row() > 0) ? f.row() : -f.col();
705 int const n = diagram->numRows() - 1;
706 size_t const l =
size();
708 os <<
"_i " << n <<
"\n";
710 os <<
"_n " << l <<
"\n";
712 DataTable<size_t> nodeId(diagram->numRows());
715 for (
int i = 1; i <= n; ++i) {
716 size_t const m = (*diagram)[i].size();
717 Node<ARITY>
const* p = (*diagram)[i].data();
720 for (
size_t j = 0; j < m; ++j, ++p) {
725 for (
int c = 0; c <= 1; ++c) {
726 NodeId fc = p->branch[c];
734 os <<
" " << nodeId[fc.row()][fc.col()];
741 MyVector<int>
const& levels = diagram->lowerLevels(i);
742 for (
int const* t = levels.begin(); t != levels.end(); ++t) {
747 os << nodeId[root_.row()][root_.col()] <<
"\n";
NodeId child(NodeId f, int b) const
Gets a child node.
Closed hash map implementation.
NodeTableHandler< ARITY > & getDiagram()
Gets the diagram.
DdStructure(int n, bool useMP=false)
Universal ZDD constructor.
void zddReduce()
ZDD reduction.
void bddReduce()
BDD reduction.
DdStructure()
Default constructor.
Ordered n-ary decision diagram structure.
int initialize(NodeId &root)
Initializes the builder.
NodeId root() const
Gets the root node.
Basic breadth-first DD builder.
bool empty() const
Checks if DD is a 0-terminal only.
ZDD evaluator that counts the number of elements.
void reduce()
BDD/ZDD reduction.
NodeId & root()
Gets the root node.
Breadth-first ZDD subset builder.
std::string bddCardinality(int numVars) const
Counts the number of minterms of the function represented by this BDD.
void subset(int i)
Builds one level.
DdStructure bdd2zdd(int numVars) const
Transforms a BDD into a ZDD.
void zddSubset(DdSpecBase< SPEC, ARITY > const &spec)
ZDD subsetting.
int getChild(NodeId &f, int level, int value) const
Implements DdSpec.
Multi-threaded breadth-first ZDD subset builder.
NodeTableHandler< ARITY > const & getDiagram() const
Gets the diagram.
void subset(int i)
Builds one level.
BDD evaluator that counts the number of elements.
int initialize(NodeId &root)
Initializes the builder.
Collection of child node values/levels for DdEval::evalNode function interface.
std::string zddCardinality() const
Counts the number of sets in the family of sets represented by this ZDD.
Base class of DD evaluators.
V * getValue(K const &key) const
Get the value that is already registered.
size_t size() const
Gets the number of nonterminal nodes.
void initialize(size_t n)
Initialize the table to be empty.
DdStructure(DdSpecBase< SPEC, ARITY > const &spec, bool useMP=false)
DD construction.
const_iterator begin() const
Returns an iterator to the first instance, which is viewed as a collection of item numbers...
const_iterator end() const
Returns an iterator to the element following the last instance.
R evaluate(DdEval< S, T, R > const &evaluator) const
Evaluates the DD from the bottom to the top.
int initialize(NodeId &root)
Initializes the builder.
void qddReduce()
QDD reduction.
bool useMultiProcessors(bool flag=true)
Enables or disables multiple processor algorithms.
int topLevel() const
Gets the level of the root node.
bool operator!=(DdStructure const &o) const
Checks structural inequivalence with another DD.
Abstract class of DD specifications using scalar states.
int getRoot(NodeId &f) const
Implements DdSpec.
DdStructure zdd2bdd(int numVars) const
Transforms a ZDD into a BDD.
bool operator==(DdStructure const &o) const
Checks structural equivalence with another DD.
int initialize(NodeId &root)
Initializes the builder.
void dumpSapporo(std::ostream &os) const
Dumps the node table in Sapporo ZDD format.
void construct(int i)
Builds one level.
size_t hashCode(NodeId const &f) const
Implements DdSpec.
void construct(int i)
Builds one level.
Multi-threaded breadth-first DD builder.
Iterator on a set of integer vectors represented by a DD.