36 #include "DdSweeper.hpp" 38 #include "NodeTable.hpp" 39 #include "../DdSpec.hpp" 40 #include "../util/MemoryPool.hpp" 41 #include "../util/MessageHandler.hpp" 42 #include "../util/MyHashTable.hpp" 43 #include "../util/MyList.hpp" 44 #include "../util/MyVector.hpp" 50 static int const headerSize = 1;
63 static NodeId*& srcPtr(SpecNode* p) {
67 static int64_t& code(SpecNode* p) {
71 static NodeId& nodeId(SpecNode* p) {
72 return *
reinterpret_cast<NodeId*
>(&p[0].code);
75 static void* state(SpecNode* p) {
76 return p + headerSize;
79 static void const* state(SpecNode
const* p) {
80 return p + headerSize;
83 static int getSpecNodeSize(
int n) {
85 throw std::runtime_error(
"storage size is not initialized!!!");
86 return headerSize + (n +
sizeof(SpecNode) - 1) /
sizeof(SpecNode);
89 template<
typename SPEC>
94 Hasher(SPEC
const& spec,
int level) :
95 spec(spec), level(level) {
98 size_t operator()(SpecNode
const* p)
const {
99 return spec.hash_code(state(p), level);
102 size_t operator()(SpecNode
const* p, SpecNode
const* q)
const {
103 return spec.equal_to(state(p), state(q), level);
108 class DdBuilderMPBase {
110 static int const headerSize = 2;
122 static NodeId*& srcPtr(SpecNode* p) {
126 static int64_t& code(SpecNode* p) {
130 static NodeId& nodeId(SpecNode* p) {
131 return *
reinterpret_cast<NodeId*
>(&p[1].code);
134 static NodeId nodeId(SpecNode
const* p) {
135 return *
reinterpret_cast<NodeId const*
>(&p[1].code);
138 static void* state(SpecNode* p) {
139 return p + headerSize;
142 static void const* state(SpecNode
const* p) {
143 return p + headerSize;
146 static int getSpecNodeSize(
int n) {
148 throw std::runtime_error(
"storage size is not initialized!!!");
149 return headerSize + (n +
sizeof(SpecNode) - 1) /
sizeof(SpecNode);
152 template<
typename SPEC>
157 Hasher(SPEC
const& spec,
int level) :
158 spec(spec), level(level) {
161 size_t operator()(SpecNode
const* p)
const {
162 return spec.hash_code(state(p), level);
165 size_t operator()(SpecNode
const* p, SpecNode
const* q)
const {
166 return spec.equal_to(state(p), state(q), level);
178 static int const AR = Spec::ARITY;
181 int const specNodeSize;
182 NodeTableEntity<AR>& output;
185 MyVector<MyList<SpecNode> > snodeTable;
187 MyVector<char> oneStorage;
189 MyVector<NodeBranchId> oneSrcPtr;
192 snodeTable.resize(n + 1);
193 if (n >= output.numRows()) output.setNumRows(n + 1);
198 DdBuilder(Spec
const& spec, NodeTableHandler<AR>& output,
int n = 0) :
200 specNodeSize(getSpecNodeSize(spec.datasize())),
201 output(output.privateEntity()),
202 sweeper(this->output, oneSrcPtr),
203 oneStorage(spec.datasize()),
204 one(oneStorage.data()) {
209 if (!oneSrcPtr.empty()) {
222 SpecNode* p0 = snodeTable[level].alloc_front(specNodeSize);
223 spec.get_copy(state(p0), s);
233 MyVector<char> tmp(spec.datasize());
234 void*
const tmpState = tmp.data();
235 int n = spec.get_root(tmpState);
243 schedule(&root, n, tmpState);
246 spec.destruct(tmpState);
247 if (!oneSrcPtr.empty()) {
259 assert(0 < i &&
size_t(i) < snodeTable.size());
261 MyList<SpecNode> &snodes = snodeTable[i];
262 size_t j0 = output[i].size();
264 int lowestChild = i - 1;
265 size_t deadCount = 0;
268 Hasher<Spec> hasher(spec, i);
269 UniqTable uniq(snodes.size() * 2, hasher, hasher);
271 for (MyList<SpecNode>::iterator t = snodes.begin();
272 t != snodes.end(); ++t) {
274 SpecNode*& p0 = uniq.add(p);
277 nodeId(p) = *srcPtr(p) = NodeId(i, m++);
280 switch (spec.merge_states(state(p0), state(p))) {
283 nodeId(p) = *srcPtr(p) = NodeId(i, m++);
291 *srcPtr(p) = nodeId(p0);
304 Node<AR>*
const outi = output[i].data();
306 SpecNode* pp = snodeTable[i - 1].alloc_front(specNodeSize);
308 for (; !snodes.empty(); snodes.pop_front()) {
309 SpecNode* p = snodes.front();
310 Node<AR>& q = outi[jj];
312 if (nodeId(p) == 1) {
313 spec.destruct(state(p));
319 for (
int b = 0; b < AR; ++b) {
320 if (nodeId(p) == 0) {
325 spec.get_copy(state(pp), state(p));
326 int ii = spec.get_child(state(pp), i, b);
330 spec.destruct(state(pp));
333 if (oneSrcPtr.empty()) {
334 spec.get_copy(one, state(pp));
336 oneSrcPtr.push_back(NodeBranchId(i, jj, b));
339 switch (spec.merge_states(one, state(pp))) {
341 while (!oneSrcPtr.empty()) {
342 NodeBranchId
const& nbi = oneSrcPtr.back();
343 assert(nbi.row >= i);
344 output[nbi.row][nbi.col].branch[nbi.val] = 0;
345 oneSrcPtr.pop_back();
348 spec.get_copy(one, state(pp));
350 oneSrcPtr.push_back(NodeBranchId(i, jj, b));
357 oneSrcPtr.push_back(NodeBranchId(i, jj, b));
361 spec.destruct(state(pp));
364 else if (ii == i - 1) {
365 srcPtr(pp) = &q.branch[b];
366 pp = snodeTable[ii].alloc_front(specNodeSize);
371 SpecNode* ppp = snodeTable[ii].alloc_front(specNodeSize);
372 spec.get_copy(state(ppp), state(pp));
373 spec.destruct(state(pp));
374 srcPtr(ppp) = &q.branch[b];
375 if (ii < lowestChild) lowestChild = ii;
380 spec.destruct(state(p));
382 if (allZero) ++deadCount;
385 snodeTable[i - 1].pop_front();
386 spec.destructLevel(i);
387 sweeper.
update(i, lowestChild, deadCount);
398 static int const AR = Spec::ARITY;
399 static int const TASKS_PER_THREAD = 10;
404 MyVector<Spec> specs;
405 int const specNodeSize;
406 NodeTableEntity<AR>& output;
409 MyVector<MyVector<MyVector<MyList<SpecNode> > > > snodeTables;
412 ElapsedTimeCounter etcP1, etcP2, etcS1;
416 for (
int y = 0; y < threads; ++y) {
417 snodeTables[y].resize(tasks);
418 for (
int x = 0; x < tasks; ++x) {
419 snodeTables[y][x].resize(n + 1);
422 if (n >= output.numRows()) output.setNumRows(n + 1);
426 DdBuilderMP(Spec
const& s, NodeTableHandler<AR>& output,
int n = 0) :
428 threads(omp_get_max_threads()),
429 tasks(MyHashConstant::primeSize(TASKS_PER_THREAD * threads)),
435 specNodeSize(getSpecNodeSize(s.datasize())),
436 output(output.privateEntity()),
437 sweeper(this->output),
438 snodeTables(threads) {
442 mh <<
"#thread = " << threads <<
", #task = " << tasks;
449 mh <<
"P1: " << etcP1 <<
"\n";
450 mh <<
"P2: " << etcP2 <<
"\n";
451 mh <<
"S1: " << etcS1 <<
"\n";
462 SpecNode* p0 = snodeTables[0][0][level].alloc_front(specNodeSize);
463 specs[0].get_copy(state(p0), s);
473 MyVector<char> tmp(specs[0].datasize());
474 void*
const tmpState = tmp.data();
475 int n = specs[0].get_root(tmpState);
483 schedule(&root, n, tmpState);
486 specs[0].destruct(tmpState);
495 assert(0 < i && i < output.numRows());
496 assert(output.numRows() - snodeTables[0][0].size() == 0);
498 MyVector<size_t> nodeColumn(tasks);
499 int lowestChild = i - 1;
500 size_t deadCount = 0;
508 #pragma omp parallel reduction(+:deadCount) 512 int yy = omp_get_thread_num();
518 Spec& spec = specs[yy];
519 MyVector<char> tmp(spec.datasize());
520 void*
const tmpState = tmp.data();
521 Hasher<Spec> hasher(spec, i);
522 UniqTable uniq(hasher, hasher);
523 int lc = lowestChild;
526 #pragma omp for schedule(dynamic) 528 for (
int x = 0; x < tasks; ++x) {
530 for (
int y = 0; y < threads; ++y) {
531 m += snodeTables[y][x][i].size();
533 if (m == 0)
continue;
538 for (
int y = 0; y < threads; ++y) {
539 MyList<SpecNode> &snodes = snodeTables[y][x][i];
541 for (MyList<SpecNode>::iterator t = snodes.begin();
542 t != snodes.end(); ++t) {
544 SpecNode*& p0 = uniq.
add(p);
550 switch (spec.merge_states(state(p0), state(p))) {
585 size_t m = output[i].size();
586 for (
int x = 0; x < tasks; ++x) {
587 size_t j = nodeColumn[x];
588 nodeColumn[x] = (j >= 1) ? m : -1;
592 output.initRow(i, m);
600 #pragma omp for schedule(dynamic) 602 for (
int x = 0; x < tasks; ++x) {
603 if (nodeColumn[x] < 0)
continue;
604 size_t j0 = nodeColumn[x] - 1;
606 for (
int y = 0; y < threads; ++y) {
607 MyList<SpecNode> &snodes = snodeTables[y][x][i];
609 for (; !snodes.empty(); snodes.pop_front()) {
610 SpecNode* p = snodes.front();
613 *srcPtr(p) = code(p) ? NodeId(i, j0 - code(p)) : 0;
614 spec.destruct(state(p));
618 size_t j = j0 + code(p);
619 *srcPtr(p) = NodeId(i, j);
621 Node<AR> &q = output[i][j];
625 for (
int b = 0; b < AR; ++b) {
627 spec.get_copy(s, state(p));
633 int ii = spec.get_child(s, i, b);
636 q.branch[b] = ii ? 1 : 0;
637 if (ii) allZero =
false;
641 int xx = spec.hash_code(s, ii) % tasks;
643 snodeTables[yy][xx][ii].alloc_front(
645 spec.get_copy(state(pp), s);
646 srcPtr(pp) = &q.branch[b];
647 if (ii < lc) lc = ii;
654 if (allZero) ++deadCount;
659 spec.destructLevel(i);
664 if (lc < lowestChild) lowestChild = lc;
667 sweeper.
update(i, lowestChild, deadCount);
682 static int const AR = Spec::ARITY;
685 int const specNodeSize;
686 NodeTableEntity<AR>
const& input;
687 NodeTableEntity<AR>& output;
688 DataTable<MyListOnPool<SpecNode> > work;
691 MyVector<char> oneStorage;
693 MyVector<NodeBranchId> oneSrcPtr;
698 ZddSubsetter(NodeTableHandler<AR>
const& input, Spec
const& s,
699 NodeTableHandler<AR>& output) :
701 specNodeSize(getSpecNodeSize(spec.datasize())),
703 output(output.privateEntity()),
704 work(input->numRows()),
705 sweeper(this->output, oneSrcPtr),
706 oneStorage(spec.datasize()),
707 one(oneStorage.data()) {
711 if (!oneSrcPtr.empty()) {
723 MyVector<char> tmp(spec.datasize());
724 void*
const tmpState = tmp.data();
725 int n = spec.get_root(tmpState);
727 int k = (root == 1) ? -1 : root.row();
729 while (n != 0 && k != 0 && n != k) {
732 k = downTable(root, 0, n);
736 n = downSpec(tmpState, n, 0, k);
740 if (n <= 0 || k <= 0) {
741 assert(n == 0 || k == 0 || (n == -1 && k == -1));
742 root = NodeId(0, n != 0 && k != 0);
747 assert(n == root.row());
750 work[n].resize(input[n].size());
752 SpecNode* p0 = work[n][root.col()].alloc_front(pools[n],
754 spec.get_copy(state(p0), tmpState);
758 spec.destruct(tmpState);
760 if (!oneSrcPtr.empty()) {
772 assert(0 < i && i < output.numRows());
773 assert(output.numRows() - pools.size() == 0);
775 Hasher<Spec>
const hasher(spec, i);
776 MyVector<char> tmp(spec.datasize());
777 void*
const tmpState = tmp.data();
778 size_t const m = input[i].size();
780 int lowestChild = i - 1;
781 size_t deadCount = 0;
783 if (work[i].empty()) work[i].resize(m);
784 assert(work[i].size() == m);
786 for (
size_t j = 0; j < m; ++j) {
787 MyListOnPool<SpecNode> &list = work[i][j];
788 size_t n = list.size();
791 UniqTable uniq(n * 2, hasher, hasher);
793 for (MyListOnPool<SpecNode>::iterator t = list.begin();
794 t != list.end(); ++t) {
796 SpecNode*& p0 = uniq.
add(p);
799 nodeId(p) = *srcPtr(p) = NodeId(i, mm++);
802 switch (spec.merge_states(state(p0), state(p))) {
805 nodeId(p) = *srcPtr(p) = NodeId(i, mm++);
813 *srcPtr(p) = nodeId(p0);
821 SpecNode* p = list.front();
822 nodeId(p) = *srcPtr(p) = NodeId(i, mm++);
826 output.initRow(i, mm);
827 Node<AR>*
const outi = output[i].data();
830 for (
size_t j = 0; j < m; ++j) {
831 MyListOnPool<SpecNode> &list = work[i][j];
833 for (MyListOnPool<SpecNode>::iterator t = list.begin();
834 t != list.end(); ++t) {
836 Node<AR>& q = outi[jj];
838 if (nodeId(p) == 1) {
839 spec.destruct(state(p));
845 for (
int b = 0; b < AR; ++b) {
846 if (nodeId(p) == 0) {
852 spec.get_copy(tmpState, state(p));
853 int kk = downTable(f, b, i - 1);
854 int ii = downSpec(tmpState, i, b, kk);
856 while (ii != 0 && kk != 0 && ii != kk) {
859 kk = downTable(f, 0, ii);
863 ii = downSpec(tmpState, ii, 0, kk);
867 if (ii <= 0 || kk <= 0) {
868 if (ii == 0 || kk == 0) {
872 if (oneSrcPtr.empty()) {
873 spec.get_copy(one, tmpState);
875 oneSrcPtr.push_back(NodeBranchId(i, jj, b));
878 switch (spec.merge_states(one, tmpState)) {
880 while (!oneSrcPtr.empty()) {
881 NodeBranchId
const& nbi =
883 assert(nbi.row >= i);
884 output[nbi.row][nbi.col].branch[nbi.val] =
886 oneSrcPtr.pop_back();
889 spec.get_copy(one, tmpState);
891 oneSrcPtr.push_back(NodeBranchId(i, jj, b));
898 oneSrcPtr.push_back(NodeBranchId(i, jj, b));
906 assert(ii == f.row() && ii == kk && ii < i);
907 if (work[ii].empty()) work[ii].resize(input[ii].size());
908 SpecNode* pp = work[ii][f.col()].alloc_front(pools[ii],
910 spec.get_copy(state(pp), tmpState);
911 srcPtr(pp) = &q.branch[b];
912 if (ii < lowestChild) lowestChild = ii;
916 spec.destruct(tmpState);
919 spec.destruct(state(p));
921 if (allZero) ++deadCount;
927 spec.destructLevel(i);
928 sweeper.
update(i, lowestChild, deadCount);
932 int downTable(NodeId& f,
int b,
int zerosupLevel)
const {
933 if (zerosupLevel < 0) zerosupLevel = 0;
935 f = input.child(f, b);
936 while (f.row() > zerosupLevel) {
937 f = input.child(f, 0);
939 return (f == 1) ? -1 : f.row();
942 int downSpec(
void* p,
int level,
int b,
int zerosupLevel) {
943 if (zerosupLevel < 0) zerosupLevel = 0;
944 assert(level > zerosupLevel);
946 int i = spec.get_child(p, level, b);
947 while (i > zerosupLevel) {
948 i = spec.get_child(p, i, 0);
962 static int const AR = Spec::ARITY;
966 MyVector<Spec> specs;
967 int const specNodeSize;
968 NodeTableEntity<AR>
const& input;
969 NodeTableEntity<AR>& output;
972 MyVector<MyVector<MyVector<MyListOnPool<SpecNode> > > > snodeTables;
973 MyVector<MemoryPools> pools;
978 NodeTableHandler<AR>& output) :
980 threads(omp_get_max_threads()),
986 specNodeSize(getSpecNodeSize(s.datasize())),
988 output(output.privateEntity()),
989 sweeper(this->output),
990 snodeTables(threads),
1000 MyVector<char> tmp(specs[0].datasize());
1001 void*
const tmpState = tmp.data();
1002 Spec& spec = specs[0];
1003 int n = spec.get_root(tmpState);
1005 int k = (root == 1) ? -1 : root.row();
1007 while (n != 0 && k != 0 && n != k) {
1010 k = downTable(root, 0, n);
1014 n = downSpec(spec, tmpState, n, 0, k);
1018 if (n <= 0 || k <= 0) {
1019 assert(n == 0 || k == 0 || (n == -1 && k == -1));
1020 root = NodeId(0, n != 0 && k != 0);
1025 assert(n == root.row());
1027 for (
int y = 0; y < threads; ++y) {
1028 snodeTables[y].resize(n + 1);
1029 pools[y].resize(n + 1);
1032 snodeTables[0][n].resize(input[n].size());
1033 SpecNode* p0 = snodeTables[0][n][root.col()].alloc_front(
1034 pools[0][n], specNodeSize);
1035 spec.get_copy(state(p0), tmpState);
1039 spec.destruct(tmpState);
1049 assert(0 < i && i < output.numRows());
1050 size_t const m = input[i].size();
1052 MyVector<size_t> nodeColumn(m);
1053 int lowestChild = i - 1;
1054 size_t deadCount = 0;
1058 #pragma omp parallel reduction(+:deadCount) 1062 int yy = omp_get_thread_num();
1066 Spec& spec = specs[yy];
1067 MyVector<char> tmp(spec.datasize());
1068 void*
const tmpState = tmp.data();
1069 Hasher<Spec> hasher(spec, i);
1070 UniqTable uniq(hasher, hasher);
1071 int lc = lowestChild;
1074 #pragma omp for schedule(dynamic) 1076 for (intmax_t j = 0; j < intmax_t(m); ++j) {
1078 for (
int y = 0; y < threads; ++y) {
1079 if (snodeTables[y][i].empty())
continue;
1080 MyListOnPool<SpecNode> &snodes = snodeTables[y][i][j];
1081 mm += snodes.size();
1086 for (
int y = 0; y < threads; ++y) {
1087 if (snodeTables[y][i].empty())
continue;
1088 MyListOnPool<SpecNode> &snodes = snodeTables[y][i][j];
1090 for (MyListOnPool<SpecNode>::iterator t = snodes.begin();
1091 t != snodes.end(); ++t) {
1093 SpecNode* pp = uniq.
add(p);
1099 code(p) = -code(pp);
1100 if (
int prune = spec.merge_states(state(pp),
1102 if (prune & 1) code(pp) = 0;
1103 if (prune & 2) code(p) = 0;
1117 for (
size_t j = 0; j < m; ++j) {
1118 size_t jj = nodeColumn[j];
1123 output.initRow(i, mm);
1127 #pragma omp for schedule(dynamic) 1129 for (intmax_t j = 0; j < intmax_t(m); ++j) {
1130 size_t const jj0 = nodeColumn[j] - 1;
1132 for (
int y = 0; y < threads; ++y) {
1133 if (snodeTables[y][i].empty())
continue;
1135 MyListOnPool<SpecNode> &snodes = snodeTables[y][i][j];
1137 for (MyListOnPool<SpecNode>::iterator t = snodes.begin();
1138 t != snodes.end(); ++t) {
1142 *srcPtr(p) = code(p) ? NodeId(i, jj0 - code(p)) : 0;
1143 spec.destruct(state(p));
1147 size_t const jj = jj0 + code(p);
1148 *srcPtr(p) = NodeId(i, jj);
1149 Node<AR> &q = output[i][jj];
1150 bool allZero =
true;
1153 for (
int b = 0; b < AR; ++b) {
1155 spec.get_copy(s, state(p));
1162 int kk = downTable(f, b, i - 1);
1163 int ii = downSpec(spec, s, i, b, kk);
1165 while (ii != 0 && kk != 0 && ii != kk) {
1168 kk = downTable(f, 0, ii);
1172 ii = downSpec(spec, s, ii, 0, kk);
1176 if (ii <= 0 || kk <= 0) {
1177 bool val = ii != 0 && kk != 0;
1179 if (val) allZero =
false;
1182 assert(ii == f.row() && ii == kk && ii < i);
1183 size_t jj = f.col();
1185 if (snodeTables[yy][ii].empty()) {
1186 snodeTables[yy][ii].resize(
1191 snodeTables[yy][ii][jj].alloc_front(
1192 pools[yy][ii], specNodeSize);
1193 spec.get_copy(state(pp), s);
1194 srcPtr(pp) = &q.branch[b];
1195 if (ii < lc) lc = ii;
1202 if (allZero) ++deadCount;
1207 snodeTables[yy][i].clear();
1208 pools[yy][i].clear();
1209 spec.destructLevel(i);
1212 #pragma omp critical 1214 if (lc < lowestChild) lowestChild = lc;
1217 sweeper.
update(i, lowestChild, deadCount);
1221 int downTable(NodeId& f,
int b,
int zerosupLevel)
const {
1222 if (zerosupLevel < 0) zerosupLevel = 0;
1224 f = input.child(f, b);
1225 while (f.row() > zerosupLevel) {
1226 f = input.child(f, 0);
1228 return (f == 1) ? -1 : f.row();
1231 int downSpec(Spec& spec,
void* p,
int level,
int b,
int zerosupLevel) {
1232 if (zerosupLevel < 0) zerosupLevel = 0;
1233 assert(level > zerosupLevel);
1235 int i = spec.get_child(p, level, b);
1236 while (i > zerosupLevel) {
1237 i = spec.get_child(p, i, 0);
1247 template<
typename S>
1250 static int const AR = Spec::ARITY;
1251 static int const headerSize = 1;
1262 static NodeId& nodeId(SpecNode* p) {
1266 static NodeId nodeId(SpecNode
const* p) {
1270 static void* state(SpecNode* p) {
1271 return p + headerSize;
1274 static void const* state(SpecNode
const* p) {
1275 return p + headerSize;
1278 template<
typename SPEC>
1283 Hasher(SPEC
const& spec,
int level) :
1284 spec(spec), level(level) {
1287 size_t operator()(SpecNode
const* p)
const {
1288 return spec.hash_code(state(p), level);
1291 size_t operator()(SpecNode
const* p, SpecNode
const* q)
const {
1292 return spec.equal_to(state(p), state(q), level);
1298 static int getSpecNodeSize(
int n) {
1300 throw std::runtime_error(
"storage size is not initialized!!!");
1301 return headerSize + (n +
sizeof(SpecNode) - 1) /
sizeof(SpecNode);
1305 int const specNodeSize;
1309 MyVector<MyList<SpecNode> > snodeTable;
1310 MyVector<UniqTable> uniqTable;
1311 MyVector<Hasher<Spec> > hasher;
1316 specNodeSize(getSpecNodeSize(spec.datasize())),
1323 spec.destruct(oneState);
1333 void dump(std::ostream& os, std::string title) {
1335 spec.destruct(oneState);
1338 oneState =
new char[spec.datasize()];
1340 int n = spec.get_root(oneState);
1342 os <<
"digraph \"" << title <<
"\" {\n";
1345 if (!title.empty()) {
1346 os <<
" labelloc=\"t\";\n";
1347 os <<
" label=\"" << title <<
"\";\n";
1351 os <<
" \"^\" [shape=none,label=\"" << title <<
"\"];\n";
1352 os <<
" \"^\" -> \"" << oneId <<
"\" [style=dashed" <<
"];\n";
1353 os <<
" \"" << oneId <<
"\" ";
1354 os <<
"[shape=square,margin=0.05,width=0,label=\"T\"];\n";
1359 for (
int i = n; i >= 1; --i) {
1360 os <<
" " << i <<
" [shape=none,label=\"";
1361 spec.printLevel(os, i);
1364 for (
int i = n - 1; i >= 1; --i) {
1365 os <<
" " << (i + 1) <<
" -> " << i <<
" [style=invis];\n";
1368 os <<
" \"^\" [shape=none,label=\"" << title <<
"\"];\n";
1369 os <<
" \"^\" -> \"" << root <<
"\" [style=dashed" <<
"];\n";
1371 snodeTable.init(n + 1);
1372 SpecNode* p = snodeTable[n].alloc_front(specNodeSize);
1373 spec.get_copy(state(p), oneState);
1377 uniqTable.reserve(n + 1);
1379 hasher.reserve(n + 1);
1380 for (
int i = 0; i <= n; ++i) {
1381 hasher.push_back(Hasher<Spec>(spec, i));
1382 uniqTable.push_back(UniqTable(hasher.back(), hasher.back()));
1385 for (
int i = n; i >= 1; --i) {
1389 for (
size_t j = 2; j < oneId.code(); ++j) {
1390 os <<
" \"" << NodeId(j) <<
"\" ";
1391 os <<
"[style=invis];\n";
1393 os <<
" \"" << oneId <<
"\" ";
1394 os <<
"[shape=square,margin=0.05,width=0,label=\"T\"];\n";
1402 void dumpStep(std::ostream& os,
int i) {
1403 MyList<SpecNode> &snodes = snodeTable[i];
1404 size_t const m = snodes.size();
1405 MyVector<char> tmp(spec.datasize());
1406 void*
const tmpState = tmp.data();
1407 MyVector<Node<AR> > nodeList(m);
1409 for (
size_t j = m - 1; j + 1 > 0; --j, snodes.pop_front()) {
1411 assert(!snodes.empty());
1412 SpecNode* p = snodes.front();
1414 os <<
" \"" << f <<
"\" [label=\"";
1415 spec.print_state(os, state(p), i);
1418 for (
int b = 0; b < AR; ++b) {
1419 NodeId& child = nodeList[j].branch[b];
1421 if (nodeId(p) == 0) {
1426 spec.get_copy(tmpState, state(p));
1427 int ii = spec.get_child(tmpState, i, b);
1435 spec.destruct(oneState);
1436 spec.get_copy(oneState, tmpState);
1440 switch (spec.merge_states(oneState, tmpState)) {
1442 oneId = oneId.code() + 1;
1443 spec.destruct(oneState);
1444 spec.get_copy(oneState, tmpState);
1457 SpecNode* pp = snodeTable[ii].alloc_front(specNodeSize);
1458 size_t jj = snodeTable[ii].size() - 1;
1459 spec.get_copy(state(pp), tmpState);
1461 SpecNode*& pp0 = uniqTable[ii].add(pp);
1463 nodeId(pp) = child = NodeId(ii, jj);
1466 switch (spec.merge_states(state(pp0), state(pp))) {
1469 nodeId(pp) = child = NodeId(ii, jj);
1474 spec.destruct(state(pp));
1475 snodeTable[ii].pop_front();
1478 child = nodeId(pp0);
1479 spec.destruct(state(pp));
1480 snodeTable[ii].pop_front();
1486 spec.destruct(tmpState);
1489 spec.destruct(state(p));
1492 for (
size_t j = 0; j < m; ++j) {
1493 for (
int b = 0; b < AR; ++b) {
1495 NodeId child = nodeList[j].branch[b];
1496 if (child == 0)
continue;
1497 if (child == 1) child = oneId;
1499 os <<
" \"" << f <<
"\" -> \"" << child <<
"\"";
1509 << ((b == 1) ?
"blue" : (b == 2) ?
"red" :
"green");
1516 os <<
" {rank=same; " << i;
1517 for (
size_t j = 0; j < m; ++j) {
1518 os <<
"; \"" << NodeId(i, j) <<
"\"";
1522 uniqTable[i - 1].clear();
1523 spec.destructLevel(i);
Closed hash table implementation.
int initialize(NodeId &root)
Initializes the builder.
Entry & add(Entry const &elem)
Insert an element if no other equivalent element is registered.
Basic breadth-first DD builder.
Breadth-first ZDD subset builder.
void subset(int i)
Builds one level.
void schedule(NodeId *fp, int level, void *s)
Schedules a top-down event.
void update(int current, int child, size_t count)
Updates status and sweeps the DD if necessary.
Multi-threaded breadth-first ZDD subset builder.
void schedule(NodeId *fp, int level, void *s)
Schedules a top-down event.
void subset(int i)
Builds one level.
int initialize(NodeId &root)
Initializes the builder.
void initialize(size_t n)
Initialize the table to be empty.
void dump(std::ostream &os, std::string title)
Dumps the node table in Graphviz (dot) format.
int initialize(NodeId &root)
Initializes the builder.
void setRoot(NodeId &root)
Set the root pointer.
int initialize(NodeId &root)
Initializes the builder.
void construct(int i)
Builds one level.
void construct(int i)
Builds one level.
Multi-threaded breadth-first DD builder.