问题
I'm trying to copy an edge from a graph and add it to another (with all his vertices and properties), I make something like:
if (!dataG.empty())
{
auto const& gr = dataG.front(); // firslt graph in G_list
auto ep = edges(gr).first; //first edge in gr
vertex_t from = source(*ep, gr);
vertex_t to = target(*ep, gr);
boost::property_map<Graph, int VertexProperties::*>::type idmap = boost::get(&VertexProperties::id, testg);
boost::property_map<Graph, int VertexProperties::*>::type labelmap = boost::get(&VertexProperties::label, testg);
idmap[from] = gr[from].id;
labelmap[from] = gr[from].label;
boost::add_vertex(VertexProperties(idmap[from], labelmap[from]), testg);
idmap[to] = gr[to].id;
labelmap[to] = gr[to].label;
boost::add_vertex(VertexProperties(idmap[to], labelmap[to]), testg);
boost::add_edge(from, to, gr[*ep], testg);
}
and I got this error:
segmentation error core dumped
The full source is here http://pastebin.com/vzCDbTiB
Sample input: http://pastebin.com/g4cgaHJB
回答1:
You want to insert the edge so the number of vertices gets automatically adjusted to accommodate the source and target for the edge.
Then, just copy the vertex properties by their bundles, no need to meddle with the member-specific maps (these are useful when you want to pass specific properties to e.g. algorithms).
Here's the simplified version:
auto const& gr = dataG.front(); // firslt graph in G_list
auto ep = edges(gr).first; // first edge in gr
vertex_t from = source(*ep, gr);
vertex_t to = target(*ep, gr);
Graph::edge_descriptor copied_edge = boost::add_edge(from, to, gr[*ep], testg).first;
testg[source(copied_edge, testg)] = gr[from];
testg[target(copied_edge, testg)] = gr[to];
Live sample:
Live On Coliru
#include <boost/graph/adjacency_list.hpp>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
/*********************************************/
// vertex
struct VertexProperties {
int id;
int label;
VertexProperties(unsigned i = 0, unsigned l = 0) : id(i), label(l) {}
};
// edge
struct EdgeProperties {
unsigned id;
unsigned label;
EdgeProperties(unsigned i = 0, unsigned l = 0) : id(i), label(l) {}
};
// Graph
struct GraphProperties {
unsigned id;
unsigned label;
GraphProperties(unsigned i = 0, unsigned l = 0) : id(i), label(l) {}
};
// adjency list
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, VertexProperties, EdgeProperties, GraphProperties>
Graph;
// descriptors
typedef boost::graph_traits<Graph>::vertex_descriptor vertex_t;
typedef std::pair<boost::graph_traits<Graph>::edge_descriptor, bool> edge_t;
// iterators
typedef boost::graph_traits<Graph>::vertex_iterator vertex_iter;
typedef boost::graph_traits<Graph>::edge_iterator edge_iter;
int main()
{
clock_t start = std::clock();
std::vector<Graph> dataG;
std::ifstream file_reader("5.txt"); // flux d'entrée pour opérer sur les fichiers.
// ifstream * file_reader= new ifstream("60.txt" ); //flux d'entrée pour opérer sur les fichiers.
std::string line;
while (std::getline(file_reader, line)) { // getline reads characters from an input stream and places them into a string
char lineType;
std::stringstream ss(line); // use a string buffer that contains a sequence of characters.
if (ss >> lineType)
switch (lineType) {
case 't': {
char diez;
unsigned gid;
if (ss >> diez >> gid) {
dataG.emplace_back(GraphProperties(gid, gid));
} else
throw std::runtime_error("Error parsing '" + line + "'");
} break;
case 'v': {
assert(!dataG.empty());
int vId, vLabel;
if (ss >> vId >> vLabel) {
boost::add_vertex(VertexProperties(vId, vLabel), dataG.back());
} else
throw std::runtime_error("Error parsing '" + line + "'");
} break;
case 'e': {
assert(!dataG.empty());
int fromId, toId, vLabel;
if (ss >> fromId >> toId >> vLabel) {
// Note that the EdgeProperty.id doesn't make sense with your input data
// as it only contains [vertexFrom vertexTo edgeData]
boost::add_edge(fromId, toId, EdgeProperties(vLabel, vLabel), dataG.back());
} else
throw std::runtime_error("Error parsing '" + line + "'");
} break;
}
else {
// ignoring empty line
}
}
Graph testg;
if (!dataG.empty()) {
auto const& gr = dataG.front(); // firslt graph in G_list
auto ep = edges(gr).first; // first edge in gr
vertex_t from = source(*ep, gr);
vertex_t to = target(*ep, gr);
Graph::edge_descriptor copied_edge = boost::add_edge(from, to, gr[*ep], testg).first;
testg[source(copied_edge, testg)] = gr[from];
testg[target(copied_edge, testg)] = gr[to];
}
typedef std::pair<edge_iter, edge_iter> edge_pair;
// int c = 0; //compteur de dataG
//++c;
std::cout << "Graph contains " << num_vertices(testg) << " vertices, and " << num_edges(testg) << " edges" << std::endl;
// Vertex list
std::cout << " Vertex list: " << std::endl;
for (size_t i = 0; i < num_vertices(testg); ++i) // size_t vertice number in the graph
{
std::cout << " v[" << i << "] ID: " << testg[i].id << ", Label: " << testg[i].label << std::endl;
}
// Edge list
std::cout << " Edge list: " << std::endl;
edge_pair ep;
for (ep = edges(testg); ep.first != ep.second; ++ep.first) // ep edge number
{
vertex_t from = source(*ep.first, testg);
vertex_t to = target(*ep.first, testg);
edge_t edg = edge(from, to, testg);
std::cout << " e[" << testg[from].id << "," << testg[to].id << "] ID: " << testg[edg.first].id
<< " , Label: " << testg[edg.first].label << std::endl;
}
std::cout << std::endl;
std::cout << "TIME: " << (std::clock() - start) / (double)CLOCKS_PER_SEC << "s" << std::endl; // fin du programme.
}
Prints
INPUT
Graph contains 2 vertices, and 1 edges
Vertex list:
v[0] ID: 0, Label: 0
v[1] ID: 1, Label: 3
Edge list:
e[0,1] ID: 10 , Label: 10
TIME: 0s
来源:https://stackoverflow.com/questions/28827006/copying-edges-with-adjacent-vertices-and-their-properties-using-boost