// 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 #include #include #include #include #include #include #include #include #include #include "point2d.hpp" #include "generators.hpp" namespace boost { namespace graph { namespace python { template bool type_already_registered() { using boost::python::objects::registered_class_object; using boost::python::type_id; return registered_class_object(type_id()).get() != 0; } template class simple_python_iterator { public: simple_python_iterator(std::pair p) : first(p.first), last(p.second) { } typename std::iterator_traits::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()) class_ >(name, no_init) .def("__iter__", identity_function()) .def("next", &simple_python_iterator::next) ; } private: Iterator first; Iterator last; }; template struct declare_readable_property_map { typedef typename property_traits::key_type key_type; typedef typename property_traits::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()) class_(name, no_init) .def("__getitem__", &getitem) ; } }; template struct declare_property_map { typedef typename property_traits::key_type key_type; typedef typename property_traits::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()) class_(name, no_init) .def("__getitem__", &getitem) .def("__setitem__", &setitem) ; } }; template 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 inline bool operator==(const basic_descriptor& u, const basic_descriptor& v) { return u.base == v.base; } template inline bool operator!=(const basic_descriptor& u, const basic_descriptor& v) { return u.base != v.base; } template struct basic_index_map { typedef Key key_type; typedef typename property_traits::value_type value_type; typedef typename property_traits::reference reference; typedef typename property_traits::category category; basic_index_map(const IndexMap& id = IndexMap()) : id(id) { } IndexMap id; }; template inline typename basic_index_map::value_type get(const basic_index_map& pm, typename basic_index_map::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 class basic_graph : public stored_minstd_rand, public adjacency_list, property > { typedef adjacency_list, property > inherited; typedef graph_traits 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::const_type base_vertex_index_map; typedef typename property_map::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 > er_iterator; typedef plod_iterator > sf_iterator; typedef small_world_iterator > sw_iterator; public: typedef basic_descriptor Vertex; typedef Vertex vertex_descriptor; typedef basic_descriptor Edge; typedef Edge edge_descriptor; typedef basic_index_map VertexIndexMap; typedef basic_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 vertex_iterator; typedef transform_iterator edge_iterator; typedef transform_iterator out_edge_iterator; typedef transform_iterator in_edge_iterator; typedef transform_iterator adjacency_iterator; basic_graph(); 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::value; } Vertex add_vertex(); void clear_vertex(Vertex vertex); void remove_vertex(Vertex vertex); std::size_t num_vertices() const; std::pair 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 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_edges(Vertex u) const; simple_python_iterator py_out_edges(Vertex u) const; std::size_t out_degree(Vertex u) const; // Bidirectional Graph concept std::pair in_edges(Vertex u) const; simple_python_iterator py_in_edges(Vertex u) const; std::size_t in_degree(Vertex u) const; // Adjacency Graph concept std::pair adjacent_vertices(Vertex u) const; simple_python_iterator py_adjacent_vertices(Vertex u) const; // Vertex property maps VertexIndexMap get_vertex_index_map() const { return get(vertex_index, base()); } template vector_property_map 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 vector_property_map 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 get_vertex_color_map(const std::string& name) { return get_vertex_map(name); } vector_property_map get_vertex_double_map(const std::string& name) { return get_vertex_map(name); } vector_property_map get_vertex_int_map(const std::string& name) { return get_vertex_map(name); } vector_property_map get_vertex_string_map(const std::string& name) { return get_vertex_map(name); } vector_property_map get_vertex_object_map(const std::string& name) { return get_vertex_map(name); } vector_property_map get_vertex_point2d_map(const std::string& name) { return get_vertex_map(name); } vector_property_map get_edge_color_map(const std::string& name) { return get_edge_map(name); } vector_property_map get_edge_double_map(const std::string& name) { return get_edge_map(name); } vector_property_map get_edge_int_map(const std::string& name) { return get_edge_map(name); } vector_property_map get_edge_string_map(const std::string& name) { return get_edge_map(name); } vector_property_map get_edge_object_map(const std::string& name) { return get_edge_map(name); } inherited& base() { return *this; } const inherited& base() const { return *this; } protected: void renumber_vertices(); void renumber_edges(); private: std::vector index_to_vertex; std::vector index_to_edge; dynamic_properties dp; }; // Vertex List Graph concept template inline std::pair::vertex_iterator, typename basic_graph::vertex_iterator> vertices(const basic_graph& g) { return g.vertices(); } template inline std::size_t num_vertices(const basic_graph& g) { return g.num_vertices(); } // Edge List Graph concept template inline std::pair::edge_iterator, typename basic_graph::edge_iterator> edges(const basic_graph& g) { return g.edges(); } template inline std::size_t num_edges(const basic_graph& g) { return g.num_edges(); } // Incidence Graph concept template inline typename basic_graph::vertex_descriptor source(typename basic_graph::edge_descriptor e, const basic_graph& g) { return g.source(e); } template inline typename basic_graph::vertex_descriptor target(typename basic_graph::edge_descriptor e, const basic_graph& g) { return g.target(e); } template inline std::pair::out_edge_iterator, typename basic_graph::out_edge_iterator> out_edges(typename basic_graph::vertex_descriptor u, const basic_graph& g) { return g.out_edges(u); } template inline std::size_t out_degree(typename basic_graph::vertex_descriptor u, const basic_graph& g) { return g.out_degree(u); } // Bidirectional Graph concept template inline std::pair::in_edge_iterator, typename basic_graph::in_edge_iterator> in_edges(typename basic_graph::vertex_descriptor u, const basic_graph& g) { return g.in_edges(u); } template inline std::size_t in_degree(typename basic_graph::vertex_descriptor u, const basic_graph& g) { return g.in_degree(u); } // Adjacency Graph concept template inline std::pair::adjacency_iterator, typename basic_graph::adjacency_iterator> adjacent_vertices(typename basic_graph::vertex_descriptor u, const basic_graph& g) { return g.adjacent_vertices(u); } // Mutable basic_graph concept template inline typename basic_graph::vertex_descriptor add_vertex(basic_graph& g) { return g.add_vertex(); } template inline std::pair::edge_descriptor, bool> add_edge(typename basic_graph::vertex_descriptor u, typename basic_graph::vertex_descriptor v, basic_graph& g) { return std::make_pair(g.add_edge(u, v), true); } template void export_basic_graph(const char* name); template typename basic_graph::VertexIndexMap get(vertex_index_t, const basic_graph& g) { return g.get_vertex_index_map(); } template typename basic_graph::EdgeIndexMap get(edge_index_t, const basic_graph& g) { return g.get_edge_index_map(); } } } } // end namespace boost::graph::python #if 0 // Triggers bugs in GCC namespace boost { template struct property_map, vertex_index_t> { typedef typename graph::python::basic_graph::VertexIndexMap type; typedef type const_type; }; template struct property_map, edge_index_t> { typedef typename graph::python::basic_graph::EdgeIndexMap type; typedef type const_type; }; } #endif #endif // BOOST_GRAPH_BASIC_GRAPH_HPP