uint64_t count64() { MessageHandler mh; mh.begin("counting") << " paths of " << typenameof(spec); std::vector<Word> tmp(stateWords + 1); Word* ptmp = tmp.data(); int const n = spec.get_root(state(ptmp)); if (n <= 0) { mh << " ..."; mh.end(0); return (n == 0) ? 0 : 1; } mh << "\n"; uint64_t total = 0; size_t maxWidth = 0; //std::cerr << "\nLevel,Width\n"; std::vector<MemoryPool> pools(n + 1); MyVector<MyList<Word> > vnodeTable(n + 1); MyVector<UniqTable> uniqTable; uniqTable.reserve(n + 1); for (int i = 0; i <= n; ++i) { uniqTable.push_back(UniqTable(hasher, hasher)); } Word* p0 = vnodeTable[n].alloc_front(stateWords + 1); spec.get_copy(state(p0), state(ptmp)); spec.destruct(state(ptmp)); number64(p0) = 1; for (int i = n; i > 0; --i) { MyList<Word>& vnodes = vnodeTable[i]; size_t m = vnodes.size(); //std::cerr << i << "," << m << "\n"; maxWidth = std::max(maxWidth, m); MyList<Word>& nextVnodes = vnodeTable[i - 1]; UniqTable& nextUniq = uniqTable[i - 1]; Word* pp = nextVnodes.alloc_front(stateWords + 1); //if (nextUniq.size() < m) nextUniq.rehash(m); for (; !vnodes.empty(); vnodes.pop_front()) { Word* p = vnodes.front(); if (number64(p) == 0) { spec.destruct(state(p)); continue; } for (int b = 0; b <= 1; ++b) { spec.get_copy(state(pp), state(p)); int ii = spec.get_child(state(pp), i, b); if (ii <= 0) { spec.destruct(state(pp)); if (ii != 0) { total += number64(p); } } else if (ii < i - 1) { Word* qq = vnodeTable[ii].alloc_front(stateWords + 1); spec.get_copy(state(qq), state(pp)); spec.destruct(state(pp)); Word* qqq = uniqTable[ii].add(qq); if (qqq == qq) { number64(qqq) = number64(p); } else { spec.destruct(state(qq)); number64(qqq) += number64(p); vnodeTable[ii].pop_front(); } } else { assert(ii == i - 1); Word* ppp = nextUniq.add(pp); if (ppp == pp) { number64(ppp) = number64(p); pp = nextVnodes.alloc_front(stateWords + 1); } else { spec.destruct(state(pp)); number64(ppp) += number64(p); } } } spec.destruct(state(p)); } nextVnodes.pop_front(); nextUniq.clear(); pools[i].clear(); spec.destructLevel(i); mh << "."; } mh.end(maxWidth); return total; }
std::string count() { MessageHandler mh; mh.begin("counting") << " paths of " << typenameof(spec); std::vector<Word> tmp(stateWords + 1); Word* ptmp = tmp.data(); int const n = spec.get_root(state(ptmp)); if (n <= 0) { mh << " ..."; mh.end(0); return (n == 0) ? "0" : "1"; } uint64_t totalStorage[n / 63 + 1]; BigNumber total(totalStorage); total.store(0); size_t maxWidth = 0; //std::cerr << "\nLevel,Width\n"; std::vector<MemoryPool> pools(n + 1); MyVector<MyList<Word> > vnodeTable(n + 1); MyVector<UniqTable> uniqTable; uniqTable.reserve(n + 1); for (int i = 0; i <= n; ++i) { uniqTable.push_back(UniqTable(hasher, hasher)); } int numberWords = 1; Word* p0 = vnodeTable[n].alloc_front(stateWords + 1); spec.get_copy(state(p0), state(ptmp)); spec.destruct(state(ptmp)); number(p0).store(1); mh.setSteps(n); for (int i = n; i > 0; --i) { MyList<Word>& vnodes = vnodeTable[i]; size_t m = vnodes.size(); //std::cerr << i << "," << m << "\n"; maxWidth = std::max(maxWidth, m); MyList<Word>& nextVnodes = vnodeTable[i - 1]; UniqTable& nextUniq = uniqTable[i - 1]; int const nextWords = stateWords + numberWords + 1; Word* pp = nextVnodes.alloc_front(nextWords); //if (nextUniq.size() < m) nextUniq.rehash(m); for (; !vnodes.empty(); vnodes.pop_front()) { Word* p = vnodes.front(); if (number(p).equals(0)) { spec.destruct(state(p)); continue; } for (int b = 0; b <= 1; ++b) { spec.get_copy(state(pp), state(p)); int ii = spec.get_child(state(pp), i, b); if (ii <= 0) { spec.destruct(state(pp)); if (ii != 0) { total.add(number(p)); } } else if (ii < i - 1) { Word* qq = vnodeTable[ii].alloc_front( nextWords + (i - ii) / 63); spec.get_copy(state(qq), state(pp)); spec.destruct(state(pp)); Word* qqq = uniqTable[ii].add(qq); if (qqq == qq) { number(qqq).store(number(p)); } else { spec.destruct(state(qq)); int w = number(qqq).add(number(p)); if (numberWords < w) { numberWords = w; //FIXME might be broken at long skip } vnodeTable[ii].pop_front(); } } else { assert(ii == i - 1); Word* ppp = nextUniq.add(pp); if (ppp == pp) { number(ppp).store(number(p)); pp = nextVnodes.alloc_front(nextWords); } else { spec.destruct(state(pp)); int w = number(ppp).add(number(p)); if (numberWords < w) { numberWords = w; //FIXME might be broken at long skip } } } } spec.destruct(state(p)); } nextVnodes.pop_front(); nextUniq.clear(); pools[i].clear(); spec.destructLevel(i); mh.step(); } mh.end(maxWidth); return total; }
int main(int argc, char *argv[]) { optNum["uec"] = -1; optNum["lb"] = 0; optNum["ub"] = INT_MAX; for (unsigned i = 0; i < sizeof(options) / sizeof(options[0]); ++i) { opt[options[i][0]] = false; } std::string graphFileName; std::string termFileName; try { for (int i = 1; i < argc; ++i) { std::string s = argv[i]; if (s[0] == '-') { s = s.substr(1); if (opt.count(s)) { opt[s] = true; } else if (i + 1 < argc && opt.count(s + " <n>")) { opt[s] = true; optNum[s] = std::atoi(argv[++i]); } else if (i + 1 < argc && opt.count(s + " " + argv[i + 1])) { opt[s] = true; optStr[s] = argv[++i]; } else { throw std::exception(); } } else if (graphFileName.empty()) { graphFileName = s; } else if (termFileName.empty()) { termFileName = s; } else { throw std::exception(); } } } catch (std::exception& e) { usage(argv[0]); return 1; } MessageHandler::showMessages(); MessageHandler mh; mh.begin("started"); GraphillionZdd base; if (opt["import"]) { base.read(); } Graph g; try { if (!graphFileName.empty()) { if (opt["a"]) { g.readAdjacencyList(graphFileName); } else { g.readEdges(graphFileName); } } else { g.addEdge("v1", "v2"); g.addEdge("v1", "v3"); g.addEdge("v1", "v4"); g.addEdge("v2", "v4"); g.addEdge("v2", "v5"); g.addEdge("v3", "v4"); g.addEdge("v3", "v6"); g.addEdge("v4", "v5"); g.addEdge("v4", "v6"); g.addEdge("v4", "v7"); g.addEdge("v5", "v7"); g.addEdge("v6", "v7"); g.setColor("v2", 0); g.setColor("v3", 0); g.update(); } if (!termFileName.empty()) { g.readVertexGroups(termFileName); } int const m = g.vertexSize(); int const n = g.edgeSize(); if (opt["st"] && m >= 1) { g.setColor(g.vertexName(1), 0); g.setColor(g.vertexName(m), 0); g.update(); } mh << "#vertex = " << m << ", #edge = " << n << ", #color = " << g.numColor() << "\n"; if (g.edgeSize() == 0) throw std::runtime_error( "ERROR: The graph is empty!!!"); if (opt["graph"]) { g.dump(std::cout); return 0; } DdStructure<2> dd(n); if (opt["import"]) { dd = DdStructure<2>(base); // dd.dumpDot(std::cout, g.edgeLabeler()); mh << "#node = " << dd.size() << ", #solution = " << dd.evaluate(ZddCardinality<>()) << "\n\n"; } if (opt["path"]) { if (!opt["uec"]) optNum["uec"] = 0; IntRange zeroOrTwo(0, 2, 2); IntRange justOne(1, 1); DegreeConstraint dc(g); for (int v = 1; v <= g.vertexSize(); ++v) { if (g.colorNumber(v) == 0) { dc.setConstraint(v, &zeroOrTwo); } else { dc.setConstraint(v, &justOne); } } dd.zddSubset(dc); mh << "#node = " << dd.size() << ", #solution = " << dd.evaluate(ZddCardinality<>()) << "\n\n"; } if (opt["matching"]) { IntRange zeroOrOne(0, 1); DegreeConstraint dc(g, &zeroOrOne); dd.zddSubset(dc); mh << "#node = " << dd.size() << ", #solution = " << dd.evaluate(ZddCardinality<>()) << "\n\n"; } if (opt["spanning"]) { IntRange oneOrMore(1); DegreeConstraint dc(g); for (int v = 1; v <= g.vertexSize(); ++v) { if (g.colorNumber(v) == 0) { dc.setConstraint(v, &oneOrMore); } } dd.zddSubset(dc); mh << "#node = " << dd.size() << ", #solution = " << dd.evaluate(ZddCardinality<>()) << "\n\n"; } if (opt["lb"] || opt["ub"]) { IntRange r(optNum["lb"], optNum["ub"]); SizeConstraint sc(g.edgeSize(), &r); dd.zddSubset(sc); mh << "#node = " << dd.size() << ", #solution = " << dd.evaluate(ZddCardinality<>()) << "\n\n"; } FrontierBasedSearch fbs(g, optNum["uec"], opt["noloop"]); dd.zddSubset(fbs); if (opt["zdd"]) dd.dumpDot(std::cout, "ZDD"); if (opt["export"]) dd.dumpSapporo(std::cout); mh << "#node = " << dd.size() << ", #solution = " << dd.evaluate(ZddCardinality<>()) << "\n\n"; if (opt["sapporo"]) { BDD_Init(1024, 1024 * 1024 * 1024); MessageHandler mh; mh.begin("ToZBDD") << " ..."; ZBDD f = dd.evaluate(ToZBDD()); mh.end(f.Size()); } if (opt["solutions"]) { int const n = g.edgeSize(); int count = optNum["solutions"]; for (typeof(dd.begin()) t = dd.begin(); t != dd.end(); ++t) { EdgeDecorator edges; edges.selected.resize(n); for (size_t i = 0; i < t->size(); ++i) { edges.selected[n - (*t)[i]] = true; } g.dump(std::cout, edges); if (--count == 0) break; } } } catch (std::exception& e) { std::cerr << e.what() << "\n"; return 1; } mh.end(); return 0; }