[Lemon-commits] [lemon_svn] marci: r1283 - in hugo/trunk/src: lemon test
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 20:44:22 CET 2006
Author: marci
Date: Fri Oct 8 15:07:51 2004
New Revision: 1283
Modified:
hugo/trunk/src/lemon/min_cost_flow.h
hugo/trunk/src/lemon/suurballe.h
hugo/trunk/src/test/min_cost_flow_test.cc
hugo/trunk/src/test/suurballe_test.cc
Log:
Suurballe and MinCostFlow classes are now able to increase the flow 1 by 1 with
this->augment()
Modified: hugo/trunk/src/lemon/min_cost_flow.h
==============================================================================
--- hugo/trunk/src/lemon/min_cost_flow.h (original)
+++ hugo/trunk/src/lemon/min_cost_flow.h Fri Oct 8 15:07:51 2004
@@ -70,108 +70,85 @@
typedef typename Graph::OutEdgeIt OutEdgeIt;
typedef typename Graph::template EdgeMap<int> EdgeIntMap;
-
typedef ResGraphWrapper<const Graph,int,CapacityMap,EdgeIntMap> ResGW;
typedef typename ResGW::Edge ResGraphEdge;
+ protected:
+
+ const Graph& g;
+ const LengthMap& length;
+ const CapacityMap& capacity;
+
+ EdgeIntMap flow;
+ typedef typename Graph::template NodeMap<Length> PotentialMap;
+ PotentialMap potential;
+
+ Node s;
+ Node t;
+
+ Length total_length;
+
class ModLengthMap {
typedef typename Graph::template NodeMap<Length> NodeMap;
- const ResGW& G;
- const LengthMap &ol;
+ const ResGW& g;
+ const LengthMap &length;
const NodeMap &pot;
public :
typedef typename LengthMap::KeyType KeyType;
typedef typename LengthMap::ValueType ValueType;
+
+ ModLengthMap(const ResGW& _g,
+ const LengthMap &_length, const NodeMap &_pot) :
+ g(_g), /*rev(_rev),*/ length(_length), pot(_pot) { }
ValueType operator[](typename ResGW::Edge e) const {
- if (G.forward(e))
- return ol[e]-(pot[G.head(e)]-pot[G.tail(e)]);
+ if (g.forward(e))
+ return length[e]-(pot[g.head(e)]-pot[g.tail(e)]);
else
- return -ol[e]-(pot[G.head(e)]-pot[G.tail(e)]);
+ return -length[e]-(pot[g.head(e)]-pot[g.tail(e)]);
}
- ModLengthMap(const ResGW& _G,
- const LengthMap &o, const NodeMap &p) :
- G(_G), /*rev(_rev),*/ ol(o), pot(p){};
- };//ModLengthMap
+ }; //ModLengthMap
+ ResGW res_graph;
+ ModLengthMap mod_length;
+ Dijkstra<ResGW, ModLengthMap> dijkstra;
- protected:
-
- //Input
- const Graph& G;
- const LengthMap& length;
- const CapacityMap& capacity;
-
-
- //auxiliary variables
+ public :
- //To store the flow
- EdgeIntMap flow;
- //To store the potential (dual variables)
- typedef typename Graph::template NodeMap<Length> PotentialMap;
- PotentialMap potential;
+ /*! \brief The constructor of the class.
+ \param _g The directed graph the algorithm runs on.
+ \param _length The length (weight or cost) of the edges.
+ \param _cap The capacity of the edges.
+ \param _s Source node.
+ \param _t Target node.
+ */
+ MinCostFlow(Graph& _g, LengthMap& _length, CapacityMap& _cap,
+ Node _s, Node _t) :
+ g(_g), length(_length), capacity(_cap), flow(_g), potential(_g),
+ s(_s), t(_t),
+ res_graph(g, capacity, flow),
+ mod_length(res_graph, length, potential),
+ dijkstra(res_graph, mod_length) {
+ reset();
+ }
- Length total_length;
-
+ /*! Tries to augment the flow between s and t by 1.
+ The return value shows if the augmentation is successful.
+ */
+ bool augment() {
+ dijkstra.run(s);
+ if (!dijkstra.reached(t)) {
+
+ //Unsuccessful augmentation.
+ return false;
+ } else {
- public :
-
- /// The constructor of the class.
-
- ///\param _G The directed graph the algorithm runs on.
- ///\param _length The length (weight or cost) of the edges.
- ///\param _cap The capacity of the edges.
- MinCostFlow(Graph& _G, LengthMap& _length, CapacityMap& _cap) : G(_G),
- length(_length), capacity(_cap), flow(_G), potential(_G){ }
-
-
- ///Runs the algorithm.
-
- ///Runs the algorithm.
- ///Returns k if there is a flow of value at least k edge-disjoint
- ///from s to t.
- ///Otherwise it returns the maximum value of a flow from s to t.
- ///
- ///\param s The source node.
- ///\param t The target node.
- ///\param k The value of the flow we are looking for.
- ///
- ///\todo May be it does make sense to be able to start with a nonzero
- /// feasible primal-dual solution pair as well.
- int run(Node s, Node t, int k) {
-
- //Resetting variables from previous runs
- total_length = 0;
-
- for (typename Graph::EdgeIt e(G); e!=INVALID; ++e) flow.set(e, 0);
-
- //Initialize the potential to zero
- for (typename Graph::NodeIt n(G); n!=INVALID; ++n) potential.set(n, 0);
-
-
- //We need a residual graph
- ResGW res_graph(G, capacity, flow);
-
-
- ModLengthMap mod_length(res_graph, length, potential);
-
- Dijkstra<ResGW, ModLengthMap> dijkstra(res_graph, mod_length);
-
- int i;
- for (i=0; i<k; ++i){
- dijkstra.run(s);
- if (!dijkstra.reached(t)){
- //There are no flow of value k from s to t
- break;
- };
-
//We have to change the potential
- for(typename ResGW::NodeIt n(res_graph); n!=INVALID; ++n)
+ for(typename ResGW::NodeIt n(res_graph); n!=INVALID; ++n)
potential[n] += dijkstra.distMap()[n];
-
-
+
//Augmenting on the sortest path
Node n=t;
ResGraphEdge e;
@@ -186,19 +163,51 @@
total_length -= length[e];
}
-
+ return true;
}
-
-
- return i;
+ }
+
+ /*! \brief Runs the algorithm.
+
+ Runs the algorithm.
+ Returns k if there is a flow of value at least k from s to t.
+ Otherwise it returns the maximum value of a flow from s to t.
+
+ \param k The value of the flow we are looking for.
+
+ \todo May be it does make sense to be able to start with a nonzero
+ feasible primal-dual solution pair as well.
+
+ \todo If the actual flow value is bigger than k, then everything is
+ cleared and the algorithm starts from zero flow. Is it a good approach?
+ */
+ int run(int k) {
+ if (flowValue()>k) reset();
+ while (flowValue()<k && augment()) { }
+ return flowValue();
}
+ /*! \brief The class is reset to zero flow and potential.
+ The class is reset to zero flow and potential.
+ */
+ void reset() {
+ total_length=0;
+ for (typename Graph::EdgeIt e(g); e!=INVALID; ++e) flow.set(e, 0);
+ for (typename Graph::NodeIt n(g); n!=INVALID; ++n) potential.set(n, 0);
+ }
+ /*! Returns the value of the actual flow.
+ */
+ int flowValue() const {
+ int i=0;
+ for (typename Graph::OutEdgeIt e(g, s); e!=INVALID; ++e) i+=flow[e];
+ for (typename Graph::InEdgeIt e(g, s); e!=INVALID; ++e) i-=flow[e];
+ return i;
+ }
- /// Gives back the total weight of the found flow.
+ /// Total weight of the found flow.
- ///This function gives back the total weight of the found flow.
- ///Assumes that \c run() has been run and nothing changed since then.
+ /// This function gives back the total weight of the found flow.
Length totalLength(){
return total_length;
}
@@ -206,29 +215,27 @@
///Returns a const reference to the EdgeMap \c flow.
///Returns a const reference to the EdgeMap \c flow.
- ///\pre \ref run() must
- ///be called before using this function.
const EdgeIntMap &getFlow() const { return flow;}
- ///Returns a const reference to the NodeMap \c potential (the dual solution).
+ /*! \brief Returns a const reference to the NodeMap \c potential (the dual solution).
- ///Returns a const reference to the NodeMap \c potential (the dual solution).
- /// \pre \ref run() must be called before using this function.
+ Returns a const reference to the NodeMap \c potential (the dual solution).
+ */
const PotentialMap &getPotential() const { return potential;}
- /// Checking the complementary slackness optimality criteria
+ /*! \brief Checking the complementary slackness optimality criteria.
- ///This function checks, whether the given solution is optimal
- ///If executed after the call of \c run() then it should return with true.
- ///This function only checks optimality, doesn't bother with feasibility.
- ///It is meant for testing purposes.
- ///
+ This function checks, whether the given flow and potential
+ satisfiy the complementary slackness cnditions (i.e. these are optimal).
+ This function only checks optimality, doesn't bother with feasibility.
+ For testing purpose.
+ */
bool checkComplementarySlackness(){
Length mod_pot;
Length fl_e;
- for(typename Graph::EdgeIt e(G); e!=INVALID; ++e) {
+ for(typename Graph::EdgeIt e(g); e!=INVALID; ++e) {
//C^{\Pi}_{i,j}
- mod_pot = length[e]-potential[G.head(e)]+potential[G.tail(e)];
+ mod_pot = length[e]-potential[g.head(e)]+potential[g.tail(e)];
fl_e = flow[e];
if (0<fl_e && fl_e<capacity[e]) {
/// \todo better comparison is needed for real types, moreover,
@@ -246,7 +253,6 @@
return true;
}
-
}; //class MinCostFlow
///@}
Modified: hugo/trunk/src/lemon/suurballe.h
==============================================================================
--- hugo/trunk/src/lemon/suurballe.h (original)
+++ hugo/trunk/src/lemon/suurballe.h Fri Oct 8 15:07:51 2004
@@ -68,14 +68,16 @@
typedef ConstMap<Edge,int> ConstMap;
- //Input
const Graph& G;
+ Node s;
+ Node t;
+
//Auxiliary variables
//This is the capacity map for the mincostflow problem
ConstMap const1map;
//This MinCostFlow instance will actually solve the problem
- MinCostFlow<Graph, LengthMap, ConstMap> mincost_flow;
+ MinCostFlow<Graph, LengthMap, ConstMap> min_cost_flow;
//Container to store found paths
std::vector< std::vector<Edge> > paths;
@@ -83,39 +85,40 @@
public :
- /// The constructor of the class.
+ /*! \brief The constructor of the class.
- ///\param _G The directed graph the algorithm runs on.
- ///\param _length The length (weight or cost) of the edges.
- Suurballe(Graph& _G, LengthMap& _length) : G(_G),
- const1map(1), mincost_flow(_G, _length, const1map){}
+ \param _G The directed graph the algorithm runs on.
+ \param _length The length (weight or cost) of the edges.
+ \param _s Source node.
+ \param _t Target node.
+ */
+ Suurballe(Graph& _G, LengthMap& _length, Node _s, Node _t) :
+ G(_G), s(_s), t(_t), const1map(1),
+ min_cost_flow(_G, _length, const1map, _s, _t) { }
///Runs the algorithm.
///Runs the algorithm.
///Returns k if there are at least k edge-disjoint paths from s to t.
- ///Otherwise it returns the number of found edge-disjoint paths from s to t.
+ ///Otherwise it returns the number of edge-disjoint paths found
+ ///from s to t.
///
- ///\param s The source node.
- ///\param t The target node.
///\param k How many paths are we looking for?
///
- int run(Node s, Node t, int k) {
-
- int i = mincost_flow.run(s,t,k);
-
+ int run(int k) {
+ int i = min_cost_flow.run(k);
//Let's find the paths
//We put the paths into stl vectors (as an inner representation).
//In the meantime we lose the information stored in 'reversed'.
//We suppose the lengths to be positive now.
- //We don't want to change the flow of mincost_flow, so we make a copy
+ //We don't want to change the flow of min_cost_flow, so we make a copy
//The name here suggests that the flow has only 0/1 values.
EdgeIntMap reversed(G);
for(typename Graph::EdgeIt e(G); e!=INVALID; ++e)
- reversed[e] = mincost_flow.getFlow()[e];
+ reversed[e] = min_cost_flow.getFlow()[e];
paths.clear();
//total_length=0;
@@ -143,39 +146,32 @@
}
- ///Returns the total length of the paths
+ ///Returns the total length of the paths.
///This function gives back the total length of the found paths.
- ///\pre \ref run() must
- ///be called before using this function.
Length totalLength(){
- return mincost_flow.totalLength();
+ return min_cost_flow.totalLength();
}
///Returns the found flow.
///This function returns a const reference to the EdgeMap \c flow.
- ///\pre \ref run() must
- ///be called before using this function.
- const EdgeIntMap &getFlow() const { return mincost_flow.flow;}
+ const EdgeIntMap &getFlow() const { return min_cost_flow.flow;}
/// Returns the optimal dual solution
///This function returns a const reference to the NodeMap
///\c potential (the dual solution).
- /// \pre \ref run() must be called before using this function.
- const EdgeIntMap &getPotential() const { return mincost_flow.potential;}
+ const EdgeIntMap &getPotential() const { return min_cost_flow.potential;}
///Checks whether the complementary slackness holds.
///This function checks, whether the given solution is optimal.
- ///It should return true after calling \ref run()
///Currently this function only checks optimality,
///doesn't bother with feasibility
///It is meant for testing purposes.
- ///
bool checkComplementarySlackness(){
- return mincost_flow.checkComplementarySlackness();
+ return min_cost_flow.checkComplementarySlackness();
}
///Read the found paths.
Modified: hugo/trunk/src/test/min_cost_flow_test.cc
==============================================================================
--- hugo/trunk/src/test/min_cost_flow_test.cc (original)
+++ hugo/trunk/src/test/min_cost_flow_test.cc Fri Oct 8 15:07:51 2004
@@ -21,11 +21,9 @@
//#include <path.h>
//#include <maps.h>
-using namespace std;
using namespace lemon;
-
bool passed = true;
/*
void check(bool rc, char *msg="") {
@@ -41,11 +39,11 @@
int main()
{
+ typedef ListGraph Graph;
+ typedef Graph::Node Node;
+ typedef Graph::Edge Edge;
- typedef ListGraph::Node Node;
- typedef ListGraph::Edge Edge;
-
- ListGraph graph;
+ Graph graph;
//Ahuja könyv példája
@@ -67,7 +65,7 @@
Edge v5_t=graph.addEdge(v5, t);
- ListGraph::EdgeMap<int> length(graph);
+ Graph::EdgeMap<int> length(graph);
length.set(s_v1, 6);
length.set(v1_v2, 4);
@@ -78,7 +76,7 @@
length.set(v4_t, 8);
length.set(v5_t, 8);
- ListGraph::EdgeMap<int> capacity(graph);
+ Graph::EdgeMap<int> capacity(graph);
capacity.set(s_v1, 2);
capacity.set(v1_v2, 2);
@@ -92,31 +90,36 @@
// ConstMap<Edge, int> const1map(1);
std::cout << "Mincostflows algorithm test..." << std::endl;
- MinCostFlow< ListGraph, ListGraph::EdgeMap<int>, ListGraph::EdgeMap<int> >
- surb_test(graph, length, capacity);
+ MinCostFlow< Graph, Graph::EdgeMap<int>, Graph::EdgeMap<int> >
+ surb_test(graph, length, capacity, s, t);
int k=1;
- check( surb_test.run(s,t,k) == 1 && surb_test.totalLength() == 19,"One path, total length should be 19");
+ surb_test.augment();
+ check( surb_test.flowValue() == 1 && surb_test.totalLength() == 19,"One path, total length should be 19");
+
+ check( surb_test.run(k) == 1 && surb_test.totalLength() == 19,"One path, total length should be 19");
check(surb_test.checkComplementarySlackness(), "Is the primal-dual solution pair really optimal?");
k=2;
- check( surb_test.run(s,t,k) == 2 && surb_test.totalLength() == 41,"Two paths, total length should be 41");
+ check( surb_test.run(k) == 2 && surb_test.totalLength() == 41,"Two paths, total length should be 41");
check(surb_test.checkComplementarySlackness(), "Is the primal-dual solution pair really optimal?");
-
+ surb_test.augment();
+ surb_test.augment();
+ surb_test.augment();
k=4;
- check( surb_test.run(s,t,k) == 3 && surb_test.totalLength() == 64,"Three paths, total length should be 64");
+ check( surb_test.run(k) == 3 && surb_test.totalLength() == 64,"Three paths, total length should be 64");
check(surb_test.checkComplementarySlackness(), "Is the primal-dual solution pair really optimal?");
- cout << (passed ? "All tests passed." : "Some of the tests failed!!!")
- << endl;
+ std::cout << (passed ? "All tests passed." : "Some of the tests failed!!!")
+ << std::endl;
return passed ? 0 : 1;
Modified: hugo/trunk/src/test/suurballe_test.cc
==============================================================================
--- hugo/trunk/src/test/suurballe_test.cc (original)
+++ hugo/trunk/src/test/suurballe_test.cc Fri Oct 8 15:07:51 2004
@@ -20,21 +20,19 @@
//#include <path.h>
#include "test_tools.h"
-using namespace std;
using namespace lemon;
-
bool passed = true;
int main()
{
+ typedef ListGraph Graph;
+ typedef Graph::Node Node;
+ typedef Graph::Edge Edge;
- typedef ListGraph::Node Node;
- typedef ListGraph::Edge Edge;
-
- ListGraph graph;
+ Graph graph;
//Ahuja könyv példája
@@ -56,7 +54,7 @@
Edge v5_t=graph.addEdge(v5, t);
- ListGraph::EdgeMap<int> length(graph);
+ Graph::EdgeMap<int> length(graph);
length.set(s_v1, 6);
length.set(v1_v2, 4);
@@ -71,29 +69,29 @@
int k=3;
- Suurballe< ListGraph, ListGraph::EdgeMap<int> >
- surb_test(graph, length);
+ Suurballe< Graph, Graph::EdgeMap<int> >
+ surb_test(graph, length, s, t);
- check( surb_test.run(s,t,k) == 2 && surb_test.totalLength() == 46,
+ check( surb_test.run(k) == 2 && surb_test.totalLength() == 46,
"Two paths, total length should be 46");
check( surb_test.checkComplementarySlackness(),
"Complementary slackness conditions are not met.");
- // typedef DirPath<ListGraph> DPath;
+ // typedef DirPath<Graph> DPath;
// DPath P(graph);
/*
surb_test.getPath(P,0);
check(P.length() == 4, "First path should contain 4 edges.");
- cout<<P.length()<<endl;
+ std::cout<<P.length()<<std::endl;
surb_test.getPath(P,1);
check(P.length() == 3, "Second path: 3 edges.");
- cout<<P.length()<<endl;
+ std::cout<<P.length()<<std::endl;
*/
k=1;
- check( surb_test.run(s,t,k) == 1 && surb_test.totalLength() == 19,
+ check( surb_test.run(k) == 1 && surb_test.totalLength() == 19,
"One path, total length should be 19");
check( surb_test.checkComplementarySlackness(),
@@ -102,8 +100,8 @@
// surb_test.getPath(P,0);
// check(P.length() == 4, "First path should contain 4 edges.");
- cout << (passed ? "All tests passed." : "Some of the tests failed!!!")
- << endl;
+ std::cout << (passed ? "All tests passed." : "Some of the tests failed!!!")
+ << std::endl;
return passed ? 0 : 1;
More information about the Lemon-commits
mailing list