I'm trying to find all edges that are part of any cycle in a undirected Graph. Using Boost's depth_first_search and my understanding of back edges, I don't see why the back_edge method is called for both edges in the sample Graph which doesn't contain any cycles.
#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/depth_first_search.hpp>
using namespace std;
using namespace boost;
typedef adjacency_list<vecS, vecS, undirectedS, no_property, property<edge_weight_t, int> > Graph;
typedef graph_traits<Graph>::edge_descriptor Edge;
class MyVisitor : public default_dfs_visitor {
public: void back_edge(Edge e, const Graph& g) const {
// should only be called when cycle found, right?
cerr << "back_edge " << e << endl;
return;
}
};
int main() {
Graph g;
add_edge(0, 1, g);
add_edge(0, 2, g);
MyVisitor vis;
depth_first_search(g, visitor(vis));
return 0;
}
Since your graph is undirected, any tree edge is also a back edge. The documentation for DFSVisitor doesn't fail to mention this.
For an undirected graph there is some ambiguity between tree edges and back edges since the edge (u,v) and (v,u) are the same edge, but both the tree_edge() and back_edge() functions will be invoked.
One way to resolve this ambiguity is to record the tree edges, and then disregard the back-edges that are already marked as tree edges. An easy way to record tree edges is to record predecessors at the tree_edge event point.
Implementing this in the most straightforward manner: Live on Coliru
#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/depth_first_search.hpp>
namespace {
using namespace boost;
typedef adjacency_list<vecS, vecS, undirectedS, no_property, property<edge_weight_t, int> > Graph;
typedef graph_traits<Graph>::edge_descriptor Edge;
typedef std::set<Edge> EdgeSet;
}
struct MyVisitor : default_dfs_visitor {
MyVisitor(EdgeSet& tree_edges) : tree_edges(tree_edges) {}
void tree_edge(Edge e, const Graph& g) const {
std::cerr << "tree_edge " << e << std::endl;
tree_edges.insert(e);
}
void back_edge(Edge e, const Graph& g) const {
if (tree_edges.find(e) == tree_edges.end())
std::cerr << "back_edge " << e << std::endl;
}
private:
EdgeSet& tree_edges;
};
int main() {
Graph g;
add_edge(0, 1, g);
add_edge(0, 2, g);
std::set<Edge> tree_edges;
MyVisitor vis(tree_edges);
depth_first_search(g, visitor(vis));
}
Related
According to https://www.boost.org/doc/libs/1_37_0/libs/graph/doc/adjacency_list.html
the declaration of clear_out_edges is:
void clear_out_edges(vertex_descriptor u, adjacency_list& g)
I have the following in my file:
typedef adjacency_list<
vecS, vecS, directedS,
property<
vertex_name_t, std::string,
property<vertex_index_t, int,
property<vertex_color_t, boost::default_color_type,
property<vertex_distance_t, double,
property<vertex_predecessor_t, Traits::edge_descriptor>
> > > >,
property<
edge_index_t, int,
property<edge_capacity_t, double,
property<edge_weight_t, double,
property<edge_residual_capacity_t, double,
property<edge_reverse_t, Traits::edge_descriptor>
> > > > >
Graph;
Graph g;
In trying to clear the edges by visiting all of the vertices via:
Graph::vertex_iterator v, vend;
for(boost::tie(v, vend) = vertices(g); v != vend; ++v){
boost::clear_out_edges(v, g);//line in question
}
the compiler complains that:
no instance of overloaded function "boost::clear_out_edges" matches the argument list -- argument types are: (boost::range_detail::integer_iterator<std::size_t>, Graph)C/C++(304)
I am surprised by this, since g is an object of class adjacency_list via the typedef.
Any help is appreciated.
You're using v as if it is a descriptor, but it's an iterator. Dereference it:
clear_out_edges(*v, g);
May I suggest modernizing a bit, and perhaps using bundled properties and less using namespace? Too much code is being copy-pasted from ancient documentation samples which are written to still compile on c++03.
Live On Wandbox
#include <boost/graph/adjacency_list.hpp>
using namespace boost;
using Traits = adjacency_list_traits<vecS, vecS, directedS>;
using Graph = adjacency_list<
vecS, vecS, directedS,
property<vertex_name_t, std::string,
property<vertex_index_t, int,
property<vertex_color_t, boost::default_color_type,
property<vertex_distance_t, double,
property<vertex_predecessor_t,
Traits::edge_descriptor>>>>>,
property<edge_index_t, int,
property<edge_capacity_t, double,
property<edge_weight_t, double,
property<edge_residual_capacity_t, double,
property<edge_reverse_t,
Traits::edge_descriptor>>>>>>;
int main()
{
Graph g(10);
for (auto v : boost::make_iterator_range(vertices(g))) {
clear_out_edges(v, g);
}
}
Or even better, depending on tastes. Note that at least vertex_index is very redundant with vecS and may actively harm your code correctness.
UPDATE
Some hints about modernizing the code, and perhaps separating the graph model from algorithm specific metadata.
Live On Wandbox
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/edmonds_karp_max_flow.hpp>
#include <boost/graph/boykov_kolmogorov_max_flow.hpp>
struct VertexProps { std::string name; };
struct EdgeProps { double capacity = 0, weight = 0, residual = 0; };
using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
VertexProps, EdgeProps>;
using V = Graph::vertex_descriptor;
using E = Graph::edge_descriptor;
int main()
{
Graph g(10);
for (auto v : boost::make_iterator_range(vertices(g))) {
clear_out_edges(v, g);
}
auto idmap = get(boost::vertex_index, g);
std::vector<boost::default_color_type> colors(num_vertices(g));
std::vector<E> predecessors(num_vertices(g));
std::vector<double> distances(num_vertices(g));
auto weightmap = get(&EdgeProps::weight, g);
auto capacity_map = get(&EdgeProps::capacity, g);
auto residual_map = get(&EdgeProps::residual, g);
std::map<E, E> reverse_edges;
V src = 0;
V sink = 1;
boost::edmonds_karp_max_flow(
g, src, sink,
boost::color_map(colors.data())
.vertex_index_map(idmap)
.distance_map(distances.data())
.predecessor_map(predecessors.data())
.weight_map(weightmap)
.capacity_map(capacity_map)
.residual_capacity_map(residual_map)
.reverse_edge_map(boost::make_assoc_property_map(reverse_edges)));
}
Keep in mind that there's a known issue with boykov_kolmogorov_max_flow (see Boost max flow algorithms do not compile. error: forming reference to void and https://github.com/boostorg/graph/issues/232).
I was trying to use the code from this thread: Boost DFS back_edge, to record the cycles in an undirected graph. To do this I need to store the predecessors for each dfs tree when it finds a back_edge. Since this is an undirected graph I think we can not use directly on_back_edge() from EventVisitor Concept. So I was thinking to record the predecessors in the void back_edge() method of below code. But I am not sure how to do this and return the cycle vertices.
Here is the code and the part I added for recording predecessors:
#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/depth_first_search.hpp>
namespace {
using namespace boost;
typedef adjacency_list<vecS, vecS, undirectedS, no_property,
property<edge_weight_t, int> > Graph;
typedef graph_traits<Graph>::edge_descriptor Edge;
typedef std::set<Edge> EdgeSet;
}
struct MyVisitorCycle : default_dfs_visitor {
MyVisitorCycle(EdgeSet &tree_edges, vector<vector<vertex_t> > &cycles1) :
tree_edges(tree_edges), cycles(cycles1) {}
void tree_edge(Edge e, const Graph& g) const {
std::cerr << "tree_edge " << e << std::endl;
tree_edges.insert(e);
}
void back_edge(Edge e, const Graph& g) const {
if (tree_edges.find(e) == tree_edges.end())
std::cerr << "back_edge " << e << std::endl;
/// I added this part
vertex_t s = vertex (0,g);
std::vector <vertex_t> p(num_vertices (g));
depth_first_search (g, s, visitor (boost::record_predecessors (&p[0],
on_tree_edge())));/// here has problem
p.push_back (target (e,g)); /// close the cycle
cycles.push_back (p);
}
private:
EdgeSet& tree_edges;
vector<vector <vertex_t> > &cycles;
};
int main() {
Graph g;
add_edge(0, 1, g);
add_edge(1, 2, g);
add_edge(2, 3, g);
add_edge(3, 0, g);
add_edge(1, 4, g);
add_edge(4, 5, g);
add_edge(5, 6, g);
add_edge(6, 3, g);
add_edge(2, 5, g);
std::set<Edge> tree_edges;
vector<vector <vertex_t> > cycles;
MyVisitorCycle vis(tree_edges, cycles);
depth_first_search(g, visitor(vis));
}
Here's a quick post, I'll come back with some notes later
Live On Coliru
#include <iostream>
#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/depth_first_search.hpp>
namespace {
using namespace boost;
typedef adjacency_list<vecS, vecS, undirectedS, no_property, property<edge_weight_t, int> > Graph;
typedef graph_traits<Graph>::edge_descriptor Edge;
typedef std::set<Edge> EdgeSet;
}
struct MyVisitor : default_dfs_visitor {
MyVisitor(EdgeSet& tree_edges) : tree_edges(tree_edges) {}
void tree_edge(Edge e, const Graph& g) const {
std::cerr << "tree_edge " << e << std::endl;
tree_edges.insert(e);
}
void back_edge(Edge e, const Graph& g) const {
if (tree_edges.find(e) == tree_edges.end())
std::cerr << "back_edge " << e << std::endl;
}
private:
EdgeSet& tree_edges;
};
int main() {
Graph g;
add_edge(0, 1, g);
add_edge(0, 2, g);
std::set<Edge> tree_edges;
MyVisitor vis(tree_edges);
std::vector<Graph::vertex_descriptor> pred(num_vertices(g), Graph::null_vertex());
depth_first_search(g, visitor(boost::make_dfs_visitor(
boost::record_predecessors(pred.data(), boost::on_back_edge{})
)));
for (auto v : make_iterator_range(vertices(g))) {
std::cout << "Predecessor for " << v << " is " << pred.at(v) << "\n";
}
}
Prints
Predecessor for 0 is 2
Predecessor for 1 is 18446744073709551615
Predecessor for 2 is 18446744073709551615
I have to use kruskals algorithm in the boost library to find the weight of the minimum spanning tree. I think I managed that one
#include <iostream>
#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/kruskal_min_spanning_tree.hpp>
#include<vector>
using namespace std;
using namespace boost;
int main(){
typedef adjacency_list <vecS,vecS,undirectedS,no_property,property <edge_weight_t,int> > Graph;
typedef graph_traits <Graph>::edge_descriptor Edge;
typedef graph_traits <Graph>::vertex_descriptor Vertex;
int a,b,c,no_vertices,no_edges;
cin>>no_vertices>>no_edges;
Graph g(no_vertices);
property_map <Graph,edge_weight_t>::type weightmap=get(edge_weight,g);
vector <Edge> spanning_tree;
for(int i=0;i<no_edges;i++)
{
bool success;
Edge e;
cin>>a>>b>>c;
tie(e,success)=add_edge(a,b,g);
weightmap[e]=c;
}
kruskal_minimum_spanning_tree(g,back_inserter(spanning_tree));
//weight of spanning tree
int ww=0;
graph_traits<Graph>::edge_iterator ei, ei_end;
for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
{
ww=ww+weightmap[*ei];
}
cout<<"\n"<<ww;
return 0;
}
Now I need to find the distance(sum of weights) between vertex 0 and the one farthest from it? Any hints as to how I could do it?
I was thinking of using vertex iterator, but then I store the weight in weightMap so how do I access it if I iterate through the vertices of my graph?
EDIT: I have modified my program,decided to use kruskal and prim
1.kruskal for the spanning tree weight
2.prim algorithm for the distance of each vertex from the vertex 0(in spanning tree stored in map distance)
Unfortunately something goes wrong, distance[*vertex] which is the third vertex doesnt give the answer 2,but gives one
Also the weight of spanning tree is 14 instead of 7
my dummy input is:
5 6
0 1 1
0 2 2
1 2 5
1 3 1
3 2 2
2 4 3
here my programs:
#include <boost/config.hpp>
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/prim_minimum_spanning_tree.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/kruskal_min_spanning_tree.hpp>
using namespace std;
int
main()
{
using namespace boost;
typedef adjacency_list < vecS, vecS, undirectedS,
property<vertex_distance_t, int>, property < edge_weight_t, int > > Graph;
int num_nodes,num_edges,a,b,c;
cin>>num_nodes>>num_edges;
Graph g(num_nodes);
property_map<Graph, edge_weight_t>::type weightmap = get(edge_weight, g);
for (int j = 0; j < num_edges ; ++j) {
cin>>a>>b>>c;
graph_traits<Graph>::edge_descriptor e;
bool inserted;
tie(e, inserted) = add_edge(a, b, g);
weightmap[e] = c;
}
vector < graph_traits < Graph >::vertex_descriptor > p(num_vertices(g));
cout<<num_vertices(g);
property_map<Graph, vertex_distance_t>::type distance = get(vertex_distance, g);
property_map<Graph, vertex_index_t>::type indexmap = get(vertex_index, g);
prim_minimum_spanning_tree
(g, *vertices(g).first, &p[0], distance, weightmap, indexmap,
default_dijkstra_visitor());
vector <graph_traits<Graph>::edge_descriptor> spanning_tree;
kruskal_minimum_spanning_tree(g,back_inserter(spanning_tree));
int ww=0;
typedef graph_traits < Graph >::edge_descriptor Edge;
for (vector<Edge>::iterator et= spanning_tree.begin(); et != spanning_tree.end(); ++et)
{
ww=ww+weightmap[*et];
}
typedef graph_traits<Graph>::vertex_iterator vertex_iter;
std::pair<vertex_iter, vertex_iter> vp;
for (vp = vertices(g); vp.first != vp.second; ++vp.first)
{
cout<<distance[*vp.first];
}
prim_minimum_spanning_tree
(g, *vertices(g).first, &p[0], distance, weightmap, indexmap,
default_dijkstra_visitor());
return EXIT_SUCCESS;
}
THank you :)
I'm not really sure how to interpret the result of the Kruskal MST algorithm (in particular the edge list). Could this be what you were looking for:
int ww = 0;
for (auto const& e : spanning_tree) {
std::cout << "Traversing: " << source(e,g) << " -> " << target(e,g) << ", cost " << weightmap[e] << "\n";
ww += weightmap[e];
}
cout << "\n" << ww;
Otherwise, you'd probably want to pass a predecessor map to Kruskal and read that for your desired path.
Meanwhile see my above sketch Live On Coliru
I am trying to iterate through the edges of a graph and output their edge weights. I am confused though. I know how to output the "edges", but this is actually just a (vertex, vertex) which defines the edge. So do I index *edgePair.first into the EdgeWeightMap to get the weight of the edge starting from vertex *edgePair.first? This doesn't compile : "no match for operator<<".
#include <iostream>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
typedef boost::property<boost::edge_weight_t, double> EdgeWeightProperty;
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, EdgeWeightProperty> Graph;
int main(int,char*[])
{
// Create a graph object
Graph g(2);
EdgeWeightProperty e = 5;
add_edge(0, 1, e, g);
boost::property_map<Graph, boost::edge_weight_t>::type EdgeWeightMap = get(boost::edge_weight_t(), g);
typedef boost::graph_traits<Graph>::edge_iterator edge_iter;
std::pair<edge_iter, edge_iter> edgePair;
for(edgePair = edges(g); edgePair.first != edgePair.second; ++edgePair.first)
{
std::cout << EdgeWeightMap[*edgePair.first] << " ";
}
return 0;
}
Any thoughts?
Thanks,
David
In this code, EdgeWeightProperty is declared as a vertex property rather than an edge property, and so it doesn't make sense to insert edges with that property. Try adding boost::no_property before EdgeWeightProperty in your adjacency_list typedef. Also, you might want to use get(EdgeWeightMap, *edgePair.first) rather than operator[] because that will work with more property map types.
Sorry if this is a very basic questions for some of you but I'm new to C++ (let alone Boost Graph Library) and couldn't figure out this problem. So far I've been able to formulate/gather code to create a graph using the code below.
Now I'm trying to figure out the code to find the longest path in this graph.
Can someone please help with what would the code be? I was having trouble trying to figure out if/how to traverse through each node and/or edge when trying to find the path?
I have to try to return all the nodes and edges in the longest path.
Any help will be greatly appreciated.
P.S. does anyone know if C++ has organized documentation like Javadoc??
#include <boost/graph/dag_shortest_paths.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <windows.h>
#include <iostream>
int main()
{
using namespace boost;
typedef adjacency_list<vecS, vecS, directedS, property<vertex_distance_t, double>, property<edge_weight_t, double> > graph_t;
graph_t g(6);
enum verts { stationA, stationB, stationC, stationD, stationE, stationF };
char name[] = "rstuvx";
add_edge(stationA, stationB, 5000.23, g);
add_edge(stationA, stationC, 3001, g);
add_edge(stationA, stationD, 2098.67, g);
add_edge(stationA, stationE, 3298.84, g);
add_edge(stationB, stationF, 2145, g);
add_edge(stationC, stationF, 4290, g);
add_edge(stationD, stationF, 2672.78, g);
add_edge(stationE, stationF, 11143.876, g);
add_edge(stationA, stationF, 1, g);
//Display all the vertices
typedef property_map<graph_t, vertex_index_t>::type IndexMap;
IndexMap index = get(vertex_index, g);
std::cout << "vertices(g) = ";
typedef graph_traits<graph_t>::vertex_iterator vertex_iter;
std::pair<vertex_iter, vertex_iter> vp;
for (vp = vertices(g); vp.first != vp.second; ++vp.first)
std::cout << index[*vp.first] << " ";
std::cout << std::endl;
// ...
// Display all the edges
// ...
std::cout << "edges(g) = " << std::endl;
graph_traits<graph_t>::edge_iterator ei, ei_end;
for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
std::cout << "(" << index[source(*ei, g)] << "," << index[target(*ei, g)] << ") \n";
std::cout << std::endl;
// ...
I think you should check the example in your boost distribution.
Online : http://www.boost.org/doc/libs/1_38_0/libs/graph/example/dijkstra-example.cpp
To make it find the longest path you need to simply inverse the weight (W), either use a Constant - W, or 1/W. If the constant is 0, then it means it's a negation (-W).
I agree that one has to be careful about sign reversal. Firstly, most shortest path algorithms are only for positive edge graphs. You do have some options (e.g Bellman-Ford algorithm) that generalize to graphs with negative weight, they are not guaranteed to return the optimal answer if there are negative cycles in the graph.