# HG changeset patch
# User alpar
# Date 1171986813 0
# Node ID e30a0fdad0d7b3085d82d1290afb6f754513bc23
# Parent b59a17034ffaa8383f4a4ce986ec8ffd3a174aea
A preflow based general network circulation algorithm and a simple demo
diff -r b59a17034ffa -r e30a0fdad0d7 demo/Makefile.am
--- a/demo/Makefile.am Tue Feb 20 13:01:22 2007 +0000
+++ b/demo/Makefile.am Tue Feb 20 15:53:33 2007 +0000
@@ -1,10 +1,23 @@
EXTRA_DIST += \
demo/Makefile \
- demo/sub_graph_adaptor_demo.dim
-
+ demo/sub_graph_adaptor_demo.dim \
+ demo/circulation-input.lgf \
+ demo/coloring.lgf \
+ demo/dir_components.lgf \
+ demo/disjoint_paths_demo.lgf \
+ demo/graph_orientation.lgf \
+ demo/partitions.lgf \
+ demo/route.lgf \
+ demo/sample.lgf \
+ demo/simann_maxcut_demo.lgf \
+ demo/strongly_connected_orientation.lgf \
+ demo/sub_gad_input.lgf \
+ demo/u_components.lgf
+
if WANT_DEMO
noinst_PROGRAMS += \
+ demo/circulation_demo \
demo/csp_demo \
demo/dim_to_dot \
demo/dijkstra_demo \
@@ -39,6 +52,8 @@
demo_csp_demo_SOURCES = demo/csp_demo.cc
+demo_circulation_demo_SOURCES = demo/circulation_demo.cc
+
demo_dim_to_dot_SOURCES = demo/dim_to_dot.cc
demo_dijkstra_demo_SOURCES = demo/dijkstra_demo.cc
diff -r b59a17034ffa -r e30a0fdad0d7 demo/circulation-input.lgf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/demo/circulation-input.lgf Tue Feb 20 15:53:33 2007 +0000
@@ -0,0 +1,165 @@
+@nodeset
+coordinates_x coordinates_y delta label
+-396.638 -311.798 0 0
+154.409 -214.714 -13 1
+-378.119 -135.808 0 2
+-138.182 -58.0452 0 3
+55 -76.1018 0 4
+-167.302 169.88 0 5
+71.6876 38.7452 0 6
+-328.784 257.777 0 7
+354.242 67.9628 13 8
+147 266 0 9
+@edgeset
+ label lo_cap up_cap
+0 1 0 0 20
+0 2 1 0 0
+1 1 2 0 3
+1 2 3 0 8
+1 3 4 0 8
+2 5 5 0 5
+3 2 6 0 5
+3 5 7 0 5
+3 6 8 0 5
+4 3 9 0 3
+5 7 10 0 3
+5 6 11 0 10
+5 8 12 0 10
+6 8 13 0 8
+8 9 14 0 20
+8 1 15 0 5
+9 5 16 0 5
+@gui
+
+ -
+ 0
+
+ -121.114-263.256
+
+
+ -
+ 1
+
+ -387.378-223.803
+
+
+ -
+ 2
+
+ 253.622-301.284
+
+
+ -
+ 3
+
+ -111.855-175.261
+
+
+ -
+ 4
+
+ 8.1134-136.379
+
+
+ -
+ 5
+
+ -272.7117.0361
+
+
+ -
+ 6
+
+ -258.151-96.9267
+
+
+ -
+ 7
+
+ -152.74255.9176
+
+
+ -
+ 8
+
+ -33.2474-9.64996
+
+
+ -
+ 9
+
+ -41.5912-67.0735
+
+
+ -
+ 10
+
+ -248.043213.829
+
+
+ -
+ 11
+
+ -47.8072104.313
+
+
+ -
+ 12
+
+ 93.4701118.922
+
+
+ -
+ 13
+
+ 212.96553.354
+
+
+ -
+ 14
+
+ 250.621166.981
+
+
+ -
+ 15
+
+ 254.326-73.3755
+
+
+ -
+ 16
+
+ -10.1511217.94
+
+
+
+
+ -
+ 0
+
+
+ -
+ 1
+ delta
+
+ -
+ 2
+ label
+
+
+
+ -
+ 0
+ up_cap
+
+ -
+ 1
+
+
+ -
+ 2
+ up_cap
+
+
+@end
diff -r b59a17034ffa -r e30a0fdad0d7 demo/circulation_demo.cc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/demo/circulation_demo.cc Tue Feb 20 15:53:33 2007 +0000
@@ -0,0 +1,108 @@
+/* -*- C++ -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2003-2006
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+///\ingroup demos
+///\file
+///\brief Demonstrating the usage of LEMON's General Flow algorithm
+///
+/// This demo program reads a general network circulation problem from the
+/// file 'circulation-input.lgf', runs the preflow based algorithm for
+/// finding a feasible solution and writes the output
+/// to 'circulation-input.lgf'
+///
+/// \include circulation_demo.cc
+
+#include
+
+#include
+#include
+#include
+#include
+
+using namespace lemon;
+
+
+int main (int, char*[])
+{
+
+ typedef ListGraph Graph;
+ typedef Graph::Node Node;
+ typedef Graph::NodeIt NodeIt;
+ typedef Graph::Edge Edge;
+ typedef Graph::EdgeIt EdgeIt;
+ typedef Graph::EdgeMap EdgeMap;
+ typedef Graph::NodeMap NodeMap;
+ typedef Graph::NodeMap DNodeMap;
+
+ Graph g;
+ EdgeMap lo(g);
+ EdgeMap up(g);
+ EdgeMap x(g);
+ NodeMap delta(g);
+ NodeMap nid(g);
+ EdgeMap eid(g);
+ DNodeMap cx(g);
+ DNodeMap cy(g);
+
+ GraphReader("circulation-input.lgf", g).
+ readEdgeMap("lo_cap", lo).
+ readEdgeMap("up_cap", up).
+ readNodeMap("delta", delta).
+ readEdgeMap("label", eid).
+ readNodeMap("label", nid).
+ readNodeMap("coordinates_x", cx).
+ readNodeMap("coordinates_y", cy).
+ run();
+
+ Circulation gen(g,lo,up,delta,x);
+ int ret=gen.run();
+ if(ret==-1)
+ {
+ std::cout << "\nA feasible flow has been found.\n";
+ if(!gen.checkX(x)) std::cerr << "Oops!!!\n";
+ GraphWriter("circulation-output.lgf", g).
+ writeEdgeMap("lo_cap", lo).
+ writeEdgeMap("up_cap", up).
+ writeEdgeMap("flow", x).
+ writeNodeMap("delta", delta).
+ writeEdgeMap("label", eid).
+ writeNodeMap("label", nid).
+ writeNodeMap("coordinates_x", cx).
+ writeNodeMap("coordinates_y", cy).
+ run();
+ }
+ else {
+ std::cout << "\nThere is no such a flow\n";
+ Graph::NodeMap bar(g);
+ gen.barrier(bar,ret);
+ if(!gen.checkBarrier(bar)) std::cerr << "Dual Oops!!!\n";
+
+ GraphWriter("circulation-output.lgf", g).
+ writeEdgeMap("lo_cap", lo).
+ writeEdgeMap("up_cap", up).
+ writeNodeMap("barrier", bar).
+ writeNodeMap("delta", delta).
+ writeEdgeMap("label", eid).
+ writeNodeMap("label", nid).
+ writeNodeMap("coordinates_x", cx).
+ writeNodeMap("coordinates_y", cy).
+ run();
+ }
+ std::cout << "The output is written to file 'circulation-output.lgf'\n\n";
+
+}
diff -r b59a17034ffa -r e30a0fdad0d7 lemon/Makefile.am
--- a/lemon/Makefile.am Tue Feb 20 13:01:22 2007 +0000
+++ b/lemon/Makefile.am Tue Feb 20 15:53:33 2007 +0000
@@ -33,6 +33,7 @@
endif
lemon_HEADERS += \
+ lemon/circulation.h \
lemon/bellman_ford.h \
lemon/bfs.h \
lemon/bin_heap.h \
diff -r b59a17034ffa -r e30a0fdad0d7 lemon/circulation.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lemon/circulation.h Tue Feb 20 15:53:33 2007 +0000
@@ -0,0 +1,299 @@
+/* -*- C++ -*-
+ * lemon/preflow_matching.h - Part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_CIRCULATION_H
+#define LEMON_CIRCULATION_H
+
+#include
+#include
+#include
+#include
+#include
+
+///\ingroup flowalgs
+///\file
+///\brief Push-prelabel algorithm for finding a feasible circulation.
+///
+namespace lemon {
+
+ ///Preflow algorithm for the Network Circulation Problem.
+
+ ///\ingroup flowalgs
+ ///This class implements a preflow algorithm
+ ///for the Network Circulation Problem.
+ ///The exact formulation of this problem is the following.
+ /// \f[\sum_{e\in\rho(v)}x(e)-\sum_{e\in\delta(v)}x(e)\leq delta(v)\quad \forall v\in V \f]
+ /// \f[ lo(e)\leq x(e) \leq up(e) \quad \forall e\in E \f]
+ ///
+ template,
+ class LCapMap=typename Graph::template EdgeMap,
+ class UCapMap=LCapMap,
+ class DeltaMap=typename Graph::template NodeMap
+ >
+ class Circulation {
+ typedef typename Graph::Node Node;
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::EdgeIt EdgeIt;
+ typedef typename Graph::InEdgeIt InEdgeIt;
+ typedef typename Graph::OutEdgeIt OutEdgeIt;
+
+
+ const Graph &_g;
+ int _node_num;
+
+ const LCapMap &_lo;
+ const UCapMap &_up;
+ const DeltaMap &_delta;
+ FlowMap &_x;
+ Tolerance _tol;
+ Elevator _levels;
+ typename Graph::template NodeMap _excess;
+
+ public:
+ ///\e
+ Circulation(const Graph &g,const LCapMap &lo,const UCapMap &up,
+ const DeltaMap &delta,FlowMap &x) :
+ _g(g),
+ _node_num(countNodes(g)),
+ _lo(lo),_up(up),_delta(delta),_x(x),
+ _levels(g,_node_num),
+ _excess(g)
+ {
+ }
+
+ private:
+
+ void addExcess(Node n,Value v)
+ {
+ if(_tol.positive(_excess[n]+=v))
+ {
+ if(!_levels.active(n)) _levels.activate(n);
+ }
+ else if(_levels.active(n)) _levels.deactivate(n);
+ }
+
+ void init()
+ {
+
+ _x=_lo;
+
+ for(NodeIt n(_g);n!=INVALID;++n) _excess[n]=-_delta[n];
+
+ for(EdgeIt e(_g);e!=INVALID;++e)
+ {
+ _excess[_g.target(e)]+=_x[e];
+ _excess[_g.source(e)]-=_x[e];
+ }
+
+ _levels.initStart();
+ for(NodeIt n(_g);n!=INVALID;++n)
+ _levels.initAddItem(n);
+ _levels.initFinish();
+ for(NodeIt n(_g);n!=INVALID;++n)
+ if(_tol.positive(_excess[n]))
+ _levels.activate(n);
+ }
+
+ public:
+ ///Check if \c x is a feasible circulation
+ template
+ bool checkX(FT &x) {
+ for(EdgeIt e(_g);e!=INVALID;++e)
+ if(x[e]<_lo[e]||x[e]>_up[e]) return false;
+ for(NodeIt n(_g);n!=INVALID;++n)
+ {
+ Value dif=_delta[n];
+ for(InEdgeIt e(_g,n);e!=INVALID;++e) dif-=x[e];
+ for(OutEdgeIt e(_g,n);e!=INVALID;++e) dif+=x[e];
+ if(_tol.negative(dif)) return false;
+ }
+ return true;
+ };
+ ///Check if the default \c x is a feasible circulation
+ bool checkX() { return checkX(_x); }
+
+ ///Chech if \c bar is a real barrier
+
+ ///Chech if \c bar is a real barrier
+ ///\sa barrier()
+ template
+ bool checkBarrier(GT &bar)
+ {
+ Value delta=0;
+ for(NodeIt n(_g);n!=INVALID;++n)
+ if(bar[n])
+ delta+=_delta[n];
+ for(EdgeIt e(_g);e!=INVALID;++e)
+ {
+ Node s=_g.source(e);
+ Node t=_g.target(e);
+ if(bar[s]&&!bar[t]) delta+=_up[e];
+ else if(bar[t]&&!bar[s]) delta-=_lo[e];
+ }
+ return _tol.negative(delta);
+ }
+ ///Chech whether or not the last execution provides a barrier
+
+ ///Chech whether or not the last execution provides a barrier
+ ///\sa barrier()
+ bool checkBarrier()
+ {
+ typename Graph:: template NodeMap bar(_g);
+ barrier(bar);
+ return checkBarrier(bar);
+ }
+ ///Run the algorithm
+
+ ///This function runs the algorithm.
+ ///\return This function returns -1 if it found a feasible circulation.
+ /// nonnegative values (including 0) mean that no feasible solution is
+ /// found. In this case the return value means an "empty level".
+ ///
+ ///\sa barrier()
+ int run()
+ {
+ init();
+
+#ifdef LEMON_CIRCULATION_DEBUG
+ for(NodeIt n(_g);n!=INVALID;++n)
+ std::cerr<< _levels[n] << ' ';
+ std::cerr << std::endl;
+#endif
+ Node act;
+ Node bact=INVALID;
+ Node last_activated=INVALID;
+ while((act=_levels.highestActive())!=INVALID) {
+ int actlevel=_levels[act];
+ int tlevel;
+ int mlevel=_node_num;
+ Value exc=_excess[act];
+ Value fc;
+
+#ifdef LEMON_CIRCULATION_DEBUG
+ for(NodeIt n(_g);n!=INVALID;++n)
+ std::cerr<< _levels[n] << ' ';
+ std::cerr << std::endl;
+ std::cerr << "Process node " << _g.id(act)
+ << " on level " << actlevel
+ << " with excess " << exc
+ << std::endl;
+#endif
+ for(OutEdgeIt e(_g,act);e!=INVALID; ++e)
+ if((fc=_up[e]-_x[e])>0)
+ if((tlevel=_levels[_g.target(e)])0)
+ if((tlevel=_levels[_g.source(e)])
+ void barrier(GT &bar,int empty_level=-1)
+ {
+ if(empty_level==-1)
+ for(empty_level=0;_levels.onLevel(empty_level);empty_level++) ;
+ for(NodeIt n(_g);n!=INVALID;++n)
+ bar[n] = _levels[n]>empty_level;
+ }
+
+ };
+
+}
+
+#endif