I\'m currently working on a project that enumerates the k-best solutions of a dynamic program using a directed hypergraph framework. My current implementation (in Python) w
I don't know of a library, but you could roll your own.
After messing around with the code for three days, I finally got a hypermap to compile without warnings on MSVC10 and GCC(http://ideone.com/oj46o).
Declarations:
#include
Definitions:
#include
#include
template
inline hypergraph::vertex::vertex(const PE& pred, const typename hypergraph::sub_allocator& alloc)
: edges_(pred, alloc)
{}
template
inline hypergraph::vertex::vertex(typename hypergraph::vertex&& rhs)
: edges_(std::move(rhs.edges_))
{}
template
inline typename hypergraph::vertex& hypergraph::vertex::operator=(typename hypergraph::vertex&& rhs)
{
edges_ = std::move(rhs);
return *this;
}
template
inline typename hypergraph::iedgeset& hypergraph::vertex::edges()
{return edges_;}
template
inline const typename hypergraph::iedgeset& hypergraph::vertex::edges() const
{return edges_;}
template
inline hypergraph::edge::edge(const PV& pred, const typename hypergraph::sub_allocator& alloc)
: vertices_(pred, alloc)
, head_(vertices_.end())
{}
template
inline hypergraph::edge::edge(edge&& rhs)
: vertices_(rhs.vertices_)
, head_(rhs.head_!=rhs.vertices_.end() ? vertices_.find(rhs.head_->first) : vertices_.end())
{}
template
inline typename hypergraph::edge& hypergraph::edge::operator=(typename hypergraph::edge&& rhs)
{
vertices_ = std::move(rhs);
if (rhs.head_ != rhs.vertices_.end())
head_ = vertices_.find(rhs.head_->first);
else
head_ = vertices_.end();
return *this;
}
template
inline void hypergraph::edge::set_head(const V& v)
{
ivertexiter iter = vertices_.find(std::ref(v));
assert(iter != vertices_.end());
head_ = iter;
}
template
inline const V* hypergraph::edge::get_head() const
{return (head_ != vertices_.end() ? &head_->first.get() : NULL);}
template
inline const typename hypergraph::ivertexset& hypergraph::edge::vertices() const
{ return vertices_; }
template
inline typename hypergraph::ivertexset& hypergraph::edge::vertices()
{ return vertices_; }
template
inline hypergraph::hypergraph(const PV& vertexpred, const PE& edgepred, const A& alloc)
:pv_(vertexpred)
,pe_(edgepred)
,a_(alloc)
,vertices_(vertexpred, a_)
,edges_(edgepred, a_)
{}
template
inline std::pair::vertexiter, bool> hypergraph::add_vertex(V v)
{ return vertices_.insert(std::pair(std::move(v),vertex(pe_, a_))); }
template
inline std::pair::edgeiter, bool> hypergraph::add_edge(E e)
{ return edges_.insert(std::pair(std::move(e), edge(pv_, a_))); }
template
inline typename hypergraph::vertexiter hypergraph::erase_vertex(const typename hypergraph::vertexiter& iter)
{
for(auto i = iter->edges().begin(); i != iter->edges().end(); ++i)
i->erase(*iter);
return vertices_.erase(iter);
}
template
inline typename hypergraph::vertexiter hypergraph::erase_vertex(const V& rhs)
{
vertexiter vi = vertices_.find(rhs);
assert(vi != vertices_.end());
vertex& v = vi->second;
for(auto i = v.edges().begin(); i != v.edges().end(); ++i)
i->second.get().vertices_.erase(std::ref(vi->first));
return vertices_.erase(vi);
}
template
inline typename hypergraph::edgeiter hypergraph::erase_edge(const typename hypergraph::edgeiter& iter)
{
for(auto i = iter->vertices().begin(); i != iter->vertices().end(); ++i)
i->edges_.erase(*iter);
return edges_.erase(iter);
}
template
inline typename hypergraph::edgeiter hypergraph::erase_edge(const E& rhs)
{
edgeiter ei = edges_.find(rhs);
assert(ei != edges_.end());
edge& e = ei->second;
for(auto i = e.vertices().begin(); i != e.vertices().end(); ++i)
i->second.get().edges_.erase(std::ref(ei->first));
return edges_.erase(ei);
}
template
inline void hypergraph::connect(const E& e, const V& v)
{
vertexiter vi = vertices_.find(v);
edgeiter ei = edges_.find(e);
assert(vi != vertices_.end());
assert(ei != edges_.end());
vi->second.edges_.insert(typename iedgeset::value_type(std::ref(ei->first), std::ref(ei->second)));
auto n = ei->second.vertices_.insert(typename ivertexset::value_type(std::ref(vi->first), std::ref(vi->second)));
if (ei->second.vertices_.size()==1)
ei->second.head_ = n.first;
}
template
inline void hypergraph::connect(const typename hypergraph::edgeiter& ei, const typename hypergraph::vertexiter& vi)
{
assert(std::distance(vertices_.begin(), vi)>=0); //actually asserts that the iterator belongs to this container
assert(std::distance(edges_.begin(), ei)>=0); //actually asserts that the iterator belongs to this container
vi->edges_.insert(typename iedgeset::value_type(std::ref(ei->first), std::ref(ei->second)));
auto n = ei->vertices_.insert(typename ivertexset::value_type(std::ref(vi->first), std::ref(vi->second)));
if (ei->second.verticies_.size()==1)
ei->second.head_ = n.first;
}
template
inline void hypergraph::disconnect(const E& e, const V& v)
{
edgeiter ei = edges_.find(e);
vertexiter vi = vertices_.find(v);
assert(ei != edges.end());
assert(vi != vertices_.end());
if (ei->head_.first == v) {
if (ei->head_ != ei->vertices.begin())
ei->head = ei->vertices.begin();
else
ei->head = ei->vertices.end();
}
ei->vertices_.erase(std::ref(vi->first));
vi->edges_.erase(std::ref(ei->first));
}
template
inline void hypergraph::disconnect(const typename hypergraph::edgeiter& ei, const typename hypergraph::vertexiter& vi)
{
assert(std::distance(edges_.begin(), ei)>=0); //actually asserts that the iterator belongs to this container
assert(std::distance(vertices_.begin(), vi)>=0); //actually asserts that the iterator belongs to this container
if (ei->head_.first == vi->first) {
if (ei->head_ != ei->vertices.begin())
ei->head = ei->vertices.begin();
else
ei->head = ei->vertices.end();
}
ei->vertices_.erase(std::ref(vi->first));
vi->edges_.erase(std::ref(ei->first));
}
template
inline typename hypergraph::vertexset& hypergraph::vertices()
{ return vertices_;}
template
inline const typename hypergraph::vertexset& hypergraph::vertices() const
{ return vertices_;}
template
inline typename hypergraph::edgeset& hypergraph::edges()
{ return edges_;}
template
inline const typename hypergraph::edgeset& hypergraph::edges() const
{ return edges_;}
template
inline A hypergraph::get_allocator() const
{ return a_;}
namespace std {
template
std::basic_ostream& operator<<(std::basic_ostream& s, const std::reference_wrapper& r)
{return s << r.get();}
template
std::basic_istream& operator>>(std::basic_istream& s, std::reference_wrapper& r)
{return s >> r.get();}
}
Note that this is not thoroughly tested, but it compiles and ran through my mini-suite without errors. (As shown in the IDEOne link). The Vertex types and the Edge identifiers can be any types you want, I tested with int verteces and string edge identifiers.