An experimental LPSolverWrapper class which uses glpk. For a short
demo, max flow problems are solved with it. This demo does not
demonstrates, but the main aims of this class are row and column
generation capabilities, i.e. to be a core for easily
implementable branch-and-cut a column generetion algorithms.
7 /// \brief Bfs and dfs iterators.
9 /// This file contains bfs and dfs iterator classes.
11 // /// \author Marton Makai
17 #include <hugo/invalid.h>
21 /// Bfs searches for the nodes wich are not marked in
23 /// Reached have to be a read-write bool node-map.
25 template <typename Graph, /*typename OutEdgeIt,*/
26 typename ReachedMap/*=typename Graph::NodeMap<bool>*/ >
29 typedef typename Graph::Node Node;
30 typedef typename Graph::OutEdgeIt OutEdgeIt;
32 std::queue<Node> bfs_queue;
34 bool b_node_newly_reached;
35 OutEdgeIt actual_edge;
38 /// In that constructor \c _reached have to be a reference
39 /// for a bool bode-map. The algorithm will search for the
40 /// initially \c false nodes
42 BfsIterator(const Graph& _graph, ReachedMap& _reached) :
43 graph(&_graph), reached(_reached),
44 own_reached_map(false) { }
45 /// The same as above, but the map storing the reached nodes
46 /// is constructed dynamically to everywhere false.
48 BfsIterator(const Graph& _graph) :
49 graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))),
50 own_reached_map(true) { }
51 /// The map storing the reached nodes have to be destroyed if
52 /// it was constructed dynamically
53 ~BfsIterator() { if (own_reached_map) delete &reached; }
54 /// This method markes \c s reached.
55 /// If the queue is empty, then \c s is pushed in the bfs queue
56 /// and the first out-edge is processed.
57 /// If the queue is not empty, then \c s is simply pushed.
58 void pushAndSetReached(Node s) {
60 if (bfs_queue.empty()) {
62 graph->first(actual_edge, s);
63 if (graph->valid(actual_edge)) {
64 Node w=graph->bNode(actual_edge);
68 b_node_newly_reached=true;
70 b_node_newly_reached=false;
77 /// As \c BfsIterator<Graph, ReachedMap> works as an edge-iterator,
78 /// its \c operator++() iterates on the edges in a bfs order.
79 BfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>&
81 if (graph->valid(actual_edge)) {
82 graph->next(actual_edge);
83 if (graph->valid(actual_edge)) {
84 Node w=graph->bNode(actual_edge);
88 b_node_newly_reached=true;
90 b_node_newly_reached=false;
95 if (!bfs_queue.empty()) {
96 graph->first(actual_edge, bfs_queue.front());
97 if (graph->valid(actual_edge)) {
98 Node w=graph->bNode(actual_edge);
101 reached.set(w, true);
102 b_node_newly_reached=true;
104 b_node_newly_reached=false;
111 /// Returns true iff the algorithm is finished.
112 bool finished() const { return bfs_queue.empty(); }
113 /// The conversion operator makes for converting the bfs-iterator
114 /// to an \c out-edge-iterator.
115 ///\bug Edge have to be in HUGO 0.2
116 operator OutEdgeIt() const { return actual_edge; }
117 /// Returns if b-node has been reached just now.
118 bool isBNodeNewlyReached() const { return b_node_newly_reached; }
119 /// Returns if a-node is examined.
120 bool isANodeExamined() const { return !(graph->valid(actual_edge)); }
121 /// Returns a-node of the actual edge, so does if the edge is invalid.
122 Node aNode() const { return bfs_queue.front(); }
123 /// \pre The actual edge have to be valid.
124 Node bNode() const { return graph->bNode(actual_edge); }
127 const ReachedMap& getReachedMap() const { return reached; }
130 const std::queue<Node>& getBfsQueue() const { return bfs_queue; }
133 /// Bfs searches for the nodes wich are not marked in
135 /// Reached have to work as a read-write bool Node-map,
136 /// Pred is a write edge node-map and
137 /// Dist is a read-write node-map of integral value, have to be.
139 template <typename Graph,
140 typename ReachedMap=typename Graph::template NodeMap<bool>,
142 =typename Graph::template NodeMap<typename Graph::Edge>,
143 typename DistMap=typename Graph::template NodeMap<int> >
144 class Bfs : public BfsIterator<Graph, ReachedMap> {
145 typedef BfsIterator<Graph, ReachedMap> Parent;
147 typedef typename Parent::Node Node;
151 /// The algorithm will search in a bfs order for
152 /// the nodes which are \c false initially.
153 /// The constructor makes no initial changes on the maps.
154 Bfs<Graph, ReachedMap, PredMap, DistMap>(const Graph& _graph, ReachedMap& _reached, PredMap& _pred, DistMap& _dist) :
155 BfsIterator<Graph, ReachedMap>(_graph, _reached),
156 pred(_pred), dist(_dist) { }
157 /// \c s is marked to be reached and pushed in the bfs queue.
158 /// If the queue is empty, then the first out-edge is processed.
159 /// If \c s was not marked previously, then
160 /// in addition its pred is set to be \c INVALID, and dist to \c 0.
161 /// if \c s was marked previuosly, then it is simply pushed.
163 if (this->reached[s]) {
164 Parent::pushAndSetReached(s);
166 Parent::pushAndSetReached(s);
167 pred.set(s, INVALID);
171 /// A bfs is processed from \c s.
174 while (!this->finished()) this->operator++();
176 /// Beside the bfs iteration, \c pred and \dist are saved in a
177 /// newly reached node.
178 Bfs<Graph, ReachedMap, PredMap, DistMap>& operator++() {
179 Parent::operator++();
180 if (this->graph->valid(this->actual_edge) && this->b_node_newly_reached)
182 pred.set(this->bNode(), this->actual_edge);
183 dist.set(this->bNode(), dist[this->aNode()]);
189 const PredMap& getPredMap() const { return pred; }
192 const DistMap& getDistMap() const { return dist; }
195 /// Dfs searches for the nodes wich are not marked in
197 /// Reached have to be a read-write bool Node-map.
199 template <typename Graph, /*typename OutEdgeIt,*/
200 typename ReachedMap/*=typename Graph::NodeMap<bool>*/ >
203 typedef typename Graph::Node Node;
204 typedef typename Graph::OutEdgeIt OutEdgeIt;
206 std::stack<OutEdgeIt> dfs_stack;
207 bool b_node_newly_reached;
208 OutEdgeIt actual_edge;
211 bool own_reached_map;
213 /// In that constructor \c _reached have to be a reference
214 /// for a bool node-map. The algorithm will search in a dfs order for
215 /// the nodes which are \c false initially
216 DfsIterator(const Graph& _graph, ReachedMap& _reached) :
217 graph(&_graph), reached(_reached),
218 own_reached_map(false) { }
219 /// The same as above, but the map of reached nodes is
220 /// constructed dynamically
221 /// to everywhere false.
222 DfsIterator(const Graph& _graph) :
223 graph(&_graph), reached(*(new ReachedMap(*graph /*, false*/))),
224 own_reached_map(true) { }
225 ~DfsIterator() { if (own_reached_map) delete &reached; }
226 /// This method markes s reached and first out-edge is processed.
227 void pushAndSetReached(Node s) {
229 reached.set(s, true);
234 /// As \c DfsIterator<Graph, ReachedMap> works as an edge-iterator,
235 /// its \c operator++() iterates on the edges in a dfs order.
236 DfsIterator<Graph, /*OutEdgeIt,*/ ReachedMap>&
238 actual_edge=dfs_stack.top();
239 //actual_node=G.aNode(actual_edge);
240 if (graph->valid(actual_edge)/*.valid()*/) {
241 Node w=graph->bNode(actual_edge);
247 reached.set(w, true);
248 b_node_newly_reached=true;
250 actual_node=graph->aNode(actual_edge);
251 graph->next(dfs_stack.top());
252 b_node_newly_reached=false;
255 //actual_node=G.aNode(dfs_stack.top());
260 /// Returns true iff the algorithm is finished.
261 bool finished() const { return dfs_stack.empty(); }
262 /// The conversion operator makes for converting the bfs-iterator
263 /// to an \c out-edge-iterator.
264 ///\bug Edge have to be in HUGO 0.2
265 operator OutEdgeIt() const { return actual_edge; }
266 /// Returns if b-node has been reached just now.
267 bool isBNodeNewlyReached() const { return b_node_newly_reached; }
268 /// Returns if a-node is examined.
269 bool isANodeExamined() const { return !(graph->valid(actual_edge)); }
270 /// Returns a-node of the actual edge, so does if the edge is invalid.
271 Node aNode() const { return actual_node; /*FIXME*/}
272 /// Returns b-node of the actual edge.
273 /// \pre The actual edge have to be valid.
274 Node bNode() const { return graph->bNode(actual_edge); }
277 const ReachedMap& getReachedMap() const { return reached; }
280 const std::stack<OutEdgeIt>& getDfsStack() const { return dfs_stack; }
283 /// Dfs searches for the nodes wich are not marked in
285 /// Reached is a read-write bool node-map,
286 /// Pred is a write node-map, have to be.
288 template <typename Graph,
289 typename ReachedMap=typename Graph::template NodeMap<bool>,
291 =typename Graph::template NodeMap<typename Graph::Edge> >
292 class Dfs : public DfsIterator<Graph, ReachedMap> {
293 typedef DfsIterator<Graph, ReachedMap> Parent;
295 typedef typename Parent::Node Node;
298 /// The algorithm will search in a dfs order for
299 /// the nodes which are \c false initially.
300 /// The constructor makes no initial changes on the maps.
301 Dfs<Graph, ReachedMap, PredMap>(const Graph& _graph, ReachedMap& _reached, PredMap& _pred) : DfsIterator<Graph, ReachedMap>(_graph, _reached), pred(_pred) { }
302 /// \c s is marked to be reached and pushed in the bfs queue.
303 /// If the queue is empty, then the first out-edge is processed.
304 /// If \c s was not marked previously, then
305 /// in addition its pred is set to be \c INVALID.
306 /// if \c s was marked previuosly, then it is simply pushed.
308 if (this->reached[s]) {
309 Parent::pushAndSetReached(s);
311 Parent::pushAndSetReached(s);
312 pred.set(s, INVALID);
315 /// A bfs is processed from \c s.
318 while (!this->finished()) this->operator++();
320 /// Beside the dfs iteration, \c pred is saved in a
321 /// newly reached node.
322 Dfs<Graph, ReachedMap, PredMap>& operator++() {
323 Parent::operator++();
324 if (this->graph->valid(this->actual_edge) && this->b_node_newly_reached)
326 pred.set(this->bNode(), this->actual_edge);
332 const PredMap& getPredMap() const { return pred; }
338 #endif //HUGO_BFS_DFS_H