Can I get boost :: write_graphviz to only write edges?

I am trying to get BGL to output a file that only has edges, since I am making the maximum connected component and I do not want to erase the vertices, but I also do not want to draw them if there is no edge.

My dot file right now:

graph G {
0;
1;
2;
3;
4;
5;
6;
7;
8;
9;
10;
11;
12;
0--1 [label="-3"];
0--5 [label="-2"];
2--3 [label="-8"];
3--8 [label="-4"];
4--5 [label="-1"];
4--6 [label="-6"];
4--7 [label="-5"];
4--8 [label="-10"];
8--9 [label="-9"];
}

      

and I print it by running

boost::write_graphviz(myfile, G, boost::default_writer(), make_edge_writer(w_map));

      

where make_edge_writer(w_map)

ensures that I print the weight (ignore the negative signs, I am actually making the maximum spanning tree, but my toy example had positive edges).

Now graphviz draws 9 vertices in my regular graph, plus the vertices {10, 11, 12) individually. If I manually edit my points file like this:

graph G {
0--1 [label="-3"];
0--5 [label="-2"];
2--3 [label="-8"];
3--8 [label="-4"];
4--5 [label="-1"];
4--6 [label="-6"];
4--7 [label="-5"];
4--8 [label="-10"];
8--9 [label="-9"];
}

      

and then run graphviz, I get the same graph minus the redundant vertices! Which basically means that Graphviz doesn't have to know the vertices in advance, right?

So, does anyone know how I can get write_graphviz

to not write the vertex indices in advance? I don't want to delete these vertices because in real life examples the redundant vertices might be inside the graph and my vertex numbers don't match my input.

Also, it really doesn't really matter, but it bullied me and I was wondering if anyone knows how to do this. I tried to move from boost::default_writer()

to my own code (which did nothing), but that didn't seem to make any difference.

+3


source to share


1 answer


Three parts answer

  • Predefining vertices in Graphviz can be helpful

Do you want to filter nodes

  • You can customize PropertyWriter

  • You can customize the rendering of the graph

I would suggest the former (because of "express your intent") or the latter (because of the "separation of concerns").

Predefining vertices in Graphviz can be helpful

Graphviz does not need to know the vertices in advance if they do not need some attributes other than the default.

 0 [label="Node 0"];
 1 [shape="Mrect"];

 0 -- 1; // works

      

But

 0 [label="Node 0"] -- 1 [shape="Mrect"]; // doesn't work

      

Actually

 0 [label="Node 0"];
 0 -- 1 [label="oops"]; // oops

      

Sets the "oops" label at the border, not the vertex with ID 1.




Connect PropertyWriter

What you really want to do is filter out vertices with zero adjacent vertices, I would say. If you insist not to do this, you can pass custom PropertyWriter properties to the EdgePropertyWriter. I guess this might work for you.

  template <class Name>
  class my_vertex_writer {
  public:
    my_vertex_writer(Graph& g) : g_(g) {}

    template <class Vertex>
    void operator()(std::ostream& out, const Vertex& v) const {
         // pseudo-code!
         if (0 == boost::size(in_edges(v, g_)))
            out << "[style=\"invis\"]";
    }
  private:
    Graph& g_;
  };

      

Renderer setup

You can use gvpr

to post-process the output:

gvpr -c 'N[$.degree==0]{$.style="invis"}' test.dot | dot -Tpng > test.png

      

enter image description here

Or, to really remove the use of space:

gvpr -c 'N[$.degree==0]{delete(0,$);}' test.dot | dot -Tpng > test.png

      

For some reason, I seemed to need to repeat this (I'm sure a trip to the documentation might fix this): gvpr

cat test.dot | 
    gvpr -c 'N[$.degree==0]{delete(0,$)}' |
    gvpr -c 'N[$.degree==0]{delete(0,$)}' |
    gvpr -c 'N[$.degree==0]{delete(0,$)}' |
    dot -Tpng > test.png

      

enter image description here

+5


source







All Articles