4

Try to write a Karger’s algorithm with boost::graph

example (first column is vertice, other are adjacent vertices):

  • 1 2 3
  • 2 1 3 4
  • 3 1 2 4
  • 4 2 3

assume I merge 2 to 1, I get the result

  • 1 2 3 2 1 1 3 4
  • 2 1 3 4
  • 3 1 2 4
  • 4 2 3

first question : How could I change the adjacent vertices("2" to "1") of vertice 1?

my naive solution

template<typename Vertex, typename Graph>
void change_adjacent_vertices_value(Vertex input, Vertex value, Graph &g)
{
    for (auto it = boost::adjacent_vertices(input, g);
         it.first != it.second; ++it.first){
        if(*it.first == value){
            *(it.first) = input; //error C2106: '=' : left operand must be l-value
        }
    }
}

Apparently, I can't set the value of the adjacent vertices to "1" by this way

The result I want after "change_adjacent_vertices_value"

  • 1 1 3 1 1 1 3 4
  • 2 1 3 4
  • 3 1 2 4
  • 4 2 3

second question : How could I pop out the adjacent vertices?

Assume I want to pop out the consecutive 1 from the vertice 1 The result I expected

  • 1 1 3 1 3 4
  • 2 1 3 4
  • 3 1 2 4
  • 4 2 3

any function like "pop_adjacent_vertex" could use?

Community
  • 1
  • 1
StereoMatching
  • 4,971
  • 6
  • 38
  • 70
  • @Codor Well, the code's not working, so it won't really be appropriate for Code Review. – Bernhard Barker Jun 01 '14 at 08:40
  • @sehe What parts do you want? – StereoMatching Jun 02 '14 at 11:47
  • The parts that are missing? The parts that I implemented yesterday trying to see the problem. – sehe Jun 02 '14 at 20:23
  • After reading the algorithm it seems to me that boost graph is overkill. Why not use a vector of linked lists? Do you care about the min cut or do you need to do other graph operations during stages of the algorithm? – pbible Jun 03 '14 at 12:00
  • @sehe I will give post the codes in several days. – StereoMatching Jun 03 '14 at 12:19
  • @pbible Yes, this algorithm can be implemented with vector, vector or other simple solution, I prefer boost::graph to implementing this algorithm because I want to get familiar with boost graph – StereoMatching Jun 03 '14 at 12:21
  • Understood. My experience with BGL is that removing vertexes is often a pain depending on using vecS, setS or others. While listS lets you remove easily, updating indexes can be a pain. BGL is good for running stock algorithms (or custom variations of stock aglos) on graphs whose structure doesn't change often. My experience... – pbible Jun 03 '14 at 14:33

1 Answers1

1

First of all, in most cases the graph vertex descriptor is simply an integer or a pointer. It means the assignments like in your code would not change the graph.

Instead you should use API from the concept of Mutable Graph: http://www.boost.org/doc/libs/1_55_0/libs/graph/doc/MutableGraph.html

In your case the code can look like:

///adds all edges from src to target and removes the vertex src from the graph
template<typename Vertex, typename Graph>
void merge_vertices(Vertex src, Vertex tgt, Graph &g)
{
    for (auto it = boost::out_edges(src, g);
         it.first != it.second; ++it.first)
    {
        Vertex u = target(*it.first,g);
        add_edge(u,tgt,g); 
        //Note, if edges have properties, you should extract and copy them as well
    }
    clear_vertex(src,g);  //removes all edges to/from "src"
    remove_vertex(src,g); //removes vertex src itself
}

To avoid confusion I would recommend using graph where vertex and edge descriptors are not invalidated when you remove an edge or vertex.

It leads to the following test example:

typedef boost::adjacency_list<boost::listS, 
         boost::listS, boost::undirectedS > graph_t;
typedef boost::graph_traits<graph_t>::vertex_descriptor vertex_t;

int main(int, char**)
{
    typedef std::map<vertex_t, size_t> IndexMap;
    IndexMap mapIndex;

    graph_t g;
    vertex_t v0 = add_vertex(g);
    mapIndex[v0]=0;
    vertex_t v1 = add_vertex(g);
    mapIndex[v1]=1;
    vertex_t v2 = add_vertex(g);
    mapIndex[v2]=2;
    vertex_t v3 = add_vertex(g);
    mapIndex[v3]=3;

    add_edge(v0,v2,g);
    add_edge(v1,v3,g);
    add_edge(v1,v0,g);
    std::cout << "Before merging " << std::endl;
    boost::print_graph(g, boost::make_assoc_property_map(mapIndex));

    merge_vertices(v1,v2,g);
    std::cout << "After merging "<< std::endl;

    boost::print_graph(g, boost::make_assoc_property_map(mapIndex));;
}

Result:

Before merging 
0 <--> 2 1 
1 <--> 3 0 
2 <--> 0 
3 <--> 1 
After merging 
0 <--> 2 2 
2 <--> 0 3 0 
3 <--> 2 
Michael Simbirsky
  • 3,045
  • 1
  • 12
  • 24