LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiAdjacencyGraph.h

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

Generated on Sat Apr 10 15:25:06 2010 for LTI-Lib by Doxygen 1.6.1