|
Boost : |
Subject: Re: [boost] [BGL] Multithread problem inserting edges and exploring the same graph
From: Cosimo Calabrese (cosimo.calabrese_at_[hidden])
Date: 2009-10-21 14:55:02
Cosimo Calabrese ha scritto:
> Jeremiah Willcock wrote:
>
>> That only works if both graphs are adjacency_lists and you have
>> control over the graph types. I would personally just make:
>>
>> template <typename T>
>> struct from_first_graph {T data;};
>> template <typename T>
>> struct from_second_graph {T data;};
>>
>> and then have my variants be:
>>
>> boost::variant<from_first_graph<graph_traits<First>::vertex_descriptor>,
>> from_second_graph<graph_traits<Second>::vertex_descriptor>
>>>
>>
>> and the same for edge descriptors. This will disambiguate the types
>> for arbitrary graphs.
>>
>
> It seems a very good idea to me. I'm trying it. I'll tell you about it
> ASAP.
>
I'm nearly to the end of the work, but I've encountered a problem. I've
implemented all the traversal concepts, but I'm in difficulty with the
Property concepts, in particular on the get( property, key ) function. I
don't understand where I'm wrong. I was inspired by the filtered_graph
and reverse_graph adaptor, but without results.
Sure, I'm relatively new to Boost, and I haven't understand very well
how the property lib works, applied on the BGL.
I attach 3 files:
- the union_different_iterator, that provides a union view of 2 containers;
- the union_graph, that provides a union view of 2 graphs (that uses
union_different_iterator);
- a main module, that tests the union_graph.
Please, can anyone help me?
Thanks,
Cosimo Calabrese.
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>
#include "union_graph.hpp"
using namespace boost;
using namespace std;
namespace boost
{
// properties installation
enum vertex_originality_t { vertex_originality = 101 };
enum edge_ID_t { edge_ID = 102 };
enum edge_originality_t { edge_originality = 103 };
BOOST_INSTALL_PROPERTY(vertex, originality);
BOOST_INSTALL_PROPERTY(edge, ID);
BOOST_INSTALL_PROPERTY(edge, originality);
}
typedef property< vertex_name_t, string,
property < vertex_originality_t, bool > > vertexs_properties;
typedef property < edge_ID_t, long,
property < edge_weight_t, long,
property < edge_originality_t, bool > > > edges_properties;
typedef adjacency_list< listS, vecS, directedS, vertexs_properties, edges_properties > Graph;
typedef property_map< Graph, edge_weight_t >::type edge_weight_map_t;
int main()
{
// Setup Test
const long NUM_VERTICES = 10;
graph_traits<Graph>::edge_descriptor e;
bool inserted;
// base hraph
Graph baseGraph( NUM_VERTICES );
edge_weight_map_t edge_weight_map_base = get( edge_weight, baseGraph );
for ( long i = 0; i < NUM_VERTICES ; ++i )
{
// 0->1, 1->2, 2->3, ... n->n+1 ..., 9->0
tie(e, inserted) = add_edge( i % NUM_VERTICES, (i + 1) % NUM_VERTICES, baseGraph );
if ( inserted )
edge_weight_map_base[ e ] = 1;
}
cout << "Base graph:" << endl;
print_graph( baseGraph );
cout << endl;
// little graph
Graph littleGraph( NUM_VERTICES );
edge_weight_map_t edge_weight_map_little = get( edge_weight, littleGraph );
tie(e, inserted) = add_edge( 0, 6, littleGraph );
if ( inserted )
edge_weight_map_little[ e ] = 1;
cout << "Little graph:" << endl;
print_graph( littleGraph );
cout << endl;
// union graph
//cout << "Union graph:" << endl;
//print_graph( make_union_graph( baseGraph, littleGraph ) );
//cout << endl;
// union graph, test vertex (0)
typedef union_graph<Graph, Graph> UG;
UG ug = make_union_graph( baseGraph, littleGraph );
graph_traits<UG>::vertex_descriptor u = WR1<graph_traits<Graph>::vertex_descriptor>( 0 );
// Test 1: out_edges e out_degree
{
graph_traits<UG>::out_edge_iterator oei, oei_end;
for ( tie( oei, oei_end ) = out_edges( u, ug ); oei != oei_end; ++oei )
{
graph_traits<UG>::vertex_descriptor t = target( *oei, ug );
cout << "Outer target: ";
if ( boost::get<WR1<graph_traits<Graph>::vertex_descriptor> >( &t ) )
cout << boost::get<WR1<graph_traits<Graph>::vertex_descriptor> >( t )._data << endl;
else
cout << boost::get<WR2<graph_traits<Graph>::vertex_descriptor> >( t )._data << endl;
}
cout << "Out degree: " << out_degree( u, ug ) << endl << endl;
}
/*
// Bidirectionality required for this test
// Test 2: in_edges, in_degree e degree
{
graph_traits<UG>::in_edge_iterator iei, iei_end;
for ( tie( iei, iei_end ) = in_edges( u, ug ); iei != iei_end; ++iei )
{
graph_traits<UG>::vertex_descriptor s = source( *iei, ug );
if ( boost::get<WR1<graph_traits<Graph>::vertex_descriptor> >( &s ) )
cout << boost::get<WR1<graph_traits<Graph>::vertex_descriptor> >( s )._data << endl;
else
cout << boost::get<WR2<graph_traits<Graph>::vertex_descriptor> >( s )._data << endl;
}
cout << "In degree: " << in_degree( u, ug ) << endl;
cout << "Degree: " << degree( u, ug ) << endl;
}
*/
// Test 3: adjacent_vertices
{
graph_traits<UG>::adjacency_iterator ai, ai_end;
for ( tie( ai, ai_end ) = adjacent_vertices( u, ug ); ai != ai_end; ++ai )
{
cout << "Adjacency: ";
if ( boost::get<WR1<graph_traits<Graph>::vertex_descriptor> >( &*ai ) )
cout << boost::get<WR1<graph_traits<Graph>::vertex_descriptor> >( *ai )._data << endl;
else
cout << boost::get<WR2<graph_traits<Graph>::vertex_descriptor> >( *ai )._data << endl;
}
cout << endl;
}
// Test 4: num_vertices, vertices
{
cout << "Num vertices: " << num_vertices( ug ) << endl;
graph_traits<UG>::vertex_iterator vi, vi_end;
for ( tie( vi, vi_end ) = vertices( ug ); vi != vi_end; ++vi )
{
cout << "Graph Vertex: ";
boost::get<WR1<graph_traits<Graph>::vertex_descriptor> >( &*vi );
if ( boost::get<WR1<graph_traits<Graph>::vertex_descriptor> >( &*vi ) )
cout << boost::get<WR1<graph_traits<Graph>::vertex_descriptor> >( *vi )._data << endl;
else
cout << boost::get<WR2<graph_traits<Graph>::vertex_descriptor> >( *vi )._data << endl;
}
cout << endl;
}
// Test 5: num_edges, edges, source, target
{
cout << "Num edges: " << num_edges( ug ) << endl;
graph_traits<UG>::edge_iterator ei, ei_end;
for ( tie( ei, ei_end ) = edges( ug ); ei != ei_end; ++ei )
{
cout << "Graph edge: ";
graph_traits<UG>::vertex_descriptor s = source( *ei, ug );
graph_traits<UG>::vertex_descriptor t = target( *ei, ug );
if ( boost::get<WR1<graph_traits<Graph>::vertex_descriptor> >( &s ) )
cout << boost::get<WR1<graph_traits<Graph>::vertex_descriptor> >( s )._data;
else
cout << boost::get<WR2<graph_traits<Graph>::vertex_descriptor> >( s )._data;
cout << "->";
if ( boost::get<WR1<graph_traits<Graph>::vertex_descriptor> >( &t ) )
cout << boost::get<WR1<graph_traits<Graph>::vertex_descriptor> >( t )._data;
else
cout << boost::get<WR2<graph_traits<Graph>::vertex_descriptor> >( t )._data;
cout << endl;
}
cout << endl;
}
// Test 6: edge
{
graph_traits<UG>::vertex_descriptor u = WR2<graph_traits<Graph>::vertex_descriptor>( 0 );
graph_traits<UG>::vertex_descriptor v = WR1<graph_traits<Graph>::vertex_descriptor>( 6 );
graph_traits<UG>::edge_descriptor e;
bool exists;
tie( e, exists ) = edge( u, v, ug );
cout << ( exists ? "This edge exists" : "This edge doesn't exists" ) << endl << endl;
}
// Test 7: properties
{
graph_traits<UG>::vertex_descriptor u = WR1<graph_traits<Graph>::vertex_descriptor>( 0 );
typedef property_map< Graph, vertex_index_t >::type vertex_index_map_t;
vertex_index_map_t indexmap = get( vertex_index, ug );
//get( indexmap, ug, u );
}
}
#ifndef _UNION_DIFFERENT_ITERATOR
#define _UNION_DIFFERENT_ITERATOR
#include <boost/variant.hpp>
#include <iterator>
#include <utility>
using namespace std;
template <typename FI1, typename FI2, template <typename> class WR_A, template <typename> class WR_B>
class union_different_iterator
: public std::iterator< forward_iterator_tag,
boost::variant<
WR_A<typename iterator_traits<FI1>::value_type>,
WR_B<typename iterator_traits<FI2>::value_type>
>
>
{
public:
typedef union_different_iterator<FI1, FI2, WR_A, WR_B> self;
typedef typename iterator_traits<FI1>::value_type value_type1;
typedef typename iterator_traits<FI2>::value_type value_type2;
union_different_iterator()
{}
union_different_iterator( FI1 begin_a, FI1 end_a, FI2 begin_b, FI2 end_b )
: _begin_a( begin_a ), _end_a( end_a ), _curr_a( begin_a ),
_begin_b( begin_b ), _end_b( end_b ), _curr_b( begin_b )
{}
union_different_iterator( const self& other )
: _begin_a( other._begin_a ), _end_a( other._end_a ), _curr_a( other._curr_a ),
_begin_b( other._begin_b ), _end_b( other._end_b ), _curr_b( other._curr_b )
{}
const self& operator=( const self& other )
{
_begin_a = other._begin_a;
_end_a = other._end_a;
_curr_a = other._curr_a;
_begin_b = other._begin_b;
_end_b = other._end_b;
_curr_b = other._curr_b;
return(*this);
}
bool operator==( const self& other ) const
{
return ( _curr_a == other._curr_a ) && ( _curr_b == other._curr_b );
}
bool operator!=( const self& other ) const
{
return !this->operator == ( other );
}
/*const*/ value_type operator*() const
{
return _curr_a == _end_a ?
value_type( WR_B<value_type2>( *_curr_b ) ) :
value_type( WR_A<value_type1>( *_curr_a ) ) ;
}
/*
value_type operator*()
{
return _curr_a == _end_a ?
value_type( WR_B<value_type2>( *_curr_b ) ) :
value_type( WR_A<value_type1>( *_curr_a ) ) ;
}
*/
/*
const pointer operator->() const
{
return _curr_a == _end_a ? _curr_b.operator->() : _curr_a.operator->();
}
pointer operator->()
{
return _curr_a == _end_a ? _curr_b.operator->() : _curr_a.operator->();
}
*/
self& operator++()
{
if ( _curr_a == _end_a )
++_curr_b;
else
++_curr_a;
return *this;
}
self operator++(int)
{
self tmp = *this; ++( *this ); return tmp;
}
self& operator--()
{
if (_curr_b == _begin_b )
--_curr_a;
else
--_curr_b;
return *this;
}
self operator--(int)
{
self tmp = *this; --( *this ); return tmp;
}
template <typename T>
bool isTypeOf()
{
if ( _curr_a == _end_a )
return boost::is_same<WR_B<T>, WR_B<value_type2> >::value;
else
return boost::is_same<WR_A<T>, WR_A<value_type1> >::value;
}
private:
FI1 _begin_a;
FI1 _end_a;
FI1 _curr_a;
FI2 _begin_b;
FI2 _end_b;
FI2 _curr_b;
};
template <typename FI1, typename FI2, template <typename> class WR_A, template <typename> class WR_B>
inline union_different_iterator<FI1, FI2, WR_A, WR_B>
make_union_different_iterator(FI1 begin_a, FI1 end_a, FI2 begin_b, FI2 end_b) {
return union_different_iterator<FI1, FI2, WR_A, WR_B>(begin_a, end_a, begin_b, end_b);
}
template <typename FI1, typename FI2, template <typename> class WR_A, template <typename> class WR_B>
inline union_different_iterator<FI1, FI2, WR_A, WR_B>
make_union_different_iterator( pair<FI1, FI1> range_a, pair<FI2, FI2> range_b ) {
return union_different_iterator<FI1, FI2, WR_A, WR_B>(range_a.first, range_a.second,
range_b.first, range_b.second);
}
template <typename FI1, typename FI2, template <typename> class WR_A, template <typename> class WR_B>
inline pair< union_different_iterator<FI1, FI2, WR_A, WR_B>,
union_different_iterator<FI1, FI2, WR_A, WR_B> >
make_union_different_range( FI1 begin_a, FI1 end_a, FI2 begin_b, FI2 end_b ) {
return make_pair( make_union_different_iterator<FI1, FI2, WR_A, WR_B>( begin_a, end_a, begin_b, end_b ),
make_union_different_iterator<FI1, FI2, WR_A, WR_B>( end_a, end_a, end_b, end_b ) );
}
template <typename FI1, typename FI2, template <typename> class WR_A, template <typename> class WR_B>
inline pair< union_different_iterator<FI1, FI2, WR_A, WR_B>,
union_different_iterator<FI1, FI2, WR_A, WR_B> >
make_union_different_range( pair<FI1, FI1> range_a, pair<FI2, FI2> range_b ) {
return make_pair( make_union_different_iterator<FI1, FI2, WR_A, WR_B>( range_a, range_b ),
make_union_different_iterator<FI1, FI2, WR_A, WR_B>( range_a.second, range_a.second,
range_b.second, range_b.second ) );
}
#endif
#ifndef BOOST_UNION_GRAPH_HPP
#define BOOST_UNION_GRAPH_HPP
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/adjacency_iterator.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/graph/exception.hpp>
#include <boost/variant.hpp>
#include "union_different_iterator.hpp"
//===========================================================================
// wrappers
template <typename T>
class WR1
{
public:
WR1() : _data( T() ) {}
WR1( T data ) : _data( data ) {}
const WR1<T> operator=( const WR1<T>& other )
{
_data = other._data;
return(*this);
}
bool operator==( const WR1<T>& other ) const
{
return _data == other._data;
}
T _data;
};
template <typename T>
class WR2
{
public:
WR2() : _data( T() ) {}
WR2( T data ) : _data( data ) {}
const WR2<T> operator=( const WR2<T>& other )
{
_data = other._data;
return(*this);
}
bool operator==( const WR2<T>& other ) const
{
return _data == other._data;
}
T _data;
};
namespace boost {
struct not_same_num_vertices : public bad_graph {
not_same_num_vertices()
: bad_graph("The two graphs of an union_graph must have the same number of vertices.")
{ }
};
//===========================================================================
// union_graph
struct union_graph_tag { };
template <typename Graph1, typename Graph2>
class union_graph {
typedef union_graph<Graph1, Graph2> self;
public:
typedef Graph1 graph_type1;
typedef Graph2 graph_type2;
// Constructor
union_graph( const Graph1& g1, const Graph2& g2 ) : m_g1(g1), m_g2(g2)
{
// TODO: precondition: Traits::directed_category must be the same
// TODO: precondition: Traits::Traits::traversal_category be the same
// TODO: precondition: Traits::edge_parallel_category be the same
if ( num_vertices( g1 ) != num_vertices( g2 ) )
throw not_same_num_vertices();
}
// Graph requirements
typedef boost::variant<WR1<typename graph_traits<Graph1>::vertex_descriptor>,
WR2<typename graph_traits<Graph2>::vertex_descriptor> > vertex_descriptor;
typedef typename graph_traits<Graph1>::directed_category directed_category;
typedef typename graph_traits<Graph1>::traversal_category traversal_category;
typedef typename graph_traits<Graph1>::edge_parallel_category edge_parallel_category;
// IncidenceGraph requirements
typedef boost::variant<WR1<typename graph_traits<Graph1>::edge_descriptor>,
WR2<typename graph_traits<Graph2>::edge_descriptor> >edge_descriptor;
typedef union_different_iterator< typename graph_traits<Graph1>::out_edge_iterator,
typename graph_traits<Graph2>::out_edge_iterator,
WR1, WR2 > out_edge_iterator;
typedef typename graph_traits<Graph1>::degree_size_type degree_size_type;
// AdjacencyGraph requirements
typedef union_different_iterator< typename graph_traits<Graph1>::adjacency_iterator,
typename graph_traits<Graph2>::adjacency_iterator,
WR1, WR2 > adjacency_iterator;
// BidirectionalGraph requirements
typedef union_different_iterator< typename graph_traits<Graph1>::in_edge_iterator,
typename graph_traits<Graph2>::in_edge_iterator,
WR1, WR2 > in_edge_iterator;
// VertexListGraph requirements
typedef union_different_iterator< typename graph_traits<Graph1>::vertex_iterator,
typename graph_traits<Graph2>::vertex_iterator,
WR1, WR2 > vertex_iterator;
typedef typename graph_traits<Graph1>::vertices_size_type vertices_size_type;
// EdgeListGraph requirements
typedef union_different_iterator< typename graph_traits<Graph1>::edge_iterator,
typename graph_traits<Graph2>::edge_iterator,
WR1, WR2 > edge_iterator;
typedef typename graph_traits<Graph1>::edges_size_type edges_size_type;
typedef typename ::boost::edge_property_type<Graph1>::type edge_property_type;
typedef typename ::boost::vertex_property_type<Graph1>::type vertex_property_type;
typedef union_graph_tag graph_tag;
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
// Bundled properties support
template<typename Descriptor>
typename graph::detail::bundled_result<Graph1, Descriptor>::type&
operator[](Descriptor x)
{ return const_cast<Graph1&>(this->m_g1)[x]; }
template<typename Descriptor>
typename graph::detail::bundled_result<Graph1, Descriptor>::type const&
operator[](Descriptor x) const
{ return this->m_g1[x]; }
#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
static vertex_descriptor null_vertex()
{
return Graph1::null_vertex();
}
// private:
const Graph1& m_g1;
const Graph2& m_g2;
};
#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
template<typename Graph1, typename Graph2>
struct vertex_bundle_type<union_graph<Graph1, Graph2> >
: vertex_bundle_type<Graph1> { };
template<typename Graph1, typename Graph2>
struct edge_bundle_type<union_graph<Graph1, Graph2> >
: edge_bundle_type<Graph1> { };
#endif // BOOST_GRAPH_NO_BUNDLED_PROPERTIES
//===========================================================================
// Non-member functions for the Filtered Edge Graph
// Helper functions
template <typename Graph1, typename Graph2>
inline union_graph<Graph1, Graph2>
make_union_graph(Graph1& g1, Graph2& g2) {
return union_graph<Graph1, Graph2>(g1, g2);
}
template <typename Graph1, typename Graph2>
inline union_graph<const Graph1, const Graph2>
make_union_graph(const Graph1& g1, const Graph2& g2 ) {
return union_graph<const Graph1, const Graph2>(g1, g2);
}
namespace detail
{
template <typename Graph1, typename Graph2>
std::pair<typename graph_traits<Graph1>::vertex_descriptor,
typename graph_traits<Graph2>::vertex_descriptor>
get_corresponding_vertices(const typename union_graph<Graph1, Graph2>::vertex_descriptor& u)
{
typedef union_graph<Graph1, Graph2> UG;
typedef graph_traits<Graph1>::vertex_descriptor VD1;
typedef graph_traits<Graph2>::vertex_descriptor VD2;
VD1 u1;
VD2 u2;
if ( boost::get<WR1<VD1> >( &u ) )
{
u1 = boost::get<WR1<VD1> >( u )._data;
u2 = u1;
}
else
{
u2 = boost::get<WR2<VD2> >( u )._data;
u1 = u2;
}
return make_pair( u1, u2 );
}
}
// IncidenceGraph requirements
template <typename Graph1, typename Graph2>
std::pair<typename union_graph<Graph1, Graph2>::out_edge_iterator,
typename union_graph<Graph1, Graph2>::out_edge_iterator>
out_edges(const typename union_graph<Graph1, Graph2>::vertex_descriptor& u,
const union_graph<Graph1, Graph2>& g)
{
typedef union_graph<Graph1, Graph2> UG;
typedef graph_traits<Graph1>::vertex_descriptor VD1;
typedef graph_traits<Graph2>::vertex_descriptor VD2;
typedef graph_traits<Graph1>::out_edge_iterator OEI1;
typedef graph_traits<Graph2>::out_edge_iterator OEI2;
VD1 u1;
VD2 u2;
tie( u1, u2 ) = detail::get_corresponding_vertices<Graph1, Graph2>( u );
return make_union_different_range<OEI1, OEI2, WR1, WR2>( out_edges(u1, g.m_g1), out_edges(u2, g.m_g2) );
}
template <typename Graph1, typename Graph2>
typename union_graph<Graph1, Graph2>::vertex_descriptor
source(const typename union_graph<Graph1, Graph2>::edge_descriptor& e,
const union_graph<Graph1, Graph2>& g)
{
typedef union_graph<Graph1, Graph2> UG;
typedef graph_traits<Graph1>::vertex_descriptor VD1;
typedef graph_traits<Graph2>::vertex_descriptor VD2;
typedef graph_traits<Graph1>::edge_descriptor ED1;
typedef graph_traits<Graph2>::edge_descriptor ED2;
if ( boost::get<WR1<ED1> >( &e ) )
{
return graph_traits<UG>::vertex_descriptor( WR1<VD1>( source( boost::get<WR1<ED1> >( e )._data, g.m_g1 ) ) );
}
else
{
return graph_traits<UG>::vertex_descriptor( WR2<VD2>( source( boost::get<WR2<ED2> >( e )._data, g.m_g2 ) ) );
}
}
template <typename Graph1, typename Graph2>
typename union_graph<Graph1, Graph2>::vertex_descriptor
target(const typename union_graph<Graph1, Graph2>::edge_descriptor& e,
const union_graph<Graph1, Graph2>& g)
{
typedef union_graph<Graph1, Graph2> UG;
typedef graph_traits<Graph1>::vertex_descriptor VD1;
typedef graph_traits<Graph2>::vertex_descriptor VD2;
typedef graph_traits<Graph1>::edge_descriptor ED1;
typedef graph_traits<Graph2>::edge_descriptor ED2;
if ( boost::get<WR1<ED1> >( &e ) )
{
return graph_traits<UG>::vertex_descriptor( WR1<VD1>( target( boost::get<WR1<ED1> >( e )._data, g.m_g1 ) ) );
}
else
{
return graph_traits<UG>::vertex_descriptor( WR2<VD2>( target( boost::get<WR2<ED2> >( e )._data, g.m_g2 ) ) );
}
}
template <typename Graph1, typename Graph2>
typename union_graph<Graph1, Graph2>::degree_size_type
out_degree(const typename union_graph<Graph1, Graph2>::vertex_descriptor& u,
const union_graph<Graph1, Graph2>& g)
{
typedef union_graph<Graph1, Graph2> UG;
typedef graph_traits<Graph1>::vertex_descriptor VD1;
typedef graph_traits<Graph2>::vertex_descriptor VD2;
VD1 u1;
VD2 u2;
tie( u1, u2 ) = detail::get_corresponding_vertices<Graph1, Graph2>( u );
return out_degree(u1, g.m_g1) + out_degree(u2, g.m_g2);
}
// BidirectionalGraph requirements
template <typename Graph1, typename Graph2>
std::pair<typename union_graph<Graph1, Graph2>::in_edge_iterator,
typename union_graph<Graph1, Graph2>::in_edge_iterator>
in_edges(const typename union_graph<Graph1, Graph2>::vertex_descriptor& u,
const union_graph<Graph1, Graph2>& g)
{
typedef union_graph<Graph1, Graph2> UG;
typedef graph_traits<Graph1>::vertex_descriptor VD1;
typedef graph_traits<Graph2>::vertex_descriptor VD2;
typedef graph_traits<Graph1>::in_edge_iterator IEI1;
typedef graph_traits<Graph2>::in_edge_iterator IEI2;
VD1 u1;
VD2 u2;
tie( u1, u2 ) = detail::get_corresponding_vertices<Graph1, Graph2>( u );
return make_union_different_range<IEI1, IEI2, WR1, WR2>( in_edges<Graph1>(u1, g.m_g1), in_edges<Graph2>(u2, g.m_g2) );
}
template <typename Graph1, typename Graph2>
typename union_graph<Graph1, Graph2>::degree_size_type
in_degree(const typename union_graph<Graph1, Graph2>::vertex_descriptor& u,
const union_graph<Graph1, Graph2>& g)
{
typedef union_graph<Graph1, Graph2> UG;
typedef graph_traits<Graph1>::vertex_descriptor VD1;
typedef graph_traits<Graph2>::vertex_descriptor VD2;
VD1 u1;
VD2 u2;
tie( u1, u2 ) = detail::get_corresponding_vertices<Graph1, Graph2>( u );
return in_degree(u1, g.m_g1) + in_degree(u2, g.m_g2);
}
template <typename Graph1, typename Graph2>
typename union_graph<Graph1, Graph2>::degree_size_type
degree(const typename union_graph<Graph1, Graph2>::vertex_descriptor& u,
const union_graph<Graph1, Graph2>& g)
{
return out_degree(u, g) + in_degree(u, g);
}
// AdjacencyGraph requirements
template <typename Graph1, typename Graph2>
std::pair<typename union_graph<Graph1, Graph2>::adjacency_iterator,
typename union_graph<Graph1, Graph2>::adjacency_iterator>
adjacent_vertices(const typename union_graph<Graph1, Graph2>::vertex_descriptor& u,
const union_graph<Graph1, Graph2>& g)
{
typedef union_graph<Graph1, Graph2> UG;
typedef graph_traits<Graph1>::vertex_descriptor VD1;
typedef graph_traits<Graph2>::vertex_descriptor VD2;
typedef graph_traits<Graph1>::adjacency_iterator AI1;
typedef graph_traits<Graph2>::adjacency_iterator AI2;
VD1 u1;
VD2 u2;
tie( u1, u2 ) = detail::get_corresponding_vertices<Graph1, Graph2>( u );
return make_union_different_range<AI1, AI2, WR1, WR2>( adjacent_vertices(u1, g.m_g1), adjacent_vertices(u2, g.m_g2) );
}
// VertexListGraph requirements
template <typename Graph1, typename Graph2>
typename union_graph<Graph1, Graph2>::vertices_size_type
num_vertices(const union_graph<Graph1, Graph2>& g)
{
return num_vertices(g.m_g1);
}
template <typename Graph1, typename Graph2>
std::pair<typename union_graph<Graph1, Graph2>::vertex_iterator,
typename union_graph<Graph1, Graph2>::vertex_iterator>
vertices(const union_graph<Graph1, Graph2>& g)
{
typedef union_graph<Graph1, Graph2> UG;
typedef graph_traits<Graph1>::vertex_iterator VI1;
typedef graph_traits<Graph2>::vertex_iterator VI2;
VI2 vi2 = VI2();
VI2 vi2_end = vi2;
return make_union_different_range<VI1, VI2, WR1, WR2>( vertices(g.m_g1), make_pair(vi2, vi2_end) );
}
// EdgeListGraph requirements
template <typename Graph1, typename Graph2>
typename union_graph<Graph1, Graph2>::edges_size_type
num_edges(const union_graph<Graph1, Graph2>& g)
{
return num_edges(g.m_g1) + num_edges(g.m_g2);
}
template <typename Graph1, typename Graph2>
std::pair<typename union_graph<Graph1, Graph2>::edge_iterator,
typename union_graph<Graph1, Graph2>::edge_iterator>
edges(const union_graph<Graph1, Graph2>& g)
{
typedef union_graph<Graph1, Graph2> UG;
typedef graph_traits<Graph1>::edge_iterator EI1;
typedef graph_traits<Graph2>::edge_iterator EI2;
return make_union_different_range<EI1, EI2, WR1, WR2>( edges(g.m_g1), edges(g.m_g2) );
}
// AdjacencyMatrix requirements
template <typename Graph1, typename Graph2>
std::pair<typename union_graph<Graph1, Graph2>::edge_descriptor, bool>
edge(const typename union_graph<Graph1, Graph2>::vertex_descriptor& u,
const typename union_graph<Graph1, Graph2>::vertex_descriptor& v,
const union_graph<Graph1, Graph2>& g)
{
typedef union_graph<Graph1, Graph2> UG;
typedef graph_traits<Graph1>::vertex_descriptor VD1;
typedef graph_traits<Graph2>::vertex_descriptor VD2;
typedef graph_traits<Graph1>::edge_descriptor ED1;
typedef graph_traits<Graph2>::edge_descriptor ED2;
VD1 u1, v1;
VD2 u2, v2;
tie( u1, u2 ) = detail::get_corresponding_vertices<Graph1, Graph2>( u );
tie( v1, v2 ) = detail::get_corresponding_vertices<Graph1, Graph2>( v );
// g1 check
{
ED1 e1;
bool exists;
tie( e1, exists ) = edge(u1, v1, g.m_g1);
if ( exists )
return make_pair( graph_traits<UG>::edge_descriptor( WR1<ED1>( e1 ) ), exists );
}
// g2 check
{
ED2 e2;
bool exists;
tie( e2, exists ) = edge(u2, v2, g.m_g2);
return make_pair( graph_traits<UG>::edge_descriptor( WR2<ED2>( e2 ) ), exists );
}
}
//===========================================================================
// Property map
namespace detail {
struct union_graph_property_selector {
template <class UnionGraph, class Property, class Tag>
struct bind_ {
typedef typename UnionGraph::graph_type Graph;
typedef property_map<Graph, Tag> Map;
typedef typename Map::type type;
typedef typename Map::const_type const_type;
};
};
} // namespace detail
template <>
struct vertex_property_selector<union_graph_tag> {
typedef detail::union_graph_property_selector type;
};
template <>
struct edge_property_selector<union_graph_tag> {
typedef detail::union_graph_property_selector type;
};
template <typename Graph1, typename Graph2, typename Property>
typename property_map<Graph1, Property>::type
get(Property p, union_graph<Graph1, Graph2>& g)
{
return get(p, const_cast<Graph1&>(g.m_g1));
}
template <typename Graph1, typename Graph2, typename Property>
typename property_map<Graph1, Property>::const_type
get(Property p, const union_graph<Graph1, Graph2>& g)
{
return get(p, (const Graph1&)g.m_g1);
}
/*
template <typename Graph1, typename Graph2, typename Property,
typename Key>
typename property_map_value<Graph1, Property>::type
get(Property p, const union_graph<Graph1, Graph2>& g, const Key& k)
{
return get(p, (const Graph1&)g.m_g1, k);
}
*/
template <typename Graph1, typename Graph2, typename Property>
typename property_map_value<Graph1, Property>::type
get(Property p, const union_graph<Graph1, Graph2>& g, const typename union_graph<Graph1, Graph2>::vertex_descriptor& u)
{
typedef graph_traits<Graph1>::vertex_descriptor VD1;
typedef graph_traits<Graph2>::vertex_descriptor VD2;
VD1 u1;
VD2 u2;
//tie( u1, u2 ) = detail::get_corresponding_vertices<Graph1, Graph2>( u );
return get(p, (const Graph1&)g.m_g1, u1);
}
template <typename Graph1, typename Graph2, typename Property,
typename Key, typename Value>
void
put(Property p, const union_graph<Graph1, Graph2>& g, const Key& k,
const Value& val)
{
put(p, const_cast<Graph1&>(g.m_g1), k, val);
}
} // namespace boost
#endif // BOOST_UNION_GRAPH_HPP
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk