c ++和boost库的哈希问题

时间:2015-04-25 08:35:47

标签: c++ boost hash codeblocks unordered-set

我正在为图表挖掘编写代码。 以下是完整的源代码:http://pastebin.com/BpjZPcEi

我试图使用std unordered_set但我在这方面遇到了问题:

bool edgeexist(Graph const& g, int const& fromid, int const& toid, unsigned const& elabel) {
    int bn = 0;

        if (num_edges(g) != 0) {
            edge_pair ep;
            for (ep = edges(g); ep.first != ep.second; ++ep.first) // ep edge number
            {
                vertex_t from = source(*ep.first, g);
                vertex_t to = target(*ep.first, g);
                edge_t edg = edge(from, to, g);

                if ((g[from].id == fromid) && (g[to].id == toid) && (g[edg.first].label == elabel)) {
                    return true;
                }

        }
    }

    return false;
}


std::unordered_set<std::array<int, 3>>  edgesdiff(Graph const& g1,Graph const& g2){

    std::unordered_set<edge_iter> v1,v2,diff;
    std::array<int, 3> t;
    std::unordered_set<std::array<int, 3>> res;


    for(auto x:edges(g1)){

            vertex_t from = source(*x, g1);
            t[0]=g1[from].id;

            vertex_t to = target(*x, g1);
            t[1]=g1[to].id;

            edge_t edg = edge(from, to, g1);
            t[2]=g1[edg.first].label;

        if(!edgeexist(g2,t[0],t[1],t[2])){res.insert(t);}


    }

return res;
}

当我在代码块上运行程序时,我收到了这条消息:

/usr/include/c++/4.9/bits/hashtable_policy.h|85|error: no match for call to ‘(const hashedge) (const boost::detail::undirected_edge_iter<std::_List_iterator<boost::list_edge<unsigned int, EdgeProperties> >, boost::detail::edge_desc_impl<boost::undirected_tag, unsigned int>, int>&)’|

这意味着什么,我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

读取代码后,无序集的散列函数不会带两个参数(更不用说Graph 按值☹)。

你至少需要这样的东西(让它可读!)

struct hashedge {
    hashedge(Graph const &g) : _g(g) {}

    size_t operator()(const edge_iter e) const {
        using namespace boost;
        size_t seed = 42;
        hash_combine(seed, _g[source(*e, _g)]);
        hash_combine(seed, _g[*e].label);
        hash_combine(seed, _g[target(*e, _g)]);
        return seed;
    }

private:
    Graph const &_g;
};

这使用了一个征服来散列捆绑的属性。所以你分别定义它们:

namespace boost {
template <> struct hash<VertexProperties> {
    size_t operator()(VertexProperties const &v) const {
        using namespace boost;
        auto seed = hash_value(v.id);
        hash_combine(seed, v.label);
        return seed;
    }
};
template <> struct hash<EdgeProperties> {
    size_t operator()(EdgeProperties const &e) const {
        using namespace boost;
        auto seed = hash_value(e.id);
        hash_combine(seed, e.label);
        return seed;
    }
};
}

编译并运作。

现在您与unordered_set<Graph>存在类似问题。我很确定你是从错误的一端看这个。你能比较传递性凝结吗?你能用过滤图吗?

这是一个部分演示,使用edge_descriptor而不是edge_iterator(因为,为什么是迭代器?):

<强> Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <iostream>
#include <unordered_set>

struct VertexProperties {
    int id;
    int label;
    VertexProperties(unsigned i = 0, unsigned l = 0) : id(i), label(l) {}
};

struct EdgeProperties {
    unsigned id;
    unsigned label;
    EdgeProperties(unsigned i = 0, unsigned l = 0) : id(i), label(l) {}
};

namespace boost {
template <> struct hash<VertexProperties> {
    size_t operator()(VertexProperties const &v) const {
        auto seed = hash_value(v.id);
        hash_combine(seed, v.label);
        return seed;
    }
};
template <> struct hash<EdgeProperties> {
    size_t operator()(EdgeProperties const &e) const {
        auto seed = hash_value(e.id);
        hash_combine(seed, e.label);
        return seed;
    }
};
}

struct GraphProperties {
    unsigned id;
    unsigned label;
    GraphProperties(unsigned i = 0, unsigned l = 0) : id(i), label(l) {}
};

// adjacency_list
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, VertexProperties, EdgeProperties, GraphProperties> Graph;
typedef boost::graph_traits<Graph>::edge_descriptor edge_descriptor;

struct hashedge {
    hashedge(Graph const &g) : _g(g) {}

    size_t operator()(const edge_descriptor e) const {
        using namespace boost;

        size_t seed = 42;
        hash_combine(seed, _g[source(e, _g)]);
        hash_combine(seed, _g[e].label);
        hash_combine(seed, _g[target(e, _g)]);
        return seed;
    }

    private:
    Graph const &_g;
};

int main() {
    std::vector<Graph> dataG;
    for (auto& g : dataG) {
        auto es = edges(g);
        std::unordered_set<edge_descriptor, hashedge> edgehash(es.first, es.second, 0ul, hashedge(g));
    }
}