You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
406 lines
13 KiB
406 lines
13 KiB
//======================================================================= |
|
// Copyright 2001 Universite Joseph Fourier, Grenoble. |
|
// Author: Francois Faure |
|
// |
|
// Distributed under 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) |
|
//======================================================================= |
|
#ifndef BOOST_GRAPH_ADJACENCY_LIST_IO_HPP |
|
#define BOOST_GRAPH_ADJACENCY_LIST_IO_HPP |
|
|
|
#include <iostream> |
|
#include <vector> |
|
#include <boost/graph/adjacency_list.hpp> |
|
#include <boost/graph/iteration_macros.hpp> |
|
#include <cctype> |
|
|
|
// Method read to parse an adjacency list from an input stream. Examples: |
|
// cin >> read( G ); |
|
// cin >> read( G, NodePropertySubset(), EdgepropertySubset() ); |
|
// |
|
// Method write to print an adjacency list to an output stream. Examples: |
|
// cout << write( G ); |
|
// cout << write( G, NodePropertySubset(), EdgepropertySubset() ); |
|
|
|
namespace boost { |
|
|
|
/* outline |
|
- basic property input |
|
- get property subset |
|
- graph parser |
|
- property printer |
|
- graph printer |
|
- user methods |
|
*/ |
|
|
|
//=========================================================================== |
|
// basic property input |
|
|
|
template<class Tag, class Value, class Next> |
|
std::istream& operator >> ( std::istream& in, property<Tag,Value,Next>& p ) |
|
{ |
|
in >> p.m_value >> *(static_cast<Next*>(&p)); // houpla !! |
|
return in; |
|
} |
|
|
|
template<class Tag, class Value> |
|
std::istream& operator >> ( std::istream& in, property<Tag,Value,no_property>& p ) |
|
{ |
|
in >> p.m_value; |
|
return in; |
|
} |
|
|
|
inline std::istream& operator >> ( std::istream& in, no_property& ) |
|
{ |
|
return in; |
|
} |
|
|
|
// basic property input |
|
//=========================================================================== |
|
// get property subsets |
|
|
|
// get a single property tagged Stag |
|
template<class Tag, class Value, class Next, class V, class Stag> |
|
void get |
|
( property<Tag,Value,Next>& p, const V& v, Stag s ) |
|
{ |
|
get( *(static_cast<Next*>(&p)),v,s ); |
|
} |
|
|
|
template<class Value, class Next, class V, class Stag> |
|
void get |
|
( property<Stag,Value,Next>& p, const V& v, Stag ) |
|
{ |
|
p.m_value = v; |
|
} |
|
|
|
// get a subset of properties tagged Stag |
|
template<class Tag, class Value, class Next, |
|
class Stag, class Svalue, class Snext> |
|
void getSubset |
|
( property<Tag,Value,Next>& p, const property<Stag,Svalue,Snext>& s ) |
|
{ |
|
get( p, s.m_value, Stag() ); |
|
getSubset( p, Snext(s) ); |
|
} |
|
|
|
template<class Tag, class Value, class Next, |
|
class Stag, class Svalue> |
|
void getSubset |
|
( property<Tag,Value,Next>& p, const property<Stag,Svalue,no_property>& s) |
|
{ |
|
get( p, s.m_value, Stag() ); |
|
} |
|
|
|
inline void getSubset |
|
( no_property&, const no_property& ) |
|
{ |
|
} |
|
|
|
#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) |
|
template<typename T, typename U> |
|
void getSubset(T& p, const U& s) |
|
{ |
|
p = s; |
|
} |
|
|
|
template<typename T> |
|
void getSubset(T&, const no_property&) |
|
{ |
|
} |
|
|
|
|
|
#endif |
|
|
|
// get property subset |
|
//=========================================================================== |
|
// graph parser |
|
typedef enum{ PARSE_NUM_NODES, PARSE_VERTEX, PARSE_EDGE } GraphParserState; |
|
|
|
template<class Graph_t, class VertexProperty, class EdgeProperty, class VertexPropertySubset, |
|
class EdgePropertySubset> |
|
struct GraphParser |
|
{ |
|
|
|
typedef Graph_t Graph; |
|
|
|
GraphParser( Graph* g ): graph(g) |
|
{} |
|
|
|
GraphParser& operator () ( std::istream& in ) |
|
{ |
|
typedef typename graph_traits<Graph>::vertex_descriptor Vertex; |
|
std::vector<Vertex> nodes; |
|
|
|
GraphParserState state = PARSE_VERTEX; |
|
|
|
unsigned int numLine = 1; |
|
char c; |
|
while ( in.get(c) ) |
|
{ |
|
if( c== '#' ) skip(in); |
|
else if( c== 'n' ) state = PARSE_NUM_NODES; |
|
else if( c== 'v' ) state = PARSE_VERTEX; |
|
else if( c== 'e' ) state = PARSE_EDGE; |
|
else if( c== '\n' ) numLine++; |
|
else if( !std::isspace(c) ){ |
|
in.putback(c); |
|
if( state == PARSE_VERTEX ){ |
|
VertexPropertySubset readProp; |
|
if( in >> readProp ) |
|
{ |
|
VertexProperty vp; |
|
getSubset( vp, readProp ); |
|
nodes.push_back( add_vertex(vp, *graph) ); |
|
} |
|
else |
|
std::cerr<<"read vertex, parse error at line"<<numLine<<std::endl; |
|
} |
|
else if( state == PARSE_EDGE ) { |
|
int source, target; |
|
EdgePropertySubset readProp; |
|
in >> source >> target; |
|
if( in >> readProp ) |
|
{ |
|
EdgeProperty ep; |
|
getSubset( ep, readProp ); |
|
add_edge(nodes[source], nodes[target], ep, *graph); |
|
} |
|
else |
|
std::cerr<<"read edge, parse error at line"<<numLine<<std::endl; |
|
} |
|
else { // state == PARSE_NUM_NODES |
|
int n; |
|
if( in >> n ){ |
|
for( int i=0; i<n; ++i ) |
|
nodes.push_back( add_vertex( *graph )); |
|
} |
|
else |
|
std::cerr<<"read num_nodes, parse error at line "<< numLine << std::endl; |
|
} |
|
} |
|
} |
|
return (*this); |
|
} |
|
|
|
|
|
protected: |
|
|
|
Graph* graph; |
|
|
|
void skip( std::istream& in ) |
|
{ |
|
char c = 0; |
|
while( c!='\n' && !in.eof() ) |
|
in.get(c); |
|
in.putback(c); |
|
} |
|
}; |
|
|
|
// parser |
|
//======================================================================= |
|
// property printer |
|
|
|
#if defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) |
|
template<class Graph, class Property> |
|
struct PropertyPrinter |
|
{ |
|
typedef typename Property::value_type Value; |
|
typedef typename Property::tag_type Tag; |
|
typedef typename Property::next_type Next; |
|
|
|
PropertyPrinter( const Graph& g ):graph(&g){} |
|
|
|
template<class Val> |
|
PropertyPrinter& operator () ( std::ostream& out, const Val& v ) |
|
{ |
|
typename property_map<Graph,Tag>::type ps = get(Tag(), *graph); |
|
out << ps[ v ] <<" "; |
|
PropertyPrinter<Graph,Next> print(*graph); |
|
print(out, v); |
|
return (*this); |
|
} |
|
private: |
|
const Graph* graph; |
|
}; |
|
#else |
|
template<class Graph, typename Property> |
|
struct PropertyPrinter |
|
{ |
|
PropertyPrinter( const Graph& g ):graph(&g){} |
|
|
|
template<class Val> |
|
PropertyPrinter& operator () ( std::ostream& out, const Val& v ) |
|
{ |
|
out << (*graph)[ v ] <<" "; |
|
return (*this); |
|
} |
|
private: |
|
const Graph* graph; |
|
}; |
|
|
|
template<class Graph, typename Tag, typename Value, typename Next> |
|
struct PropertyPrinter<Graph, property<Tag, Value, Next> > |
|
{ |
|
PropertyPrinter( const Graph& g ):graph(&g){} |
|
|
|
template<class Val> |
|
PropertyPrinter& operator () ( std::ostream& out, const Val& v ) |
|
{ |
|
typename property_map<Graph,Tag>::type ps = get(Tag(), *graph); |
|
out << ps[ v ] <<" "; |
|
PropertyPrinter<Graph,Next> print(*graph); |
|
print(out, v); |
|
return (*this); |
|
} |
|
private: |
|
const Graph* graph; |
|
}; |
|
#endif |
|
|
|
template<class Graph> |
|
struct PropertyPrinter<Graph, no_property> |
|
{ |
|
PropertyPrinter( const Graph& ){} |
|
|
|
template<class Val> |
|
PropertyPrinter& operator () ( std::ostream&, const Val& ){ return *this; } |
|
}; |
|
|
|
// property printer |
|
//========================================================================= |
|
// graph printer |
|
|
|
template<class Graph_t, class EdgeProperty> |
|
struct EdgePrinter |
|
{ |
|
|
|
typedef Graph_t Graph; |
|
typedef typename graph_traits<Graph>::vertex_descriptor Vertex; |
|
|
|
EdgePrinter( const Graph& g ) |
|
: graph(g) |
|
{} |
|
|
|
const EdgePrinter& operator () ( std::ostream& out ) const |
|
{ |
|
// assign indices to vertices |
|
std::map<Vertex,int> indices; |
|
int num = 0; |
|
BGL_FORALL_VERTICES_T(v, graph, Graph) { |
|
indices[v] = num++; |
|
} |
|
|
|
// write edges |
|
PropertyPrinter<Graph, EdgeProperty> print_Edge(graph); |
|
out << "e" << std::endl; |
|
BGL_FORALL_EDGES_T(e, graph, Graph) { |
|
out << indices[source(e,graph)] << " " << indices[target(e,graph)] << " "; |
|
print_Edge(out,e); |
|
out << std::endl; |
|
} |
|
out << std::endl; |
|
return (*this); |
|
} |
|
|
|
protected: |
|
|
|
const Graph& graph; |
|
|
|
}; |
|
|
|
template<class Graph, class V, class E> |
|
struct GraphPrinter: public EdgePrinter<Graph,E> |
|
{ |
|
GraphPrinter( const Graph& g ) |
|
: EdgePrinter<Graph,E>(g) |
|
{} |
|
|
|
const GraphPrinter& operator () ( std::ostream& out ) const |
|
{ |
|
PropertyPrinter<Graph, V> printNode(this->graph); |
|
out << "v"<<std::endl; |
|
BGL_FORALL_VERTICES_T(v, this->graph, Graph) { |
|
printNode(out,v); |
|
out << std::endl; |
|
} |
|
|
|
EdgePrinter<Graph,E>::operator ()( out ); |
|
return (*this); |
|
} |
|
}; |
|
|
|
template<class Graph, class E> |
|
struct GraphPrinter<Graph,no_property,E> |
|
: public EdgePrinter<Graph,E> |
|
{ |
|
GraphPrinter( const Graph& g ) |
|
: EdgePrinter<Graph,E>(g) |
|
{} |
|
|
|
const GraphPrinter& operator () ( std::ostream& out ) const |
|
{ |
|
out << "n "<< num_vertices(this->graph) << std::endl; |
|
EdgePrinter<Graph,E>::operator ()( out ); |
|
return (*this); |
|
} |
|
}; |
|
|
|
// graph printer |
|
//========================================================================= |
|
// user methods |
|
|
|
/// input stream for reading a graph |
|
template<class Graph, class VP, class EP, class VPS, class EPS> |
|
std::istream& operator >> ( std::istream& in, GraphParser<Graph,VP,EP,VPS,EPS> gp ) |
|
{ |
|
gp(in); |
|
return in; |
|
} |
|
|
|
/// graph parser for given subsets of internal vertex and edge properties |
|
template<class EL, class VL, class D, class VP, class EP, class GP, class VPS, class EPS> |
|
GraphParser<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP,VPS,EPS> |
|
read( adjacency_list<EL,VL,D,VP,EP,GP>& g, VPS vps, EPS eps ) |
|
{ |
|
return GraphParser<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP,VPS,EPS>(&g); |
|
} |
|
|
|
/// graph parser for all internal vertex and edge properties |
|
template<class EL, class VL, class D, class VP, class EP, class GP> |
|
GraphParser<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP,VP,EP> |
|
read( adjacency_list<EL,VL,D,VP,EP,GP>& g ) |
|
{ |
|
return GraphParser<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP,VP,EP>(&g); |
|
} |
|
|
|
|
|
/// output stream for writing a graph |
|
template<class Graph, class VP, class EP> |
|
std::ostream& operator << ( std::ostream& out, const GraphPrinter<Graph,VP,EP>& gp ) |
|
{ |
|
gp(out); |
|
return out; |
|
} |
|
|
|
/// write the graph with given property subsets |
|
template<class EL, class VL, class D, class VP, class EP, class GP, class VPS, class EPS> |
|
GraphPrinter<adjacency_list<EL,VL,D,VP,EP,GP>,VPS,EPS> |
|
write( const adjacency_list<EL,VL,D,VP,EP,GP>& g, VPS, EPS ) |
|
{ |
|
return GraphPrinter<adjacency_list<EL,VL,D,VP,EP,GP>,VPS,EPS>(g); |
|
} |
|
|
|
/// write the graph with all internal vertex and edge properties |
|
template<class EL, class VL, class D, class VP, class EP, class GP> |
|
GraphPrinter<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP> |
|
write( const adjacency_list<EL,VL,D,VP,EP,GP>& g ) |
|
{ |
|
return GraphPrinter<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP>(g); |
|
} |
|
|
|
// user methods |
|
//========================================================================= |
|
}// boost |
|
#endif
|
|
|