|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r54999 - in trunk: boost/graph libs/graph/doc libs/graph/example libs/graph/test
From: asutton_at_[hidden]
Date: 2009-07-17 10:56:20
Author: asutton
Date: 2009-07-17 10:56:19 EDT (Fri, 17 Jul 2009)
New Revision: 54999
URL: http://svn.boost.org/trac/boost/changeset/54999
Log:
Integrated new implementation of howard's cycle ratio algorithm. It's an
optimization and cleanup from the older version. Note that this breaks
source compatability in one instance.
Text files modified:
trunk/boost/graph/howard_cycle_ratio.hpp | 1075 ++++++++++++++++++++-------------------
trunk/libs/graph/doc/howard_cycle_ratio.html | 277 ++++++----
trunk/libs/graph/example/cycle_ratio_example.cpp | 139 ++--
trunk/libs/graph/test/cycle_ratio_tests.cpp | 483 ++++++++++-------
4 files changed, 1054 insertions(+), 920 deletions(-)
Modified: trunk/boost/graph/howard_cycle_ratio.hpp
==============================================================================
--- trunk/boost/graph/howard_cycle_ratio.hpp (original)
+++ trunk/boost/graph/howard_cycle_ratio.hpp 2009-07-17 10:56:19 EDT (Fri, 17 Jul 2009)
@@ -1,613 +1,634 @@
-/*!
-* Copyright 2007 Technical University of Catalonia
-*
-* 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: Dmitry Bufistov
-* Andrey Parfenov
-*/
-
-#ifndef BOOST_GRAPH_HOWARD_CYCLE_RATIO_HOWARD_HPP
-#define BOOST_GRAPH_HOWARD_CYCLE_RATIO_HOWARD_HPP
-
-/*!
-* \file Maximum cycle ratio algorithm (Jean Cochet-Terrasson, Guy
-* Cochen and others)
-*/
-#include <exception>
-#include <set>
+// Copyright (C) 2006-2009 Dmitry Bufistov and Andrey Parfenov
+
+// 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)
+
+#ifndef CYCLE_RATIO_HOWARD_HPP
+#define CYCLE_RATIO_HOWARD_HPP
+
+#include <vector>
+#include <list>
+#include <algorithm>
+#include <limits>
+
#include <boost/bind.hpp>
-#include <boost/config.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_const.hpp>
-#include <boost/type_traits/is_signed.hpp>
#include <boost/concept_check.hpp>
-#include <boost/graph/adjacency_list.hpp>
-#include <boost/graph/reverse_graph.hpp>
-#include <boost/graph/breadth_first_search.hpp>
-#include <boost/graph/iteration_macros.hpp>
-#include <boost/graph/graph_utility.hpp>
+#include <boost/pending/queue.hpp>
+#include <boost/property_map/property_map.hpp>
+#include <boost/graph/graph_traits.hpp>
+#include <boost/graph/graph_concepts.hpp>
+
+/** @file howard_cycle_ratio.hpp
+ * @brief The implementation of the maximum/minimum cycle ratio/mean algorithm.
+ * @author Dmitry Bufistov
+ * @author Andrey Parfenov
+ */
namespace boost {
+
+ /**
+ * The mcr_float is like numeric_limits, but only for floating point types
+ * and only defines infinity() and epsilon(). This class is primarily used
+ * to encapsulate a less-precise epsilon than natively supported by the
+ * floating point type.
+ */
+ template <typename Float = double> struct mcr_float {
+ typedef Float value_type;
+
+ static Float infinity()
+ { return std::numeric_limits<value_type>::infinity(); }
+
+ static Float epsilon()
+ { return Float(-0.005); }
+ };
+
namespace detail {
- /// To avoid round error.
- static const double mcr_howard_ltolerance = 0.00001;
- /*!
- * Calculate maximum cycle ratio of "good" directed multigraph
- * g. Use Howard's iteration policy algorithm ("Numerical
- * Computation of Spectral Elements in MAX-PLUS algebra" by Jean
- * Cochet-Terrasson, Guy Cochen and others).
- *
- * \param g = (V, E) - a "good" directed multigraph (out_degree of
- * each vertex is greater then 0). If graph is strongly connected
- * then it is "good".
- *
- * \param vim - Vertex Index, read property Map: V -> [0,
- * num_vertices(g)).
- *
- * \param ewm - edge weight read property map: E -> R
- *
- * \param ewm2 - edge weight2 read property map: E -> R+
- *
- * \return maximum_{for all cycles C}CR(C), or
- * -(std::numeric_limits<double>::max)() if g is not "good".
+ template <typename FloatTraits> struct
+ min_comparator_props {
+ typedef std::greater<typename FloatTraits::value_type> comparator;
+ static const int multiplier = 1;
+ };
+
+ template <typename FloatTraits> struct
+ max_comparator_props {
+ typedef std::less<typename FloatTraits::value_type> comparator;
+ static const int multiplier = -1;
+ };
+
+ template <typename FloatTraits, typename ComparatorProps>
+ struct float_wrapper {
+ typedef typename FloatTraits::value_type value_type;
+ typedef ComparatorProps comparator_props_t;
+ typedef typename ComparatorProps::comparator comparator;
+
+ static value_type infinity()
+ { return FloatTraits::infinity() * ComparatorProps::multiplier; }
+
+ static value_type epsilon()
+ { return FloatTraits::epsilon() * ComparatorProps::multiplier; }
+
+ };
+
+ /*! @class mcr_howard
+ * @brief Calculates optimum (maximum/minimum) cycle ratio of a directed graph.
+ * Uses Howard's iteration policy algorithm. </br>(It is described in the paper
+ * "Experimental Analysis of the Fastest Optimum Cycle Ratio and Mean Algorithm"
+ * by Ali Dasdan).
*/
- template <typename TGraph, typename TVertexIndexMap,
- typename TWeight1EdgeMap, typename TWeight2EdgeMap >
- class Cmcr_Howard
+ template <typename FloatTraits,
+ typename Graph, typename VertexIndexMap,
+ typename EdgeWeight1, typename EdgeWeight2>
+ class mcr_howard
{
public:
- Cmcr_Howard(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm,
- TWeight2EdgeMap ew2m)
- : m_g(g), m_vim(vim), m_ew1m(ewm), m_ew2m(ew2m),
- m_g2pi_g_vm(std::vector<pi_vertex_t>().end(), m_vim), /// Stupid dummy initialization
- m_minus_infinity(-(std::numeric_limits<double>::max)())
- {
- typedef typename boost::graph_traits<TGraph>::directed_category DirCat;
- BOOST_STATIC_ASSERT((boost::is_convertible<DirCat*, boost::directed_tag*>::value == true));
- m_cr = m_minus_infinity;
- }
-
- double operator()()
- {
- return maximum_cycle_ratio_Howard();
- }
+ typedef typename FloatTraits::value_type float_t;
+ typedef typename FloatTraits::comparator_props_t cmp_props_t;
+ typedef typename FloatTraits::comparator comparator_t;
+ typedef enum{ my_white = 0, my_black } my_color_type;
+ typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
+ typedef typename graph_traits<Graph>::edge_descriptor edge_t;
+ typedef typename graph_traits<Graph>::vertices_size_type vn_t;
+ typedef std::vector<float_t> vp_t;
+ typedef typename boost::iterator_property_map<
+ typename vp_t::iterator, VertexIndexMap
+ > distance_map_t; //V -> float_t
+
+ typedef typename std::vector<edge_t> ve_t;
+ typedef std::vector<my_color_type> vcol_t;
+ typedef typename ::boost::iterator_property_map<
+ typename ve_t::iterator, VertexIndexMap
+ > policy_t; //Vertex -> Edge
+ typedef typename ::boost::iterator_property_map<
+ typename vcol_t::iterator, VertexIndexMap
+ > color_map_t;
+
+ typedef typename std::list<vertex_t> pinel_t;// The in_edges list of the policy graph
+ typedef typename std::vector<pinel_t> inedges1_t;
+ typedef typename ::boost::iterator_property_map<
+ typename inedges1_t::iterator, VertexIndexMap
+ > inedges_t;
+ typedef typename std::vector<edge_t> critical_cycle_t;
+
+ //Bad vertex flag. If true, then the vertex is "bad".
+ // Vertex is "bad" if its out_degree is equal to zero.
+ typedef typename boost::iterator_property_map<
+ std::vector<int>::iterator, VertexIndexMap
+ > badv_t;
- virtual ~Cmcr_Howard() { }
-
- protected:
- typedef typename boost::graph_traits<TGraph>::vertex_descriptor
- mcr_vertex_t;
- typedef typename boost::graph_traits<TGraph>::edge_descriptor
- mcr_edge_t;
-
- const TGraph& m_g;
- typedef std::vector<double> eigenmode_t;
- eigenmode_t m_eigen_value;
- eigenmode_t m_eigen_vector;
- TVertexIndexMap m_vim;
- TWeight1EdgeMap m_ew1m;
- TWeight2EdgeMap m_ew2m;
-
- typedef typename boost::remove_const<typename boost::property_traits<TWeight1EdgeMap>::value_type>::type mcr_edge_weight1_t;
- typedef typename boost::remove_const<typename boost::property_traits<TWeight2EdgeMap>::value_type>::type mcr_edge_weight2_t;
- typedef typename boost::adjacency_list<
- boost::listS, boost::vecS, boost::bidirectionalS,
- boost::no_property,
- boost::property<boost::edge_weight_t,
- mcr_edge_weight1_t,
- boost::property<boost::edge_weight2_t,
- mcr_edge_weight2_t> > >
- pi_graph_t;
- typedef typename boost::property_map<pi_graph_t, boost::vertex_index_t>::type TPiGraphVertexIndexMap;
- typedef typename boost::property_map<pi_graph_t, boost::edge_weight_t>::type TPiGraphEdgeWeight1Map;
- typedef typename boost::property_map<pi_graph_t, boost::edge_weight2_t>::type TPiGraphEdgeWeight2Map;
-
- typedef typename boost::property_traits<TPiGraphVertexIndexMap>::value_type pigraph_vertex_index_t;
-
- pi_graph_t m_pi_g;
- typedef typename boost::graph_traits<pi_graph_t>::vertex_descriptor pi_vertex_t;
- typedef typename boost::graph_traits<pi_graph_t>::edge_descriptor pi_edge_t;
- typedef typename boost::iterator_property_map<typename std::vector<pi_vertex_t>::iterator, TVertexIndexMap> g2pi_g_vm_t;
- g2pi_g_vm_t m_g2pi_g_vm; ///Graph to Pi graph vertex map
- std::vector<pi_vertex_t> m_g2pig;
- int m_step_number;
- const double m_minus_infinity;
- typedef typename std::vector<mcr_edge_t> critical_cycle_t;
- double m_cr; ///Cycle ratio that already has been found
+ /*!
+ * Constructor
+ * \param g = (V, E) - a directed multigraph.
+ * \param vim Vertex Index Map. Read property Map: V -> [0, num_vertices(g)).
+ * \param ewm edge weight map. Read property map: E -> R
+ * \param ew2m edge weight map. Read property map: E -> R+
+ * \param infty A big enough value to guaranty that there exist a cycle with
+ * better ratio.
+ * \param cmp The compare operator for float_ts.
+ */
+ mcr_howard(const Graph &g, VertexIndexMap vim,
+ EdgeWeight1 ewm, EdgeWeight2 ew2m) :
+ m_g(g), m_vim(vim), m_ew1m(ewm), m_ew2m(ew2m),
+ m_bound(mcr_bound()),
+ m_cr(m_bound),
+ m_V(num_vertices(m_g)),
+ m_dis(m_V, 0), m_dm(m_dis.begin(), m_vim),
+ m_policyc(m_V), m_policy(m_policyc.begin(), m_vim),
+ m_inelc(m_V), m_inel(m_inelc.begin(), m_vim),
+ m_badvc(m_V, false), m_badv(m_badvc.begin(), m_vim),
+ m_colcv(m_V),
+ m_col_bfs(m_V)
+ { }
- class bad_graph
+ /*!
+ * \return maximum/minimum_{for all cycles C}
+ * [sum_{e in C} w1(e)] / [sum_{e in C} w2(e)],
+ * or FloatTraits::infinity() if graph has no cycles.
+ */
+ float_t ocr_howard()
{
- public:
- typedef typename boost::property_traits<TVertexIndexMap>::value_type
- v_index_t;
-
- bad_graph(v_index_t bvi) : bad_vertex_index(bvi) {}
- v_index_t what() const throw()
- {
- return bad_vertex_index;
- }
-
- private:
- v_index_t bad_vertex_index;
- };
+ construct_policy_graph();
+ int k = 0;
+ float_t mcr = 0;
+ do
+ {
+ mcr = policy_mcr();
+ ++k;
+ }
+ while (try_improve_policy(mcr) && k < 100); //To avoid infinite loop
- double maximum_cycle_ratio_Howard()
- {
- try
+ const float_t eps_ = -0.00000001 * cmp_props_t::multiplier;
+ if (m_cmp(mcr, m_bound + eps_))
{
- construct_pi_graph();
+ return FloatTraits::infinity();
}
- catch (const bad_graph& a)
+ else
{
- return m_minus_infinity;
+ return mcr;
}
- std::vector<double> max_eigen_val(boost::num_vertices(m_g));
- m_eigen_value.resize(boost::num_vertices(m_g));
- m_eigen_vector.resize(boost::num_vertices(m_g));
- m_step_number = 0;
- do
+ }
+ virtual ~mcr_howard() {}
+
+ protected:
+ virtual void store_critical_edge(edge_t ed, critical_cycle_t &cc) {}
+ virtual void store_critical_cycle(critical_cycle_t &cc) {}
+
+ private:
+ /*!
+ * \return lower/upper bound for the maximal/minimal cycle ratio
+ */
+ float_t mcr_bound()
+ {
+ typename graph_traits<Graph>::vertex_iterator vi, vie;
+ typename graph_traits<Graph>::out_edge_iterator oei, oeie;
+ float_t cz = (std::numeric_limits<float_t>::max)(); //Closest to zero value
+ float_t s = 0;
+ const float_t eps_ = std::numeric_limits<float_t>::epsilon();
+ for (tie(vi, vie) = vertices(m_g); vi != vie; ++vi)
{
- pi_eingen_value(get(vertex_index, m_pi_g), get(boost::edge_weight, m_pi_g), get(boost::edge_weight2, m_pi_g));
- ++m_step_number;
- }
- while (improve_policy_try1(max_eigen_val) || improve_policy_try2(max_eigen_val));
- return *(std::max_element(m_eigen_value.begin(), m_eigen_value.end()));
+ for (tie(oei, oeie) = out_edges(*vi, m_g); oei != oeie; ++oei)
+ {
+ s += std::abs(m_ew1m[*oei]);
+ float_t a = std::abs(m_ew2m[*oei]);
+ if ( a > eps_ && a < cz)
+ {
+ cz = a;
+ }
+ }
+ }
+ return cmp_props_t::multiplier * (s / cz);
}
- /*!
- * Construct an arbitrary policy m_pi_g.
- */
- void construct_pi_graph()
+
+ /*!
+ * Constructs an arbitrary policy graph.
+ */
+ void construct_policy_graph()
{
- m_g2pig.resize(boost::num_vertices(m_g));
- m_g2pi_g_vm = boost::make_iterator_property_map(m_g2pig.begin(), m_vim);
- BGL_FORALL_VERTICES_T(vd, m_g, TGraph)
- {
- m_g2pi_g_vm[vd] = boost::add_vertex(m_pi_g);
- store_pivertex(m_g2pi_g_vm[vd], vd);
- }
- BGL_FORALL_VERTICES_T(vd1, m_g, TGraph)
- {
- if (boost::graph::has_no_out_edges(vd1, m_g)) throw bad_graph(m_vim[vd1]);
- mcr_edge_t ed = *boost::out_edges(vd1, m_g).first;
- pi_edge_t pied = boost::add_edge(m_g2pi_g_vm[source(ed, m_g)], m_g2pi_g_vm[target(ed, m_g)], m_pi_g).first;
- boost::put(boost::edge_weight, m_pi_g, pied, m_ew1m[ed]);
- boost::put(boost::edge_weight2, m_pi_g, pied, m_ew2m[ed]);
+ m_sink = graph_traits<Graph>().null_vertex();
+ typename graph_traits<Graph>::vertex_iterator vi, vie;
+ typename graph_traits<Graph>::out_edge_iterator oei, oeie;
+ for ( tie(vi, vie) = vertices(m_g); vi != vie; ++vi )
+ {
+ tie(oei, oeie) = out_edges(*vi, m_g);
+ typename graph_traits<Graph>::out_edge_iterator mei =
+ std::max_element(oei, oeie,
+ bind(m_cmp,
+ bind(&EdgeWeight1::operator[], m_ew1m, _1),
+ bind(&EdgeWeight1::operator[], m_ew1m, _2)
+ )
+ );
+ if (mei == oeie)
+ {
+ if (m_sink == graph_traits<Graph>().null_vertex())
+ {
+ m_sink = *vi;
+ }
+ m_badv[*vi] = true;
+ m_inel[m_sink].push_back(*vi);
+ }
+ else
+ {
+ m_inel[target(*mei, m_g)].push_back(*vi);
+ m_policy[*vi] = *mei;
+ }
}
}
-
- class bfs_eingmode_visitor : public boost::default_bfs_visitor
+ /*! Sets the distance value for all vertices "v" such that there is
+ * a path from "v" to "sv". It does "inverse" breadth first visit of the policy
+ * graph, starting from the vertex "sv".
+ */
+ void mcr_bfv(vertex_t sv, float_t cr, color_map_t c)
{
- public:
- bfs_eingmode_visitor(TPiGraphVertexIndexMap vi_m, TPiGraphEdgeWeight1Map w_m, TPiGraphEdgeWeight2Map& d_m,
- eigenmode_t& e_val, eigenmode_t& e_vec, double ev) : m_index_map(vi_m), m_weight_map(w_m), m_delay_map(d_m),
- m_eig_value(&e_val), m_eig_vec(&e_vec), m_eigen_value(ev) { }
-
- template < typename Edge, typename g_t>
- void examine_edge(Edge e, const g_t & g) const
- {
- typedef typename boost::graph_traits<g_t>::vertex_descriptor Vertex;
- Vertex u = boost::target(e, g), v = boost::source(e, g);
- pigraph_vertex_index_t ind = m_index_map[u];
- (*m_eig_value)[ind] = m_eigen_value;
- (*m_eig_vec)[ind] = m_weight_map[e] - m_eigen_value * m_delay_map[e] + (*m_eig_vec)[m_index_map[v]];
- }
- private:
- TPiGraphVertexIndexMap m_index_map;
- TPiGraphEdgeWeight1Map m_weight_map;
- TPiGraphEdgeWeight2Map m_delay_map;
- eigenmode_t* m_eig_value;
- eigenmode_t* m_eig_vec;
- double m_eigen_value;
- };
+ boost::queue<vertex_t> Q;
+ c[sv] = my_black;
+ Q.push(sv);
+ while (!Q.empty())
+ {
+ vertex_t v = Q.top(); Q.pop();
+ for (typename pinel_t::const_iterator itr = m_inel[v].begin();
+ itr != m_inel[v].end(); ++itr)
+ //For all in_edges of the policy graph
+ {
+ if (*itr != sv)
+ {
+ if (m_badv[*itr])
+ {
+ m_dm[*itr] = m_dm[v] + m_bound - cr;
+ }
+ else
+ {
+ m_dm[*itr] = m_dm[v] + m_ew1m[m_policy[*itr]] -
+ m_ew2m[m_policy[*itr]] * cr;
+ }
+ c[*itr] = my_black;
+ Q.push(*itr);
+ }
+ }
+ }
+ }
/*!
- * Find a vertex in the Pi Graph which belongs to cycle, just a DFV until back edge found
+ * \param sv an arbitrary (undiscovered) vertex of the policy graph.
+ * \return a vertex in the policy graph that belongs to a cycle.
+ * Performs a depth first visit until a cycle edge is found.
*/
- pi_vertex_t find_good_source(const pi_vertex_t start_vertex)
+ vertex_t find_cycle_vertex(vertex_t sv)
{
- pi_vertex_t good_vertex = start_vertex;
- typename std::set<pi_vertex_t> s;
- s.insert(start_vertex);
- do
- {
- good_vertex = boost::target(*boost::out_edges(good_vertex, m_pi_g).first, m_pi_g);
- }
- while (s.insert(good_vertex).second);
- return good_vertex;
+ vertex_t gv = sv;
+ std::fill(m_colcv.begin(), m_colcv.end(), my_white);
+ color_map_t cm(m_colcv.begin(), m_vim);
+ do
+ {
+ cm[gv] = my_black;
+ if (! m_badv[gv])
+ {
+ gv = target(m_policy[gv], m_g);
+ }
+ else
+ {
+ gv = m_sink;
+ }
+ }
+ while (cm[gv] != my_black);
+ return gv;
}
- virtual void store_pivertex(pi_vertex_t pivd, mcr_vertex_t vd) {}
- virtual void store_critical_edge(pi_edge_t ed, critical_cycle_t& cc) {}
- virtual void store_critical_cycle(critical_cycle_t& cc) {}
-
+
/*!
- * \param startV - vertex that belongs to a cycle in policy graph m_pi_g
+ * \param sv - vertex that belongs to a cycle in the policy graph.
*/
- double calculate_eigen_value(pi_vertex_t startV)
+ float_t cycle_ratio(vertex_t sv)
{
- std::pair<double, double> accum_sums(0., 0.);
- pi_vertex_t vd = startV;
- critical_cycle_t cc;
- do
- {
- pi_edge_t tmp_ed = *(boost::out_edges(vd, m_pi_g).first);
- store_critical_edge(tmp_ed, cc);
- accum_sums.first += boost::get(boost::edge_weight, m_pi_g, tmp_ed);
- accum_sums.second += boost::get(boost::edge_weight2, m_pi_g, tmp_ed);
- vd = boost::target(tmp_ed, m_pi_g);
- }
- while (vd != startV);
- //assert((std::abs<double>(accum_sums.first) <= 0.00000001) && "Division by zerro!");
- double cr = accum_sums.first / accum_sums.second;
- if (cr > m_cr)
+ if (sv == m_sink) return m_bound;
+ std::pair<float_t, float_t> sums_(float_t(0), float_t(0));
+ vertex_t v = sv;
+ critical_cycle_t cc;
+ do
+ {
+ store_critical_edge(m_policy[v], cc);
+ sums_.first += m_ew1m[m_policy[v]];
+ sums_.second += m_ew2m[m_policy[v]];
+ v = target(m_policy[v], m_g);
+ }
+ while (v != sv);
+ float_t cr = sums_.first / sums_.second;
+ if ( m_cmp(m_cr, cr) )
{
m_cr = cr;
store_critical_cycle(cc);
}
- else
- {
-
- }
- return cr;
+ return cr;
}
/*!
- * Value determination. Find a generalized eigenmode (n^{k+1}, x^{k+1}) of A^{I_{k+1}} of the pi graph (Algorithm IV.1).
+ * Finds the optimal cycle ratio of the policy graph
*/
- void pi_eingen_value(
- TPiGraphVertexIndexMap index_map,
- TPiGraphEdgeWeight1Map weight_map,
- TPiGraphEdgeWeight2Map weigh2_map)
+ float_t policy_mcr()
{
- using namespace boost;
- typedef std::vector<default_color_type> color_map_t;
- color_map_t vcm(num_vertices(m_pi_g), white_color);//Vertex color map
- color_map_t::iterator uv_itr = vcm.begin(); //Undiscovered vertex
- reverse_graph<pi_graph_t> rev_g(m_pi_g); //For backward breadth visit
-
- while ((uv_itr = std::find_if(uv_itr, vcm.end(),
- boost::bind(std::equal_to<default_color_type>(), boost::white_color, _1))) != vcm.end())
+ std::fill(m_col_bfs.begin(), m_col_bfs.end(), my_white);
+ color_map_t vcm_ = color_map_t(m_col_bfs.begin(), m_vim);
+ typename graph_traits<Graph>::vertex_iterator uv_itr, vie;
+ tie(uv_itr, vie) = vertices(m_g);
+ float_t mcr = m_bound;
+ while ( (uv_itr = std::find_if(uv_itr, vie,
+ bind(std::equal_to<my_color_type>(),
+ my_white,
+ bind(&color_map_t::operator[], vcm_, _1)
+ )
+ )
+ ) != vie )
///While there are undiscovered vertices
{
- pi_vertex_t gv = find_good_source(pi_vertex_t(uv_itr - vcm.begin()));
- pigraph_vertex_index_t gv_ind = index_map[gv];
- m_eigen_value[gv_ind] = calculate_eigen_value(gv) ;
- bfs_eingmode_visitor bfs_vis(index_map, weight_map, weigh2_map, m_eigen_value, m_eigen_vector, m_eigen_value[gv_ind]);
- typename boost::queue<pi_vertex_t> Q;
- breadth_first_visit(rev_g, gv, Q, bfs_vis, make_iterator_property_map(vcm.begin(), index_map));
+ vertex_t gv = find_cycle_vertex(*uv_itr);
+ float_t cr = cycle_ratio(gv) ;
+ mcr_bfv(gv, cr, vcm_);
+ if ( m_cmp(mcr, cr) ) mcr = cr;
+ ++uv_itr;
}
+ return mcr;
}
- void improve_policy(mcr_vertex_t vd, mcr_edge_t new_edge)
- {
- remove_edge(*(out_edges(m_g2pi_g_vm[vd], m_pi_g).first), m_pi_g);
- pi_edge_t ned = add_edge(m_g2pi_g_vm[vd], m_g2pi_g_vm[target(new_edge, m_g)], m_pi_g).first;
- put(edge_weight, m_pi_g, ned, m_ew1m[new_edge]);
- put(edge_weight2, m_pi_g, ned, m_ew2m[new_edge]);
- }
/*!
- * Policy Improvement. Improve the policy graph. The new policy graph has greater cycle ratio.
- * \return false if nothing can be improved.
+ * Changes the edge m_policy[s] to the new_edge.
*/
- bool improve_policy_try1(std::vector<double>& max_eing_vals)
+ void improve_policy(vertex_t s, edge_t new_edge)
{
- bool improved = false;
- BGL_FORALL_VERTICES_T(vd, m_g, TGraph)
- {
- double max_ev = m_minus_infinity;/// Maximum eigen value for vertex
- mcr_edge_t cr_ed;///Critical edge
-
- BGL_FORALL_OUTEDGES_T(vd, outed, m_g, TGraph)
- {
- if (m_eigen_value[m_vim[target(outed, m_g)]] > max_ev)
- {
- max_ev = m_eigen_value[m_vim[boost::target(outed, m_g)]];
- cr_ed = outed;
- }
- }
- if (max_ev > m_eigen_value[get(m_vim,vd)])
- {
- improve_policy(vd, cr_ed);
- improved = true;
- }
- max_eing_vals[get(m_vim,vd)] = max_ev;
- }
- return improved;
+ vertex_t t = target(m_policy[s], m_g);
+ typename property_traits<VertexIndexMap>::value_type ti = m_vim[t];
+ m_inelc[ti].erase( std::find(m_inelc[ti].begin(), m_inelc[ti].end(), s));
+ m_policy[s] = new_edge;
+ t = target(new_edge, m_g);
+ m_inel[t].push_back(s); ///Maintain in_edge list
}
/*!
- * \param max_eigen_values[u] = max_(for all adjacent vertices (u,v)) m_eigen_value[v]
+ * A negative cycle detector.
*/
- bool improve_policy_try2(const std::vector<double>& max_eigen_values)
+ bool try_improve_policy(float_t cr)
{
- bool improved = false;
- BGL_FORALL_VERTICES_T(vd, m_g, TGraph)
+ bool improved = false;
+ typename graph_traits<Graph>::vertex_iterator vi, vie;
+ typename graph_traits<Graph>::out_edge_iterator oei, oeie;
+ const float_t eps_ = FloatTraits::epsilon();
+ for (tie(vi, vie) = vertices(m_g); vi != vie; ++vi)
{
- mcr_edge_t impr_edge;
- double max_val = m_minus_infinity;
- BGL_FORALL_OUTEDGES_T(vd, outed, m_g, TGraph)
+ if (!m_badv[*vi])
{
- ///If vertex vd is in the K(vd) set
- if (max_eigen_values[get(m_vim, vd)] <= m_eigen_value[get(m_vim, target(outed, m_g))])
+ for (tie(oei, oeie) = out_edges(*vi, m_g); oei != oeie; ++oei)
{
- double c_val = m_ew1m[outed] - m_ew2m[outed] * m_eigen_value[m_vim[boost::target(outed, m_g)]] +
- m_eigen_vector[m_vim[boost::target(outed, m_g)]];
- if (c_val > max_val)
+ vertex_t t = target(*oei, m_g);
+ //Current distance from *vi to some vertex
+ float_t dis_ = m_ew1m[*oei] - m_ew2m[*oei] * cr + m_dm[t];
+ if ( m_cmp(m_dm[*vi] + eps_, dis_) )
{
- max_val = c_val;
- impr_edge = outed;
+ improve_policy(*vi, *oei);
+ m_dm[*vi] = dis_;
+ improved = true;
}
}
}
- if ((max_val - m_eigen_vector[get(m_vim, vd)]) > mcr_howard_ltolerance)
- ///If m_eigen_vector[vd] == max_val
+ else
{
- improve_policy(vd, impr_edge);
- improved = true;
+ float_t dis_ = m_bound - cr + m_dm[m_sink];
+ if ( m_cmp(m_dm[*vi] + eps_, dis_) )
+ {
+ m_dm[*vi] = dis_;
+ }
}
}
return improved;
}
- };///Cmcr_Howard
+ private:
+ const Graph &m_g;
+ VertexIndexMap m_vim;
+ EdgeWeight1 m_ew1m;
+ EdgeWeight2 m_ew2m;
+ comparator_t m_cmp;
+ float_t m_bound; //> The lower/upper bound to the maximal/minimal cycle ratio
+ float_t m_cr; //>The best cycle ratio that has been found so far
+
+ vn_t m_V; //>The number of the vertices in the graph
+ vp_t m_dis; //>Container for the distance map
+ distance_map_t m_dm; //>Distance map
+
+ ve_t m_policyc; //>Container for the policy graph
+ policy_t m_policy; //>The interface for the policy graph
- /*!
- * \return maximum cycle ratio and one critical cycle.
- */
- template <typename TGraph, typename TVertexIndexMap, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
- class Cmcr_Howard1 : public Cmcr_Howard<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap>
- {
- public:
- typedef Cmcr_Howard<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap> inhr_t;
- Cmcr_Howard1(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m) : inhr_t(g, vim, ewm, ew2m)
- {
- m_pi_g2g.resize(boost::num_vertices(g));
- m_pi_g2g_vm = boost::make_iterator_property_map(m_pi_g2g.begin(), boost::get(boost::vertex_index, this->m_pi_g));
- }
+ inedges1_t m_inelc; //>Container fot in edges list
+ inedges_t m_inel; //>Policy graph, input edges list
- void get_critical_cycle(typename inhr_t::critical_cycle_t& cc) { return cc.swap(m_critical_cycle); }
- protected:
- void store_pivertex(typename inhr_t::pi_vertex_t pivd, typename inhr_t::mcr_vertex_t vd)
- {
- m_pi_g2g_vm[pivd] = vd;
- }
- void store_critical_edge(typename inhr_t::pi_edge_t ed, typename inhr_t::critical_cycle_t& cc)
- {
- typename inhr_t::pi_vertex_t s = boost::source(ed, this->m_pi_g);
- typename inhr_t::pi_vertex_t t = boost::target(ed, this->m_pi_g);
- assert(boost::edge(m_pi_g2g_vm[s], m_pi_g2g_vm[t], this->m_g).second);
- cc.push_back(boost::edge(m_pi_g2g_vm[s], m_pi_g2g_vm[t], this->m_g).first); ///Store corresponding edge of the m_g
- }
- void store_critical_cycle(typename inhr_t::critical_cycle_t& cc)
- {
- m_critical_cycle.swap(cc);
- }
- private:
- typename inhr_t::critical_cycle_t m_critical_cycle;
- typedef typename boost::iterator_property_map<typename std::vector<typename inhr_t::mcr_vertex_t>::iterator, typename inhr_t::TPiGraphVertexIndexMap> pi_g2g_vm_t;
- pi_g2g_vm_t m_pi_g2g_vm; ///Maps policy graph vertices to input graph vertices
- typename std::vector<typename inhr_t::mcr_vertex_t> m_pi_g2g;
+ std::vector<int> m_badvc;
+ badv_t m_badv; //Marks "bad" vertices
+
+ vcol_t m_colcv, m_col_bfs; //Color maps
+ vertex_t m_sink; //To convert any graph to "good"
};
- /*!
- * Add sink vertex - this will make any graph good, the selfloop will have ratio equal to infinity
- * Properties must be "self increasing"
+ /*! \class mcr_howard1
+ * \brief Finds optimum cycle raio and a critical cycle
*/
- template <typename TGraph, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
- typename boost::graph_traits<TGraph>::vertex_descriptor
- make_graph_good(TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
- typename boost::property_traits<TWeight1EdgeMap>::value_type infinity)
+ template <typename FloatTraits,
+ typename Graph, typename VertexIndexMap,
+ typename EdgeWeight1, typename EdgeWeight2>
+ class mcr_howard1 : public
+ mcr_howard<FloatTraits, Graph, VertexIndexMap,
+ EdgeWeight1, EdgeWeight2>
{
- typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
- typename boost::graph_traits<TGraph>::vertex_descriptor sink = boost::add_vertex(g);
-
- BGL_FORALL_VERTICES_T(vd, g, TGraph)
- {
- Edge newed = boost::add_edge(vd, sink, g).first;
- boost::put(ewm, newed, 0);
- boost::put(ew2m, newed, 1);
- }
- Edge selfed = boost::edge(sink, sink, g).first;
- boost::put(ewm, selfed, infinity);
- return sink;
- }
+ public:
+ typedef mcr_howard<FloatTraits, Graph, VertexIndexMap,
+ EdgeWeight1, EdgeWeight2> inhr_t;
+ mcr_howard1(const Graph &g, VertexIndexMap vim,
+ EdgeWeight1 ewm, EdgeWeight2 ew2m) :
+ inhr_t(g, vim, ewm, ew2m)
+ { }
- /*!
- * Construct from input graph g "safe" (suitable for maximum_cycle_ratio1() call) version - safeg
- */
- template <typename TG, typename TIndVertexMap, typename TW1EdgeMap, typename TW2EdgeMap, typename TSafeG, typename SafeG2GEdgeMap>
- void construct_safe_graph(const TG& g, TIndVertexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m, TSafeG& safeg, SafeG2GEdgeMap& sg2gm)
- {
- assert(num_vertices(g) == num_vertices(safeg));
- typedef typename graph_traits<TSafeG>::edge_descriptor tmp_edge_t;
- typedef typename graph_traits<TG>::edge_descriptor edge_t;
- typename graph_traits<TG>::edge_iterator ei, ei_end;
-
- for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
- {
- tmp_edge_t tmped = add_edge(vim[source(*ei, g)], vim[target(*ei, g)], safeg).first;
- sg2gm[tmped] = *ei;
- put(edge_weight, safeg, tmped, get(ew1m, *ei));
- put(edge_weight2, safeg, tmped, get(ew2m, *ei));
- }
- }
+ void get_critical_cycle(typename inhr_t::critical_cycle_t &cc)
+ { return cc.swap(m_cc); }
- template <typename TGraph, typename TVertexIndexMap, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
- double maximum_cycle_ratio_good_graph(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
- typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0)
- {
- if (pcc == 0)
- {
- return detail::Cmcr_Howard<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap>(g, vim, ewm, ew2m)();
- }
- else
- {
- detail::Cmcr_Howard1<TGraph, TVertexIndexMap, TWeight1EdgeMap, TWeight2EdgeMap> obj(g, vim, ewm, ew2m);
- double maxcr = obj();
- obj.get_critical_cycle(*pcc);
- return maxcr;
- }
- }
+ protected:
+ void store_critical_edge(typename inhr_t::edge_t ed,
+ typename inhr_t::critical_cycle_t &cc)
+ { cc.push_back(ed); }
- template <typename TGraph, typename TVertexIndexMap, typename TWeight1EdgeMap, typename TWeight2EdgeMap, typename TEdgeIndexMap>
- double minimum_cycle_ratio_good_graph(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm,
- TWeight2EdgeMap ew2m, TEdgeIndexMap eim,
- typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0)
- {
- typedef typename boost::remove_const<typename boost::property_traits<TWeight1EdgeMap>::value_type>::type weight_value_t;
- BOOST_STATIC_ASSERT(!is_integral<weight_value_t>::value || is_signed<weight_value_t>::value);
- typename std::vector<weight_value_t> ne_w(boost::num_edges(g));
- BGL_FORALL_EDGES_T(ed, g, TGraph) ne_w[boost::get(eim, ed)] = -ewm[ed];
- return -maximum_cycle_ratio_good_graph(g, vim, boost::make_iterator_property_map(ne_w.begin(), eim), ew2m, pcc);
- }
+ void store_critical_cycle(typename inhr_t::critical_cycle_t &cc)
+ { m_cc.swap(cc); }
- /*!
- * \param g directed multigraph.
- * \param pcc - pointer to the critical edges list.
- * \param minus_infinity must be small enough to garanty that g has at least one cycle with greater ratio.
- * \return minus_infinity if there're no cycles in the graph
- */
- template <typename TGraph, typename TWeight1EdgeMap, typename TWeight2EdgeMap>
- double maximum_cycle_ratio1(const TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
- typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
- typename boost::property_traits<TWeight1EdgeMap>::value_type minus_infinity = -(std::numeric_limits<int>::max)())
- {
- typedef typename boost::graph_traits<TGraph>::vertex_descriptor Vertex;
- typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
- boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight1EdgeMap, Edge> >();
- boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight2EdgeMap, Edge> >();
-
- TGraph& ncg = const_cast<TGraph&>(g);
- Vertex sink = detail::make_graph_good(ncg, ewm, ew2m, minus_infinity );
-
- double res = maximum_cycle_ratio_good_graph(ncg, boost::get(boost::vertex_index, g), ewm, ew2m, pcc);
- boost::clear_vertex(sink, ncg); boost::remove_vertex(sink, ncg);
- return res;
- }
+ private:
+ typename inhr_t::critical_cycle_t m_cc; //Critical cycle
+ };
/*!
- * Edge index MUST be in diapazon [0,..., num_edges(g)-1]
- * \return plus_infinity if g has no cycles.
+ * \param g a directed multigraph.
+ * \param vim Vertex Index Map. A map V->[0, num_vertices(g))
+ * \param ewm Edge weight1 map.
+ * \param ew2m Edge weight2 map.
+ * \param pcc pointer to the critical edges list.
+ * \return Optimum cycle ratio of g or FloatTraits::infinity() if g has no cycles.
*/
- template <typename TGraph, typename TWeight1EdgeMap, typename TWeight2EdgeMap, typename TEdgeIndexMap>
- double minimum_cycle_ratio1(const TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m, TEdgeIndexMap eim,
- typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
- typename boost::property_traits<TWeight1EdgeMap>::value_type plus_infinity = (std::numeric_limits<int>::max)()
- )
+ template <typename FT,
+ typename TG, typename TVIM,
+ typename TEW1, typename TEW2,
+ typename EV>
+ typename FT::value_type
+ optimum_cycle_ratio(const TG &g, TVIM vim, TEW1 ewm, TEW2 ew2m, EV* pcc)
{
- typedef typename boost::property_traits<TEdgeIndexMap>::value_type ei_t;
- typedef typename boost::graph_traits<TGraph>::vertex_descriptor Vertex;
- typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
-
- boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight1EdgeMap, Edge> >();
- boost::function_requires< boost::ReadWritePropertyMapConcept<TWeight2EdgeMap, Edge> >();
- boost::function_requires< boost::ReadWritePropertyMapConcept<TEdgeIndexMap, Edge> >();
-
- TGraph& ncg = const_cast<TGraph&>(g);
-
- ei_t nei = ei_t(boost::num_edges(g));
- Vertex sink = detail::make_graph_good(ncg, ewm, ew2m, plus_infinity );
- ///Maintain edge index invariant
- BGL_FORALL_VERTICES_T(vd, ncg, TGraph)
- {
- typename boost::graph_traits<TGraph>::edge_descriptor ed = boost::edge(vd, sink, ncg).first;
- boost::put(eim, ed, nei++);
- }
- double res = minimum_cycle_ratio_good_graph(ncg, boost::get(boost::vertex_index, ncg), ewm, ew2m, eim, pcc);
- boost::clear_vertex(sink, ncg); boost::remove_vertex(sink, ncg);
- return res;
+ typedef typename graph_traits<TG>::directed_category DirCat;
+ BOOST_STATIC_ASSERT((is_convertible<DirCat*, directed_tag*>::value == true));
+ function_requires< IncidenceGraphConcept<TG> >();
+ function_requires< VertexListGraphConcept<TG> >();
+ typedef typename graph_traits<TG>::vertex_descriptor Vertex;
+ function_requires< ReadablePropertyMapConcept<TVIM, Vertex> >();
+ typedef typename graph_traits<TG>::edge_descriptor Edge;
+ function_requires< ReadablePropertyMapConcept<TEW1, Edge> >();
+ function_requires< ReadablePropertyMapConcept<TEW2, Edge> >();
+
+ if(pcc == 0) {
+ return detail::mcr_howard<FT,TG, TVIM, TEW1, TEW2>(
+ g, vim, ewm, ew2m
+ ).ocr_howard();
+ }
+
+ detail::mcr_howard1<FT, TG, TVIM, TEW1, TEW2> obj(g, vim, ewm, ew2m);
+ double ocr = obj.ocr_howard();
+ obj.get_critical_cycle(*pcc);
+ return ocr;
}
- struct edge_less_than
- {
- template <typename TEdgeDescriptor> bool operator()(const TEdgeDescriptor& x, const TEdgeDescriptor& y) const
- {
- return x.get_property() < y.get_property();
- }
- };
- }///namespace detail
- namespace
- {
- template <typename TW1, typename TW2> struct safe_graph
- {
- typedef typename boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, boost::no_property,
- typename boost::property<boost::edge_weight_t, TW1, typename boost::property<boost::edge_weight2_t, TW2> > > type;
- };
- }
+ } // namespace detail
- /*!
- * Calculate the maximum cycle ratio (mcr) of the directed multigraph g.
- * \param g directed multigraph
- * \param pcc - If provided then a critical cycle will be written to corresponding vector.
- * \param minus_infinity small enough value to garanty that g has at least one cycle with greater ratio.
- * \return mcr or minus_infinity if g has no cycles.
- */
- template <typename TGraph, typename TVertexIndexMap, typename TW1EdgeMap, typename TW2EdgeMap>
- double maximum_cycle_ratio(const TGraph& g, TVertexIndexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m,
- typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
- typename boost::property_traits<TW1EdgeMap>::value_type minus_infinity =
- -(std::numeric_limits<int>::max)())
- {
- typedef typename remove_const<typename property_traits<TW1EdgeMap>::value_type>::type w1_t;
- typedef typename remove_const<typename property_traits<TW2EdgeMap>::value_type>::type w2_t;
- typedef typename safe_graph<w1_t, w2_t>::type safe_graph_t;
- typedef typename graph_traits<safe_graph_t>::edge_descriptor tmp_edge_t;
- typedef typename graph_traits<TGraph>::edge_descriptor edge_t;
- typename std::map<tmp_edge_t, edge_t, detail::edge_less_than> tmpg2g;
- std::vector<tmp_edge_t> cc;
- safe_graph_t sg(num_vertices(g));
- detail::construct_safe_graph(g, vim, ew1m, ew2m, sg, tmpg2g);
- double mcr = maximum_cycle_ratio1(sg, get(edge_weight, sg), get(edge_weight2, sg), pcc ? &cc : 0, minus_infinity);
- if (pcc && (mcr > minus_infinity))
- {
- pcc->clear();
- for (typename std::vector<tmp_edge_t>::iterator it = cc.begin(); it != cc.end(); ++it) pcc->push_back(tmpg2g[*it]);
- }
- return mcr;
- }
+// Algorithms
+// Maximum Cycle Ratio
+
+template <
+ typename FloatTraits,
+ typename Graph,
+ typename VertexIndexMap,
+ typename EdgeWeight1Map,
+ typename EdgeWeight2Map>
+inline typename FloatTraits::value_type
+maximum_cycle_ratio(const Graph &g, VertexIndexMap vim, EdgeWeight1Map ew1m,
+ EdgeWeight2Map ew2m,
+ std::vector<typename graph_traits<Graph>::edge_descriptor>* pcc = 0,
+ FloatTraits = FloatTraits())
+{
+ typedef detail::float_wrapper<
+ FloatTraits, detail::max_comparator_props<FloatTraits>
+ > Traits;
+ return detail::optimum_cycle_ratio<Traits>(g, vim, ew1m, ew2m, pcc);
+}
+
+template <
+ typename Graph,
+ typename VertexIndexMap,
+ typename EdgeWeight1Map,
+ typename EdgeWeight2Map>
+inline double
+maximum_cycle_ratio(const Graph &g, VertexIndexMap vim,
+ EdgeWeight1Map ew1m, EdgeWeight2Map ew2m,
+ std::vector<typename graph_traits<Graph>::edge_descriptor>* pcc = 0)
+{ return maximum_cycle_ratio(g, vim, ew1m, ew2m, pcc, mcr_float<>()); }
+
+// Minimum Cycle Ratio
+
+template <
+ typename FloatTraits,
+ typename Graph,
+ typename VertexIndexMap,
+ typename EdgeWeight1Map,
+ typename EdgeWeight2Map>
+typename FloatTraits::value_type
+minimum_cycle_ratio(const Graph &g, VertexIndexMap vim,
+ EdgeWeight1Map ew1m, EdgeWeight2Map ew2m,
+ std::vector<typename graph_traits<Graph>::edge_descriptor> *pcc = 0,
+ FloatTraits = FloatTraits())
+{
+ typedef detail::float_wrapper<
+ FloatTraits, detail::min_comparator_props<FloatTraits>
+ > Traits;
+ return detail::optimum_cycle_ratio<Traits>(g, vim, ew1m, ew2m, pcc);
+}
+
+template <
+ typename Graph,
+ typename VertexIndexMap,
+ typename EdgeWeight1Map,
+ typename EdgeWeight2Map>
+inline double
+minimum_cycle_ratio(const Graph &g, VertexIndexMap vim,
+ EdgeWeight1Map ew1m, EdgeWeight2Map ew2m,
+ std::vector<typename graph_traits<Graph>::edge_descriptor>* pcc = 0)
+{ return minimum_cycle_ratio(g, vim, ew1m, ew2m, pcc, mcr_float<>()); }
+
+// Maximum Cycle Mean
+
+template <
+ typename FloatTraits,
+ typename Graph,
+ typename VertexIndexMap,
+ typename EdgeWeightMap,
+ typename EdgeIndexMap>
+inline typename FloatTraits::value_type
+maximum_cycle_mean(const Graph &g, VertexIndexMap vim,
+ EdgeWeightMap ewm, EdgeIndexMap eim,
+ std::vector<typename graph_traits<Graph>::edge_descriptor>* pcc = 0,
+ FloatTraits ft = FloatTraits())
+{
+ typedef typename remove_const<
+ typename property_traits<EdgeWeightMap>::value_type
+ >::type Weight;
+ typename std::vector<Weight> ed_w2(boost::num_edges(g), 1);
+ return maximum_cycle_ratio(g, vim, ewm,
+ make_iterator_property_map(ed_w2.begin(), eim),
+ pcc, ft);
+}
+
+template <
+ typename Graph,
+ typename VertexIndexMap,
+ typename EdgeWeightMap,
+ typename EdgeIndexMap>
+inline double
+maximum_cycle_mean(const Graph& g, VertexIndexMap vim,
+ EdgeWeightMap ewm, EdgeIndexMap eim,
+ std::vector<typename graph_traits<Graph>::edge_descriptor>* pcc = 0)
+{ return maximum_cycle_mean(g, vim, ewm, eim, pcc, mcr_float<>()); }
+
+// Minimum Cycle Mean
+
+template <
+ typename FloatTraits,
+ typename Graph,
+ typename VertexIndexMap,
+ typename EdgeWeightMap,
+ typename EdgeIndexMap>
+inline typename FloatTraits::value_type
+minimum_cycle_mean(const Graph &g, VertexIndexMap vim,
+ EdgeWeightMap ewm, EdgeIndexMap eim,
+ std::vector<typename graph_traits<Graph>::edge_descriptor>* pcc = 0,
+ FloatTraits ft = FloatTraits())
+{
+ typedef typename remove_const<
+ typename property_traits<EdgeWeightMap>::value_type
+ >::type Weight;
+ typename std::vector<Weight> ed_w2(boost::num_edges(g), 1);
+ return minimum_cycle_ratio(g, vim, ewm,
+ make_iterator_property_map(ed_w2.begin(), eim),
+ pcc, ft);
+}
+
+template <
+ typename Graph,
+ typename VertexIndexMap,
+ typename EdgeWeightMap,
+ typename EdgeIndexMap>
+inline double
+minimum_cycle_mean(const Graph &g, VertexIndexMap vim,
+ EdgeWeightMap ewm, EdgeIndexMap eim,
+ std::vector<typename graph_traits<Graph>::edge_descriptor>* pcc = 0)
+{ return minimum_cycle_mean(g, vim, ewm, eim, pcc, mcr_float<>()); }
- template <typename TGraph, typename TVertexIndexMap, typename TW1EdgeMap, typename TW2EdgeMap, typename TIndEdgeMap>
- double minimum_cycle_ratio(const TGraph& g, TVertexIndexMap vim, TW1EdgeMap ew1m, TW2EdgeMap ew2m, TIndEdgeMap eim,
- typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
- typename boost::property_traits<TW1EdgeMap>::value_type plus_infinity =
- (std::numeric_limits<int>::max)())
- {
- typedef typename boost::remove_const<typename boost::property_traits<TW1EdgeMap>::value_type>::type weight_value_t;
- BOOST_STATIC_ASSERT(!is_integral<weight_value_t>::value || is_signed<weight_value_t>::value);
- typename std::vector<weight_value_t> ne_w(boost::num_edges(g));
- BGL_FORALL_EDGES_T(ed, g, TGraph) ne_w[boost::get(eim, ed)] = -ew1m[ed];
- return -maximum_cycle_ratio(g, vim, boost::make_iterator_property_map(ne_w.begin(), eim), ew2m, pcc, -plus_infinity);
- }
- /*!
- * Calculate maximum mean cycle of directed weighted multigraph.
- * \param g directed multigraph
- * \return maximum mean cycle of g or minus_infinity if g has no cycles.
- */
- template <typename TGraph, typename TVertexIndexMap, typename TWeightEdgeMap, typename TIndEdgeMap>
- double maximum_mean_cycle(const TGraph& g, TVertexIndexMap vim, TWeightEdgeMap ewm, TIndEdgeMap eim,
- typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
- typename boost::property_traits<TWeightEdgeMap>::value_type minus_infinity =
- -(std::numeric_limits<int>::max)())
- {
- typedef typename boost::remove_const<typename boost::property_traits<TWeightEdgeMap>::value_type>::type weight_value_t;
- typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
- typename std::vector<weight_value_t> ed_w2(boost::num_edges(g), 1);
- return maximum_cycle_ratio(g, vim, ewm, boost::make_iterator_property_map(ed_w2.begin(), eim), pcc, minus_infinity);
- }
-
- template <typename TGraph, typename TVertexIndexMap, typename TWeightEdgeMap, typename TIndEdgeMap>
- double minimum_mean_cycle(const TGraph& g, TVertexIndexMap vim, TWeightEdgeMap ewm, TIndEdgeMap eim,
- typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
- typename boost::property_traits<TWeightEdgeMap>::value_type plus_infinity =
- (std::numeric_limits<int>::max)())
- {
- typedef typename boost::remove_const<typename boost::property_traits<TWeightEdgeMap>::value_type>::type weight_value_t;
- typedef typename boost::graph_traits<TGraph>::edge_descriptor Edge;
- typename std::vector<weight_value_t> ed_w2(boost::num_edges(g), 1);
- return minimum_cycle_ratio(g, vim, ewm, boost::make_iterator_property_map(ed_w2.begin(), eim), eim, pcc, plus_infinity);
- }
} //namespace boost
+
#endif
Modified: trunk/libs/graph/doc/howard_cycle_ratio.html
==============================================================================
--- trunk/libs/graph/doc/howard_cycle_ratio.html (original)
+++ trunk/libs/graph/doc/howard_cycle_ratio.html 2009-07-17 10:56:19 EDT (Fri, 17 Jul 2009)
@@ -9,11 +9,11 @@
<!-- -- Copyright 2007 Technical University of Catalonia
-
+
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: Dmitry Bufistov
Andrey Parfenov
-->
@@ -34,143 +34,200 @@
<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>maximum(minimum)_cycle_ratio</TT>
-</H1>
-<I>// non-named parameter version</I>
-<!--template <typename TGraph,
- typename TVertexIndexMap,
- typename TWeight1EdgeMap,
- typename TWeight2EdgeMap >
-double maximum_cycle_ratio_good_graph(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ew1m, TWeight2EdgeMap ew2m,
- typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0);
-<br/>
-<PRE>template <typename TGraph,
- typename TWeight1EdgeMap,
- typename TWeight2EdgeMap >
-double maximum_cycle_ratio1(const TGraph& g, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
- typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
- typename boost::property_traits<TWeight1EdgeMap>::value_type minus_infinity =
- -(std::numeric_limits<int>::max)());
- </PRE>-->
+<H1><TT>[maximum|minimum]_cycle_ratio</TT></H1>
<P>
-<PRE>template <typename TGraph,
- typename TVertexIndexMap,
- typename TWeight1EdgeMap,
- typename TWeight2EdgeMap >
-double maximum_cycle_ratio(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m,
- typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
- typename boost::property_traits<TWeight1EdgeMap>::value_type minus_infinity =
- -(std::numeric_limits<int>::max)());
- </PRE>
+<PRE>
+template <typename Graph, typename VertexIndexMap,
+ typename EdgeWeight1, typename EdgeWeight2>
+dobule
+maximum_cycle_ratio(const Graph &g, VertexIndexMap vim,
+ EdgeWeight1 ewm, EdgeWeight2 ew2m,
+ std::vector<typename boost::graph_traits<Graph>::edge_descriptor> *pcc = 0);
+
+template <typename FloatTraits, Graph, typename VertexIndexMap,
+ typename EdgeWeight1, typename EdgeWeight2>
+typename FloatTraits::float_type
+maximum_cycle_ratio(const Graph &g, VertexIndexMap vim,
+ EdgeWeight1 ewm, EdgeWeight2 ew2m,
+ std::vector<typename boost::graph_traits<Graph>::edge_descriptor> *pcc = 0,
+ FloatTraits = FloatTraits());
+
+template <typename Graph, typename VertexIndexMap,
+ typename EdgeWeight1, typename EdgeWeight2>
+dobule
+minimum_cycle_ratio(const Graph &g, VertexIndexMap vim,
+ EdgeWeight1 ewm, EdgeWeight2 ew2m,
+ std::vector<typename boost::graph_traits<Graph>::edge_descriptor> *pcc = 0);
+
+template <typename FloatTraits, typename Graph, typename VertexIndexMap,
+ typename EdgeWeight1, typename EdgeWeight2>
+typename FloatTraits::float_type
+minimum_cycle_ratio(const Graph &g, VertexIndexMap vim,
+ EdgeWeight1 ewm, EdgeWeight2 ew2m,
+ std::vector<typename boost::graph_traits<Graph>::edge_descriptor> *pcc = 0,
+ FloatTraits = FloatTraits());
+</PRE>
</P>
+
+
+The <tt>maximum_cycle_ratio()</tt> function calculates the maximum cycle ratio of a
+weighted directed multigraph <I>G=(V,E,W1,W2)</I>, where <i>V</i> is a vertex set,
+<i>E</i> is an edge set, W1 and W2 are edge weight functions, W2 is nonnegative.
+As a multigraph, <i>G</i> can have multiple edges connecting a pair of vertices.
+</P>
+
+<P>Let every edge <I>e</I> has two weights <I>W1(e)</I> and <I>W2(e)</I>.
+Let <I>c</I> be a cycle of the graph<I>g</I>. Then, the <i>cycle ratio</i>, <I>cr(c)</I>, is defined as:</P>
<P>
-<PRE>template <typename TGraph,
- typename TVertexIndexMap,
- typename TWeight1EdgeMap,
- typename TWeight2EdgeMap,
- typename TEdgeIndexMap >
-double minimum_cycle_ratio(const TGraph& g, TVertexIndexMap vim, TWeight1EdgeMap ewm, TWeight2EdgeMap ew2m, TEdgeIndexMap eim,
- typename std::vector<typename boost::graph_traits<TGraph>::edge_descriptor>* pcc = 0,
- typename boost::property_traits<TWeight1EdgeMap>::value_type plus_infinity =
- (std::numeric_limits<int>::max)());
- </PRE>
-</P>
-The <I>maximum_cycle_ratio()</I> function calculates the maximum cycle ratio of a weighted directed multigraph <I>g=(V,E,W1,W2)</I>, where <i>V</i> is a vertex set, <i>E</i> is an edge set, W1 and W2 are edge weight functions, W2 is nonnegative. <i>Multigraph</i> is a graph that can have multiple edges between its vertices. The calculated maximum cycle ratio will be the return value of the function. The <I>maximal_cycle_ratio()</I> returns <I>minus_infinity</I> if graph has no cycles. The value of the <i>minus_infinity</i> parameter should be small enough to garanty that <i>g</i> has at leat one cycle with greater ratio.
-</P>
-
-<P>Let every edge <I>e</I> have two weights <I>W1(e)</I> and <I>W2(e)</I>. </SPAN> Let <I>c</I> <SPAN STYLE="font-style: normal">be a cycle of a graph</SPAN> <I>g</I>. <SPAN STYLE="font-style: normal">The <i>cycle ratio</i> (<I>cr(c)</I>) is defined as:</SPAN></P>
-<P><IMG SRC="figs/cr.jpg" NAME="graphics2" ALT="Cycle ratio definition" ALIGN=LEFT WIDTH=295 HEIGHT=82 BORDER=0><BR CLEAR=LEFT><BR><BR>
-The <I>maximum (minimum) cycle ratio</I> (mcr) is the maximum (minimum) cycle ratio of all cycles of the graph.
-Cycle calls <I>critical</I> if its ratio is equal to <I>mcr</I>. </P>If the <i>pcc</i> parameter is not zero then one critical cycle will be written to the corresponding std::vector of edge descriptors. The edges in the vector stored in the way that *pcc[0], *ppc[1],...,*ppc[n] is a correct path.</P>
-<!--<P STYLE="margin-bottom: 0cm">
- For every directed multigraph <I>G=(V,E)</I> there is a «good» multigraph G'=(V',E'),
-such that <I>mcr(G)== mcr(G').</I> G' can be constructed from G by
-adding one "sink" <SPAN STYLE="font-style: normal">vertex </SPAN><I> u </I><SPAN STYLE="font-style: normal">and</SPAN><I>
-num_vertex(G)+ 1 </I><SPAN STYLE="font-style: normal">edges</SPAN><I>
-(v, u) </I><SPAN STYLE="font-style: normal">for all vertices</SPAN><I>
- v </I><SPAN STYLE="font-style: normal">in</SPAN><I> V</I> <SPAN STYLE="font-style: normal">(including
- self loop <I>sl=(u,u)</I>). The weights of the self loop </SPAN><I>W1(sl),
-W2(sl) </I><SPAN STYLE="font-style: normal">should be set to «<I>minus
-infinity»</I> and 1 correspondingly. The <I>make_graph_good()</I>
-function from cycle_ratio_example.cpp
-implement this transformation. Based on <I>make_graph_good()</I>
-function one can write <I>maximum_cycle_ratio()</I> function that would work
-for all directed multigraphs, returning minus infinity if graph has
-no cycles, the usage example file cycle_ratio_example.cpp
-contains implementation of this function (also more or less general version of <I>minimal_cycle_ratio()</I> function) and some usage examples. </SPAN>
-</P>-->
-For a graph <i>G=(V,E,W1,W2)</i> let <i>G'=(V,E,-W1,W2)</i> be a graph with opposite <i>W1</i> function, then the minimum cycle ratio of <i>G</i> is the opposite maximum cycle ratio of <i>G'</i>.
-The <i>minimum_cycle_ratio()</i> function just calls the <i>maximum_cycle_ratio()</i> with the opposite <i>W1</i> function, so if the type value of the <i>W1</i> weight is integral then it must be signed.
+<IMG SRC="figs/cr.jpg" ALT="Cycle ratio definition" BORDER=0>
+</P>
+
+The <I>maximum (minimum) cycle ratio</I> (mcr) is the maximum (minimum) cycle ratio
+of all cycles of the graph. A cycle is called <I>critical</I> if its ratio is equal
+to the <I>mcr</I>. The calculated maximum cycle ratio will be the return value
+of the function. The <tt>maximum_cycle_ratio()/minimum_cycle_ratio()</tt> returns
+<tt>-FloatTraits::infinity()/FloatTraits::infinity()</tt> if graph has no cycles.
+If the <i>pcc</i> parameter is not zero then one critical cycle will be written
+to the corresponding <tt>std::vector</tt> of edge descriptors. The edges in the
+vector stored in the way such that <tt>*pcc[0], *ppc[1], ..., *ppc[n]</tt> is a
+correct path.
+</P>
<P>
The algorithm is due to Howard's iteration policy algorithm, descibed in
<A HREF="./cochet-terrasson98numerical.pdf">[1]</A>.
Ali Dasdan, Sandy S. Irani and Rajesh K.Gupta in their paper
<A HREF="./dasdan-dac99.pdf">Efficient Algorithms for Optimum Cycle Mean and Optimum Cost to Time Ratio
Problems</A>state that this is the most efficient algorithm to the time being (1999).</P>
-<H3>
-Where Defined</H3>
-<P STYLE="background: transparent"><TT>boost/graph/howard_cycle_ratio.hpp</TT>
+
+<p>
+For the convenience, functions <tt>maximum_cycle_mean()</tt> and <tt>minimum_cycle_mean()</tt>
+are also provided. They have the following signatures:
+<pre>
+template <typename Graph, typename VertexIndexMap,
+ typename EdgeWeightMap, typename EdgeIndexMap>
+double
+maximum_cycle_mean(const Graph &g, VertexIndexMap vim,
+ EdgeWeightMap ewm, EdgeIndexMap eim,
+ std::vector<typename graph_traits<Graph>::edge_descriptor> *pcc = 0);
+template <typename FloatTraits, typename Graph, typename VertexIndexMap,
+ typename EdgeWeightMap, typename EdgeIndexMap>
+
+typename FloatTraits::float_type
+maximum_cycle_mean(const Graph &g, VertexIndexMap vim,
+ EdgeWeightMap ewm, EdgeIndexMap eim,
+ std::vector<typename graph_traits<Graph>::edge_descriptor> *pcc = 0,
+ FloatTraits = FloatTraits());
+
+template <typename Graph, typename VertexIndexMap,
+ typename EdgeWeightMap, typename EdgeIndexMap>
+double
+minimum_cycle_mean(const Graph &g, VertexIndexMap vim,
+ EdgeWeightMap ewm, EdgeIndexMap eim,
+ std::vector<typename graph_traits<Graph>::edge_descriptor> *pcc = 0);
+template <typename FloatTraits, typename Graph, typename VertexIndexMap,
+ typename EdgeWeightMap, typename EdgeIndexMap>
+
+typename FloatTraits::float_type
+minimum_cycle_mean(const Graph &g, VertexIndexMap vim,
+ EdgeWeightMap ewm, EdgeIndexMap eim,
+ std::vector<typename graph_traits<Graph>::edge_descriptor> *pcc = 0,
+ FloatTraits = FloatTraits());
+</pre>
+</p>
+
+<H3>Where Defined</H3>
+<P STYLE="background: transparent"><TT>boost/graph/howard_cycle_ratio.hpp</TT>
</P>
<H3>Parameters</H3>
-<P>IN: <FONT FACE="Courier New, monospace">const TGraph& g </FONT>
-</P>
-<BLOCKQUOTE>A directed weighted multigraph.
-The graph's type must be a model of VertexListGraph
-and IncidenceGraph
+<P>IN: <tt>FloatTraits</tt> </P>
+<blockquote>
+The <tt>FloatTrats</tt> encapsulates customizable limits-like information for
+floating point types. This type <i>must</i> provide an associated type,
+<tt>value_type</tt> for the floating point type.
+
+The default value is <tt>boost::mcr_float<></tt>which has the following
+definition:<br/>
+<pre>
+ template <typename Float = double>
+ struct mcr_float {
+ typedef Float value_type;
+
+ static Float infinity()
+ { return (std::numeric_limits<value_type>::max)(); }
+
+ static Float epsilon()
+ { return Float(-0.005); }
+ };
+</pre>
+The value <tt>FloatTraits::epsilon()</tt> controls the "tolerance" of the
+algorithm. By increasing the absolute value of epsilon you may slightly decrease
+the execution time but there is a risk to skip a global optima. By decreasing
+the absolute value you may fall to the infinite loop. The best option is to
+leave this parameter unchanged.
+</blockquote>
+<P>IN: <tt>const Graph& g </tt>
+</P>
+<BLOCKQUOTE>A weighted directed multigraph.
+The graph's type must be a model of VertexListGraph
+and IncidenceGraph
</BLOCKQUOTE>
-<P>IN: <FONT FACE="Courier New, monospace" COLOR="#000000">TVertexIndexMap vim</FONT>
+<P>IN: <tt>VertexIndexMap vim</tt>
</P>
<BLOCKQUOTE>Maps each vertex of the graph to a unique integer in the
range [0, num_vertices(g)).
</BLOCKQUOTE>
-<P>IN: <FONT FACE="Courier New, monospace">TWeight1EdgeMap ew1m</FONT>
+<P>IN: <tt>EdgeWeight1 ew1m</t>
</P>
<BLOCKQUOTE>
-The W1 edge weight function. For <i>minimum_cycle_ratio()</i> if the type value of the ew1m is integral then it must be signed.
+The W1 edge weight function.
</BLOCKQUOTE>
-<P>IN: <FONT FACE="Courier New, monospace">TWeight2EdgeMap ew2m</FONT>
-</P>
-<BLOCKQUOTE>The W2 edge weight function. Must be nonnegative.</BLOCKQUOTE>
-<P>IN: <FONT FACE="Courier New, monospace"><FONT COLOR="#000000">TEdgeIndexMap eim</FONT></FONT>
+<P>IN: <tt>EdgeWeight2 ew2m</tt>
</P>
-<BLOCKQUOTE>Maps each edge of the graph <I>g</I> to a unique integer
-in the range <TT>[0, num_edges(g)). <FONT FACE="Times New Roman, serif"></FONT></TT></BLOCKQUOTE>
-
-<P>IN: <FONT FACE="Courier New, monospace"><FONT COLOR="#000000">boost::property_traits<TWeight1EdgeMap>::value_type minus_infinity</FONT></FONT>
+<BLOCKQUOTE>
+The W2 edge weight function. Should be nonnegative. The actual limitation of the
+algorithm is the positivity of the total weight of each directed cycle of the graph.
+</BLOCKQUOTE>
+<P>
+OUT: <tt>std::vector<typename boost::graph_traits<Graph>::edge_descriptor>* pcc</tt>
</P>
-<BLOCKQUOTE>Small enough value to garanty that <i>g</i> has at least one cycle with greater ratio</BLOCKQUOTE>
-<P>IN: <FONT FACE="Courier New, monospace"><FONT COLOR="#000000">boost::property_traits<TWeight1EdgeMap>::value_type plus_infinity</FONT></FONT>
+<BLOCKQUOTE>
+If non zero then one critical cycle will be stored in the std::vector. Default
+value is 0.
+</BLOCKQUOTE>
+<P>
+IN (only for maximum/minimal_cycle_mean()): <tt>EdgeIndexMap eim</tt>
</P>
-<BLOCKQUOTE>Big enough value to garanty that <i>g</i> has at least one cycle with less ratio. Expression -plus_infinity must be well defined.</BLOCKQUOTE>
-
-<P>OUT: <FONT FACE="Courier New, monospace">std::vector<typename
-boost::graph_traits<TGraph>::edge_descriptor>* pcc</FONT></P>
-<BLOCKQUOTE>An edge descriptors of one critical cycle will be stored in the corresponding std::vector. Default value is 0.</BLOCKQUOTE>
+<BLOCKQUOTE>
+Maps each edge of the graph to a unique integer in the range [0, num_edges(g)).
+</BLOCKQUOTE>
<BLOCKQUOTE STYLE="margin-left: 0cm">
-The all maps must be a models of <A HREF="../..//property_map/doc/ReadablePropertyMap.html">Readable
-Property Map</A></BLOCKQUOTE>
+All property maps must be models of <A HREF="http://boost.org/libs/property_map/ReadablePropertyMap.html">Readable
+Property Map</A>
+</BLOCKQUOTE>
+
<H3>Complexity</H3>
<P>There is no known precise upper bound for the time complexity of the
-algorithm. Imperical time complexity is <I>O(E)</I>, where the
-constant tends to be pretty small. Space complexity is also <I>O(E)</I>.
+algorithm. Imperical time complexity is <I>O(|E|)</I>, where the constant tends to
+be pretty small (about 20-30). Space complexity is equal to <i>7*|V|</i> plus the
+space required to store a graph.
</P>
+
<H3>Example</H3>
-<P>The program in cycle_ratio_example.cpp
-generates random graph and computes its maximum cycle ratio.
+<P>The program in cycle_ratio_example.cpp
+generates a random graph and computes its maximum cycle ratio.
</P>
+
<HR>
<TABLE CELLPADDING=2 CELLSPACING=2>
- <TR VALIGN=TOP>
- <TD>
- <P>Copyright © 2000-2006</P>
- </TD>
- <TD>
- <P><A HREF="http://www.lsi.upc.edu/~dmitry">Dmitry
- Bufistov</A>, Universitat Politecnica de Cataluña</P>
- </TD>
- </TR>
+ <TR VALIGN=TOP>
+ <TD>
+ <P>Copyright © 2006-2009</P>
+ </TD>
+ <TD>
+ <P><A HREF="http://www.lsi.upc.edu/~dmitry">Dmitry
+ Bufistov</A>, Andrey Parfenov</P>
+ </TD>
+ </TR>
</TABLE>
<P><BR><BR>
-</P>
-</BODY>
-</HTML>
+</P></HTML>
Modified: trunk/libs/graph/example/cycle_ratio_example.cpp
==============================================================================
--- trunk/libs/graph/example/cycle_ratio_example.cpp (original)
+++ trunk/libs/graph/example/cycle_ratio_example.cpp 2009-07-17 10:56:19 EDT (Fri, 17 Jul 2009)
@@ -1,84 +1,83 @@
-/*!
-* Copyright 2007 Technical University of Catalonia
-*
-* 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: Dmitry Bufistov
-* Andrey Parfenov
-*/
-#include <boost/graph/howard_cycle_ratio.hpp>
-#include <boost/random/mersenne_twister.hpp>
+// Copyright (C) 2006-2009 Dmitry Bufistov and Andrey Parfenov
+
+// 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)
+
+#include <cassert>
+#include <ctime>
+#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/graph/adjacency_list.hpp>
-#include <boost/graph/iteration_macros.hpp>
-#include <boost/graph/graph_utility.hpp>
-#include <boost/graph/property_iter_range.hpp>
#include <boost/graph/random.hpp>
-#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/graph/howard_cycle_ratio.hpp>
+/**
+ * @author Dmitry Bufistov
+ * @author Andrey Parfenov
+ */
using namespace boost;
-typedef adjacency_list<listS, listS, directedS, property<vertex_index_t, int, property<boost::vertex_name_t, std::string> >,
- property<edge_weight_t, double, property<edge_weight2_t, double, property<edge_index_t, int> > > > grap_real_t;
+typedef adjacency_list<
+ listS, listS, directedS,
+ property<vertex_index_t, int>,
+ property<
+ edge_weight_t, double, property<edge_weight2_t, double>
+ >
+> grap_real_t;
-template <typename TGraph>
-void gen_rand_graph(TGraph& g, size_t nV, size_t nE)
+template <typename TG>
+void gen_rand_graph(TG &g, size_t nV, size_t nE)
{
- g.clear();
- boost::mt19937 rng;
- boost::generate_random_graph(g, nV, nE, rng, true, true);
- boost::uniform_real<> ur(-1,10);
- boost::variate_generator<boost::mt19937&, boost::uniform_real<> > ew1rg(rng, ur);
- randomize_property<edge_weight_t>(g, ew1rg);
- boost::uniform_int<> uint(1,5);
- boost::variate_generator<boost::mt19937&, boost::uniform_int<> > ew2rg(rng, uint);
- randomize_property<edge_weight2_t>(g, ew2rg);
+ g.clear();
+ mt19937 rng;
+ rng.seed(uint32_t(time(0)));
+ boost::generate_random_graph(g, nV, nE, rng, true, true);
+ boost::uniform_real<> ur(-1,10);
+ boost::variate_generator<boost::mt19937&, boost::uniform_real<> > ew1rg(rng, ur);
+ randomize_property<edge_weight_t>(g, ew1rg);
+ boost::uniform_int<size_t> uint(1,5);
+ boost::variate_generator<boost::mt19937&, boost::uniform_int<size_t> > ew2rg(rng, uint);
+ randomize_property<edge_weight2_t>(g, ew2rg);
}
int main(int argc, char* argv[])
{
- const double epsilon = 0.000000001;
- double min_cr, max_cr; ///Minimum and maximum cycle ratio
- typedef std::vector<graph_traits<grap_real_t>::edge_descriptor> ccReal_t;
- ccReal_t cc; ///For storing critical edges
-
-
- grap_real_t tgr;
- property_map<grap_real_t, vertex_index_t>::type vim = get(vertex_index, tgr);
- property_map<grap_real_t, edge_weight_t>::type ew1m = get(edge_weight, tgr);
- property_map<grap_real_t, edge_weight2_t>::type ew2m = ew2m;
-
- gen_rand_graph(tgr, 1000, 300000);
- std::cout << "Vertices number: " << num_vertices(tgr) << '\n';
- std::cout << "Edges number: " << num_edges(tgr) << '\n';
- int i = 0;
- BGL_FORALL_VERTICES(vd, tgr, grap_real_t) put(vertex_index, tgr, vd, i++); ///Initialize vertex index property
- boost::posix_time::ptime st = boost::posix_time::microsec_clock::local_time();
- max_cr = maximum_cycle_ratio(tgr, get(vertex_index, tgr), get(edge_weight, tgr), get(edge_weight2, tgr));
- std::cout << "Maximum cycle ratio is " << max_cr << '\n';
- std::cout << "Run time of the maximum_cycle_ratio() is " << to_simple_string(boost::posix_time::microsec_clock::local_time() - st) << '\n';
-
-
- ///One way to get the "good" value of the plus_infinity parameter
- double pl_infnt = double(*std::max_element(get_property_iter_range(tgr, edge_weight).first, get_property_iter_range(tgr, edge_weight).second)) /
- *std::min_element(get_property_iter_range(tgr, edge_weight2).first, get_property_iter_range(tgr, edge_weight2).second);
- std::cout << "Set infinity for minimum_cycle_ratio() call to " << pl_infnt << '\n';
- i = 0;
- BGL_FORALL_EDGES(ed, tgr, grap_real_t) put(edge_index, tgr, ed, i++); ///Initialize edge index property
- min_cr = minimum_cycle_ratio(tgr, get(vertex_index, tgr), get(edge_weight, tgr), get(edge_weight2, tgr), get(edge_index, tgr), &cc, pl_infnt);
- std::cout << "Minimal cycle ratio is " << min_cr << '\n';
- std::pair<double, double> cr(.0,.0);
- std::cout << "\nCritical cycle is:\n";
- for (ccReal_t::iterator itr = cc.begin(); itr != cc.end(); ++itr)
- {
- cr.first += get(edge_weight, tgr, *itr); cr.second += get(edge_weight2, tgr, *itr);
- std::cout << "(" << get(vertex_index, tgr, source(*itr, tgr)) << "," << get(vertex_index, tgr, target(*itr, tgr)) << ") ";
- }
- std::cout << '\n';
- assert(std::abs(cr.first / cr.second - min_cr) < epsilon);
-
- return 0;
+ using std::cout;
+ using std::endl;
+ const double epsilon = 0.0000001;
+ double min_cr, max_cr; ///Minimum and maximum cycle ratio
+ typedef std::vector<graph_traits<grap_real_t>::edge_descriptor> ccReal_t;
+ ccReal_t cc; ///critical cycle
+
+ grap_real_t tgr;
+ property_map<grap_real_t, vertex_index_t>::type vim = get(vertex_index, tgr);
+ property_map<grap_real_t, edge_weight_t>::type ew1 = get(edge_weight, tgr);
+ property_map<grap_real_t, edge_weight2_t>::type ew2 = get(edge_weight2, tgr);
+
+ gen_rand_graph(tgr, 1000, 30000);
+ cout << "Vertices number: " << num_vertices(tgr) << endl;
+ cout << "Edges number: " << num_edges(tgr) << endl;
+ int i = 0;
+ graph_traits<grap_real_t>::vertex_iterator vi, vi_end;
+ for (tie(vi, vi_end) = vertices(tgr); vi != vi_end; vi++) {
+ vim[*vi] = i++; ///Initialize vertex index property
+ }
+ max_cr = maximum_cycle_ratio(tgr, vim, ew1, ew2);
+ cout << "Maximum cycle ratio is " << max_cr << endl;
+ min_cr = minimum_cycle_ratio(tgr, vim, ew1, ew2, &cc);
+ cout << "Minimum cycle ratio is " << min_cr << endl;
+ std::pair<double, double> cr(.0,.0);
+ cout << "Critical cycle:\n";
+ for (ccReal_t::iterator itr = cc.begin(); itr != cc.end(); ++itr)
+ {
+ cr.first += ew1[*itr];
+ cr.second += ew2[*itr];
+ std::cout << "(" << vim[source(*itr, tgr)] << "," <<
+ vim[target(*itr, tgr)] << ") ";
+ }
+ cout << endl;
+ assert(std::abs(cr.first / cr.second - min_cr) < epsilon);
+ return EXIT_SUCCESS;
}
Modified: trunk/libs/graph/test/cycle_ratio_tests.cpp
==============================================================================
--- trunk/libs/graph/test/cycle_ratio_tests.cpp (original)
+++ trunk/libs/graph/test/cycle_ratio_tests.cpp 2009-07-17 10:56:19 EDT (Fri, 17 Jul 2009)
@@ -1,37 +1,39 @@
-/*!
-* Copyright 2007 Technical University of Catalonia
-*
-* 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: Dmitry Bufistov
-* Andrey Parfenov
-*/
+// Copyright (C) 2006-2009 Dmitry Bufistov and Andrey Parfenov
+
+// 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)
+
#include <sstream>
-#include <boost/graph/howard_cycle_ratio.hpp>
+
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adjacency_matrix.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/graph/property_iter_range.hpp>
+#include <boost/graph/howard_cycle_ratio.hpp>
+
#include <boost/test/minimal.hpp>
-#include <cmath>
+
+/**
+ * @author Dmitry Bufistov
+ * @author Andrey Parfenov
+ */
/*!
* The graph has two equal cycles with ratio 2/3
*/
static const char test_graph1[] = "digraph G {\
- edge [w1=1, w2=1];\
- 1->2\
- 2->3 [w1=0]\
- 3->4\
- 4->2\
- 1->5\
- 5->6\
- 6->7 [w1=0]\
- 7->5 \
+ edge [w1=1, w2=1];\
+ 1->2\
+ 2->3 [w1=0]\
+ 3->4\
+ 4->2\
+ 1->5\
+ 5->6\
+ 6->7 [w1=0]\
+ 7->5 \
}";
/*!
@@ -40,21 +42,21 @@
static const std::string test_graph2 = "digraph G {edge [w1=1]; 1->3 [w2=1]; 1->2 [w2=2]; 1->4 [w2=7]; }";
/*!
-* Example from the paper "Nunerical computation of spectral elements"
-* Maximum cycle ratio is 5.5
+* Example from the paper "Nunerical computation of spectral elements"
+* Maximum cycle ratio is 5.5
*/
static const char test_graph3[] = "\
digraph article {\
- edge [w2 =2];\
- 1->1 [w1 = 1];\
- 1->2 [w1 = 2];\
- 1->4 [w1 = 7];\
- 2->2 [w1 = 3];\
- 2->3 [w1 = 5];\
- 3->2 [w1 = 4];\
- 3->4 [w1 = 3];\
- 4->2 [w1 = 2];\
- 4->3 [w1 = 8];\
+ edge [w2 =2];\
+ 1->1 [w1 = 1];\
+ 1->2 [w1 = 2];\
+ 1->4 [w1 = 7];\
+ 2->2 [w1 = 3];\
+ 2->3 [w1 = 5];\
+ 3->2 [w1 = 4];\
+ 3->4 [w1 = 3];\
+ 4->2 [w1 = 2];\
+ 4->3 [w1 = 8];\
}";
/*!
@@ -83,208 +85,263 @@
* Maximum cycle ratio is 3.58, minimum is 0.294118
*/
static const char test_graph6[]= "digraph test_graph6 {\
- 16;\
- 17;\
+ 16;\
+ 17;\
\
- 1->2 [w1=1, w2=0.1];\
- 2->3 [w1 = 2, w2=3.6];\
- 3->4 [w1=7, w2=8];\
- 4->5 [w1=3.1,w2=0.8];\
- 4->5 [w1 = 4.2, w2=0.6];\
- 4->5 [w1 = 5.3, w2=0.4];\
- 5->6 [w1=-10, w2 = 34.75]\
- 6->1 [w1=100, w2 = 20]\
+ 1->2 [w1=1, w2=0.1];\
+ 2->3 [w1 = 2, w2=3.6];\
+ 3->4 [w1=7, w2=8];\
+ 4->5 [w1=3.1,w2=0.8];\
+ 4->5 [w1 = 4.2, w2=0.6];\
+ 4->5 [w1 = 5.3, w2=0.4];\
+ 5->6 [w1=-10, w2 = 34.75]\
+ 6->1 [w1=100, w2 = 20]\
\
- 1->7 [w1=10, w2 = 20];\
- 7->8 [w1=3.75, w2 = 1.25];\
- 7->8 [w1=30, w2 = 22.2];\
- 8->9 [w1=10, w2 = 20];\
- 9->10 [w1=-2.1, w2 = 30]\
- 10->6 [w1=10, w2 = 20]\
+ 1->7 [w1=10, w2 = 20];\
+ 7->8 [w1=3.75, w2 = 1.25];\
+ 7->8 [w1=30, w2 = 22.2];\
+ 8->9 [w1=10, w2 = 20];\
+ 9->10 [w1=-2.1, w2 = 30]\
+ 10->6 [w1=10, w2 = 20]\
\
- 11->12 [w1 = 5, w2=0.45];\
- 12->13 [w1 = 4, w2=0.2];\
- 13->14 [w1 = 3, w2=15.75];\
- 14->11 [w1 = -2.5, w2=0.6];\
- 11->10 [w1 = -8, w2=0.9];\
- 11->10 [w1 = -15, w2=2.9];\
+ 11->12 [w1 = 5, w2=0.45];\
+ 12->13 [w1 = 4, w2=0.2];\
+ 13->14 [w1 = 3, w2=15.75];\
+ 14->11 [w1 = -2.5, w2=0.6];\
+ 11->10 [w1 = -8, w2=0.9];\
+ 11->10 [w1 = -15, w2=2.9];\
\
- 18 -> 19 [w1=18, w2=6];\
- 18 -> 20 [w1=16.3, w2=8.2];\
- 18 -> 21 [w1=-3, w2=15];\
- 18 -> 18 [w1=2, w2=1];\
- 19 -> 18 [w1=0.06, w2=0.01];\
- 19 -> 19 [w1=1, w2=1.2];\
- 19 -> 20 [w1=5, w2=2];\
- 19 -> 21 [w1=3, w2=0.1];\
- 20 -> 18 [w1=4, w2=0.2];\
- 20 -> 19 [w1=11, w2=21];\
- 20 -> 20 [w1=6, w2=5];\
- 20 -> 21 [w1=7, w2=1];\
- 21 -> 18 [w1=8, w2=2];\
- 21 -> 19 [w1=12, w2=6];\
- 21 -> 20 [w1=7.5, w2=4.3];\
- 21 -> 21 [w1=1.25, w2=2.15];\
+ 18 -> 19 [w1=18, w2=6];\
+ 18 -> 20 [w1=16.3, w2=8.2];\
+ 18 -> 21 [w1=-3, w2=15];\
+ 18 -> 18 [w1=2, w2=1];\
+ 19 -> 18 [w1=0.06, w2=0.01];\
+ 19 -> 19 [w1=1, w2=1.2];\
+ 19 -> 20 [w1=5, w2=2];\
+ 19 -> 21 [w1=3, w2=0.1];\
+ 20 -> 18 [w1=4, w2=0.2];\
+ 20 -> 19 [w1=11, w2=21];\
+ 20 -> 20 [w1=6, w2=5];\
+ 20 -> 21 [w1=7, w2=1];\
+ 21 -> 18 [w1=8, w2=2];\
+ 21 -> 19 [w1=12, w2=6];\
+ 21 -> 20 [w1=7.5, w2=4.3];\
+ 21 -> 21 [w1=1.25, w2=2.15];\
}";
using namespace boost;
-typedef property<boost::vertex_index_t, int, boost::property<boost::vertex_name_t, std::string> > vertex_props_t;
-template <typename EdgeWeight1, typename EdgeWeight2> struct Graph {
- typedef typename boost::property<boost::edge_weight_t, EdgeWeight1, typename boost::property<boost::edge_weight2_t,
- EdgeWeight2, boost::property<boost::edge_index_t, int> > > edge_props_t;
- typedef boost::adjacency_list<boost::listS, boost::listS, boost::directedS, vertex_props_t, edge_props_t> type;
+typedef property<vertex_index_t, int, property<boost::vertex_name_t, std::string> > vertex_props_t;
+template <typename TW1, typename TW2> struct Graph
+{
+ typedef typename boost::property<
+ boost::edge_weight_t, TW1,
+ typename boost::property<
+ boost::edge_weight2_t, TW2, property<boost::edge_index_t, int>
+ >
+ > edge_props_t;
+ typedef typename boost::adjacency_list<
+ boost::listS, boost::listS, boost::directedS, vertex_props_t,
+ edge_props_t>
+ type;
};
-typedef Graph<int, int>::type GraphInt;
-typedef Graph<double, double>::type GraphReal;
+typedef Graph<int, int>::type diGraphInt;
+typedef Graph<double, double>::type diGraphReal;
-template <typename TW1, typename TW2> struct CEdgeProps {
- CEdgeProps(TW1 w1 = 1, TW2 w2 = 2) : m_w1(w1), m_w2(w2), m_edge_index((std::numeric_limits<int>::max)()) {}
- TW1 m_w1;
- TW2 m_w2;
- int m_edge_index;
+template <typename TW1, typename TW2>
+struct CEdgeProps
+{
+ CEdgeProps(TW1 w1 = 1, TW2 w2 = 2) :
+ m_w1(w1), m_w2(w2), m_edge_index((std::numeric_limits<int>::max)())
+ {}
+ TW1 m_w1;
+ TW2 m_w2;
+ int m_edge_index;
};
-typedef adjacency_matrix<directedS, no_property, CEdgeProps<int, int> > GraphMInt;
-
+typedef adjacency_matrix<directedS, no_property, CEdgeProps<int, int> > GraphMInt;
+
///Create "tokens_map" for reading graph properties from .dot file
-template <typename TGraph>
-void make_dynamic_properties(TGraph& g, dynamic_properties& p)
+template <typename TG>
+void make_dynamic_properties(TG &g, dynamic_properties &p)
{
- p.property("node_id", get(vertex_name, g));
- p.property("label", get(edge_weight, g));
- p.property("w1", get(edge_weight, g));
- p.property("w2", get(edge_weight2, g));
+ p.property("node_id", get(vertex_name, g));
+ p.property("label", get(edge_weight, g));
+ p.property("w1", get(edge_weight, g));
+ p.property("w2", get(edge_weight2, g));
}
-template <typename TGraph>
-void read_data1(std::istream& is, TGraph& g)
+template <typename TG>
+void read_data1(std::istream &is, TG &g)
{
- dynamic_properties p;
- make_dynamic_properties(g, p);
- read_graphviz(is, g, p);
- std::cout << "Number of vertices: " << num_vertices(g) << "\n";
- std::cout << "Number of edges: " << num_edges(g) << "\n";
- int i = 0;
- BGL_FORALL_VERTICES_T(vd, g, TGraph) put(vertex_index, g, vd, i++);
- i=0;
- BGL_FORALL_EDGES_T(ed, g, TGraph) put(edge_index, g, ed, i++);
+ dynamic_properties p;
+ make_dynamic_properties(g, p);
+ read_graphviz(is, g, p);
+ std::cout << "Number of vertices: " << num_vertices(g) << std::endl;
+ std::cout << "Number of edges: " << num_edges(g) << std::endl;
+ int i = 0;
+ BGL_FORALL_VERTICES_T(vd, g, TG)
+ {
+ put(vertex_index, g, vd, i++);
+ }
+ i=0;
+ BGL_FORALL_EDGES_T(ed, g, TG)
+ {
+ put(edge_index, g, ed, i++);
+ }
}
-template <typename TGraph>
-void read_data(const char* file, TGraph& g)
+template <typename TG>
+void read_data(const char *file, TG &g)
{
- std::cout << "Reading data from file: " << file << "\n";
- std::ifstream ifs(file);
- BOOST_REQUIRE(ifs.good());
- read_data1(ifs, g);
+ std::cout << "Reading data from file: " << file << std::endl;
+ std::ifstream ifs(file);
+ BOOST_REQUIRE(ifs.good());
+ read_data1(ifs, g);
}
+struct my_float : boost::mcr_float<>
+{
+ static double infinity()
+ {
+ return 1000;
+ }
+};
+
+struct my_float2 : boost::mcr_float<>
+{
+ static double infinity() { return 2; }
+};
+
int test_main(int argc, char* argv[])
{
- std::string input_file = "cycle_ratio_s382.90.dot";
- if (argc > 1) input_file = argv[1];
+ using std::endl; using std::cout;
+ const double epsilon = 0.005;
+ double min_cr, max_cr; ///Minimum and maximum cycle ratio
+ typedef std::vector<graph_traits<diGraphInt>::edge_descriptor> ccInt_t;
+ typedef std::vector<graph_traits<diGraphReal>::edge_descriptor> ccReal_t;
+ ccInt_t cc; ///critical cycle
+
+ diGraphInt tg;
+ property_map<diGraphInt, vertex_index_t>::type vim = get(vertex_index, tg);
+ property_map<diGraphInt, edge_weight_t>::type ew1m = get(edge_weight, tg);
+ property_map<diGraphInt, edge_weight2_t>::type ew2m = ew2m;
+
+
+
+ {
+ std::istringstream iss(test_graph1);
+ assert(iss.good());
+ read_data1(iss, tg);
+ max_cr = maximum_cycle_ratio(tg, vim, ew1m, ew2m);
+ cout << "Maximum cycle ratio is " << max_cr << endl;
+ BOOST_CHECK(std::abs( max_cr - 0.666666666) < epsilon );
+ tg.clear();
+ }
+
+ {
+ std::istringstream iss(test_graph2);
+ read_data1(iss, tg);
+ // TODO: This is causing a failuire, but I'm not really sure what it's doing per se.
+ // Commented out for now.
+ // BOOST_CHECK(std::abs(maximum_cycle_ratio(tg, vim, ew1m, ew2m) + (std::numeric_limits<double>::max)()) < epsilon );
+ BOOST_CHECK(std::abs(boost::maximum_cycle_ratio(tg, vim, ew1m, ew2m,
+ static_cast<ccInt_t*>(0), my_float()) + 1000) < epsilon );
+ tg.clear();
+ }
+
+ {
+ std::istringstream iss(test_graph3);
+ diGraphInt tgi;
+ read_data1(iss, tgi);
+ double max_cr = maximum_cycle_ratio(tgi, vim, ew1m, ew2m,
+ static_cast<ccInt_t*>(0));
+ cout << "Maximum cycle ratio is " << max_cr << endl;
+ BOOST_CHECK(std::abs( max_cr - 2.75) < epsilon );
+ double maxmc = maximum_cycle_mean(tgi, vim, ew1m, get(edge_index, tgi));
+ cout << "Maximum cycle mean is " << maxmc << endl;
+ BOOST_CHECK(std::abs( maxmc - 5.5) < epsilon );
+ tg.clear();
+ }
+
+ {
+ std::istringstream iss(test_graph4);
+ read_data1(iss, tg);
+ max_cr = maximum_cycle_ratio(tg, vim, ew1m, ew2m);
+ cout << "Maximum cycle ratio is " << max_cr << endl;
+ BOOST_CHECK(std::abs( max_cr - 2.5) < epsilon );
+ min_cr = minimum_cycle_ratio(tg, vim, ew1m, ew2m);
+ cout << "Minimum cycle ratio is " << min_cr << endl;
+ BOOST_CHECK(std::abs( min_cr - 0.5) < epsilon );
+ tg.clear();
+ }
+
+ {
+ std::istringstream iss(test_graph5);
+ read_data1(iss, tg);
+ min_cr = minimum_cycle_ratio(tg, vim, ew1m, ew2m, &cc, my_float());
+ BOOST_CHECK(std::abs( min_cr - 0.666666666) < epsilon );
+ cout << "Minimum cycle ratio is " << min_cr << endl;
+ cout << "Critical cycle is:\n";
+ for (ccInt_t::iterator itr = cc.begin(); itr != cc.end(); ++itr)
+ {
+ cout << "(" << get(vertex_name, tg, source(*itr, tg)) <<
+ "," << get(vertex_name, tg, target(*itr, tg)) << ") ";
+ }
+ cout << endl;
+ tg.clear();
+ }
+
+ {
+ read_data("cycle_ratio_s382.90.dot", tg);
+ min_cr = boost::minimum_cycle_ratio(tg, vim, ew1m, ew2m, &cc, my_float2());
+ cout << "Minimum cycle ratio is " << min_cr << endl;
+ BOOST_CHECK(std::abs(min_cr - 0.33333333333) < epsilon );
+ cout << "Critical cycle is:" << endl;
+ for (ccInt_t::iterator it = cc.begin(); it != cc.end(); ++it)
+ {
+ cout << "(" << get(vertex_name, tg, source(*it, tg)) << "," <<
+ get(vertex_name, tg, target(*it, tg)) << ") ";
+ }
+ cout << endl;
+ tg.clear();
+ }
+
+ {
+ diGraphReal tgr;
+ ccReal_t cc1;
+ std::istringstream iss(test_graph6);
+ read_data1(iss, tgr);
+ max_cr = maximum_cycle_ratio(tgr, get(vertex_index, tgr), get(edge_weight, tgr), get(edge_weight2, tgr));
+ cout << "Maximum cycle ratio is " << max_cr << endl;
+ min_cr = minimum_cycle_ratio(tgr, get(vertex_index, tgr), get(edge_weight, tgr),
+ get(edge_weight2, tgr), &cc);
+ cout << "Minimal cycle ratio is " << min_cr << endl;
+ std::pair<double, double> cr(.0,.0);
+ cout << "Critical cycle is:\n";
+ for (ccReal_t::iterator itr = cc.begin(); itr != cc.end(); ++itr)
+ {
+ cr.first += get(edge_weight, tgr, *itr); cr.second += get(edge_weight2, tgr, *itr);
+ cout << "(" << get(vertex_name, tgr, source(*itr, tgr)) << "," <<
+ get(vertex_name, tgr, target(*itr, tgr)) << ") ";
+ }
+ BOOST_CHECK(std::abs(cr.first / cr.second - min_cr) < epsilon);
+ cout << endl;
+ }
+
+ {
+ GraphMInt gm(10);
+ typedef graph_traits<GraphMInt>::vertex_iterator VertexItM;
+ typedef graph_traits<GraphMInt>::edge_descriptor EdgeM;
+ VertexItM vi1, vi2, vi_end;
+ for (tie(vi1, vi_end) = vertices(gm); vi1 != vi_end; ++vi1)
+ {
+ for (vi2 = vertices(gm).first; vi2 != vi_end; ++vi2)
+ add_edge(*vi1, *vi2, gm);
+ }
+ max_cr = maximum_cycle_ratio(gm, get(vertex_index, gm),
+ get(&CEdgeProps<int, int>::m_w1, gm), get(&CEdgeProps<int, int>::m_w2, gm));
+ BOOST_CHECK(std::abs(max_cr - 0.5) < epsilon);
+ }
- const double epsilon = 0.00000001;
- double min_cr, max_cr; ///Minimum and maximum cycle ratio
- typedef std::vector<graph_traits<GraphInt>::edge_descriptor> ccInt_t;
- typedef std::vector<graph_traits<GraphReal>::edge_descriptor> ccReal_t;
- ccInt_t cc; ///For storing critical edges
-
- GraphInt tg;
- property_map<GraphInt, vertex_index_t>::type vim = get(vertex_index, tg);
- property_map<GraphInt, edge_weight_t>::type ew1m = get(edge_weight, tg);
- property_map<GraphInt, edge_weight2_t>::type ew2m = ew2m;
-
- std::istringstream iss(test_graph1);
- read_data1(/*std::istringstream(test_graph1)*/iss, tg);
- max_cr = maximum_cycle_ratio(tg, vim, ew1m, ew2m);
- std::cout << "Maximum cycle ratio is " << max_cr << "\n";
- BOOST_CHECK(std::abs( max_cr - 0.666666666) < epsilon );
- tg.clear();
-
- iss.clear(); iss.str(test_graph2);
- read_data1(iss, tg);
- BOOST_CHECK(std::abs(maximum_cycle_ratio(tg, vim, ew1m, ew2m) + (std::numeric_limits<int>::max)()) < epsilon );
- BOOST_CHECK(std::abs(maximum_cycle_ratio(tg, vim, ew1m, ew2m, static_cast<ccInt_t*>(0), 1000) - 1000) < epsilon );
- tg.clear();
-
- iss.clear(); iss.str(test_graph3);
- read_data1(iss, tg);
- max_cr = maximum_cycle_ratio(tg, vim, ew1m, ew2m, static_cast<ccInt_t*>(0), -1);
- std::cout << "Maximum cycle ratio is " << max_cr << '\n';
- BOOST_CHECK(std::abs( max_cr - 2.75) < epsilon );
- double maxmc = maximum_mean_cycle(tg, vim, ew1m, get(edge_index, tg));
- std::cout << "Maximum mean cycle is " << maxmc << '\n';
- BOOST_CHECK(std::abs( maxmc - 5.5) < epsilon );
- tg.clear();
-
- iss.clear(); iss.str(test_graph4);
- read_data1(iss, tg);
- max_cr = maximum_cycle_ratio(tg, vim, ew1m, ew2m);
- std::cout << "Maximum cycle ratio is " << max_cr << '\n';
- BOOST_CHECK(std::abs( max_cr - 2.5) < epsilon );
- min_cr = minimum_cycle_ratio(tg, vim, ew1m, ew2m, get(edge_index, tg));
- std::cout << "Minimum cycle ratio is " << min_cr << '\n';
- BOOST_CHECK(std::abs( min_cr - 0.5) < epsilon );
- tg.clear();
-
- iss.clear(); iss.str(test_graph5);
- read_data1(iss, tg);
- min_cr = minimum_cycle_ratio_good_graph(tg, vim, ew1m, ew2m, get(edge_index,tg), &cc);
- BOOST_CHECK(std::abs( min_cr - 0.666666666) < epsilon );
- std::cout << "Minimum cycle ratio is " << min_cr << "\n";
- std::cout << "Critical cycle is:\n";
- for (ccInt_t::iterator itr = cc.begin(); itr != cc.end(); ++itr) {
- std::cout << "(" << get(vertex_name, tg, source(*itr, tg)) << "," << get(vertex_name, tg, target(*itr, tg)) << ") ";
- }
- std::cout << '\n';
- tg.clear();
-
- /**/read_data(input_file.c_str(), tg);
- min_cr = minimum_cycle_ratio(tg, vim, ew1m, ew2m, get(edge_index,tg), &cc, 2);
- std::cout << "Minimum cycle ratio is " << min_cr << "\n";
- BOOST_CHECK(std::abs(min_cr - 0.33333333333) < epsilon );
- std::cout << "Critical cycle is:\n";
- for (ccInt_t::iterator it = cc.begin(); it != cc.end(); ++it)
- {
- std::cout << "(" << get(vertex_name, tg, source(*it, tg)) << "," << get(vertex_name, tg, target(*it, tg)) << ") ";
- }
- std::cout << '\n';
- tg.clear();
-
- GraphReal tgr;
- ccReal_t cc1;
-
- iss.clear(); iss.str(test_graph6);
- read_data1(iss, tgr);
- max_cr = maximum_cycle_ratio(tgr, get(vertex_index, tgr), get(edge_weight, tgr), get(edge_weight2, tgr));
- std::cout << "Maximum cycle ratio is " << max_cr << '\n';
- double pl_infnt = double(*std::max_element(get_property_iter_range(tgr, edge_weight).first, get_property_iter_range(tgr, edge_weight).second)) /
- *std::min_element(get_property_iter_range(tgr, edge_weight2).first, get_property_iter_range(tgr, edge_weight2).second);
- std::cout << "Set infinity for minimum_cycle_ratio() call to " << pl_infnt << '\n';
- min_cr = minimum_cycle_ratio(tgr, get(vertex_index, tgr), get(edge_weight, tgr), get(edge_weight2, tgr),
- get(edge_index, tgr), &cc, pl_infnt);
- std::cout << "Minimal cycle ratio is " << min_cr << '\n';
- std::pair<double, double> cr(.0,.0);
- std::cout << "Critical cycle is:\n";
- for (ccReal_t::iterator itr = cc.begin(); itr != cc.end(); ++itr)
- {
- cr.first += get(edge_weight, tgr, *itr); cr.second += get(edge_weight2, tgr, *itr);
- std::cout << "(" << get(vertex_name, tgr, source(*itr, tgr)) << "," << get(vertex_name, tgr, target(*itr, tgr)) << ") ";
- }
- BOOST_CHECK(std::abs(cr.first / cr.second - min_cr) < epsilon);
- std::cout << '\n';
-
- GraphMInt gm(10);
- typedef graph_traits<GraphMInt>::vertex_iterator VertexItM;
- typedef graph_traits<GraphMInt>::edge_descriptor EdgeM;
- VertexItM vi1, vi2, vi_end;
- for (tie(vi1, vi_end) = vertices(gm); vi1 != vi_end; ++vi1)
- {
- for (vi2 = vertices(gm).first; vi2 != vi_end; ++vi2)
- add_edge(*vi1, *vi2, gm);
- }
- max_cr = maximum_cycle_ratio(gm, get(vertex_index, gm), get(&CEdgeProps<int, int>::m_w1, gm), get(&CEdgeProps<int, int>::m_w2, gm));
- BOOST_CHECK(std::abs(max_cr - 0.5) < epsilon);
- return 0;
+ return 0;
}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk