lemon/network_simplex.h
changeset 2444 06f3702bf18d
parent 2440 c9218405595b
child 2457 8c791ee69a45
equal deleted inserted replaced
0:7ef6c97ad0ab 1:76addb67b01f
    28 #include <limits>
    28 #include <limits>
    29 #include <lemon/smart_graph.h>
    29 #include <lemon/smart_graph.h>
    30 #include <lemon/graph_utils.h>
    30 #include <lemon/graph_utils.h>
    31 
    31 
    32 /// \brief The pivot rule used in the algorithm.
    32 /// \brief The pivot rule used in the algorithm.
    33 #define EDGE_BLOCK_PIVOT
       
    34 //#define FIRST_ELIGIBLE_PIVOT
    33 //#define FIRST_ELIGIBLE_PIVOT
    35 //#define BEST_ELIGIBLE_PIVOT
    34 //#define BEST_ELIGIBLE_PIVOT
       
    35 #define EDGE_BLOCK_PIVOT
    36 //#define CANDIDATE_LIST_PIVOT
    36 //#define CANDIDATE_LIST_PIVOT
    37 //#define SORTED_LIST_PIVOT
    37 //#define SORTED_LIST_PIVOT
       
    38 
       
    39 //#define _DEBUG_ITER_
       
    40 
    38 
    41 
    39 /// \brief State constant for edges at their lower bounds.
    42 /// \brief State constant for edges at their lower bounds.
    40 #define LOWER	1
    43 #define LOWER	1
    41 /// \brief State constant for edges in the spanning tree.
    44 /// \brief State constant for edges in the spanning tree.
    42 #define TREE	0
    45 #define TREE	0
    43 /// \brief State constant for edges at their upper bounds.
    46 /// \brief State constant for edges at their upper bounds.
    44 #define UPPER	-1
    47 #define UPPER	-1
    45 
    48 
    46 #ifdef EDGE_BLOCK_PIVOT
    49 #ifdef EDGE_BLOCK_PIVOT
    47   /// \brief Number of blocks for the "Edge Block" pivot rule.
    50   /// \brief Number of blocks for the "Edge Block" pivot rule.
    48   #define BLOCK_NUM	  100
    51   #define BLOCK_NUM		100
    49   /// \brief Lower bound for the number of edges to use "Edge Block"
    52   /// \brief Lower bound for the size of blocks.
    50   // pivot rule instead of "First Eligible" pivot rule.
    53   #define MIN_BLOCK_SIZE	10
    51   #define MIN_BOUND	  1000
       
    52 #endif
    54 #endif
    53 
    55 
    54 #ifdef CANDIDATE_LIST_PIVOT
    56 #ifdef CANDIDATE_LIST_PIVOT
    55   #include <list>
    57   #include <list>
    56   /// \brief The maximum length of the edge list for the
    58   /// \brief The maximum length of the edge list for the
    57   /// "Candidate List" pivot rule.
    59   /// "Candidate List" pivot rule.
    58   #define LIST_LENGTH	  100
    60   #define LIST_LENGTH		100
    59   /// \brief The maximum number of minor iterations between two major
    61   /// \brief The maximum number of minor iterations between two major
    60   /// itarations.
    62   /// itarations.
    61   #define MINOR_LIMIT	  50
    63   #define MINOR_LIMIT		10
    62 #endif
    64 #endif
    63 
    65 
    64 #ifdef SORTED_LIST_PIVOT
    66 #ifdef SORTED_LIST_PIVOT
    65   #include <deque>
    67   #include <deque>
    66   #include <algorithm>
    68   #include <algorithm>
    67   /// \brief The maximum length of the edge list for the
    69   /// \brief The maximum length of the edge list for the
    68   /// "Sorted List" pivot rule.
    70   /// "Sorted List" pivot rule.
    69   #define LIST_LENGTH	  500
    71   #define LIST_LENGTH		500
    70   #define LOWER_DIV	  4
    72   #define LOWER_DIV		3
    71 #endif
    73 #endif
    72 
       
    73 //#define _DEBUG_ITER_
       
    74 
    74 
    75 namespace lemon {
    75 namespace lemon {
    76 
    76 
    77   /// \addtogroup min_cost_flow
    77   /// \addtogroup min_cost_flow
    78   /// @{
    78   /// @{
   511       thread[last] = root;
   511       thread[last] = root;
   512 
   512 
   513 #ifdef EDGE_BLOCK_PIVOT
   513 #ifdef EDGE_BLOCK_PIVOT
   514       // Initializing block_size for the edge block pivot rule
   514       // Initializing block_size for the edge block pivot rule
   515       int edge_num = countEdges(graph);
   515       int edge_num = countEdges(graph);
   516       block_size = edge_num > MIN_BOUND ? edge_num / BLOCK_NUM + 1 : 1;
   516       block_size = edge_num >= BLOCK_NUM * MIN_BLOCK_SIZE ? 
       
   517 		   edge_num / BLOCK_NUM : MIN_BLOCK_SIZE;
   517 #endif
   518 #endif
   518 #ifdef CANDIDATE_LIST_PIVOT
   519 #ifdef CANDIDATE_LIST_PIVOT
   519       minor_count = 0;
   520       minor_count = 0;
   520 #endif
   521 #endif
   521 
   522 
   561 
   562 
   562 #ifdef EDGE_BLOCK_PIVOT
   563 #ifdef EDGE_BLOCK_PIVOT
   563     /// \brief Finds entering edge according to the "Edge Block"
   564     /// \brief Finds entering edge according to the "Edge Block"
   564     /// pivot rule.
   565     /// pivot rule.
   565     bool findEnteringEdge(EdgeIt &next_edge) {
   566     bool findEnteringEdge(EdgeIt &next_edge) {
   566       if (block_size == 1) {
   567       // Performing edge block selection
   567 	// Performing first eligible selection
   568       Cost curr, min = 0;
   568 	for (EdgeIt e = next_edge; e != INVALID; ++e) {
   569       EdgeIt min_edge(graph);
   569 	  if (state[e] * red_cost[e] < 0) {
   570       int cnt = 0;
   570 	    in_edge = e;
   571       for (EdgeIt e = next_edge; e != INVALID; ++e) {
   571 	    next_edge = ++e;
   572 	if ((curr = state[e] * red_cost[e]) < min) {
   572 	    return true;
   573 	  min = curr;
   573 	  }
   574 	  min_edge = e;
   574 	}
   575 	}
       
   576 	if (++cnt == block_size) {
       
   577 	  if (min < 0) break;
       
   578 	  cnt = 0;
       
   579 	}
       
   580       }
       
   581       if (!(min < 0)) {
   575 	for (EdgeIt e(graph); e != next_edge; ++e) {
   582 	for (EdgeIt e(graph); e != next_edge; ++e) {
   576 	  if (state[e] * red_cost[e] < 0) {
       
   577 	    in_edge = e;
       
   578 	    next_edge = ++e;
       
   579 	    return true;
       
   580 	  }
       
   581 	}
       
   582 	return false;
       
   583       } else {
       
   584 	// Performing edge block selection
       
   585 	Cost curr, min = 0;
       
   586 	EdgeIt min_edge(graph);
       
   587 	int cnt = 0;
       
   588 	for (EdgeIt e = next_edge; e != INVALID; ++e) {
       
   589 	  if ((curr = state[e] * red_cost[e]) < min) {
   583 	  if ((curr = state[e] * red_cost[e]) < min) {
   590 	    min = curr;
   584 	    min = curr;
   591 	    min_edge = e;
   585 	    min_edge = e;
   592 	  }
   586 	  }
   593 	  if (++cnt == block_size) {
   587 	  if (++cnt == block_size) {
   594 	    if (min < 0) break;
   588 	    if (min < 0) break;
   595 	    cnt = 0;
   589 	    cnt = 0;
   596 	  }
   590 	  }
   597 	}
   591 	}
   598 	if (!(min < 0)) {
   592       }
   599 	  for (EdgeIt e(graph); e != next_edge; ++e) {
   593       in_edge = min_edge;
   600 	    if ((curr = state[e] * red_cost[e]) < min) {
   594       if ((next_edge = ++min_edge) == INVALID)
   601 	      min = curr;
   595 	next_edge = EdgeIt(graph);
   602 	      min_edge = e;
   596       return min < 0;
   603 	    }
       
   604 	    if (++cnt == block_size) {
       
   605 	      if (min < 0) break;
       
   606 	      cnt = 0;
       
   607 	    }
       
   608 	  }
       
   609 	}
       
   610 	in_edge = min_edge;
       
   611 	if ((next_edge = ++min_edge) == INVALID)
       
   612 	  next_edge = EdgeIt(graph);
       
   613 	return min < 0;
       
   614       }
       
   615     }
   597     }
   616 #endif
   598 #endif
   617 
   599 
   618 #ifdef CANDIDATE_LIST_PIVOT
   600 #ifdef CANDIDATE_LIST_PIVOT
   619     /// \brief Functor class for removing non-eligible edges from the
   601     /// \brief Functor class for removing non-eligible edges from the
   694       Cost curr, min = 0;
   676       Cost curr, min = 0;
   695       for (EdgeIt e(graph); e != INVALID; ++e) {
   677       for (EdgeIt e(graph); e != INVALID; ++e) {
   696 	if ((curr = state[e] * red_cost[e]) < min / LOWER_DIV) {
   678 	if ((curr = state[e] * red_cost[e]) < min / LOWER_DIV) {
   697 	  candidates.push_back(e);
   679 	  candidates.push_back(e);
   698 	  if (curr < min) min = curr;
   680 	  if (curr < min) min = curr;
   699 	  if (candidates.size() >= LIST_LENGTH) break;
   681 	  if (candidates.size() == LIST_LENGTH) break;
   700 	}
   682 	}
   701       }
   683       }
   702       if (candidates.size() == 0) return false;
   684       if (candidates.size() == 0) return false;
   703       sort(candidates.begin(), candidates.end(), sort_func);
   685       sort(candidates.begin(), candidates.end(), sort_func);
       
   686       in_edge = candidates.front();
       
   687       candidates.pop_front();
   704       return true;
   688       return true;
   705     }
   689     }
   706 #endif
   690 #endif
   707 
   691 
   708     /// \brief Finds the join node.
   692     /// \brief Finds the join node.
   907 	++iter_num;
   891 	++iter_num;
   908 #endif
   892 #endif
   909       }
   893       }
   910 
   894 
   911 #ifdef _DEBUG_ITER_
   895 #ifdef _DEBUG_ITER_
   912       t_iter.stop();
       
   913       std::cout << "Network Simplex algorithm finished. " << iter_num
   896       std::cout << "Network Simplex algorithm finished. " << iter_num
   914 		<< " pivot iterations performed.";
   897 		<< " pivot iterations performed." << std::endl;
   915 #endif
   898 #endif
   916 
   899 
   917       // Checking if the flow amount equals zero on all the
   900       // Checking if the flow amount equals zero on all the
   918       // artificial edges
   901       // artificial edges
   919       for (InEdgeIt e(graph, root); e != INVALID; ++e)
   902       for (InEdgeIt e(graph, root); e != INVALID; ++e)