mirror of
https://github.com/boostorg/graph.git
synced 2026-01-29 07:32:21 +00:00
libs/graph/src/python/basic_graph.cpp, libs/graph/src/python/basic_graph.hpp:
- Allow one to build a graph from anything that looks like a Python list or
tuple.
[SVN r28324]
482 lines
16 KiB
C++
482 lines
16 KiB
C++
// Copyright 2004-5 The Trustees of Indiana University.
|
|
|
|
// Use, modification and distribution is subject to the Boost Software
|
|
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
// Authors: Douglas Gregor
|
|
// Andrew Lumsdaine
|
|
#ifndef BOOST_GRAPH_BASIC_GRAPH_HPP
|
|
#define BOOST_GRAPH_BASIC_GRAPH_HPP
|
|
|
|
#include <boost/graph/graph_traits.hpp>
|
|
#include <boost/graph/adjacency_list.hpp>
|
|
#include <boost/iterator/transform_iterator.hpp>
|
|
#include <boost/vector_property_map.hpp>
|
|
#include <boost/dynamic_property_map.hpp>
|
|
#include <boost/random/linear_congruential.hpp>
|
|
#include <boost/graph/erdos_renyi_generator.hpp>
|
|
#include <boost/graph/plod_generator.hpp>
|
|
#include <boost/graph/small_world_generator.hpp>
|
|
#include <boost/python.hpp>
|
|
#include "point2d.hpp"
|
|
#include "generators.hpp"
|
|
|
|
namespace boost { namespace graph { namespace python {
|
|
|
|
template<typename T> bool type_already_registered()
|
|
{
|
|
using boost::python::objects::registered_class_object;
|
|
using boost::python::type_id;
|
|
|
|
return registered_class_object(type_id<T>()).get() != 0;
|
|
}
|
|
|
|
template<typename Iterator>
|
|
class simple_python_iterator
|
|
{
|
|
public:
|
|
simple_python_iterator(std::pair<Iterator, Iterator> p)
|
|
: first(p.first), last(p.second) { }
|
|
|
|
typename std::iterator_traits<Iterator>::value_type next()
|
|
{
|
|
using boost::python::objects::stop_iteration_error;
|
|
|
|
if (first == last) stop_iteration_error();
|
|
return *first++;
|
|
}
|
|
|
|
static void declare(const char* name)
|
|
{
|
|
using boost::python::class_;
|
|
using boost::python::no_init;
|
|
using boost::python::objects::identity_function;
|
|
if (!type_already_registered<simple_python_iterator>())
|
|
class_<simple_python_iterator<Iterator> >(name, no_init)
|
|
.def("__iter__", identity_function())
|
|
.def("next", &simple_python_iterator<Iterator>::next)
|
|
;
|
|
}
|
|
|
|
private:
|
|
Iterator first;
|
|
Iterator last;
|
|
};
|
|
|
|
template<typename PropertyMap>
|
|
struct declare_readable_property_map
|
|
{
|
|
typedef typename property_traits<PropertyMap>::key_type key_type;
|
|
typedef typename property_traits<PropertyMap>::value_type value_type;
|
|
|
|
static value_type getitem(const PropertyMap& pm, const key_type& key)
|
|
{ return get(pm, key); }
|
|
|
|
static void declare(const char* name)
|
|
{
|
|
using boost::python::class_;
|
|
using boost::python::no_init;
|
|
|
|
if (!type_already_registered<PropertyMap>())
|
|
class_<PropertyMap>(name, no_init)
|
|
.def("__getitem__", &getitem)
|
|
;
|
|
}
|
|
};
|
|
|
|
template<typename PropertyMap>
|
|
struct declare_property_map
|
|
{
|
|
typedef typename property_traits<PropertyMap>::key_type key_type;
|
|
typedef typename property_traits<PropertyMap>::value_type value_type;
|
|
|
|
static value_type getitem(const PropertyMap& pm, const key_type& key)
|
|
{ return get(pm, key); }
|
|
|
|
static void
|
|
setitem(const PropertyMap& pm, const key_type& key,const value_type& value)
|
|
{ return put(pm, key, value); }
|
|
|
|
static void declare(const char* name)
|
|
{
|
|
using boost::python::class_;
|
|
using boost::python::no_init;
|
|
|
|
if (!type_already_registered<PropertyMap>())
|
|
class_<PropertyMap>(name, no_init)
|
|
.def("__getitem__", &getitem)
|
|
.def("__setitem__", &setitem)
|
|
;
|
|
}
|
|
};
|
|
|
|
template<typename T, typename DirectedS>
|
|
struct basic_descriptor
|
|
{
|
|
basic_descriptor() {}
|
|
basic_descriptor(T base) : base(base) { }
|
|
|
|
operator T() const { return base; }
|
|
|
|
struct create
|
|
{
|
|
typedef basic_descriptor result_type;
|
|
basic_descriptor operator()(T base) const { return base; }
|
|
};
|
|
|
|
T base;
|
|
};
|
|
|
|
template<typename T, typename DirectedS>
|
|
inline bool
|
|
operator==(const basic_descriptor<T, DirectedS>& u,
|
|
const basic_descriptor<T, DirectedS>& v)
|
|
{ return u.base == v.base; }
|
|
|
|
template<typename T, typename DirectedS>
|
|
inline bool
|
|
operator!=(const basic_descriptor<T, DirectedS>& u,
|
|
const basic_descriptor<T, DirectedS>& v)
|
|
{ return u.base != v.base; }
|
|
|
|
template<typename Key, typename IndexMap>
|
|
struct basic_index_map
|
|
{
|
|
typedef Key key_type;
|
|
typedef typename property_traits<IndexMap>::value_type value_type;
|
|
typedef typename property_traits<IndexMap>::reference reference;
|
|
typedef typename property_traits<IndexMap>::category category;
|
|
|
|
basic_index_map(const IndexMap& id = IndexMap())
|
|
: id(id) { }
|
|
|
|
IndexMap id;
|
|
};
|
|
|
|
template<typename Key, typename IndexMap>
|
|
inline typename basic_index_map<Key, IndexMap>::value_type
|
|
get(const basic_index_map<Key, IndexMap>& pm,
|
|
typename basic_index_map<Key, IndexMap>::key_type const& key)
|
|
{ return get(pm.id, key.base); }
|
|
|
|
enum graph_file_kind { gfk_adjlist, gfk_graphviz };
|
|
|
|
struct stored_minstd_rand
|
|
{
|
|
stored_minstd_rand(int seed = 1) : gen(seed) { }
|
|
|
|
minstd_rand gen;
|
|
};
|
|
|
|
template<typename DirectedS>
|
|
class basic_graph
|
|
: public stored_minstd_rand,
|
|
public adjacency_list<listS, listS, DirectedS,
|
|
property<vertex_index_t, std::size_t>,
|
|
property<edge_index_t, std::size_t> >
|
|
{
|
|
typedef adjacency_list<listS, listS, DirectedS,
|
|
property<vertex_index_t, std::size_t>,
|
|
property<edge_index_t, std::size_t> > inherited;
|
|
typedef graph_traits<inherited> traits;
|
|
|
|
typedef typename traits::vertex_iterator base_vertex_iterator;
|
|
typedef typename traits::edge_iterator base_edge_iterator;
|
|
typedef typename traits::out_edge_iterator base_out_edge_iterator;
|
|
typedef typename traits::in_edge_iterator base_in_edge_iterator;
|
|
typedef typename traits::adjacency_iterator base_adjacency_iterator;
|
|
typedef typename property_map<inherited, vertex_index_t>::const_type
|
|
base_vertex_index_map;
|
|
typedef typename property_map<inherited, edge_index_t>::const_type
|
|
base_edge_index_map;
|
|
typedef typename traits::vertex_descriptor base_vertex_descriptor;
|
|
typedef typename traits::edge_descriptor base_edge_descriptor;
|
|
|
|
typedef erdos_renyi_iterator<minstd_rand, basic_graph<DirectedS> >
|
|
er_iterator;
|
|
typedef plod_iterator<minstd_rand, basic_graph<DirectedS> >
|
|
sf_iterator;
|
|
typedef small_world_iterator<minstd_rand, basic_graph<DirectedS> >
|
|
sw_iterator;
|
|
|
|
public:
|
|
typedef basic_descriptor<base_vertex_descriptor, DirectedS>
|
|
Vertex;
|
|
typedef Vertex vertex_descriptor;
|
|
typedef basic_descriptor<base_edge_descriptor, DirectedS>
|
|
Edge;
|
|
typedef Edge edge_descriptor;
|
|
typedef basic_index_map<Vertex, base_vertex_index_map>
|
|
VertexIndexMap;
|
|
typedef basic_index_map<Edge, base_edge_index_map> EdgeIndexMap;
|
|
typedef std::size_t vertices_size_type;
|
|
typedef std::size_t edges_size_type;
|
|
typedef std::size_t degree_size_type;
|
|
typedef typename traits::directed_category directed_category;
|
|
typedef typename traits::edge_parallel_category edge_parallel_category;
|
|
typedef typename traits::traversal_category traversal_category;
|
|
typedef transform_iterator<typename Vertex::create, base_vertex_iterator>
|
|
vertex_iterator;
|
|
typedef transform_iterator<typename Edge::create, base_edge_iterator>
|
|
edge_iterator;
|
|
typedef transform_iterator<typename Edge::create, base_out_edge_iterator>
|
|
out_edge_iterator;
|
|
typedef transform_iterator<typename Edge::create, base_in_edge_iterator>
|
|
in_edge_iterator;
|
|
typedef transform_iterator<typename Vertex::create, base_adjacency_iterator>
|
|
adjacency_iterator;
|
|
|
|
basic_graph();
|
|
basic_graph(::boost::python::object);
|
|
basic_graph(const std::string& filename, graph_file_kind kind);
|
|
basic_graph(erdos_renyi, int seed);
|
|
basic_graph(power_law_out_degree, int seed);
|
|
basic_graph(small_world, int seed);
|
|
|
|
bool is_directed() const
|
|
{ return is_convertible<directed_category, directed_tag>::value; }
|
|
|
|
Vertex add_vertex();
|
|
void clear_vertex(Vertex vertex);
|
|
void remove_vertex(Vertex vertex);
|
|
std::size_t num_vertices() const;
|
|
std::pair<vertex_iterator, vertex_iterator> vertices() const;
|
|
vertex_iterator vertices_begin() const;
|
|
vertex_iterator vertices_end() const;
|
|
|
|
Edge add_edge(Vertex u, Vertex v);
|
|
void remove_edge(Edge edge);
|
|
std::size_t num_edges() const;
|
|
std::pair<edge_iterator, edge_iterator> edges() const;
|
|
edge_iterator edges_begin() const;
|
|
edge_iterator edges_end() const;
|
|
|
|
// Incidence Graph concept
|
|
Vertex source(Edge e) const;
|
|
Vertex target(Edge e) const;
|
|
std::pair<out_edge_iterator, out_edge_iterator> out_edges(Vertex u) const;
|
|
simple_python_iterator<out_edge_iterator> py_out_edges(Vertex u) const;
|
|
std::size_t out_degree(Vertex u) const;
|
|
|
|
// Bidirectional Graph concept
|
|
std::pair<in_edge_iterator, in_edge_iterator> in_edges(Vertex u) const;
|
|
simple_python_iterator<in_edge_iterator> py_in_edges(Vertex u) const;
|
|
std::size_t in_degree(Vertex u) const;
|
|
|
|
// Adjacency Graph concept
|
|
std::pair<adjacency_iterator, adjacency_iterator>
|
|
adjacent_vertices(Vertex u) const;
|
|
|
|
simple_python_iterator<adjacency_iterator>
|
|
py_adjacent_vertices(Vertex u) const;
|
|
|
|
// Vertex property maps
|
|
VertexIndexMap get_vertex_index_map() const
|
|
{ return get(vertex_index, base()); }
|
|
|
|
template<typename T>
|
|
vector_property_map<T, VertexIndexMap>
|
|
get_vertex_map(const std::string& name);
|
|
|
|
bool has_vertex_map(const std::string& name) const;
|
|
|
|
// Edge property maps
|
|
EdgeIndexMap get_edge_index_map() const
|
|
{ return get(edge_index, base()); }
|
|
|
|
template<typename T>
|
|
vector_property_map<T, EdgeIndexMap>
|
|
get_edge_map(const std::string& name);
|
|
|
|
bool has_edge_map(const std::string& name) const;
|
|
|
|
// Graph I/O
|
|
void read_graphviz(const std::string& filename,
|
|
const std::string& node_id = std::string("node_id"));
|
|
|
|
void write_graphviz(const std::string& filename,
|
|
const std::string& node_id = std::string("node_id"));
|
|
|
|
void write_graphviz_def(const std::string& filename)
|
|
{ write_graphviz(filename); }
|
|
|
|
// Simple functions for Visual C++ 7.1 :(
|
|
vector_property_map<default_color_type, VertexIndexMap>
|
|
get_vertex_color_map(const std::string& name)
|
|
{ return get_vertex_map<default_color_type>(name); }
|
|
|
|
vector_property_map<double, VertexIndexMap>
|
|
get_vertex_double_map(const std::string& name)
|
|
{ return get_vertex_map<double>(name); }
|
|
|
|
vector_property_map<int, VertexIndexMap>
|
|
get_vertex_int_map(const std::string& name)
|
|
{ return get_vertex_map<int>(name); }
|
|
|
|
vector_property_map<std::string, VertexIndexMap>
|
|
get_vertex_string_map(const std::string& name)
|
|
{ return get_vertex_map<std::string>(name); }
|
|
|
|
vector_property_map<boost::python::object, VertexIndexMap>
|
|
get_vertex_object_map(const std::string& name)
|
|
{ return get_vertex_map<boost::python::object>(name); }
|
|
|
|
vector_property_map<point2d, VertexIndexMap>
|
|
get_vertex_point2d_map(const std::string& name)
|
|
{ return get_vertex_map<point2d>(name); }
|
|
|
|
vector_property_map<default_color_type, EdgeIndexMap>
|
|
get_edge_color_map(const std::string& name)
|
|
{ return get_edge_map<default_color_type>(name); }
|
|
|
|
vector_property_map<double, EdgeIndexMap>
|
|
get_edge_double_map(const std::string& name)
|
|
{ return get_edge_map<double>(name); }
|
|
|
|
vector_property_map<int, EdgeIndexMap>
|
|
get_edge_int_map(const std::string& name)
|
|
{ return get_edge_map<int>(name); }
|
|
|
|
vector_property_map<std::string, EdgeIndexMap>
|
|
get_edge_string_map(const std::string& name)
|
|
{ return get_edge_map<std::string>(name); }
|
|
|
|
vector_property_map<boost::python::object, EdgeIndexMap>
|
|
get_edge_object_map(const std::string& name)
|
|
{ return get_edge_map<boost::python::object>(name); }
|
|
|
|
inherited& base() { return *this; }
|
|
const inherited& base() const { return *this; }
|
|
|
|
protected:
|
|
void renumber_vertices();
|
|
void renumber_edges();
|
|
|
|
private:
|
|
std::vector<vertex_descriptor> index_to_vertex;
|
|
std::vector<edge_descriptor> index_to_edge;
|
|
dynamic_properties dp;
|
|
};
|
|
|
|
// Vertex List Graph concept
|
|
template<typename DirectedS>
|
|
inline std::pair<typename basic_graph<DirectedS>::vertex_iterator,
|
|
typename basic_graph<DirectedS>::vertex_iterator>
|
|
vertices(const basic_graph<DirectedS>& g)
|
|
{ return g.vertices(); }
|
|
|
|
template<typename DirectedS>
|
|
inline std::size_t num_vertices(const basic_graph<DirectedS>& g)
|
|
{ return g.num_vertices(); }
|
|
|
|
// Edge List Graph concept
|
|
template<typename DirectedS>
|
|
inline std::pair<typename basic_graph<DirectedS>::edge_iterator,
|
|
typename basic_graph<DirectedS>::edge_iterator>
|
|
edges(const basic_graph<DirectedS>& g)
|
|
{ return g.edges(); }
|
|
|
|
template<typename DirectedS>
|
|
inline std::size_t num_edges(const basic_graph<DirectedS>& g)
|
|
{ return g.num_edges(); }
|
|
|
|
// Incidence Graph concept
|
|
template<typename DirectedS>
|
|
inline typename basic_graph<DirectedS>::vertex_descriptor
|
|
source(typename basic_graph<DirectedS>::edge_descriptor e,
|
|
const basic_graph<DirectedS>& g)
|
|
{ return g.source(e); }
|
|
|
|
template<typename DirectedS>
|
|
inline typename basic_graph<DirectedS>::vertex_descriptor
|
|
target(typename basic_graph<DirectedS>::edge_descriptor e,
|
|
const basic_graph<DirectedS>& g)
|
|
{ return g.target(e); }
|
|
|
|
template<typename DirectedS>
|
|
inline std::pair<typename basic_graph<DirectedS>::out_edge_iterator,
|
|
typename basic_graph<DirectedS>::out_edge_iterator>
|
|
out_edges(typename basic_graph<DirectedS>::vertex_descriptor u,
|
|
const basic_graph<DirectedS>& g)
|
|
{ return g.out_edges(u); }
|
|
|
|
template<typename DirectedS>
|
|
inline std::size_t
|
|
out_degree(typename basic_graph<DirectedS>::vertex_descriptor u,
|
|
const basic_graph<DirectedS>& g)
|
|
{ return g.out_degree(u); }
|
|
|
|
// Bidirectional Graph concept
|
|
template<typename DirectedS>
|
|
inline std::pair<typename basic_graph<DirectedS>::in_edge_iterator,
|
|
typename basic_graph<DirectedS>::in_edge_iterator>
|
|
in_edges(typename basic_graph<DirectedS>::vertex_descriptor u,
|
|
const basic_graph<DirectedS>& g)
|
|
{ return g.in_edges(u); }
|
|
|
|
template<typename DirectedS>
|
|
inline std::size_t
|
|
in_degree(typename basic_graph<DirectedS>::vertex_descriptor u,
|
|
const basic_graph<DirectedS>& g)
|
|
{ return g.in_degree(u); }
|
|
|
|
// Adjacency Graph concept
|
|
template<typename DirectedS>
|
|
inline std::pair<typename basic_graph<DirectedS>::adjacency_iterator,
|
|
typename basic_graph<DirectedS>::adjacency_iterator>
|
|
adjacent_vertices(typename basic_graph<DirectedS>::vertex_descriptor u,
|
|
const basic_graph<DirectedS>& g)
|
|
{ return g.adjacent_vertices(u); }
|
|
|
|
// Mutable basic_graph<DirectedS> concept
|
|
template<typename DirectedS>
|
|
inline typename basic_graph<DirectedS>::vertex_descriptor
|
|
add_vertex(basic_graph<DirectedS>& g)
|
|
{ return g.add_vertex(); }
|
|
|
|
template<typename DirectedS>
|
|
inline std::pair<typename basic_graph<DirectedS>::edge_descriptor, bool>
|
|
add_edge(typename basic_graph<DirectedS>::vertex_descriptor u,
|
|
typename basic_graph<DirectedS>::vertex_descriptor v,
|
|
basic_graph<DirectedS>& g)
|
|
{ return std::make_pair(g.add_edge(u, v), true); }
|
|
|
|
template<typename DirectedS>
|
|
void export_basic_graph(const char* name);
|
|
|
|
template<typename DirectedS>
|
|
typename basic_graph<DirectedS>::VertexIndexMap
|
|
get(vertex_index_t, const basic_graph<DirectedS>& g)
|
|
{ return g.get_vertex_index_map(); }
|
|
|
|
template<typename DirectedS>
|
|
typename basic_graph<DirectedS>::EdgeIndexMap
|
|
get(edge_index_t, const basic_graph<DirectedS>& g)
|
|
{ return g.get_edge_index_map(); }
|
|
|
|
} } } // end namespace boost::graph::python
|
|
|
|
#if 0
|
|
// Triggers bugs in GCC
|
|
namespace boost {
|
|
template<typename DirectedS>
|
|
struct property_map<graph::python::basic_graph<DirectedS>, vertex_index_t>
|
|
{
|
|
typedef typename graph::python::basic_graph<DirectedS>::VertexIndexMap
|
|
type;
|
|
typedef type const_type;
|
|
};
|
|
|
|
template<typename DirectedS>
|
|
struct property_map<graph::python::basic_graph<DirectedS>, edge_index_t>
|
|
{
|
|
typedef typename graph::python::basic_graph<DirectedS>::EdgeIndexMap
|
|
type;
|
|
typedef type const_type;
|
|
};
|
|
}
|
|
#endif
|
|
|
|
#endif // BOOST_GRAPH_BASIC_GRAPH_HPP
|