Exemple #1
0
    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;
    }
Exemple #2
0
    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;
}