copying edges with adjacent vertices and their properties using BOOST

北战南征 提交于 2019-12-13 07:49:05

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!