-
Notifications
You must be signed in to change notification settings - Fork 212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added Karps Minimum Cycle Algorithm #281
base: develop
Are you sure you want to change the base?
Changes from all commits
5bb73cd
2bc8d04
cea3ee8
4f4b4e0
5a8bf11
40cccbb
b508420
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||
<HTML> | ||
<HEAD> | ||
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1"> | ||
<TITLE>Boost Graph Library: Karps Minimum Cycle Mean</TITLE> | ||
<META NAME="CREATED BY" CONTENT="G YUVAN SHANKAR"> | ||
|
||
|
||
<!--Use, modification and distribution is subject to the Boost Software | ||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||
http://www.boost.org/LICENSE_1_0.txt) | ||
|
||
Authors: G Yuvan Shankar | ||
--> | ||
<!-- | ||
<STYLE> | ||
@page { size: 3.5cm 2.5cm } | ||
TD P { color: #000000 } | ||
H1 { color: #000000 } | ||
P { color: #000000 } | ||
PRE { color: #000000 } | ||
H3 { color: #000000 } | ||
BLOCKQUOTE { color: #000000 } | ||
A:link { color: #0000ee } | ||
A:visited { color: #551a8b } | ||
</STYLE> | ||
--> | ||
</HEAD> | ||
<BODY TEXT="#000000" LINK="#0000ee" VLINK="#551a8b" BGCOLOR="#ffffff" DIR="LTR"> | ||
<P><IMG SRC="../../..//boost.png" NAME="graphics1" ALT="C++ Boost" ALIGN=BOTTOM WIDTH=277 HEIGHT=86 BORDER=0> | ||
</P> | ||
<H1><TT>karp_minimum_cycle_mean</TT></H1> | ||
<P> | ||
<PRE> | ||
template <typename Graph> | ||
double karp_minimum_cycle_mean(Graph g); | ||
</PRE> | ||
</P> | ||
|
||
|
||
The <tt>karp_minimum_cycle_mean()</tt> function calculates minimum cycle mean of a | ||
weighted directed graph <I>G=(V,E,W)</I>, where <i>V</i> is a vertex set, | ||
<i>E</i> is an edge set, <I>W: E -> R</I> is an edge weight function . | ||
</P> | ||
|
||
<P>We define the mean weight of a cycle <I>C=<e<sub>1</sub>,e<sub>1</sub>,e<sub>2</sub>..,e<sub>k</sub>></I> of edges in E to be</P> | ||
<P> | ||
<IMG SRC="figs/mcm.jpg" ALT="mean weight of cycle" BORDER=0> | ||
</P> | ||
|
||
The <I>minimum cycle mean</I> is the minimum cycle mean | ||
of all cycles of the graph. The <tt>karp_minimum_cycle_mean()</tt> returns the | ||
calculated minimum cycle mean. Returns -1 if the graph has no cycles. | ||
|
||
</P> | ||
<P> | ||
This algorithm was described by Richard M. Karp in his paper | ||
<A HREF="./dasdan-dac99.pdf">A characterization of the minimum cycle mean in a digraph</A></P> | ||
|
||
|
||
<H3>Where Defined</H3> | ||
<P STYLE="background: transparent"><TT><A HREF="../../../boost/graph/karp_minimum_cycle_mean.hpp">boost/graph/karp_minimum_cycle_mean.hpp</A></TT> | ||
</P> | ||
<H3>Parameters</H3> | ||
|
||
<P>IN: <tt>const Graph g </tt> | ||
</P> | ||
<BLOCKQUOTE>A weighted directed graph. | ||
</BLOCKQUOTE> | ||
|
||
<P> | ||
OUT: double <tt>minimum_mean_weight</tt> | ||
</P> | ||
|
||
<H3>Complexity</H3> | ||
<P>The implemented algorithm runs in O(|V||E|) time. Where V and E are vertex set and edge set respectively. | ||
</P> | ||
|
||
<H3>Example</H3> | ||
<P>The program in <A HREF="../example/minimum_cycle_mean_example.cpp">libs/graph/example/minimum_cycle_mean_example.cpp</A> | ||
finds the minimum cycle mean of the defined graph. | ||
</P> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#include <iostream> | ||
#include <boost/graph/karp_minimum_cycle_mean.hpp> | ||
typedef boost::property<boost::edge_weight_t, double> EdgeWeight; | ||
typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, boost::no_property, EdgeWeight> 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<<boost::karp_minimum_cycle_mean(g); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
#ifndef BOOST_GRAPH_KARP_MINIMUM_CYCLE_MEAN_HPP | ||
#define BOOST_GRAPH_KARP_MINIMUM_CYCLE_MEAN_HPP | ||
|
||
#include <iostream> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't allow |
||
#include <boost/graph/graph_traits.hpp> | ||
#include <boost/graph/adjacency_list.hpp> | ||
|
||
namespace boost | ||
{ | ||
template<typename Graph> | ||
double karp_minimum_cycle_mean(Graph g) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you'll want to take |
||
{ | ||
typedef typename boost::graph_traits<Graph>::vertex_iterator vertex_iterator; | ||
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; | ||
typename property_map<Graph, edge_weight_t>::type weight = get(edge_weight,g); | ||
typedef typename boost::graph_traits<Graph>::out_edge_iterator out_edge_iterator; | ||
BOOST_CONCEPT_ASSERT((GraphConcept< Graph >)); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A comment about this file in general, we don't have automatic Clang format running (yet), so please follow the convention in the rest of the library:
|
||
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 ,vertex_iterator> vertex_iterator_pair= vertices(g); | ||
std::vector<vertex_descriptor> 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<n; j++) | ||
{ | ||
std::pair <out_edge_iterator ,out_edge_iterator> edge_iterator_pair= boost::out_edges(vertices_vector[j],g); | ||
std::vector<typename boost::graph_traits<Graph>::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<n; i++) | ||
{ | ||
if (distance_matrix[n][i] != -1) | ||
{ | ||
for (int j=0; j<n; j++) | ||
if (distance_matrix[j][i] != -1) | ||
avg[i] = std::max(avg[i],(double)(distance_matrix[n][i]-distance_matrix[j][i])/(n-j)); | ||
} | ||
} | ||
double minimum_mean_weight = avg[0]; | ||
for (int i=0; i<n; i++) | ||
if (avg[i] != -1 && avg[i] < minimum_mean_weight) | ||
minimum_mean_weight = avg[i]; | ||
|
||
return minimum_mean_weight; | ||
} | ||
|
||
} | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#include <iostream> | ||
#include <boost/graph/karp_minimum_cycle_mean.hpp> | ||
#include <boost/core/lightweight_test.hpp> | ||
typedef boost::property<boost::edge_weight_t, double> EdgeWeight; | ||
typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, boost::no_property, EdgeWeight> 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(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please give a proper citation of the paper.