# 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