Major improvements in NetworkSimplex.
Main changes:
- Use -potenital[] instead of potential[] to conform to the usual
terminology.
- Use function parameter instead of #define commands to select pivot rule.
- Use much faster implementation for the candidate list pivot rule.
It is about 5-20 times faster now.
- Add a new pivot rule called "Limited Search" that is a modified
version of "Block Search". It is about 25 percent faster on rather
sparse graphs.
- By default "Limited Search" is used for sparse graphs and
"Block Search" is used otherwise. This combined method is the most
efficient on every input class.
- Change the name of private members to start with "_".
- Change the name of function parameters not to start with "_".
- Remove unnecessary documentation for private members.
- Many doc improvements.
3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
23 #include <lemon/bits/invalid.h>
24 #include <lemon/bits/utility.h>
26 #include <lemon/bits/base_extender.h>
27 #include <lemon/bits/graph_extender.h>
29 #include <lemon/dim2.h>
33 ///\brief GridUGraph class.
37 class GridUGraphBase {
41 typedef GridUGraphBase UGraph;
52 void construct(int w, int h) {
53 _height = h; _width = w;
54 _nodeNum = h * w; _edgeNum = 2 * _nodeNum - w - h;
55 _edgeLimit = _nodeNum - w;
58 Edge _down(Node n) const {
59 if (n.id < _nodeNum - _width) {
66 Edge _up(Node n) const {
68 return Edge(n.id - _width);
74 Edge _right(Node n) const {
75 if (n.id % _width < _width - 1) {
76 return _edgeLimit + n.id % _width + (n.id / _width) * (_width - 1);
82 Edge _left(Node n) const {
83 if (n.id % _width > 0) {
84 return _edgeLimit + n.id % _width + (n.id / _width) * (_width - 1) - 1;
92 class IndexError : public RuntimeError {
94 virtual const char* what() const throw() {
95 return "lemon::GridUGraph::IndexError";
100 Node operator()(int i, int j) const {
101 LEMON_ASSERT(0 <= i && i < width() && 0 <= j &&
102 j < height(), IndexError());
103 return Node(i + j * _width);
106 int row(Node n) const {
107 return n.id / _width;
110 int col(Node n) const {
111 return n.id % _width;
122 typedef True NodeNumTag;
123 typedef True EdgeNumTag;
125 int nodeNum() const { return _nodeNum; }
126 int edgeNum() const { return _edgeNum; }
128 int maxNodeId() const { return nodeNum() - 1; }
129 int maxEdgeId() const { return edgeNum() - 1; }
131 Node source(Edge e) const {
132 if (e.id < _edgeLimit) {
135 return (e.id - _edgeLimit) % (_width - 1) +
136 (e.id - _edgeLimit) / (_width - 1) * _width;
140 Node target(Edge e) const {
141 if (e.id < _edgeLimit) {
142 return e.id + _width;
144 return (e.id - _edgeLimit) % (_width - 1) +
145 (e.id - _edgeLimit) / (_width - 1) * _width + 1;
149 static int id(Node v) { return v.id; }
150 static int id(Edge e) { return e.id; }
152 static Node nodeFromId(int id) { return Node(id);}
154 static Edge edgeFromId(int id) { return Edge(id);}
156 typedef True FindEdgeTag;
158 Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
159 if (prev != INVALID) return INVALID;
160 if (v.id - u.id == _width) return Edge(u.id);
161 if (v.id - u.id == 1 && u.id % _width < _width - 1) {
162 return Edge(u.id / _width * (_width - 1) +
163 u.id % _width + _edgeLimit);
170 friend class GridUGraphBase;
174 Node(int _id) { id = _id;}
177 Node (Invalid) { id = -1; }
178 bool operator==(const Node node) const {return id == node.id;}
179 bool operator!=(const Node node) const {return id != node.id;}
180 bool operator<(const Node node) const {return id < node.id;}
186 friend class GridUGraphBase;
191 Edge(int _id) : id(_id) {}
195 Edge (Invalid) { id = -1; }
196 bool operator==(const Edge edge) const {return id == edge.id;}
197 bool operator!=(const Edge edge) const {return id != edge.id;}
198 bool operator<(const Edge edge) const {return id < edge.id;}
201 void first(Node& node) const {
202 node.id = nodeNum() - 1;
205 static void next(Node& node) {
209 void first(Edge& edge) const {
210 edge.id = edgeNum() - 1;
213 static void next(Edge& edge) {
217 void firstOut(Edge& edge, const Node& node) const {
218 if (node.id < _nodeNum - _width) {
220 } else if (node.id % _width < _width - 1) {
221 edge.id = _edgeLimit + node.id % _width +
222 (node.id / _width) * (_width - 1);
228 void nextOut(Edge& edge) const {
229 if (edge.id >= _edgeLimit) {
231 } else if (edge.id % _width < _width - 1) {
232 edge.id = _edgeLimit + edge.id % _width +
233 (edge.id / _width) * (_width - 1);
239 void firstIn(Edge& edge, const Node& node) const {
240 if (node.id >= _width) {
241 edge.id = node.id - _width;
242 } else if (node.id % _width > 0) {
243 edge.id = _edgeLimit + node.id % _width +
244 (node.id / _width) * (_width - 1) - 1;
250 void nextIn(Edge& edge) const {
251 if (edge.id >= _edgeLimit) {
253 } else if (edge.id % _width > 0) {
254 edge.id = _edgeLimit + edge.id % _width +
255 (edge.id / _width + 1) * (_width - 1) - 1;
263 int _nodeNum, _edgeNum;
268 typedef UGraphExtender<UndirGraphExtender<GridUGraphBase> >
269 ExtendedGridUGraphBase;
273 /// \brief Grid graph class
275 /// This class implements a special graph type. The nodes of the
276 /// graph can be indiced by two integer \c (i,j) value where \c i
277 /// is in the \c [0,width) range and j is in the [0, height) range.
278 /// Two nodes are connected in the graph if the indices differ only
279 /// on one position and only one is the difference.
281 /// \image html grid_ugraph.png
282 /// \image latex grid_ugraph.eps "Grid graph" width=\textwidth
284 /// The graph can be indiced in the following way:
286 /// GridUGraph graph(w, h);
287 /// GridUGraph::NodeMap<int> val(graph);
288 /// for (int i = 0; i < graph.width(); ++i) {
289 /// for (int j = 0; j < graph.height(); ++j) {
290 /// val[graph(i, j)] = i + j;
295 /// The graph type is fully conform to the \ref concepts::UGraph
296 /// "Undirected Graph" concept, and it also has an
297 ///important extra feature that
298 ///its maps are real \ref concepts::ReferenceMap "reference map"s.
301 /// \author Balazs Dezso
302 class GridUGraph : public ExtendedGridUGraphBase {
305 typedef ExtendedGridUGraphBase Parent;
307 /// \brief Map to get the indices of the nodes as dim2::Point<int>.
309 /// Map to get the indices of the nodes as dim2::Point<int>.
312 /// \brief The key type of the map
313 typedef GridUGraph::Node Key;
314 /// \brief The value type of the map
315 typedef dim2::Point<int> Value;
317 /// \brief Constructor
320 IndexMap(const GridUGraph& _graph) : graph(_graph) {}
322 /// \brief The subscript operator
324 /// The subscript operator.
325 Value operator[](Key key) const {
326 return dim2::Point<int>(graph.row(key), graph.col(key));
330 const GridUGraph& graph;
333 /// \brief Map to get the row of the nodes.
335 /// Map to get the row of the nodes.
338 /// \brief The key type of the map
339 typedef GridUGraph::Node Key;
340 /// \brief The value type of the map
343 /// \brief Constructor
346 RowMap(const GridUGraph& _graph) : graph(_graph) {}
348 /// \brief The subscript operator
350 /// The subscript operator.
351 Value operator[](Key key) const {
352 return graph.row(key);
356 const GridUGraph& graph;
359 /// \brief Map to get the column of the nodes.
361 /// Map to get the column of the nodes.
364 /// \brief The key type of the map
365 typedef GridUGraph::Node Key;
366 /// \brief The value type of the map
369 /// \brief Constructor
372 ColMap(const GridUGraph& _graph) : graph(_graph) {}
374 /// \brief The subscript operator
376 /// The subscript operator.
377 Value operator[](Key key) const {
378 return graph.col(key);
382 const GridUGraph& graph;
385 /// \brief Constructor
388 GridUGraph(int n, int m) { construct(n, m); }
390 /// \brief Resize the graph
392 void resize(int n, int m) {
393 Parent::notifier(Edge()).clear();
394 Parent::notifier(UEdge()).clear();
395 Parent::notifier(Node()).clear();
397 Parent::notifier(Node()).build();
398 Parent::notifier(UEdge()).build();
399 Parent::notifier(Edge()).build();
402 /// \brief The node on the given position.
404 /// Gives back the node on the given position.
405 Node operator()(int i, int j) const {
406 return Parent::operator()(i, j);
409 /// \brief Gives back the row index of the node.
411 /// Gives back the row index of the node.
412 int row(Node n) const {
413 return Parent::row(n);
416 /// \brief Gives back the coloumn index of the node.
418 /// Gives back the coloumn index of the node.
419 int col(Node n) const {
420 return Parent::col(n);
423 /// \brief Gives back the width of the graph.
425 /// Gives back the width of the graph.
427 return Parent::width();
430 /// \brief Gives back the height of the graph.
432 /// Gives back the height of the graph.
434 return Parent::height();
437 /// \brief Gives back the edge goes down from the node.
439 /// Gives back the edge goes down from the node. If there is not
440 /// outgoing edge then it gives back INVALID.
441 Edge down(Node n) const {
443 return ue != INVALID ? direct(ue, true) : INVALID;
446 /// \brief Gives back the edge goes up from the node.
448 /// Gives back the edge goes up from the node. If there is not
449 /// outgoing edge then it gives back INVALID.
450 Edge up(Node n) const {
452 return ue != INVALID ? direct(ue, false) : INVALID;
455 /// \brief Gives back the edge goes right from the node.
457 /// Gives back the edge goes right from the node. If there is not
458 /// outgoing edge then it gives back INVALID.
459 Edge right(Node n) const {
460 UEdge ue = _right(n);
461 return ue != INVALID ? direct(ue, true) : INVALID;
464 /// \brief Gives back the edge goes left from the node.
466 /// Gives back the edge goes left from the node. If there is not
467 /// outgoing edge then it gives back INVALID.
468 Edge left(Node n) const {
470 return ue != INVALID ? direct(ue, false) : INVALID;
475 /// \brief Index map of the grid graph
477 /// Just returns an IndexMap for the grid graph.
478 inline GridUGraph::IndexMap indexMap(const GridUGraph& graph) {
479 return GridUGraph::IndexMap(graph);
482 /// \brief Row map of the grid graph
484 /// Just returns a RowMap for the grid graph.
485 inline GridUGraph::RowMap rowMap(const GridUGraph& graph) {
486 return GridUGraph::RowMap(graph);
489 /// \brief Column map of the grid graph
491 /// Just returns a ColMap for the grid graph.
492 inline GridUGraph::ColMap colMap(const GridUGraph& graph) {
493 return GridUGraph::ColMap(graph);