[Lemon-commits] [lemon_svn] athos: r50 - hugo/trunk/src/work/athos
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 20:37:02 CET 2006
Author: athos
Date: Tue Jan 27 17:23:51 2004
New Revision: 50
Added:
hugo/trunk/src/work/athos/
hugo/trunk/src/work/athos/makefile
hugo/trunk/src/work/athos/pf_demo.cc
hugo/trunk/src/work/athos/preflow_push.hh
Log:
preflow_push.hh: Preflow-push valtozat by athos
A tesztfile: pf_demo.cc
Kulon makefile is van.
Added: hugo/trunk/src/work/athos/makefile
==============================================================================
--- (empty file)
+++ hugo/trunk/src/work/athos/makefile Tue Jan 27 17:23:51 2004
@@ -0,0 +1,7 @@
+CXXFLAGS = -Wall -ansi -g
+CXX = g++-3.0
+
+pf_demo: pf_demo.cc ../marci_graph_traits.hh ../marci_list_graph.hh ../marci_property_vector.hh preflow_push.hh ../reverse_bfs.hh
+ $(CXX) $(CXXFLAGS) -I. -I.. pf_demo.cc -o pf_demo
+
+
Added: hugo/trunk/src/work/athos/pf_demo.cc
==============================================================================
--- (empty file)
+++ hugo/trunk/src/work/athos/pf_demo.cc Tue Jan 27 17:23:51 2004
@@ -0,0 +1,172 @@
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include "marci_list_graph.hh"
+#include "marci_graph_traits.hh"
+#include "marci_property_vector.hh"
+#include "preflow_push.hh"
+
+using namespace marci;
+
+
+int main (int, char*[])
+{
+ typedef graph_traits<list_graph>::node_iterator node_iterator;
+ typedef graph_traits<list_graph>::edge_iterator edge_iterator;
+ typedef graph_traits<list_graph>::each_node_iterator each_node_iterator;
+ typedef graph_traits<list_graph>::each_edge_iterator each_edge_iterator;
+ typedef graph_traits<list_graph>::out_edge_iterator out_edge_iterator;
+ typedef graph_traits<list_graph>::in_edge_iterator in_edge_iterator;
+ typedef graph_traits<list_graph>::sym_edge_iterator sym_edge_iterator;
+
+ list_graph flow_test;
+
+
+ //Ahuja könyv példája
+ node_iterator s=flow_test.add_node();
+ node_iterator v2=flow_test.add_node();
+ node_iterator v3=flow_test.add_node();
+ node_iterator v4=flow_test.add_node();
+ node_iterator v5=flow_test.add_node();
+ node_iterator t=flow_test.add_node();
+
+ node_property_vector<list_graph, std::string> node_name(flow_test);
+ node_name.put(s, "s");
+ node_name.put(v2, "v2");
+ node_name.put(v3, "v3");
+ node_name.put(v4, "v4");
+ node_name.put(v5, "v5");
+ node_name.put(t, "t");
+
+
+ edge_iterator s_v2=flow_test.add_edge(s, v2);
+ edge_iterator s_v3=flow_test.add_edge(s, v3);
+
+ edge_iterator v2_v4=flow_test.add_edge(v2, v4);
+ edge_iterator v2_v5=flow_test.add_edge(v2, v5);
+
+ edge_iterator v3_v5=flow_test.add_edge(v3, v5);
+
+ edge_iterator v4_t=flow_test.add_edge(v4, t);
+ edge_iterator v5_t=flow_test.add_edge(v5, t);
+
+ //Kis modositas
+ edge_iterator v2_s=flow_test.add_edge(v2, s);
+
+ edge_property_vector<list_graph, int> cap(flow_test);
+ cap.put(s_v2, 10);
+ cap.put(s_v3, 10);
+ cap.put(v2_v4, 5);
+ cap.put(v2_v5, 8);
+ cap.put(v3_v5, 5);
+ cap.put(v4_t, 8);
+ cap.put(v5_t, 8);
+
+ //Kis modositas
+ cap.put(v2_s, 100);
+
+ //Kis modositas
+ //edge_iterator t_s=flow_test.add_edge(t, s);
+ //cap.put(t_s, 20);
+
+
+ /*
+ //Marci példája
+ node_iterator s=flow_test.add_node();
+ node_iterator v1=flow_test.add_node();
+ node_iterator v2=flow_test.add_node();
+ node_iterator v3=flow_test.add_node();
+ node_iterator v4=flow_test.add_node();
+ node_iterator t=flow_test.add_node();
+
+ node_property_vector<list_graph, std::string> node_name(flow_test);
+ node_name.put(s, "s");
+ node_name.put(v1, "v1");
+ node_name.put(v2, "v2");
+ node_name.put(v3, "v3");
+ node_name.put(v4, "v4");
+ node_name.put(t, "t");
+
+ edge_iterator s_v1=flow_test.add_edge(s, v1);
+ edge_iterator s_v2=flow_test.add_edge(s, v2);
+ edge_iterator v1_v2=flow_test.add_edge(v1, v2);
+ edge_iterator v2_v1=flow_test.add_edge(v2, v1);
+ edge_iterator v1_v3=flow_test.add_edge(v1, v3);
+ edge_iterator v3_v2=flow_test.add_edge(v3, v2);
+ edge_iterator v2_v4=flow_test.add_edge(v2, v4);
+ edge_iterator v4_v3=flow_test.add_edge(v4, v3);
+ edge_iterator v3_t=flow_test.add_edge(v3, t);
+ edge_iterator v4_t=flow_test.add_edge(v4, t);
+
+ edge_property_vector<list_graph, int> cap(flow_test);
+ cap.put(s_v1, 16);
+ cap.put(s_v2, 13);
+ cap.put(v1_v2, 10);
+ cap.put(v2_v1, 4);
+ cap.put(v1_v3, 12);
+ cap.put(v3_v2, 9);
+ cap.put(v2_v4, 14);
+ cap.put(v4_v3, 7);
+ cap.put(v3_t, 20);
+ cap.put(v4_t, 4);
+ */
+ /*Egyszerû példa
+ node_iterator s=flow_test.add_node();
+ node_iterator v1=flow_test.add_node();
+ node_iterator v2=flow_test.add_node();
+ node_iterator t=flow_test.add_node();
+
+ node_property_vector<list_graph, std::string> node_name(flow_test);
+ node_name.put(s, "s");
+ node_name.put(v1, "v1");
+ node_name.put(v2, "v2");
+ node_name.put(t, "t");
+
+ edge_iterator s_v1=flow_test.add_edge(s, v1);
+ edge_iterator v1_v2=flow_test.add_edge(v1, v2);
+ edge_iterator v2_t=flow_test.add_edge(v2, t);
+
+ edge_property_vector<list_graph, int> cap(flow_test);
+
+ cap.put(s_v1, 16);
+ cap.put(v1_v2, 10);
+ cap.put(v2_t, 4);
+ */
+
+ std::cout << "preflow-push algorithm test..." << std::endl;
+ std::cout << "on directed graph graph" << std::endl; //<< flow_test;
+ std::cout << "names and capacity values" << std::endl;
+ for(each_node_iterator i=flow_test.first_node(); i.valid(); ++i) {
+ std::cout << node_name.get(i) << ": ";
+ std::cout << "out edges: ";
+ for(out_edge_iterator j=flow_test.first_out_edge(i); j.valid(); ++j)
+ std::cout << node_name.get(flow_test.tail(j)) << "-"<< cap.get(j) << "->" << node_name.get(flow_test.head(j)) << " ";
+ std::cout << "in edges: ";
+ for(in_edge_iterator j=flow_test.first_in_edge(i); j.valid(); ++j)
+ std::cout << node_name.get(flow_test.tail(j)) << "-"<< cap.get(j) << "->" << node_name.get(flow_test.head(j)) << " ";
+ std::cout << std::endl;
+ }
+
+
+ //for(each_node_iterator i=flow_test.first_node(); i.valid(); ++i) {
+ // std::cout << i << " ";
+ //}
+
+ preflow_push<list_graph, int> preflow_push_test(flow_test, s, t, cap);
+ cout << preflow_push_test.run()<<endl;
+
+ //cap.put(v5_t, 9);
+ //cout << preflow_push_test.run()<<endl;
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+
Added: hugo/trunk/src/work/athos/preflow_push.hh
==============================================================================
--- (empty file)
+++ hugo/trunk/src/work/athos/preflow_push.hh Tue Jan 27 17:23:51 2004
@@ -0,0 +1,411 @@
+#ifndef PREFLOW_PUSH_HH
+#define PREFLOW_PUSH_HH
+
+#include <algorithm>
+#include <list>
+#include <vector>
+//#include "pf_hiba.hh"
+//#include <marci_list_graph.hh>
+#include <marci_graph_traits.hh>
+#include "reverse_bfs.hh"
+
+using namespace std;
+
+namespace marci {
+
+ template <typename graph_type, typename T>
+ class preflow_push {
+
+ //Hasznos typedef-ek
+ typedef graph_traits<graph_type>::node_iterator node_iterator;
+ typedef graph_traits<graph_type>::edge_iterator edge_iterator;
+ typedef graph_traits<graph_type>::each_node_iterator each_node_iterator;
+ typedef graph_traits<graph_type>::each_edge_iterator each_edge_iterator;
+ typedef graph_traits<graph_type>::out_edge_iterator out_edge_iterator;
+ typedef graph_traits<graph_type>::in_edge_iterator in_edge_iterator;
+ typedef graph_traits<graph_type>::sym_edge_iterator sym_edge_iterator;
+
+ //---------------------------------------------
+ //Parameters of the algorithm
+ //---------------------------------------------
+ //Fully examine an active node until excess becomes 0
+ enum node_examination_t {examine_full, examine_to_relabel};
+ //No more implemented yet:, examine_only_one_edge};
+ node_examination_t node_examination;
+ //Which implementation to be used
+ enum implementation_t {impl_fifo, impl_highest_label};
+ //No more implemented yet:};
+ implementation_t implementation;
+ //---------------------------------------------
+ //Parameters of the algorithm
+ //---------------------------------------------
+
+ private:
+ //input
+ graph_type& G;
+ node_iterator s;
+ node_iterator t;
+ edge_property_vector<graph_type, T> &capacity;
+ //output
+ edge_property_vector<graph_type, T> preflow;
+ T maxflow_value;
+
+ //auxiliary variables for computation
+ int number_of_nodes;
+ node_property_vector<graph_type, int> level;
+ node_property_vector<graph_type, T> excess;
+
+ //Number of nodes on each level
+ vector<int> num_of_nodes_on_level;
+
+ //For the FIFO implementation
+ list<node_iterator> fifo_nodes;
+ //For 'highest label' implementation
+ int highest_active;
+ //int second_highest_active;
+ vector< list<node_iterator> > active_nodes;
+
+ public:
+
+ //Constructing the object using the graph, source, sink and capacity vector
+ preflow_push(
+ graph_type& _G,
+ node_iterator _s,
+ node_iterator _t,
+ edge_property_vector<graph_type, T>& _capacity)
+ : G(_G), s(_s), t(_t),
+ capacity(_capacity),
+ preflow(_G),
+ //Counting the number of nodes
+ number_of_nodes(number_of(G.first_node())),
+ level(_G),
+ excess(_G)//,
+ // Default constructor: active_nodes()
+ {
+ //Simplest parameter settings
+ node_examination = examine_full;//examine_to_relabel;//
+ //Which implementation to be usedexamine_full
+ implementation = impl_highest_label;//impl_fifo;
+
+ //
+ num_of_nodes_on_level.resize(2*number_of_nodes-1);
+ num_of_nodes_on_level.clear();
+
+ switch(implementation){
+ case impl_highest_label :{
+ active_nodes.resize(2*number_of_nodes-1);
+ active_nodes.clear();
+ break;
+ }
+ default:
+ break;
+ }
+
+ }
+
+ //Returns the value of a maximal flow
+ T run();
+
+ edge_property_vector<graph_type, T> getmaxflow(){
+ return preflow;
+ }
+
+
+ private:
+ //For testing purposes only
+ //Lists the node_properties
+ void write_property_vector(node_property_vector<graph_type, T> a,
+ char* prop_name="property"){
+ for(each_node_iterator i=G.first_node(); i.valid(); ++i) {
+ cout<<"Node id.: "<<G.id(i)<<", "<<prop_name<<" value: "<<a.get(i)<<endl;
+ }
+ cout<<endl;
+ }
+
+ //Modifies the excess of the node and makes sufficient changes
+ void modify_excess(const node_iterator& a ,T v){
+ T old_value=excess.get(a);
+ excess.put(a,old_value+v);
+ }
+
+ //This private procedure is supposed to modify the preflow on edge j
+ //by value v (which can be positive or negative as well)
+ //and maintain the excess on the head and tail
+ //Here we do not check whether this is possible or not
+ void modify_preflow(edge_iterator j, const T& v){
+
+ //Auxiliary variable
+ T old_value;
+
+ //Modifiyng the edge
+ old_value=preflow.get(j);
+ preflow.put(j,old_value+v);
+
+
+ //Modifiyng the head
+ modify_excess(G.head(j),v);
+
+ //Modifiyng the tail
+ modify_excess(G.tail(j),-v);
+
+ }
+
+ //Gives the active node to work with
+ //(depending on the implementation to be used)
+ node_iterator get_active_node(){
+ //cout<<highest_active<<endl;
+
+ switch(implementation) {
+ case impl_highest_label : {
+
+ //First need to find the highest label for which there"s an active node
+ while( highest_active>=0 && active_nodes[highest_active].empty() ){
+ --highest_active;
+ }
+
+ if( highest_active>=0) {
+ node_iterator a=active_nodes[highest_active].front();
+ active_nodes[highest_active].pop_front();
+ return a;
+ }
+ else {
+ return node_iterator();
+ }
+
+ break;
+
+ }
+ case impl_fifo : {
+
+ if( ! fifo_nodes.empty() ) {
+ node_iterator a=fifo_nodes.front();
+ fifo_nodes.pop_front();
+ return a;
+ }
+ else {
+ return node_iterator();
+ }
+ break;
+ }
+ }
+ //
+ return node_iterator();
+ }
+
+ //Puts node 'a' among the active nodes
+ void make_active(const node_iterator& a){
+ //s and t never become active
+ if (a!=s && a!= t){
+ switch(implementation){
+ case impl_highest_label :
+ active_nodes[level.get(a)].push_back(a);
+ break;
+ case impl_fifo :
+ fifo_nodes.push_back(a);
+ break;
+ }
+
+ }
+
+ //Update highest_active label
+ if (highest_active<level.get(a)){
+ highest_active=level.get(a);
+ }
+
+ }
+
+ //Changes the level of node a and make sufficent changes
+ void change_level_to(node_iterator a, int new_value){
+ int seged = level.get(a);
+ level.put(a,new_value);
+ --num_of_nodes_on_level[seged];
+ ++num_of_nodes_on_level[new_value];
+ }
+
+ //Collection of things useful (or necessary) to do before running
+ void preprocess(){
+
+ //---------------------------------------
+ //Initialize parameters
+ //---------------------------------------
+
+ //Setting starting preflow, level and excess values to zero
+ //This can be important, if the algorithm is run more then once
+ for(each_node_iterator i=G.first_node(); i.valid(); ++i) {
+ level.put(i,0);
+ excess.put(i,0);
+ for(out_edge_iterator j=G.first_out_edge(i); j.valid(); ++j)
+ preflow.put(j, 0);
+ }
+ num_of_nodes_on_level[0]=number_of_nodes;
+ highest_active=0;
+ //---------------------------------------
+ //Initialize parameters
+ //---------------------------------------
+
+
+ //------------------------------------
+ //This is the only part that uses BFS
+ //------------------------------------
+ //Setting starting level values using reverse bfs
+ reverse_bfs<graph_type> rev_bfs(G,t);
+ rev_bfs.run();
+ //write_property_vector(rev_bfs.dist,"rev_bfs");
+ for(each_node_iterator i=G.first_node(); i.valid(); ++i) {
+ change_level_to(i,rev_bfs.dist(i));
+ //level.put(i,rev_bfs.dist.get(i));
+ }
+ //------------------------------------
+ //This is the only part that uses BFS
+ //------------------------------------
+
+
+ //Starting level of s
+ change_level_to(s,number_of_nodes);
+ //level.put(s,number_of_nodes);
+
+
+ //we push as much preflow from s as possible to start with
+ for(out_edge_iterator j=G.first_out_edge(s); j.valid(); ++j){
+ modify_preflow(j,capacity.get(j) );
+ make_active(G.head(j));
+ int lev=level.get(G.head(j));
+ if(highest_active<lev){
+ highest_active=lev;
+ }
+ }
+ //cout<<highest_active<<endl;
+ }
+
+
+ //If the preflow is less than the capacity on the given edge
+ //then it is an edge in the residual graph
+ bool is_admissible_forward_edge(out_edge_iterator j, int& new_level){
+ if (capacity.get(j)>preflow.get(j)){
+ if(level.get(G.tail(j))==level.get(G.head(j))+1){
+ return true;
+ }
+ else{
+ if (level.get(G.head(j)) < new_level)
+ new_level=level.get(G.head(j));
+ }
+ }
+ return false;
+ }
+
+ //If the preflow is greater than 0 on the given edge
+ //then the edge reversd is an edge in the residual graph
+ bool is_admissible_backward_edge(in_edge_iterator j, int& new_level){
+ if (0<preflow.get(j)){
+ if(level.get(G.tail(j))==level.get(G.head(j))-1){
+ return true;
+ }
+ else{
+ if (level.get(G.tail(j)) < new_level)
+ new_level=level.get(G.tail(j));
+ }
+
+ }
+ return false;
+ }
+
+
+ }; //class preflow_push
+
+ template<typename graph_type, typename T>
+ T preflow_push<graph_type, T>::run() {
+
+ preprocess();
+
+ T e,v;
+ node_iterator a;
+ while (a=get_active_node(), a.valid()){
+ //cout<<G.id(a)<<endl;
+ //write_property_vector(excess,"excess");
+ //write_property_vector(level,"level");
+
+ //Initial value for the new level for the active node we are dealing with
+ int new_level=2*number_of_nodes;
+
+ bool go_to_next_node=false;
+ e = excess.get(a);
+ while (!go_to_next_node){
+
+ //Out edges from node a
+ {
+ out_edge_iterator j=G.first_out_edge(a);
+ while (j.valid() && e){
+
+ if (is_admissible_forward_edge(j,new_level)){
+ v=min(e,capacity.get(j) - preflow.get(j));
+ e -= v;
+ //New node might become active
+ if (excess.get(G.head(j))==0){
+ make_active(G.head(j));
+ }
+ modify_preflow(j,v);
+ }
+ ++j;
+ }
+ }
+ //In edges to node a
+ {
+ in_edge_iterator j=G.first_in_edge(a);
+ while (j.valid() && e){
+ if (is_admissible_backward_edge(j,new_level)){
+ v=min(e,preflow.get(j));
+ e -= v;
+ //New node might become active
+ if (excess.get(G.tail(j))==0){
+ make_active(G.tail(j));
+ }
+ modify_preflow(j,-v);
+ }
+ ++j;
+ }
+ }
+
+ //cout<<G.id(a)<<" "<<new_level<<endl;
+
+ if (0==e){
+ //Saturating push
+ go_to_next_node=true;
+ }
+ else{//If there is still excess in node a
+
+ //Level remains empty
+ if (num_of_nodes_on_level[level.get(a)]==1){
+ change_level_to(a,number_of_nodes);
+ //go_to_next_node=True;
+ }
+ else{
+ change_level_to(a,new_level+1);
+ //increase_level(a);
+ }
+
+
+
+
+ switch(node_examination){
+ case examine_to_relabel:
+ make_active(a);
+
+ go_to_next_node = true;
+ break;
+ default:
+ break;
+ }
+
+
+
+ }//if (0==e)
+ }
+ }
+ maxflow_value = excess.get(t);
+ return maxflow_value;
+ }//run
+
+
+}//namespace marci
+
+#endif //PREFLOW_PUSH_HH
More information about the Lemon-commits
mailing list