00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef _CJNLTOPOLOGY_H_
00021 #define _CJNLTOPOLOGY_H_ 1
00022
00023 #define INFWEIGHT 9999999 // 99999 // for APSP and others
00024
00025 #include <string>
00026 #include <vector>
00027 #include <stdexcept>
00028 #include <list>
00029 #include <map>
00030 #include <functional>
00031 #include <utility>
00032 #include "CjMatrix.hh"
00033 #include "CjNLTopologyException.hh"
00034 #include <boost/lexical_cast.hpp>
00035 #include <boost/logic/tribool.hpp>
00036
00037 #include <boost/random/mersenne_twister.hpp>
00038 #include <boost/random.hpp>
00039
00040 namespace jmitie {
00041
00042 namespace corelib {
00043 }
00044 using boost::logic::tribool;
00045
00046
00047 #define MAX_BRIDGE_VALS 1000
00048
00067 class CjNLTopology {
00068 public:
00070 typedef int WT;
00072 typedef int LD;
00074
00076 typedef std::pair< unsigned int, WT > adjwl_pair_t;
00078
00080 typedef std::pair< unsigned int, LD > lpl_pair_t;
00082
00084 typedef std::pair< unsigned int, unsigned int > rpl_pair_t;
00085
00087 enum layercapab_t { NONE = 0, DIST = 1, GEO = (1 << 1), RPL = (1 << 2), RPN = (1 << 3), LPL = (1 << 4), LPN = (1 << 5) };
00104
00105 struct link_t {
00106 link_t( unsigned int node_a_, unsigned int node_b_, WT wt_ab_, WT wt_ba_ ):node_a(node_a_),node_b(node_b_),wt_ab(wt_ab_),wt_ba(wt_ba_) {}
00107 unsigned int node_a;
00108 unsigned int node_b;
00109 WT wt_ab;
00110 WT wt_ba;
00111 };
00112
00113 private:
00114 void APSP_DFSearch() const;
00115 void APSP_DFSearch_localcache() const;
00116 void APSP_DFSrecursive(const int from, const int currNode, const int currDistance, int *distances ) const;
00117 void APSP_DFSrecursive_localcache(const int from, const int currNode, const unsigned int numHops, const int currDistance, int *distances, adjwl_pair_t ** adjL ) const;
00118 WT updateCell(const unsigned int row, const unsigned int col, WT & cell, const WT new_weight);
00119 void DFSrecursive(const unsigned int where, bool *visited, unsigned int &numVisited, const unsigned int skip_a = 0, const unsigned int skip_b = 0 ) const;
00120 CjNLTopology(const CjNLTopology &);
00121
00122 protected:
00125 struct adjlist_cmp_lt : public std::binary_function<adjwl_pair_t, adjwl_pair_t, bool> { bool operator()( const adjwl_pair_t & lhs, const adjwl_pair_t & rhs ) { return lhs.first < rhs.first; } };
00127 struct adjlist_cmp_eq : public std::binary_function<adjwl_pair_t, adjwl_pair_t, bool> { bool operator()( const adjwl_pair_t & lhs, const adjwl_pair_t & rhs ) { return ((lhs.first == rhs.first) && (lhs.second == rhs.second)); } };
00128
00129
00131 std::string m_name;
00133 unsigned int m_numNodes;
00135 const unsigned int m_maxNodes;
00137 unsigned int m_numLinks;
00139 CjMatrix <WT> * m_wt;
00141 const CjMatrix <LD> * m_traf;
00143 const CjMatrix<double> * m_geo;
00144
00146 unsigned int * m_tiebreaker;
00147
00149 enum apsp_t { APSP_MAT = 1, APSP_DFS, APSP_DFSLC, APSP_LAST };
00159
00160
00162 apsp_t m_apsp;
00163
00164
00165
00167 mutable bool m_autoSync;
00169
00171 mutable std::vector<adjwl_pair_t> * m_adj_wtlist;
00173
00175 mutable bool m_valid_adj_wtlist;
00176
00178
00180 mutable CjMatrix <unsigned int> * m_rpl;
00182
00184 mutable bool m_valid_rpl;
00185
00187
00189 mutable CjMatrix <LD> * m_lpl;
00191 mutable bool m_valid_lpl;
00192
00194
00196 mutable unsigned int * m_rpn;
00198 mutable bool m_valid_rpn;
00200
00202 mutable LD * m_lpn;
00204 mutable bool m_valid_lpn;
00205
00206
00208 link_t m_lastRemoved;
00210 bool m_lastRemoved_set;
00212 link_t m_lastAdded;
00214 bool m_lastAdded_set;
00215
00217
00234 mutable CjMatrix <tribool *> * m_isBridge;
00236
00238 mutable bool m_valid_isBridge;
00240
00243 mutable tribool m_bridge_vals [MAX_BRIDGE_VALS];
00245
00247 mutable tribool * m_ptr_true;
00249
00251 mutable tribool * m_ptr_false;
00253
00255 mutable tribool * m_ptr_ind;
00256
00258 mutable CjMatrix <WT> * m_distances;
00260 mutable bool m_valid_distances;
00261
00263 mutable unsigned int * m_node_degree;
00265 mutable bool m_valid_node_degree;
00266
00268 bool mk_adjL() const;
00270
00272 bool mk_distances() const;
00274 bool mk_node_degrees() const;
00276
00278 bool mk_lrpn_lrpl() const;
00279
00281 void compact_bridge_vals() const;
00283 void invalidateBridges() const;
00285 void invalidateNonBridges() const;
00287 void init_bridge_vals() const;
00288
00289 public:
00291
00302 CjNLTopology( const std::string name, unsigned int maxNodes, const CjMatrix<WT> & weightMatrix, const CjMatrix<LD> * trafficMatrix = 0, const CjMatrix<double> * geo = 0 );
00304 void init_tiebreaker( boost::mt19937 * m_rng = 0 );
00306
00309 void initRPN() const;
00311
00314 void initRPL() const;
00316
00320 void initLPN() const;
00322
00326 void initLPL() const;
00328 std::string getName() const { return m_name; }
00330
00334 bool hasCapability( CjNLTopology::layercapab_t c ) const { return ( ( c & getCapability() ) == c ); }
00336 CjNLTopology::layercapab_t getCapability() const;
00338
00340 unsigned int getRPL(unsigned int from, unsigned int to) const;
00342
00344 CjNLTopology::LD getLPL(unsigned int from, unsigned int to) const;
00346
00348 unsigned int getRPN(unsigned int node) const;
00350
00352 CjNLTopology::LD getLPN(unsigned int node) const;
00353
00355
00357 const CjMatrix <LD> * getTrafficMatrix() const { return m_traf; }
00359
00361 const CjMatrix <double> * getGeoMatrix() const { return m_geo; }
00363
00365 double getGeoDistance(unsigned int a, unsigned int b) const { return m_geo->at(a,b); }
00366
00368 bool getAutoSync() const { return m_autoSync; }
00370 bool setAutoSync(bool newval) const { bool oldval = m_autoSync; m_autoSync = newval; return oldval; }
00371
00373
00378 WT getWeight(const unsigned int node_a, const unsigned int node_b) const;
00380
00387 WT setWeight(const unsigned int node_a, const unsigned int node_b, const WT new_weight);
00389
00397 std::pair<CjNLTopology::WT, CjNLTopology::WT> setBiDirWeights(const unsigned int node_a, const unsigned int node_b, const WT ab, const WT ba );
00399
00407 bool isFullyConnected(bool testDirectionally = false, unsigned int skip_a = 0, unsigned int skip_b = 0 ) const;
00409
00411 bool isSymmetric() { return m_wt->isSymmetric(); }
00413
00417 unsigned int getDegree(const unsigned int node) const;
00418
00420
00426 CjNLTopology::WT getDistance(unsigned int from, unsigned int to ) const;
00427
00429
00433 CjNLTopology::WT operator()(unsigned int node_a, unsigned int node_b );
00435
00442 CjNLTopology::WT operator()(unsigned int node_a, unsigned int node_b, CjNLTopology::WT new_weight);
00444
00450 const std::vector<adjwl_pair_t> * getNeighbours(const unsigned int node) const;
00452
00458 unsigned int nextHop (const unsigned int where, const unsigned int destination ) const;
00460
00468 bool isBridgeLink(const unsigned int from, const unsigned int to) const;
00470
00476 tribool getBridgeState(const unsigned int from, const unsigned int to) const;
00478
00481 unsigned int addDisconnectedNode();
00483
00485 unsigned int newNodeNumber() const throw();
00487
00491 unsigned int addNodeAndConnect(const unsigned int other, const WT to_other, const WT from_other );
00493
00499 void bulkSetWeight( std::vector<link_t> & pairs, bool bidir = false );
00501 unsigned int getNumNodes() const {return m_numNodes;}
00503 unsigned int getNumLinks() const {return m_numLinks;}
00505 unsigned int getMaxNodes() const {return m_maxNodes;}
00507 unsigned int getNumSelfLoops() const;
00509
00512 double fractionConnectedNodePairs(bool incSelfLoops=false) const;
00514 CjNLTopology::link_t getLastRemovedLink() const;
00516 CjNLTopology::link_t getLastAddedLink() const;
00518 bool forceAdjListUpdate() const;
00520 bool forceDistancesUpdate() const;
00522
00524 bool checkAdjL_integrity() const;
00526
00528 bool checkDegD_integrity() const;
00529 ~CjNLTopology();
00530
00531 };
00532
00533 inline CjNLTopology::layercapab_t operator| (CjNLTopology::layercapab_t a, CjNLTopology::layercapab_t b) { return CjNLTopology::layercapab_t(static_cast<int>(a) | static_cast<int>(b)); }
00534 inline CjNLTopology::layercapab_t operator& (CjNLTopology::layercapab_t a, CjNLTopology::layercapab_t b) { return CjNLTopology::layercapab_t(static_cast<int>(a) & static_cast<int>(b)); }
00535 inline CjNLTopology::layercapab_t & operator|= (CjNLTopology::layercapab_t & a, CjNLTopology::layercapab_t b) { return a = a | b; }
00536 inline CjNLTopology::layercapab_t & operator&= (CjNLTopology::layercapab_t & a, CjNLTopology::layercapab_t b) { return a = a & b; }
00537
00538
00539 inline double CjNLTopology::fractionConnectedNodePairs(bool incSelfLoops) const {
00540 return (double)m_numLinks/(double)(m_numNodes*(m_numNodes - (incSelfLoops?0:1)));
00541 }
00542
00543 inline unsigned int CjNLTopology::getDegree(const unsigned int node) const {
00544 if(node>=m_numNodes) throw E_CjNLT_BoundsError("CjNLTopology::getDegree(const unsigned int node): Requested node " + boost::lexical_cast<std::string>(node) + " is more than the number of nodes, " + boost::lexical_cast<std::string>(m_numNodes) + ".");
00545 mk_node_degrees();
00546 return m_node_degree[node];
00547 }
00548
00549 inline CjNLTopology::WT CjNLTopology::getWeight(const unsigned int row, const unsigned int col) const { return m_wt->at(row,col); }
00550 inline CjNLTopology::WT CjNLTopology::setWeight(const unsigned int row, const unsigned int col, const WT new_weight) {
00551 CjNLTopology::WT & cell = m_wt->at(row,col);
00552 return updateCell(row, col, cell, new_weight);
00553 }
00554
00555 inline std::pair<CjNLTopology::WT, CjNLTopology::WT> CjNLTopology::setBiDirWeights(const unsigned int node_a, const unsigned int node_b, const WT ab, const WT ba ) {
00556 CjNLTopology::WT & a_to_b = m_wt->at( node_a, node_b );
00557 CjNLTopology::WT & b_to_a = m_wt->at( node_b, node_a );
00558 CjNLTopology::WT old_ab = updateCell( node_a, node_b, a_to_b, ab);
00559 CjNLTopology::WT old_ba = updateCell( node_b, node_a, b_to_a, ba);
00560 return std::make_pair(old_ab, old_ba);
00561 }
00562
00563 inline CjNLTopology::WT CjNLTopology::operator()(const unsigned int row, const unsigned int col, const WT new_weight) {
00564 CjNLTopology::WT & cell = m_wt->operator()(row,col);
00565 return updateCell(row, col, cell, new_weight);
00566 }
00567
00568 inline CjNLTopology::WT CjNLTopology::operator()(const unsigned int row, const unsigned int col) {
00569 return m_wt->operator()(row,col);
00570 }
00571
00572
00573 inline CjNLTopology::link_t CjNLTopology::getLastRemovedLink() const {
00574 if (m_lastRemoved_set) return m_lastRemoved;
00575 else throw std::runtime_error("There is no previous removed link");
00576 }
00577
00578
00579 inline CjNLTopology::link_t CjNLTopology::getLastAddedLink() const {
00580 if (m_lastAdded_set) return m_lastAdded;
00581 else throw std::runtime_error("There is no previous added link");
00582 }
00583
00585 class RandomSource : public std::unary_function <ptrdiff_t, ptrdiff_t> {
00586 protected:
00587 boost::uniform_01<> w;
00588 boost::variate_generator<boost::mt19937&, boost::uniform_01<> > ball;
00589 public:
00590 RandomSource( boost::mt19937& rng ):w(),ball(rng,w) {}
00591 ptrdiff_t operator()(ptrdiff_t i) { return ((ptrdiff_t)(ball()*(double)i))%i; }
00592 };
00593
00595 struct Scoped_autosync_disable {
00596 bool m_status;
00597 CjNLTopology & m_top;
00598 Scoped_autosync_disable (CjNLTopology & top):m_status(top.setAutoSync(false)),m_top(top) {}
00599 ~Scoped_autosync_disable() { m_top.setAutoSync(m_status); }
00600 };
00601
00602 }
00603
00604 #endif // _CJNLTOPOLOGY_H_