diff --git a/doc/figs/mcm.jpg b/doc/figs/mcm.jpg new file mode 100644 index 000000000..2a225b604 Binary files /dev/null and b/doc/figs/mcm.jpg differ diff --git a/doc/karp_minimum_cycle_mean.html b/doc/karp_minimum_cycle_mean.html new file mode 100644 index 000000000..16c73443e --- /dev/null +++ b/doc/karp_minimum_cycle_mean.html @@ -0,0 +1,83 @@ + + + + + Boost Graph Library: Karps Minimum Cycle Mean + + + + + + + +

C++ Boost +

+

karp_minimum_cycle_mean

+

+

+template <typename Graph>
+double karp_minimum_cycle_mean(Graph g);
+
+

+ + +The karp_minimum_cycle_mean() function calculates minimum cycle mean of a +weighted directed graph G=(V,E,W), where V is a vertex set, +E is an edge set, W: E -> R is an edge weight function . +

+ +

We define the mean weight of a cycle C=<e1,e1,e2..,ek> of edges in E to be

+

+mean weight of cycle +

+ +The minimum cycle mean is the minimum cycle mean +of all cycles of the graph. The karp_minimum_cycle_mean() returns the +calculated minimum cycle mean. Returns -1 if the graph has no cycles. + +

+

+This algorithm was described by Richard M. Karp in his paper +A characterization of the minimum cycle mean in a digraph

+ + +

Where Defined

+

boost/graph/karp_minimum_cycle_mean.hpp +

+

Parameters

+ +

IN: const Graph g +

+
A weighted directed graph. +
+ +

+OUT: double minimum_mean_weight +

+ +

Complexity

+

The implemented algorithm runs in O(|V||E|) time. Where V and E are vertex set and edge set respectively. +

+ +

Example

+

The program in libs/graph/example/minimum_cycle_mean_example.cpp +finds the minimum cycle mean of the defined graph. +

+ diff --git a/example/minimum_cycle_mean_example.cpp b/example/minimum_cycle_mean_example.cpp new file mode 100644 index 000000000..d6928aaf3 --- /dev/null +++ b/example/minimum_cycle_mean_example.cpp @@ -0,0 +1,28 @@ +#include +#include +typedef boost::property EdgeWeight; +typedef boost::adjacency_list DirectedGraph; +int main() { + + DirectedGraph g; + /** + * Create the graph drawn below. + * + * + * 10 + * ________ + * / 1 3 \ + * 1-->2--->3 + ^ ^ / + * 8\0| /2 + * \|/ + * 4 + **/ + boost::add_edge(0, 1, 1, g); + boost::add_edge(1, 2, 3, g); + boost::add_edge(2, 3, 2, g); + boost::add_edge(3, 1, 0, g); + boost::add_edge(3, 0, 8, g); + boost::add_edge(0, 2, 10, g); + std::cout< +#include +#include + +namespace boost +{ + template + double karp_minimum_cycle_mean(Graph g) + { + typedef typename boost::graph_traits::vertex_iterator vertex_iterator; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typename property_map::type weight = get(edge_weight,g); + typedef typename boost::graph_traits::out_edge_iterator out_edge_iterator; + BOOST_CONCEPT_ASSERT((GraphConcept< Graph >)); + + int n = num_vertices(g); + double distance_matrix[n+1][n]; + std::fill(distance_matrix[0],distance_matrix[0]+(n+1)*(n), -1.0); + distance_matrix[0][0] = 0; + + std::pair vertex_iterator_pair= vertices(g); + std::vector vertices_vector; + for(vertex_iterator a=vertex_iterator_pair.first; a!=vertex_iterator_pair.second;a++) + { + vertices_vector.push_back(*a);; + } + + for (int i=1; i<=n; i++) + { + for (int j=0; j edge_iterator_pair= boost::out_edges(vertices_vector[j],g); + std::vector::edge_descriptor> incident_edges; + for(out_edge_iterator b=edge_iterator_pair.first;b!=edge_iterator_pair.second;b++) + { + incident_edges.push_back(*b); + } + for (int k=0; k< out_degree(vertices_vector[j],g); k++) + { + vertex_descriptor t=target(incident_edges[k],g); + auto it = find(vertices_vector.begin(), vertices_vector.end(), t); + int index = it - vertices_vector.begin(); + if (distance_matrix[i-1][index] != -1) + { + double curr_wt = distance_matrix[i-1][index] + + get(weight,incident_edges[k]); + if (distance_matrix[i][j] == -1) + distance_matrix[i][j] = curr_wt; + else + distance_matrix[i][j] = std::min(distance_matrix[i][j], curr_wt); + } + } + } + } + double avg[n]; + std::fill(avg,avg+n,-1.0); + + for (int i=0; i +#include +#include +typedef boost::property EdgeWeight; +typedef boost::adjacency_list DirectedGraph; +int main() { + const double epsilon = 0.005; + { + DirectedGraph g1; + /** + * Create the graph drawn below. + * + * + * 10 + * ________ + * / 1 3 \ + * 1-->2--->3 + ^ ^ / + * 8\0| /2 + * \|/ + * 4 + **/ + boost::add_edge(0, 1, 1, g1); + boost::add_edge(1, 2, 3, g1); + boost::add_edge(2, 3, 2, g1); + boost::add_edge(3, 1, 0, g1); + boost::add_edge(3, 0, 8, g1); + boost::add_edge(0, 2, 10, g1); + double min_cycle_mean = boost::karp_minimum_cycle_mean(g1); + std::cout << min_cycle_mean << std::endl; + BOOST_TEST(std::abs(min_cycle_mean - 1.666666666) < epsilon); + } + { + DirectedGraph g2; + /** + * Create the graph drawn below. + * 1 + * 1-->2 + * + **/ + boost::add_edge(0, 1, 1, g2); + double min_cycle_mean = boost::karp_minimum_cycle_mean(g2); + std::cout << min_cycle_mean << std::endl; + BOOST_TEST(std::abs(min_cycle_mean +1) < epsilon); + } + + return boost::report_errors(); +}