latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 2003, 2004, 2005, 2006 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * This file is part of the LTI-Computer Vision Library (LTI-Lib) 00006 * 00007 * The LTI-Lib is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public License (LGPL) 00009 * as published by the Free Software Foundation; either version 2.1 of 00010 * the License, or (at your option) any later version. 00011 * 00012 * The LTI-Lib is distributed in the hope that it will be 00013 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00014 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with the LTI-Lib; see the file LICENSE. If 00019 * not, write to the Free Software Foundation, Inc., 59 Temple Place - 00020 * Suite 330, Boston, MA 02111-1307, USA. 00021 */ 00022 00023 00024 /*-------------------------------------------------------------------- 00025 * project ....: LTI-Lib: Image Processing and Computer Vision Library 00026 * file .......: ltiAdjacencyGraph.h 00027 * authors ....: Pablo Alvarado 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 01.07.2003 00030 * revisions ..: $Id: ltiAdjacencyGraph.h,v 1.4 2007/01/10 02:26:16 alvarado Exp $ 00031 */ 00032 00033 #ifndef _LTI_ADJACENCY_GRAPH_H_ 00034 #define _LTI_ADJACENCY_GRAPH_H_ 00035 00036 #include "ltiMacroSymbols.h" 00037 00038 // only for compilers different than VC++ 6.0 available 00039 #ifdef _LTI_MSC_6 00040 00041 #pragma message("Insufficient C++ Template Support for lti::adjacencyGraph.") 00042 #pragma message("You need a newer compiler") 00043 00044 #else 00045 00046 #include "ltiObject.h" 00047 #include "ltiPriorityQueue.h" 00048 #include "ltiIoHandler.h" 00049 #include "ltiTypeInfo.h" 00050 #include <utility> // for std::pair 00051 00052 namespace lti { 00053 // ------------------------------------------------------------------------ 00054 // -- Edge basic classes -- 00055 // ------------------------------------------------------------------------ 00056 /** 00057 * Basic class for symmetric edges. You can specialize it for other types of 00058 * W than the standard ones (float,double,int,etc.) 00059 * 00060 * The template type W is the weight type, which is usually float or double, 00061 * but it can be a \e signed integer type too. 00062 */ 00063 template <class W> 00064 class symmetricEdgeTraits { 00065 public: 00066 /** 00067 * Constant used to mark a weight as invalid, unexistent, etc. 00068 */ 00069 static const W Invalid; 00070 00071 /** 00072 * Constant used to indicate if the adjacency edges are symmetric, 00073 * i.e. if weight(A,B) == weight(B,A). 00074 */ 00075 static const bool Symmetric; 00076 }; 00077 00078 /** 00079 * Basic class for asymmetric edges. You can specialize it for other types 00080 * of W than the standard ones (float,double,int,etc.) 00081 * 00082 * The template type W is the weight type, which is usually float or double, 00083 * but it can be a \e signed integer type too. 00084 */ 00085 template <class W> 00086 class asymmetricEdgeTraits { 00087 public: 00088 /** 00089 * Constant used to mark a weight as invalid, unexistent, etc. 00090 */ 00091 static const W Invalid; 00092 00093 /** 00094 * Constant used to indicate if the adjacency edges are symmetric, 00095 * i.e. if weight(A,B) == weight(B,A). 00096 */ 00097 static const bool Symmetric; 00098 }; 00099 00100 /** 00101 * Dummy weigh functor that returns the default weight type. 00102 * 00103 * The template parameters are: 00104 * - N node type 00105 * - W weight type (usually float or double) 00106 * - D edge data type 00107 */ 00108 template<class N,class W,class D> 00109 class adjacencyGraphVoidWeightFunction { 00110 public: 00111 /** 00112 * Method to compute the edge weight from the nodes and the data of 00113 * the edge 00114 */ 00115 inline W operator()(const N& first,const N& second,const D& data) const { 00116 return W(); 00117 } 00118 }; 00119 00120 // ------------------------------------------------------------------------ 00121 // -- adjacencyGraph -- 00122 // ------------------------------------------------------------------------ 00123 00124 /** 00125 * Adjacency Graph. 00126 * 00127 * An adjacency graph is a set of nodes and edges linking nodes. 00128 * Each node can contain some data (of type N). Each edge contains 00129 * also some data (of type D) and a weight (of type W). 00130 * 00131 * The adjacency property between two nodes is symmetrical, i.e. if 00132 * A is adjacent to B, then B is adjacent to A. However, the 00133 * weights and data of the edges from A-to-B or B-to-A not 00134 * necessarily have to be the same. This means that an adjacency 00135 * graph ensures always two edges between two nodes. Furthermore, a 00136 * node can never be adjacent to itself. 00137 * 00138 * Several methods are provided to merge nodes, insert other ones, insert 00139 * edges to connect nodes, and update the data of existing nodes or edges. 00140 * 00141 * This class can be used for example to represent an adjacency 00142 * graph of all regions in an image partition. The main data 00143 * structure is an affinity matrix: an usually sparse matrix 00144 * encoding the weight of the edges between the nodes of a graph. 00145 * 00146 * A second property of this class is that it is possible to access in 00147 * O(1) the edge of the graph with the smallest weight, even if you change 00148 * the weights of the edges during the use of the graph. 00149 * 00150 * Merging two nodes implies updating the weights of the edges in 00151 * the neighborhood of the new merged node, and the data object of 00152 * the node. For this reason this class needs a function object to compute 00153 * weight_type weight_function(const N&,const N&,const D&) const 00154 * which computes the weight of an edge as a function of the two linked 00155 * nodes and the information chunk stored in the edge itself. Of course, if 00156 * you want, you can avoid the mergeNodes() method and set the weight of 00157 * your graph by yourself. For this last case there is also a 00158 * topologicalMerge() method, that won't recompute anything, not even the 00159 * new node's data. 00160 * 00161 * <b>Template parameters</b> 00162 * 00163 * The required template types are the following: 00164 * - Type \b N specifies the node information type. Each node gets an own 00165 * identification id which is always an integer greater or equal zero. 00166 * With it, you can get or set the node's data (of type N). 00167 * The type name of N is node_type. 00168 * Following are the requirements for this type N: 00169 * - The operator=(const N&) to copy another node's data. 00170 * - The operator+= to merge the contents of two nodes. 00171 * - Overload of the global function lti::read(ioHandler&,N) 00172 * - Overload of the global function lti::write(ioHandler&,const N&) 00173 * - The weight type \b W with following interface 00174 * - operator= to copy other weights 00175 * - operator< that allows to define an order of weight_type elements 00176 * - operator== to compare equality 00177 * - operator!= to compare inequality 00178 * - Overload of the global function lti::read(ioHandler&,W&) 00179 * - Overload of the global function lti::write(ioHandler&,const W&) 00180 * This type is usually just \c float or \c double. Its name is 00181 * weight_type 00182 * - The edge data type \b D, which allows to describe additional 00183 * information about the edge. This information is used together with 00184 * the nodes information in the computation of the edge's weight. It 00185 * can describe for example the number of pixels in the border between 00186 * two regions. 00187 * This type (named edge_data_type) must support 00188 * - operator+=(const D& other) to combine the information of another edge. 00189 * - Overload of the global function lti::read(ioHandler&,D&) 00190 * - Overload of the global function lti::write(ioHandler&,const D&) 00191 * - The weight computation functor \b F is a small class with the 00192 * implementation of the operator() with following interface: 00193 * <code>W operator()(const N& first,const N& second,const D& data) const 00194 * </code> 00195 * The graph provides methods to get a const reference to the internal 00196 * instance of this functor or to set the internal instance. This allow 00197 * the computation of the weights to use some additional data. 00198 * If this functors must have a state, you should implement the assignment 00199 * operator=(), which will be used by the method setWeightFunctor() 00200 * This type has the name weight_functor 00201 * - Type E specifies the edge traits. It must provide following 00202 * interface: 00203 * - A static constant attribute E::Invalid of type W 00204 * which will represent an invalid edge. Since the weights 00205 * usually represent similarities or distances between nodes, they 00206 * are usually zero or possitive. Therefore, usual invalid flags 00207 * are negative constants. 00208 * - A static constant boolean attribute E::Symmetric, which is \c true 00209 * if the weights are symmetric, i.e. if weight(A,B) == weight(B,A), or 00210 * false otherwise. 00211 * The name of this type is edge_traits 00212 * 00213 * Please note that for all standard types (int, float, double, etc.) and 00214 * most all types in the \c lti namespace, the lti::read and lti::write 00215 * functions are already implemented. 00216 * 00217 * Since each node is identified by an unique id of type \c id_type, 00218 * the edges can be uniquely specified by a pair of id_type elements. 00219 * 00220 * <b>Symmetric edges</b> 00221 * 00222 * The use of a symmetric edge type (edge_traits::Symmetric == true) have 00223 * several implications: 00224 * - The computation of the weight occurs only once for the given 00225 * edge (a,b) and (b,a) will get the same value. 00226 * - Only the lower diagonal affinity matrix will be stored, to save some 00227 * space. 00228 * 00229 * <b>Iterators</b> 00230 * 00231 * You can use the iterators and edge_iterators to iterate on the 00232 * graph nodes or the node's outgoing edges respectively. 00233 * 00234 * The iterators visit only valid nodes, and allow you to access 00235 * the data of the node in the usual way (operator*), but you can also 00236 * get the id of the visited node with the method id(). 00237 * 00238 * The edge_iterators allow to access the data of an edge. Using 00239 * several methods of the graph class, you can also efficiently 00240 * access other information like the nodes linked by the pointed 00241 * edge, or the weight assigned to the edge. 00242 * 00243 * <b>IO</b> 00244 * 00245 * The adjacency graphs are mathObjects, and therefore are 00246 * serializable. If you want to edit the written files, you need to 00247 * know the syntax therein. 00248 * A file contains four data blocks: 00249 * -# The size of the data structure, which is always greater or equal 00250 * the number of nodes. 00251 * -# The nodes list containing for each node two elements: the 00252 * node's id and the data of the node. 00253 * -# A boolean indicating if the saved data belongs to a symmetric graph 00254 * or not. 00255 * -# The edge list containing for each edge three elements: the edge as 00256 * pair of node ids, the edge's weight, the edge's data 00257 * 00258 * You can find another more general weighted graph representation 00259 * in the class lti::weightedGraph. 00260 * 00261 * @see lti::weightedGragh 00262 * @see lti::adjacencyGraphEdge,lti::adjacencyGraphNode 00263 */ 00264 template< class N, // the node type 00265 class W = float, // the weight type 00266 class D = int, // the edge data type 00267 class F = adjacencyGraphVoidWeightFunction<N,W,D>, // functor 00268 class E = symmetricEdgeTraits<W> > 00269 class adjacencyGraph : public mathObject { 00270 public: 00271 /** 00272 * @name Type definitions 00273 */ 00274 //@{ 00275 /** 00276 * Type of the weight of the edges 00277 * 00278 * It provides with following interface 00279 * - operator= to copy other weights 00280 * - operator< 00281 * - operator== to compare equality 00282 * - operator!= to compare inequality 00283 */ 00284 typedef W weight_type; 00285 00286 /** 00287 * Type for the identification key of the nodes. 00288 * 00289 * All nodes in a graph have consecutive indices. When a node is removed, 00290 * its index can be (and will be) reused, so that you should take care not 00291 * to use "obsoleted" indices, because they could bring you to a new 00292 * node you didn't want. 00293 */ 00294 typedef int id_type; 00295 00296 /** 00297 * The edge type contains two adjacent nodes "first" and "second". The 00298 * edge direction is always from first to second. 00299 */ 00300 typedef std::pair<id_type,id_type> node_pair; 00301 00302 /** 00303 * Type of the nodes 00304 */ 00305 typedef N node_type; 00306 00307 /** 00308 * Type of the nodes 00309 */ 00310 typedef N value_type; 00311 00312 /** 00313 * Type for additional edge information (besides the weight). 00314 */ 00315 typedef D edge_data_type; 00316 00317 /** 00318 * Edge traits type containing the Symmetric and Invalid constants. 00319 */ 00320 typedef E edge_traits; 00321 00322 /** 00323 * Type of the functor implementing the weight computation functor 00324 */ 00325 typedef F weight_functor; 00326 00327 //@} 00328 00329 protected: 00330 00331 /** 00332 * @name Protected type definitions 00333 */ 00334 //@{ 00335 00336 /** 00337 * Priority queue type used. 00338 * 00339 * The priority queue keeps the edges sorted in increasing order by their 00340 * weights. 00341 * 00342 * The weight_type is used as key to sort the elements, 00343 * the point type is used to indicate the source and destination nodes 00344 * (y source, x destination), 00345 */ 00346 typedef priorityQueue<weight_type, node_pair> queue_type; 00347 00348 /** 00349 * Entry type used in the sparse matrix representing the affinity matrix 00350 * 00351 * The entry contains an attribute index to access the weight of the 00352 * corresponding edge in the priority queue and additional information of 00353 * type data_type. 00354 */ 00355 class entry_type { 00356 public: 00357 // --------------------------------------------------------------------- 00358 // The attributes 00359 // --------------------------------------------------------------------- 00360 00361 /** 00362 * Index of this entry in the priority queue. 00363 */ 00364 typename queue_type::index_type index; 00365 00366 /** 00367 * The data contains information relevant for the two regions to which 00368 * this entry belongs. It can be for example the length of the common 00369 * border, or the distance between the colors of the boundaries. 00370 */ 00371 edge_data_type data; 00372 00373 /** 00374 * Type to point to another entry 00375 */ 00376 typedef typename std::map<id_type, 00377 typename adjacencyGraph<N,W,D,F,E>::entry_type>::iterator entry_iterator; 00378 00379 /** 00380 * Iterator to the complement of this entry. 00381 * 00382 * If this entry belongs to the ids (i,j), then the complement has 00383 * the ids (j,i). 00384 * 00385 * The use of this iterator saves time computing the position of the 00386 * complement, which is in manipulation operations required (like 00387 * merge or remove). 00388 * 00389 * This is possible considering that map has the important 00390 * property that inserting a new element into a map does not 00391 * invalidate iterators that point to existing elements. Erasing 00392 * an element from a map also does not invalidate any iterators, 00393 * except, of course, for iterators that actually point to the 00394 * element that is being erased. 00395 */ 00396 entry_iterator complement; 00397 00398 // --------------------------------------------------------------------- 00399 // The methods 00400 // --------------------------------------------------------------------- 00401 00402 /** 00403 * default constructor 00404 */ 00405 entry_type() : index(),data(),complement() {} 00406 00407 /** 00408 * construct with given values 00409 */ 00410 entry_type(const typename queue_type::index_type& idx, 00411 const edge_data_type& dta = edge_data_type(), 00412 const entry_iterator& it = entry_iterator()) 00413 : index(idx),data(dta),complement(it) { 00414 } 00415 00416 /** 00417 * copy constructor 00418 */ 00419 entry_type(const entry_type& other) 00420 : index(other.index),data(other.data),complement(other.complement) { 00421 } 00422 00423 /** 00424 * change the index and return a reference to this entry 00425 */ 00426 entry_type& setIndex(const typename queue_type::index_type& idx) { 00427 index=idx; 00428 return *this; 00429 } 00430 00431 /** 00432 * copy operator 00433 */ 00434 entry_type& operator=(const entry_type& other) { 00435 index = other.index; 00436 data = other.data; 00437 complement = other.complement; 00438 00439 return *this; 00440 } 00441 }; 00442 00443 /** 00444 * The row of the affinity matrix contains for one specific node, 00445 * all nodes to which an edge exists. 00446 */ 00447 typedef std::map<id_type,entry_type> row_type; 00448 00449 /** 00450 * Type for (sparse) adjacency matrix of complex elements 00451 */ 00452 typedef std::vector< row_type > adjacency_type; 00453 00454 /** 00455 * Type used to contain the nodes' data and a flag indicating how many 00456 * outgoing edges can be found in the node. This number will be 00457 * negative if the node has been deleted. 00458 */ 00459 typedef std::vector< std::pair<int,node_type> > nodes_type; 00460 00461 //@} 00462 00463 public: 00464 00465 // ----------------------------------------------------------------------- 00466 // iterators 00467 // ----------------------------------------------------------------------- 00468 class const_iterator; 00469 00470 /** 00471 * The graph iterator iterates on all nodes. 00472 * 00473 * This class is similar to the usual iterators of the STL. 00474 * The iterator allows you to access the data the nodes, but 00475 * you can also get the node's id for other kind of processing. 00476 * 00477 * For example: 00478 * \code 00479 * adjacencyGraph::iterator it; 00480 * // ... do something with a graph an let the iterator point somewhere 00481 * // therein. 00482 * adjacencyGraphNode node = (*it); // get the pointed data. 00483 * adjacencyGraph::id_type = it.id(); // get the id of the pointed node. 00484 * \endcode 00485 */ 00486 class iterator { 00487 friend class adjacencyGraph<N,W,D,F,E>; 00488 # ifdef _LTI_MSC_6 00489 friend class const_iterator; 00490 # else 00491 friend class adjacencyGraph<N,W,D,F,E>::const_iterator; 00492 # endif 00493 00494 public: 00495 /** 00496 * Default constructor 00497 */ 00498 iterator() 00499 : pos(0), theVector(0) {}; 00500 00501 /** 00502 * copy constructor 00503 */ 00504 iterator(const iterator& other) 00505 : pos(other.pos),theVector(other.theVector) {}; 00506 00507 /** 00508 * advance to next item 00509 */ 00510 inline iterator& operator++() { // prefix 00511 do { 00512 ++pos; 00513 } while ((pos < static_cast<int>(theVector->size())) && 00514 ((*theVector)[pos].first < 0)) ; 00515 return *this; 00516 }; 00517 00518 /** 00519 * advance to next item 00520 */ 00521 inline iterator operator++(int) { // postfix 00522 iterator tmp(*this); 00523 do { 00524 ++pos; 00525 } while ((pos < static_cast<int>(theVector->size())) && 00526 ((*theVector)[pos].first < 0)); 00527 return tmp; 00528 }; 00529 00530 /** 00531 * recede to previous item // prefix 00532 */ 00533 inline iterator& operator--() { 00534 do { 00535 --pos; 00536 } while ((pos >= 0) && 00537 ((*theVector)[pos].first < 0)); 00538 return *this; 00539 }; 00540 00541 /** 00542 * recede to previous item 00543 */ 00544 inline iterator operator--(int) { 00545 iterator tmp(*this); 00546 do { 00547 --pos; 00548 } while ((pos >= 0) && ((*theVector)[pos].first < 0)); 00549 return tmp; 00550 }; // postfix 00551 00552 /** 00553 * compare if both pointed positions are the same 00554 */ 00555 inline bool operator==(const iterator& other) const { 00556 return (pos == other.pos); 00557 }; 00558 00559 /** 00560 * compare if both pointed positions are different 00561 */ 00562 inline bool operator!=(const iterator& other) const { 00563 return (pos != other.pos); 00564 }; 00565 00566 /** 00567 * get pointed data 00568 */ 00569 inline node_type& operator*() {return (*theVector)[pos].second;}; 00570 00571 /** 00572 * get pointed node's id. 00573 * 00574 * Please note that the id can become invalid if the pointed node 00575 * is removed. 00576 */ 00577 inline id_type id() const { 00578 return pos; 00579 } 00580 00581 /** 00582 * copy member 00583 */ 00584 inline iterator& operator=(const iterator& other) { 00585 pos = other.pos; 00586 theVector = other.theVector; 00587 return *this; 00588 }; 00589 00590 protected: 00591 /** 00592 * protected constructor (for internal use only) 00593 */ 00594 explicit iterator(const int startPos,nodes_type* vct) 00595 : pos(startPos), theVector(vct) {}; 00596 00597 /** 00598 * for internal use only!!! 00599 */ 00600 const int& getPos() const {return pos;}; 00601 00602 /** 00603 * for internal use only!!! 00604 */ 00605 const nodes_type* getVector() const {return theVector;}; 00606 00607 private: 00608 /** 00609 * actual vector index 00610 */ 00611 int pos; 00612 00613 /** 00614 * pointer to the actual vector 00615 */ 00616 nodes_type* theVector; 00617 }; 00618 00619 /** 00620 * The graph const_iterator iterates on all nodes in a read-only fashion. 00621 * 00622 * This class is similar to the usual iterators of the STL. 00623 * The const_iterator also allows you to access the id of the nodes. 00624 * See the class iterator for more information. 00625 * 00626 */ 00627 class const_iterator { 00628 friend class adjacencyGraph<N,W,D,F,E>; 00629 public: 00630 /** 00631 * Default constructor 00632 */ 00633 const_iterator() 00634 : pos(0), theVector(0) {}; 00635 00636 /** 00637 * copy constructor 00638 */ 00639 const_iterator(const const_iterator& other) 00640 : pos(other.pos),theVector(other.theVector) {}; 00641 00642 /** 00643 * copy constructor 00644 */ 00645 const_iterator(const iterator& other) {(*this)=other;}; 00646 00647 /** 00648 * advance to next item 00649 */ 00650 inline const_iterator& operator++() { // prefix 00651 do { 00652 ++pos; 00653 } while ((pos < static_cast<int>(theVector->size())) && 00654 ((*theVector)[pos].first < 0)) ; 00655 return *this; 00656 }; 00657 00658 /** 00659 * advance to next item 00660 */ 00661 inline const_iterator operator++(int) { // postfix 00662 const_iterator tmp(*this); 00663 do { 00664 ++pos; 00665 } while ((pos < static_cast<int>(theVector->size())) && 00666 ((*theVector)[pos].first < 0)); 00667 return tmp; 00668 }; 00669 00670 /** 00671 * recede to previous item // prefix 00672 */ 00673 inline const_iterator& operator--() { 00674 do { 00675 --pos; 00676 } while ((pos >= 0) && ((*theVector)[pos].first < 0)); 00677 return *this; 00678 }; 00679 00680 /** 00681 * recede to previous item 00682 */ 00683 inline const_iterator operator--(int) { 00684 const_iterator tmp(*this); 00685 do { 00686 --pos; 00687 } while ((pos >= 0) && ((*theVector)[pos].first < 0)); 00688 return tmp; 00689 }; // postfix 00690 00691 /** 00692 * compare if both pointed positions are the same 00693 */ 00694 inline bool operator==(const const_iterator& other) const { 00695 return (pos == other.pos); 00696 }; 00697 00698 /** 00699 * compare if both pointed positions are the same 00700 */ 00701 inline bool operator==(const iterator& other) const { 00702 return (pos == other.pos); 00703 }; 00704 00705 /** 00706 * compare if both pointed positions are different 00707 */ 00708 inline bool operator!=(const const_iterator& other) const { 00709 return (pos != other.pos); 00710 }; 00711 00712 /** 00713 * compare if both pointed positions are different 00714 */ 00715 inline bool operator!=(const iterator& other) const { 00716 return (pos != other.pos); 00717 }; 00718 00719 00720 /** 00721 * get pointed data 00722 */ 00723 inline const node_type& operator*() const { 00724 return (*theVector)[pos].second; 00725 }; 00726 00727 /** 00728 * get pointed node's id. 00729 * 00730 * Please note that the id can become invalid if the pointed node 00731 * is removed. 00732 */ 00733 inline id_type id() const { 00734 return pos; 00735 } 00736 00737 /** 00738 * copy member 00739 */ 00740 inline const_iterator& operator=(const iterator& other) { 00741 pos = other.getPos(); 00742 theVector = other.getVector(); 00743 return *this; 00744 }; 00745 00746 /** 00747 * copy member 00748 */ 00749 inline const_iterator& operator=(const const_iterator& other) { 00750 pos = other.pos; 00751 theVector = other.theVector; 00752 return *this; 00753 }; 00754 00755 protected: 00756 /** 00757 * protected constructor (for internal use only) 00758 */ 00759 explicit const_iterator(const int startPos,const nodes_type* vct) 00760 : pos(startPos), theVector(vct) {}; 00761 00762 private: 00763 /** 00764 * actual vector index 00765 */ 00766 int pos; 00767 00768 /** 00769 * pointer to the actual vector 00770 */ 00771 const nodes_type* theVector; 00772 }; 00773 00774 class const_edge_iterator; 00775 00776 /** 00777 * The edge iterator iterates on all outgoing edges of a node. 00778 * 00779 * This class is similar to the usual iterators of the STL. 00780 * The iterator allows you to access the data the edge, but 00781 * you can also get the next node's id for other kind of processing. 00782 * 00783 * Since you got this iterator, you should know somehow which is the 00784 * starting edge node. 00785 * 00786 * To access the edge's data, use the operator* (for example, if 00787 * \c it is an edge_iterator, get the data with (*it) ). To get the 00788 * ids of the nodes or the weight of the edge, use the corresponding 00789 * methods in the adjacencyGraph class. 00790 * 00791 */ 00792 class edge_iterator { 00793 friend class adjacencyGraph<N,W,D,F,E>; 00794 # ifdef _LTI_MSC_6 00795 friend class const_edge_iterator; 00796 # else 00797 friend class adjacencyGraph<N,W,D,F,E>::const_edge_iterator; 00798 # endif 00799 00800 public: 00801 /** 00802 * Default constructor 00803 */ 00804 edge_iterator() : pos(),currentNode() {}; 00805 00806 /** 00807 * copy constructor 00808 */ 00809 edge_iterator(const edge_iterator& other) 00810 : pos(other.pos),currentNode(other.currentNode) {}; 00811 00812 /** 00813 * advance to next item 00814 */ 00815 inline edge_iterator& operator++() { // prefix 00816 ++pos; 00817 return *this; 00818 }; 00819 00820 /** 00821 * advance to next item 00822 */ 00823 inline edge_iterator operator++(int) { // postfix 00824 edge_iterator tmp(*this); 00825 ++pos; 00826 return tmp; 00827 }; 00828 00829 /** 00830 * recede to previous item // prefix 00831 */ 00832 inline edge_iterator& operator--() { 00833 --pos; 00834 return *this; 00835 }; 00836 00837 /** 00838 * recede to previous item 00839 */ 00840 inline edge_iterator operator--(int) { 00841 edge_iterator tmp(*this); 00842 --pos; 00843 return tmp; 00844 }; // postfix 00845 00846 /** 00847 * compare if both pointed positions are the same 00848 */ 00849 inline bool operator==(const edge_iterator& other) const { 00850 return (pos == other.pos); 00851 }; 00852 00853 /** 00854 * compare if both pointed positions are different 00855 */ 00856 inline bool operator!=(const edge_iterator& other) const { 00857 return (pos != other.pos); 00858 }; 00859 00860 /** 00861 * get pointed data 00862 */ 00863 inline edge_data_type& operator*() {return (*pos).second.data;}; 00864 00865 /** 00866 * get pointed data 00867 */ 00868 inline const edge_data_type& operator*() const { 00869 return (*pos).second.data; 00870 }; 00871 00872 /** 00873 * copy member 00874 */ 00875 inline edge_iterator& operator=(const edge_iterator& other) { 00876 pos = other.pos; 00877 currentNode = other.currentNode; 00878 return *this; 00879 }; 00880 00881 protected: 00882 /** 00883 * protected constructor (for internal use only) 00884 * 00885 * @param startPos map iterator 00886 * @param node id of the current node 00887 */ 00888 explicit edge_iterator(const typename row_type::iterator& startPos, 00889 const id_type node) 00890 : pos(startPos),currentNode(node) {}; 00891 00892 /** 00893 * for internal use only!!! 00894 */ 00895 const typename row_type::iterator& getPos() const {return pos;}; 00896 00897 /** 00898 * get complete matrix element entry 00899 * for internal use only!!! 00900 */ 00901 entry_type& getRWEntry() const { 00902 return (*pos).second; 00903 }; 00904 00905 /** 00906 * get complete matrix element entry 00907 * for internal use only!!! 00908 */ 00909 const entry_type& getEntry() const { 00910 return (*pos).second; 00911 }; 00912 00913 /** 00914 * for internal use only!!! 00915 */ 00916 id_type getNode() const {return currentNode;}; 00917 00918 private: 00919 /** 00920 * actual vector index 00921 */ 00922 typename row_type::iterator pos; 00923 00924 /** 00925 * current node, from which all edges come out 00926 */ 00927 id_type currentNode; 00928 }; 00929 00930 /** 00931 * The graph const_iterator iterates on all nodes in a read-only fashion. 00932 * 00933 * This class is similar to the usual iterators of the STL. 00934 * The iterator allows you to access the data the edge, but 00935 * you can also get the next node's id for other kind of processing. 00936 * 00937 * Since you got this iterator, you should know somehow which is the 00938 * starting edge node. 00939 * 00940 * To access the edge's data, use the operator* (for example, if 00941 * \c it is an edge_iterator, get the data with (*it) ). To get the 00942 * ids of the nodes or the weight of the edge, use the corresponding 00943 * methods in the adjacencyGraph class. 00944 */ 00945 class const_edge_iterator { 00946 friend class adjacencyGraph<N,W,D,F,E>; 00947 public: 00948 /** 00949 * Default constructor 00950 */ 00951 const_edge_iterator() : pos(),currentNode() {}; 00952 00953 /** 00954 * copy constructor 00955 */ 00956 const_edge_iterator(const const_edge_iterator& other) 00957 : pos(other.pos),currentNode(other.currentNode) {}; 00958 00959 /** 00960 * copy constructor 00961 */ 00962 const_edge_iterator(const edge_iterator& other) {(*this)=other;}; 00963 00964 /** 00965 * advance to next item 00966 */ 00967 inline const_edge_iterator& operator++() { // prefix 00968 ++pos; 00969 return *this; 00970 }; 00971 00972 /** 00973 * advance to next item 00974 */ 00975 inline const_edge_iterator operator++(int) { // postfix 00976 const_edge_iterator tmp(*this); 00977 ++pos; 00978 return tmp; 00979 }; 00980 00981 /** 00982 * recede to previous item // prefix 00983 */ 00984 inline const_edge_iterator& operator--() { 00985 --pos; 00986 return *this; 00987 }; 00988 00989 /** 00990 * recede to previous item 00991 */ 00992 inline const_edge_iterator operator--(int) { 00993 const_edge_iterator tmp(*this); 00994 --pos; 00995 return tmp; 00996 }; // postfix 00997 00998 /** 00999 * compare if both pointed positions are the same 01000 */ 01001 inline bool operator==(const const_edge_iterator& other) const { 01002 return (pos == other.pos); 01003 }; 01004 01005 /** 01006 * compare if both pointed positions are the same 01007 */ 01008 inline bool operator==(const edge_iterator& other) const { 01009 return (pos == other.getPos()); 01010 }; 01011 01012 /** 01013 * compare if both pointed positions are different 01014 */ 01015 inline bool operator!=(const const_edge_iterator& other) const { 01016 return (pos != other.pos); 01017 }; 01018 01019 /** 01020 * compare if both pointed positions are different 01021 */ 01022 inline bool operator!=(const edge_iterator& other) const { 01023 return (pos != other.getPos()); 01024 }; 01025 01026 /** 01027 * get pointed data 01028 */ 01029 inline const edge_data_type& operator*() const { 01030 return (*pos).second.data; 01031 }; 01032 01033 /** 01034 * copy member 01035 */ 01036 inline const_edge_iterator& operator=(const edge_iterator& other) { 01037 pos = other.getPos(); 01038 currentNode = other.getNode(); 01039 return *this; 01040 }; 01041 01042 /** 01043 * copy member 01044 */ 01045 inline const_edge_iterator& operator=(const const_edge_iterator& other) { 01046 pos = other.pos; 01047 currentNode = other.currentNode; 01048 return *this; 01049 }; 01050 01051 protected: 01052 /** 01053 * protected constructor (for internal use only) 01054 */ 01055 explicit const_edge_iterator(const typename row_type::const_iterator& sp, 01056 const id_type node) 01057 : pos(sp),currentNode(node) {}; 01058 01059 /** 01060 * get complete matrix element entry 01061 * for internal use only!!! 01062 */ 01063 const entry_type& getEntry() const { 01064 return (*pos).second; 01065 }; 01066 01067 /** 01068 * for internal use only!!! 01069 */ 01070 id_type getNode() const {return currentNode;}; 01071 01072 private: 01073 /** 01074 * actual vector index 01075 */ 01076 typename row_type::const_iterator pos; 01077 01078 /** 01079 * current node, from which all edges come out 01080 */ 01081 id_type currentNode; 01082 }; 01083 01084 // ----------------------------------------------------------------------- 01085 // adjacency graph methods 01086 // ----------------------------------------------------------------------- 01087 01088 /** 01089 * default constructor 01090 */ 01091 adjacencyGraph(); 01092 01093 /** 01094 * Construct a graph with the given number of nodes, each 01095 * one initialized with the given data. 01096 */ 01097 adjacencyGraph(const int number,const node_type& nodeData = node_type()); 01098 01099 /** 01100 * copy constructor 01101 */ 01102 adjacencyGraph(const adjacencyGraph<N,W,D,F,E>& other); 01103 01104 /** 01105 * @name Iterators 01106 */ 01107 //@{ 01108 /** 01109 * Return a const_iterator to the first valid node of the graph. 01110 * 01111 * Note that you can not change the values of the graph's nodes 01112 * when you use a const_iterator. See also begin() 01113 */ 01114 const_iterator begin() const; 01115 01116 /** 01117 * Return an iterator to the first valid node of the graph. 01118 * The use of the iterators is similar to the iterators of the 01119 * Standard Template Library (STL). 01120 * If you need to iterate on all nodes of a graph, you can 01121 * use following code: 01122 * 01123 * \code 01124 * int tmp,accu; // a temporal variable 01125 * lti::adjacencyGraph myGraph(10); // a graph with 10 elements 01126 * lti::adjacencyGraph::iterator it,eit; 01127 * 01128 * for (it=myGraph.begin(),eit=myGraph.end(); it!=eit ; ++it) { 01129 * // get the id of the nodes 01130 * lti::adjacencyGraph::id_type theId = it.id(); 01131 * // do something with the graph id 01132 * } 01133 * \endcode 01134 */ 01135 iterator begin(); 01136 01137 /** 01138 * returns last index as a const iterator. 01139 * For an example see begin() 01140 */ 01141 const_iterator end() const; 01142 01143 /** 01144 * returns last index as an iterator 01145 * For an example see begin() 01146 */ 01147 iterator end(); 01148 01149 /** 01150 * Get edge iterator to the first outgoing edge of the given start node 01151 */ 01152 edge_iterator begin(const id_type startNode); 01153 01154 /** 01155 * Get edge iterator to the end of the outgoing edge list for the 01156 * given start node. 01157 */ 01158 edge_iterator end(const id_type startNode); 01159 01160 /** 01161 * Get edge iterator to the first outgoing edge of the given start node 01162 */ 01163 const_edge_iterator begin(const id_type startNode) const; 01164 01165 /** 01166 * Get edge iterator to the end of the outgoing edge list for the 01167 * given start node. 01168 */ 01169 const_edge_iterator end(const id_type startNode) const; 01170 01171 //@} 01172 01173 /** 01174 * @name Node operations 01175 */ 01176 //@{ 01177 01178 /** 01179 * Check if the given id is a valid one 01180 */ 01181 bool isNodeIdValid(const id_type id) const; 01182 01183 /** 01184 * Return the data contained in the node with the given id. 01185 * 01186 * You must ensure that the given id is valid. If it is not, 01187 * an assertion will be thrown in debug modus, or some problems 01188 * will occur in release modus (segmentation fault or similar). 01189 * 01190 */ 01191 const node_type& getNodeData(const id_type id) const; 01192 01193 /** 01194 * Return the data contained in the node with the given id. 01195 * 01196 * You must ensure that the given id is valid. If it is not, 01197 * an assertion will be thrown in debug modus, or some problems 01198 * will occur in release modus (segmentation fault or similar). 01199 * 01200 */ 01201 node_type& getNodeData(const id_type id); 01202 01203 /** 01204 * Change the data in a given node. 01205 * 01206 * You must ensure that the given id is valid. If it is not, 01207 * an assertion will be thrown in debug modus, or some problems 01208 * will occur in release modus (segmentation fault or similar). 01209 * 01210 */ 01211 node_type& setNodeData(const id_type id,const node_type& data); 01212 01213 /** 01214 * Insert a node in the graph with the given data. 01215 * @param nodeData data to be included in the new node. If not given, a 01216 * default object will be created. 01217 * @return an identification key for the new inserted node. 01218 */ 01219 id_type insertNode(const node_type& nodeData = node_type()); 01220 01221 /** 01222 * Insert the given number of nodes in the graphs, all having copies of 01223 * the same data object. 01224 * @param number number of nodes to be inserted. 01225 * @param nodeData data to be included in the new nodes. If omitted, a 01226 * default object will be created. 01227 * @return true if successful, false otherwise. 01228 */ 01229 bool insertNodes(const int number, 01230 const node_type& nodeData = node_type()); 01231 01232 /** 01233 * Remove the node and all edges from/to it. 01234 * 01235 * @param id identification key for the node to be removed. 01236 * @return true if node could be deleted. false if some problem occurred, 01237 * for example if the id is not valid. 01238 */ 01239 bool removeNode(const id_type id); 01240 01241 /** 01242 * Merge the two given nodes. 01243 * Topological merge of the two given nodes. 01244 * 01245 * The difference of this method with topologicalMerge is that 01246 * besides ensuring a topological merge, the data of the merged 01247 * edges and nodes is updated. Consider for instance the 01248 * following graph with nodes A,B,w,x,y,z and edges Ax,Az,Aw,AB,Bw,By: 01249 * 01250 * \code 01251 * x---A---B---y 01252 * |\ | 01253 * | \ | 01254 * z w 01255 * \endcode 01256 * 01257 * The merge of A and B results in 01258 * 01259 * \code 01260 * x---A---y 01261 * |\ 01262 * | \ 01263 * z w 01264 * \endcode 01265 * 01266 * Here, the new weight of Aw is computed using the operator+= of the 01267 * weight_type type, which in this case does an update of: 01268 * - the node information of A (which is the combination of the previous 01269 * node data A and B). For this task, the N type must provide 01270 * the operator+=. 01271 * - the edge weights between A and its old 01272 * neighbors x, z and w, the additional information update of 01273 * the edge Aw, which now encompasses the old Aw and Bw, 01274 * and the weights to the new neighbor y. The update of edge information 01275 * assumes that the data_type provides the operator+=. 01276 * 01277 * @param first one of the two nodes to be merged. 01278 * @param second the node to be merged with the first one. 01279 * @return the id of the new merged node. This will usually be the 01280 * id of the first node. 01281 * If one of the ids does not exist, a negative id will be 01282 * returned. 01283 */ 01284 id_type mergeNodes(const id_type first,const id_type second); 01285 01286 01287 /** 01288 * Merge two nodes. 01289 * 01290 * @see mergeNodes(const id_type,const id_type) 01291 */ 01292 id_type mergeNodes(const node_pair& edge); 01293 01294 01295 /** 01296 * Topological merge of the two given nodes. 01297 * 01298 * The difference of this method with mergeNodes is that it only 01299 * ensures that the topology of the merge node is kept. Consider 01300 * the following graph with nodes A,B,w,x,y,z and edges 01301 * Ax,Az,Aw,AB,Bw and By: 01302 * 01303 * \code 01304 * x---A---B---y 01305 * |\ | 01306 * | \ | 01307 * z w 01308 * \endcode 01309 * 01310 * The merge of A and B results in 01311 * 01312 * \code 01313 * x---A---y 01314 * |\ 01315 * | \ 01316 * z w 01317 * \endcode 01318 * 01319 * Here, the weight of Aw is kept and the weight of A remain unchainged. 01320 * 01321 * @param first one of the two nodes to be merged. 01322 * @param second the node to be merged with the first one. 01323 * @return the id of the new merged node. This will usually be the 01324 * id of the first node. 01325 * If one of the ids does not exist, a negative id will be 01326 * returned. 01327 */ 01328 id_type topologicalMerge(const id_type first,const id_type second); 01329 01330 /** 01331 * Merge two nodes 01332 * 01333 * @see topologicalMerge(const id_type,const id_type) 01334 */ 01335 id_type topologicalMerge(const node_pair& edge); 01336 01337 01338 /** 01339 * Return the number of outgoing edges for the given node 01340 */ 01341 int numberEdges(const id_type node) const; 01342 01343 01344 /** 01345 * Remove all nodes and edges from the graph and insert the given 01346 * number of nodes, without any edges. 01347 * 01348 * This method ensures that the ids for the nodes lie between zero 01349 * and \a number-1. 01350 * 01351 * @param number number of nodes the graph must have. 01352 * @param nodeData data to be included in all nodes. If omitted, a 01353 * default data object will be created. 01354 * @return true if successful, false otherwise. 01355 */ 01356 bool resize(const int number, 01357 const node_type& nodeData = node_type()); 01358 01359 01360 /** 01361 * Return the number of nodes of this graph. This value needs to be 01362 * computed, and therefore takes a little bit time. 01363 * 01364 * This value counts all nodes, independently if they are connected to 01365 * other nodes or not. In an adjacency graph, isolated nodes can exist, 01366 * but they do not make much sence, since they are not adjacent to 01367 * anything. Hence, Many algorithms require instead the number returned by 01368 * totalAdjacentNodes(). 01369 * 01370 * @see totalAdjacentNodes(); 01371 * 01372 */ 01373 int size() const; 01374 01375 /** 01376 * Return the number of nodes of this graph, that are connected to at 01377 * least another node. Note that this value is always less or equal 01378 * the size(). 01379 * 01380 * This value needs to be computed, and therefore, takes a little 01381 * bit time. 01382 * 01383 * In an adjacency graph, isolated nodes can exist, but they do not make 01384 * much sence, since they are not adjacent to anyone. Many algorithm 01385 * require instead the number of nodes that are adjacent to something, 01386 * which is exactly what this method computes. 01387 * 01388 * @see size(); 01389 */ 01390 int totalAdjacentNodes() const; 01391 01392 /** 01393 * Return the total number of edges of this graph. This value needs to be 01394 * computed, and therefore takes a little bit time. 01395 */ 01396 int totalEdges() const; 01397 01398 /** 01399 * Return the largest valid node id (or negative if the graph is empty) 01400 */ 01401 id_type lastValidId() const; 01402 01403 //@} 01404 01405 01406 /** 01407 * @name Edge related methods 01408 */ 01409 //@{ 01410 01411 /** 01412 * Get edge weight. 01413 * 01414 * Please remember that getEdgeWeight(a,b) is not necessarily the same 01415 * than getEdgeWeight(b,a). This depends on the definition of 01416 * the function object of type weight_functor 01417 * 01418 * @param a first node 01419 * @param b second node 01420 * @return the weight of the edge or edge_traits::Invalid if edge does 01421 * not exist 01422 */ 01423 const weight_type& getEdgeWeight(const id_type a, 01424 const id_type b) const; 01425 01426 01427 /** 01428 * Get edge weight. 01429 * 01430 * Please remember that getEdgeWeight(a,b) is not necessarily the same 01431 * than getEdgeWeight(b,a). This depends on the definition of 01432 * the function E::weight() 01433 * 01434 * @param edge the pair of nodes describing an edge. 01435 * @return the weight of the edge or edge_traits::Invalid if edge does 01436 * not exist or is a topological edge, without associated weight. 01437 */ 01438 const weight_type& getEdgeWeight(const node_pair& edge) const; 01439 01440 /** 01441 * Get edge weight. 01442 * 01443 * Please remember that getEdgeWeight(a,b) is not necessarily the same 01444 * than getEdgeWeight(b,a). This depends on the definition of 01445 * the function E::weight() 01446 * 01447 * @param it iterator to the edge 01448 * @return the weight of the edge or edge_traits::Invalid if it 01449 * is a topological edge, without associated weight 01450 */ 01451 const weight_type& getEdgeWeight(const edge_iterator& it) const; 01452 01453 /** 01454 * Get edge weight. 01455 * 01456 * Please remember that getEdgeWeight(a,b) is not necessarily the same 01457 * than getEdgeWeight(b,a). This depends on the definition of 01458 * the function E::weight() 01459 * 01460 * @param it iterator to the edge 01461 * @return the weith of the edge or edge_traits::Invalid if edge does not exist 01462 */ 01463 const weight_type& getEdgeWeight(const const_edge_iterator& it) const; 01464 01465 /** 01466 * Change the weight of the given edge. 01467 * 01468 * This method updates the weigth of the edge (a,b). 01469 * 01470 * If the constant E::Symmetric is true, then also the weight of 01471 * the edge (b,a) is updated. 01472 * 01473 * @param a first node 01474 * @param b second node 01475 * @param weight new weight for the edge. 01476 * @return true if update successful, or false if the edge didn't exist. 01477 */ 01478 bool updateEdgeWeight(const id_type a, 01479 const id_type b, 01480 const weight_type& weight); 01481 01482 /** 01483 * Change the weight of the given edge. 01484 * 01485 * This method updates the weigth of the edge (a,b). 01486 * 01487 * If the constant E::Symmetric is true, then also the weight of 01488 * the edge (b,a) is updated. 01489 * 01490 * @param edges pair of nodes (a=edges.first,b=edges.second) 01491 * @param weight new weight for the edge. 01492 * @return true if update successful, or false if the edge didn't exist. 01493 */ 01494 bool updateEdgeWeight(const node_pair& edges, 01495 const weight_type& weight); 01496 01497 /** 01498 * Change the weight of the given edge 01499 * 01500 * This method updates the weigth of the edge (a,b). 01501 * 01502 * If the constant E::Symmetric is true, then also the weight of 01503 * the edge (b,a) is updated. 01504 * 01505 * @param it iterator to the edge 01506 * @param weight new weight for the edge. 01507 * @return true if update successful, or false if the edge didn't exist. 01508 */ 01509 bool updateEdgeWeight(const edge_iterator& it, 01510 const weight_type& weight); 01511 01512 /** 01513 * Recompute the weight of the given edge. 01514 * 01515 * This method updates the weigth of the edge (a,b) to the one computed 01516 * by the E::weight() method. 01517 * 01518 * If the constant E::Symmetric is true, then also the weight of 01519 * the edge (b,a) is updated. 01520 * 01521 * @param a first node 01522 * @param b second node 01523 * @return true if update successful, or false if the edge didn't exist. 01524 */ 01525 bool updateEdgeWeight(const id_type a, 01526 const id_type b); 01527 01528 /** 01529 * Change the weight of the given edge. 01530 * 01531 * This method updates the weigth of the edge (a,b) to the one computed 01532 * by the E::weight() method. 01533 * 01534 * If the constant E::Symmetric is true, then also the weight of 01535 * the edge (b,a) is updated. 01536 * 01537 * @param edges pair of nodes (a=edges.first,b=edges.second) 01538 * @return true if update successful, or false if the edge didn't exist. 01539 */ 01540 bool updateEdgeWeight(const node_pair& edges); 01541 01542 /** 01543 * Change the weight of the given edge 01544 * 01545 * This method updates the weigth of the edge (a,b) to the one computed 01546 * by the E::weight() method. 01547 * 01548 * If the constant E::Symmetric is true, then also the weight of 01549 * the edge (b,a) is updated. 01550 * 01551 * @param it iterator to the edge 01552 * @return true if update successful, or false if the edge didn't exist. 01553 */ 01554 bool updateEdgeWeight(const edge_iterator& it); 01555 01556 /** 01557 * Change the data of the given edge. 01558 * 01559 * This method updates the data of the edge (a,b). 01560 * 01561 * If the constant E::Symmetric is true, then also the data of 01562 * the edge (b,a) is updated. 01563 * 01564 * @param a first node 01565 * @param b second node 01566 * @param data new data for the edge. 01567 * @return true if update successful, or false if the edge didn't exist. 01568 */ 01569 bool setEdgeData(const id_type a, 01570 const id_type b, 01571 const edge_data_type& data); 01572 01573 /** 01574 * Change the data of the given edge. 01575 * 01576 * This method updates the data of the edge (a,b). 01577 * 01578 * If the constant E::Symmetric is true, then also the data of 01579 * the edge (b,a) is updated. 01580 * 01581 * @param edges pair of nodes (a=edges.first,b=edges.second) 01582 * @param data new data for the edge. 01583 * @return true if update successful, or false if the edge didn't exist. 01584 */ 01585 bool setEdgeData(const node_pair& edges, 01586 const edge_data_type& data); 01587 01588 /** 01589 * Change the data of the given edge 01590 * 01591 * This method updates the data of the edge (a,b). 01592 * 01593 * If the constant E::Symmetric is true, then also the data of 01594 * the edge (b,a) is updated. 01595 * 01596 * @param it iterator to the edge 01597 * @param data new data for the edge. 01598 * @return true if update successful, or false if the edge didn't exist. 01599 */ 01600 bool setEdgeData(const edge_iterator& it, 01601 const edge_data_type& data); 01602 01603 01604 /** 01605 * Get a read-only reference to the data object of the edge. 01606 * 01607 * If you have a const_edge_iterator, remember that you can get the edge 01608 * data dereferencing it, i.e. if \c iter is your iterator, then 01609 * <code>(*iter)</code> is the edge's data. 01610 * 01611 * @param a first node 01612 * @param b second node 01613 * @return read-only reference to the data. If the edge didn't exist 01614 * expect unpredictable behaviour! 01615 * 01616 */ 01617 const edge_data_type& getEdgeData(const id_type a, 01618 const id_type b) const; 01619 01620 /** 01621 * Get a read-only reference to the data object of the edge. 01622 * 01623 * If you have a const_edge_iterator, remember that you can get the edge 01624 * data dereferencing it, i.e. if \c iter is your iterator, then 01625 * <code>(*iter)</code> is the edge's data. 01626 * 01627 * @param edges pair of nodes (a=edges.first,b=edges.second) 01628 * @return read-only reference to the data. If the edge didn't exist 01629 * expect unpredictable behaviour! 01630 */ 01631 const edge_data_type& getEdgeData(const node_pair& edges) const; 01632 01633 /** 01634 * Get a writable reference to the data object of the edge. 01635 * 01636 * If you have an edge_iterator, remember that you can get the edge 01637 * data dereferencing it, i.e. if \c iter is your iterator, then 01638 * <code>(*iter)</code> is the edge's data. 01639 * 01640 * @param a first node 01641 * @param b second node 01642 * @return read-only reference to the data. If the edge didn't exist 01643 * expect unpredictable behaviour! 01644 */ 01645 edge_data_type& getEdgeData(const id_type a, 01646 const id_type b); 01647 01648 /** 01649 * Get a writable reference to the data object of the edge. 01650 * 01651 * If you have an edge_iterator, remember that you can get the edge 01652 * data dereferencing it, i.e. if \c iter is your iterator, then 01653 * <code>(*iter)</code> is the edge's data. 01654 * 01655 * @param edges pair of nodes (a=edges.first,b=edges.second) 01656 * @return read-only reference to the data. If the edge didn't exist 01657 * expect unpredictable behaviour! 01658 */ 01659 edge_data_type& getEdgeData(const node_pair& edges); 01660 01661 /** 01662 * Get edge with the lowest weight in the graph. 01663 * @param a first node 01664 * @param b second node 01665 * @param weight weight of the edge 01666 * @return true if graph not empty, false otherwise (in which case the 01667 * three parameters will be left untouched. 01668 */ 01669 bool getLowestWeightEdge(id_type& a, 01670 id_type& b, 01671 weight_type& weight) const; 01672 01673 01674 /** 01675 * Get pair of nodes with the lowest valid edge weight. 01676 * @param edge the edge contains both nodes 01677 * @param weight weight of the edge 01678 * @return true if graph not empty, false otherwise (in which case the 01679 * three parameters will be left untouched). 01680 */ 01681 bool getLowestWeightEdge(node_pair& edge, 01682 weight_type& weight) const; 01683 01684 01685 /** 01686 * Get the id of the node at the other side of the edge pointed by the 01687 * given iterator 01688 */ 01689 id_type getOtherNode(const edge_iterator& it) const; 01690 01691 /** 01692 * Get the id of the node at the other side of the edge pointed by the 01693 * given iterator 01694 */ 01695 id_type getOtherNode(const const_edge_iterator& it) const; 01696 01697 /** 01698 * Get edge as node_pair pointed by the given iterator 01699 */ 01700 node_pair getEdge(const edge_iterator& it) const; 01701 01702 /** 01703 * Get edge as node_pair pointed by the given iterator 01704 */ 01705 node_pair getEdge(const const_edge_iterator& it) const; 01706 01707 /** 01708 * Insert an edge between the first and second nodes, identified by their 01709 * ids. The edge is assumed symmetrical, so that an edge with the same 01710 * data type will be inserted between the second and the first nodes. 01711 * 01712 * The weight of both edges (first->second, second->first) will be 01713 * computed from the data of both nodes and the given edge data, 01714 * using the function E::weight(). 01715 * 01716 * @param first id of the first node (source one). 01717 * @param second id of the second node (destination one). 01718 * @param init initial data set for the edge. 01719 * @return true if edge could be set successfully inserted, false 01720 * otherwise (for example, if one or both ids are invalid, or if 01721 * the edge already existed). 01722 */ 01723 bool insertEdge(const id_type first, 01724 const id_type second, 01725 const edge_data_type& init = edge_data_type()); 01726 01727 /** 01728 * Insert an edge between the first and second nodes, identified by their 01729 * ids. The edge is assumed symmetrical, so that an edge with the same 01730 * data type will be inserted between the second and the first nodes. 01731 * 01732 * The weight of both edges (first->second, second->first) will be 01733 * computed from the data of both nodes and the given edge data, 01734 * using the function E::weight(). 01735 * 01736 * @param nodes the first and second nodes, which identify the edge 01737 * @param init initial data set for the edge. 01738 * @return true if edge could be set successfully inserted, false 01739 * otherwise (for example, if one or both ids are invalid, or if 01740 * the edge already existed). 01741 */ 01742 bool insertEdge(const node_pair& nodes, 01743 const edge_data_type& init = edge_data_type()); 01744 01745 01746 /** 01747 * Insert an edge between the first and second nodes, identified by their 01748 * ids. 01749 * 01750 * The weight of both edges (first->second, second->first) will be 01751 * computed from the data of both nodes and the given edge data, 01752 * using the function E::weight(). 01753 * 01754 * @param first id of the first node (source one). 01755 * @param second id of the second node (destination one). 01756 * @param init12 initial data for the first to second edge. 01757 * @param init21 initial data for the second to first edge. 01758 * @return true if edge could be set successfully inserted, false 01759 * otherwise (for example, if one or both ids are invalid, or if 01760 * the edge already existed). 01761 */ 01762 bool insertEdge(const id_type first, 01763 const id_type second, 01764 const edge_data_type& init12, 01765 const edge_data_type& init21); 01766 01767 /** 01768 * Insert an edge between the first and second nodes, identified by their 01769 * ids. The data of each 01770 * 01771 * The weight of both edges (first->second, second->first) will be 01772 * computed from the data of both nodes and the given edge data, 01773 * using the function E::weight(). 01774 * 01775 * @param nodes the first and second nodes, which identify the edge 01776 * @param init12 initial data for the first to second edge. 01777 * @param init21 initial data for the second to first edge. 01778 * @return true if edge could be set successfully inserted, false 01779 * otherwise (for example, if one or both ids are invalid, or if 01780 * the edge already existed). 01781 */ 01782 bool insertEdge(const node_pair& nodes, 01783 const edge_data_type& init12, 01784 const edge_data_type& init21); 01785 01786 /** 01787 * Insert an edge between the first and second nodes, identified by their 01788 * ids. 01789 * @param first id of the first node (source one). 01790 * @param second id of the second node (destination one). 01791 * @param init12 initial data for the first to second edge. 01792 * @param weight12 weight of the edge between first and second 01793 * @param init21 initial data for the second to first edge. 01794 * @param weight21 weight of the edge between second and first 01795 * @return true if edge could be set successfully inserted, false 01796 * otherwise (for example, if one or both ids are invalid, or if 01797 * the edge already existed). 01798 */ 01799 bool insertWeightedEdge(const id_type first, 01800 const id_type second, 01801 const edge_data_type& init12, 01802 const weight_type& weight12, 01803 const edge_data_type& init21, 01804 const weight_type& weight21); 01805 01806 /** 01807 * Insert an edge between the first and second nodes, identified by their 01808 * ids. The data of each 01809 * 01810 * @param nodes the first and second nodes, which identify the edge 01811 * @param init12 initial data for the first to second edge. 01812 * @param weight12 weight of the edge between nodes.first and nodes.second 01813 * @param init21 initial data for the second to first edge. 01814 * @param weight21 weight of the edge between nodes.second and nodes.first 01815 * @return true if edge could be set successfully inserted, false 01816 * otherwise (for example, if one or both ids are invalid, or if 01817 * the edge already existed). 01818 */ 01819 bool insertWeightedEdge(const node_pair& nodes, 01820 const edge_data_type& init12, 01821 const weight_type& weight12, 01822 const edge_data_type& init21, 01823 const weight_type& weight21); 01824 01825 01826 /** 01827 * Return a reference to the given edge's data, or create the edge 01828 * pair if it didn't exist and return the reference to the created 01829 * data. 01830 * 01831 * The created edge will not have an associated weight, to save the time 01832 * of computing the weight and administrating it in the corresponding 01833 * sorted data structure. 01834 * 01835 * This method is useful for complex graph operations, which need to build 01836 * first the graph structure and compute in a second stage all weights and 01837 * set them at once with the method TODO. Avoiding an unnecessary 01838 * preliminar weight computation and the unnecessary sorting of such 01839 * weight permits to save lots of time. 01840 * 01841 * Of course, this method can also be (ab)used to create simple 01842 * non-weighted bidirectional adjacency graphs if you need to analyze only 01843 * topological features of an adjacency problem. 01844 * 01845 * You can later assign a weight to the edges with the updateEdgeWeight 01846 * methods. 01847 * 01848 */ 01849 edge_data_type& forceTopologicalEdge(const node_pair& nodes); 01850 01851 /** 01852 * Return a reference to the given edge's data, or create the edge 01853 * pair if it didn't exist and return the reference to the created 01854 * data. 01855 * 01856 * The created edge will not have an associated weight, to save the time 01857 * of computing the weight and administrating it in the corresponding 01858 * sorted data structure. 01859 * 01860 * This method is useful for complex graph operations, which need to build 01861 * first the graph structure and compute in a second stage all weights and 01862 * set them at once with the method TODO. Avoiding an unnecessary 01863 * preliminar weight computation and the unnecessary sorting of such 01864 * weight permits to save lots of time. 01865 * 01866 * Of course, this method can also be (ab)used to create simple 01867 * non-weighted bidirectional adjacency graphs if you need to analyze only 01868 * topological features of an adjacency problem. 01869 * 01870 * You can later assign a weight to the edges with the updateEdgeWeight 01871 * methods. 01872 * 01873 */ 01874 edge_data_type& forceTopologicalEdge(const id_type first, 01875 const id_type second); 01876 01877 /** 01878 * Remove the edge between the given two nodes. 01879 * 01880 * In order to ensure the adjacency graph consistency not only the 01881 * first-to-second edge will be removed, but also the 01882 * second-to-first one. 01883 * 01884 * @param first id of the first node (source one). 01885 * @param second id of the second node (destination one). 01886 * @return true if edge could be deleted. false if some problem occurred, 01887 * for example if the ids are not valid, or the edge didn't exist. 01888 */ 01889 bool removeEdge(const id_type first,const id_type second); 01890 01891 /** 01892 * Remove the edge between the given two nodes. 01893 * 01894 * In order to ensure the adjacency graph consistency not only the 01895 * first-to-second edge will be removed, but also the 01896 * second-to-first one. 01897 * 01898 * @param nodes first and second node ids, which identify the edge 01899 * @return true if edge could be deleted. false if some problem occurred, 01900 * for example if the ids are not valid, or the edge didn't exist. 01901 */ 01902 bool removeEdge(const node_pair& nodes); 01903 01904 /** 01905 * Remove the edge between the given two nodes. 01906 * 01907 * In order to ensure the adjacency graph consistency not only the 01908 * first-to-second edge will be removed, but also the 01909 * second-to-first one. 01910 * 01911 * @param edge edge_iterator pointing to the edge to be removed. 01912 */ 01913 bool removeEdge(const edge_iterator& edge); 01914 01915 /** 01916 * Call the E::weight() method to compute the weight an edge 01917 * from a to b should have, considering the node and edges current data. 01918 * 01919 * Please note that if you just want to get the current weight of an edge, 01920 * the getEdgeWeight methods are much much faster (they don't compute 01921 * anything, but just return a previously set or computed weight value). 01922 * 01923 * For this method, you should check if a and b are valid ids or your 01924 * program may crash! 01925 * 01926 * Note that after topological node merges or topogical edge insertions 01927 * the weight values of edges can be edge_traits::Invalid. Therefore, 01928 * this method is provided to compute them, without changing anything. 01929 */ 01930 weight_type computeEdgeWeight(const id_type a, 01931 const id_type b) const; 01932 01933 01934 /** 01935 * Call the E::weight() method to compute the weight an edge 01936 * from a to b should have, considering the node and edges current data. 01937 * 01938 * Please note that if you just want to get the current weight of an edge, 01939 * the getEdgeWeight methods are much much faster (they don't compute 01940 * anything, but just return a previously set or computed weight value). 01941 * 01942 * For this method, you should check if a and b are valid ids or your 01943 * program may crash! 01944 * 01945 * Note that after topological node merges or topogical edge insertions 01946 * the weight values of edges can be edge_traits::Invalid. Therefore, 01947 * this method is provided to compute them, without changing anything. 01948 */ 01949 weight_type computeEdgeWeight(const node_pair& edge) const; 01950 01951 /** 01952 * Call the E::weight() method to compute the weight an edge 01953 * from a to b should have, considering the node and edges current data. 01954 * 01955 * Please note that if you just want to get the current weight of an edge, 01956 * the getEdgeWeight methods are much much faster (they don't compute 01957 * anything, but just return a previously set or computed weight value). 01958 * 01959 * For this method, you should check if a and b are valid ids or your 01960 * program may crash! 01961 * 01962 * Note that after topological node merges or topogical edge insertions 01963 * the weight values of edges can be edge_traits::Invalid. Therefore, 01964 * this method is provided to compute them, without changing anything. 01965 */ 01966 weight_type computeEdgeWeight(const edge_iterator& it) const; 01967 01968 /** 01969 * Call the E::weight() method to compute the weight an edge 01970 * from a to b should have, considering the node and edges current data. 01971 * 01972 * Please note that if you just want to get the current weight of an edge, 01973 * the getEdgeWeight methods are much much faster (they don't compute 01974 * anything, but just return a previously set or computed weight value). 01975 * 01976 * For this method, you should check if a and b are valid ids or your 01977 * program may crash! 01978 * 01979 * Note that after topological node merges or topogical edge insertions 01980 * the weight values of edges can be edge_traits::Invalid. Therefore, 01981 * this method is provided to compute them, without changing anything. 01982 */ 01983 weight_type computeEdgeWeight(const const_edge_iterator& it) const; 01984 01985 /** 01986 * This method uses the data in the nodes and the edges to recompute 01987 * all graph weights. It is more efficient than recomputing the 01988 * weights one by one, since the sorting of the weights can occur 01989 * at once, and not iteratively. 01990 * 01991 * If the graph is symmetric, only the bottom diagonal affinity matrix 01992 * will be used, i.e. only the edges (a,b) with a>b will be considered 01993 * to the computations and the results will also be assigned to (b,a). 01994 */ 01995 bool recomputeAllWeights(); 01996 01997 //@} 01998 01999 /** 02000 * Remove all nodes and edges from the graph 02001 */ 02002 bool clear(); 02003 02004 /** 02005 * Check if the graph is empty, i.e. if it has no nodes. 02006 */ 02007 inline bool empty() const; 02008 02009 /** 02010 * @name Weight computation functor 02011 */ 02012 //@{ 02013 /** 02014 * Get a read-only reference to the internal weight computation functor 02015 * of type weight_functor (template parameter F) 02016 */ 02017 const weight_functor& getWeightFunctor() const; 02018 02019 /** 02020 * Set a the functor to be used to compute the weights. 02021 * 02022 * This method assumes that the weight_functor implements the operator=(), 02023 * even the default implementation or a specialized one. 02024 */ 02025 void setWeightFunctor(const weight_functor& ftor); 02026 //@} 02027 02028 /** 02029 * @name Copy methods 02030 */ 02031 //@{ 02032 /** 02033 * copy the other adjacency matrix 02034 */ 02035 adjacencyGraph<N,W,D,F,E>& copy(const adjacencyGraph<N,W,D,F,E>& other); 02036 02037 /** 02038 * copy the other adjacency matrix 02039 */ 02040 adjacencyGraph<N,W,D,F,E>& 02041 operator=(const adjacencyGraph<N,W,D,F,E>& other); 02042 02043 /** 02044 * returns a copy of this object 02045 */ 02046 virtual mathObject* clone() const; 02047 //@} 02048 02049 /** 02050 * returns the name of this class 02051 */ 02052 virtual const char* getTypeName() const; 02053 02054 /** 02055 * write the parameters in the given ioHandler 02056 * 02057 * The adjacency graphs are mathObjects, and therefore are 02058 * serializable. If you want to edit the written files, you need to 02059 * know the syntax therein. 02060 * A file contains four data blocks: 02061 * -# The size of the data structure, which is always greater or equal 02062 * to the number of nodes. 02063 * -# The nodes list containing for each node two elements: the 02064 * node's id and the data of the node. 02065 * -# A boolean indicating if the saved data belongs to a symmetric graph 02066 * or not. 02067 * -# The edge list containing for each one three elements: the edge as 02068 * pair of node ids, the edge's weight, the edge's data 02069 * 02070 * @param handler the ioHandler to be used 02071 * @param complete if true (the default) the enclosing begin/end will 02072 * be also written, otherwise only the data block will be written. 02073 * @return true if write was successful 02074 */ 02075 virtual bool write(ioHandler& handler, const bool complete=true) const; 02076 02077 /** 02078 * read the parameters from the given ioHandler 02079 * @param handler the ioHandler to be used 02080 * @param complete if true (the default) the enclosing begin/end will 02081 * be also written, otherwise only the data block will be written. 02082 * @return true if write was successful 02083 */ 02084 virtual bool read(ioHandler& handler,const bool complete=true); 02085 02086 /** 02087 * Check Graph Consistency 02088 * 02089 * This method is for debug purposes only. 02090 * 02091 * If everything is ok, this should by equivalent to \c true. But 02092 * if some bug decided to live here, it can produce a \c false, 02093 * which shouldn't ever happen! 02094 * 02095 * Don't ever rely on this method to do anything, since it will be removed 02096 * as soon as we are sure, everything works. In other words, this method 02097 * is already deprecated! 02098 */ 02099 bool checkConsistency() const; 02100 02101 protected: 02102 /** 02103 * adjacency matrix 02104 */ 02105 adjacency_type adjacency; 02106 02107 /** 02108 * The nodes 02109 */ 02110 nodes_type nodes; 02111 02112 /** 02113 * priority queue ordered by the distances. 02114 */ 02115 queue_type distances; 02116 02117 /** 02118 * first valid vector index 02119 */ 02120 id_type firstValidNodeIndex; 02121 02122 /** 02123 * first valid vector index 02124 */ 02125 id_type lastValidNodeIndex; 02126 02127 /** 02128 * Number of elements in the nodes vector that has been freed 02129 */ 02130 int freeElements; 02131 02132 /** 02133 * The one and only instance of E, used to compute the weights 02134 * between two nodes 02135 */ 02136 weight_functor theWeightFunctor; 02137 02138 /** 02139 * After copying or loading a graph, the "complement" interators in the 02140 * entries of the matrix are invalid. This method ensures consistency 02141 */ 02142 bool fixEntryIterators(); 02143 02144 /** 02145 * Insert an edge between the first and second nodes, identified by their 02146 * ids. 02147 * 02148 * This method assumes the validity of the first and second ids, and 02149 * therefore is protected! 02150 * 02151 * @param first id of the first node (source one). 02152 * @param second id of the second node (destination one). 02153 * @param init12 initial data for the first to second edge. 02154 * @param weight12 weight of the edge between first and second 02155 * @param init21 initial data for the second to first edge. 02156 * @param weight21 weight of the edge between second and first 02157 * @return true if edge could be set successfully inserted, false 02158 * otherwise (for example, if one or both ids are invalid, or if 02159 * the edge already existed). 02160 */ 02161 bool insertWeightedEdgeProt(const id_type first, 02162 const id_type second, 02163 const edge_data_type& init12, 02164 const weight_type& weight12, 02165 const edge_data_type& init21, 02166 const weight_type& weight21); 02167 02168 02169 /** 02170 * Get the id of the node corresponding to the given 02171 * iterator 02172 */ 02173 id_type getNodeId(const typename entry_type::entry_iterator& it) const; 02174 02175 }; 02176 } 02177 02178 #include "ltiAdjacencyGraph_template.h" 02179 #include "ltiUndebug.h" 02180 #endif 02181 #endif