COIN-OR::LEMON - Graph Library

Ticket #168: d6df00b92912.patch

File d6df00b92912.patch, 19.4 KB (added by Poroszkai Daniel, 9 years ago)

Update weighted bp matching for typesafe node sets

  • lemon/bp_matching.h

    # HG changeset patch
    # User Daniel Poroszkai <poroszd@inf.elte.hu>
    # Date 1328397120 -3600
    # Node ID d6df00b92912ec0c3f5863f7abc7a6f36cc2c2b9
    # Parent  a4a945914af3e7c3c798b763899229b9e1d05009
    Update weighted bp matching to work with typesafe bipartite node sets
    
    diff --git a/lemon/bp_matching.h b/lemon/bp_matching.h
    a b  
    4545    /// The graph type of the algorithm
    4646    typedef BGR BpGraph;
    4747    /// The type of the matching map on the red nodes
    48     typedef typename BpGraph::template RedMap<typename BpGraph::Edge>
     48    typedef typename BpGraph::template RedNodeMap<typename BpGraph::Edge>
    4949    RedMatchingMap;
    5050    /// The type of the matching map on the blue nodes
    51     typedef typename BpGraph::template BlueMap<typename BpGraph::Edge>
     51    typedef typename BpGraph::template BlueNodeMap<typename BpGraph::Edge>
    5252    BlueMatchingMap;
    5353
    5454  private:
     
    118118      RM = new RedMatchingMap(*G, INVALID);
    119119      BM = new BlueMatchingMap(*G, INVALID);
    120120     
    121       for( RedIt n(*G); n != INVALID; ++n ){
     121      for( RedNodeIt n(*G); n != INVALID; ++n ){
    122122        for( IncEdgeIt eit(*G, n); eit != INVALID; ++eit ) {
    123123          if( (*BM)[ G->blueNode(eit) ] == INVALID ){
    124124            (*BM)[G->blueNode(eit) ] = eit;
     
    164164    /// called before using this function.
    165165    bool step()
    166166    {
    167       queue<Node> sources;
     167      queue<RedNode> sources;
    168168      BoolNodeMap _processed(*G, false);
    169169      EdgeNodeMap _pred(*G, INVALID);
    170170      BoolNodeMap _reached(*G, false);
    171       vector<Node> H;
     171      vector<RedNode> H;
    172172      bool isAlternatePath = false;
    173       for( RedIt n(*G); n != INVALID; ++n ){
     173      for( RedNodeIt n(*G); n != INVALID; ++n ){
    174174        if( (*RM)[n] == INVALID ){
    175175          sources.push( n );
    176176        }
    177177      }
    178178       
    179179      while ( !sources.empty() && !isAlternatePath ){
    180         Node s = sources.front();
     180        RedNode s = sources.front();
    181181        if(_processed[s]) {sources.pop(); continue;}
    182182        _processed[s] = true;
    183183        _reached[s] = true;
    184184        H.push_back( s );
    185         Node m;
     185        BlueNode m;
    186186        for(IncEdgeIt e(*G,s);e!=INVALID;++e) {
    187187          if(!_reached[m=G->blueNode(e)]) {
    188188            _reached[m]=true;
    189189            _pred[m]=e;
    190190            if( (*BM)[m] != INVALID ) {
    191               Node n;
     191              RedNode n;
    192192              if (!_reached[n = G->redNode((*BM)[m])] ) {
    193193                sources.push( n );
    194194                _pred[n] = (*BM)[m];
     
    257257    int matchingSize() const
    258258    {
    259259      int size = 0;
    260       for ( BlueIt n(*G); n != INVALID; ++n) {
     260      for ( BlueNodeIt n(*G); n != INVALID; ++n) {
    261261        if ( (*BM)[n] != INVALID) {
    262262          ++size;
    263263        }
     
    281281    /// not covered by the matching.
    282282    Edge matching(const Node& n) const
    283283    {
    284       return G->blue(n) ? (*BM)[n] : (*RM)[n];
     284      return G->blue(n) ? (*BM)[G->asBlueNodeUnsafe(n)] : (*RM)[G->asRedNodeUnsafe(n)];
    285285    }
    286286
    287287    /// \brief Return a const reference to the blue matching map.
     
    310310    {
    311311      Edge e;
    312312      if( G->blue(node) ){
    313         if( ( e = (*BM)[node]) != INVALID ) return G->redNode(e);
     313        if( ( e = (*BM)[G->asBlueNodeUnsafe(node)]) != INVALID ) return G->redNode(e);
    314314        else return INVALID;
    315315      }
    316316      else {
    317         if( ( e = (*RM)[node]) != INVALID ) return G->blueNode(e);
     317        if( ( e = (*RM)[G->asRedNodeUnsafe(node)]) != INVALID ) return G->blueNode(e);
    318318        else return INVALID;
    319319      }
    320320    }
     
    351351    typedef typename WeightMap::Value Value;
    352352   
    353353    /// The type of the red matching map
    354     typedef typename BpGraph::template RedMap<typename BpGraph::Edge>
     354    typedef typename BpGraph::template RedNodeMap<typename BpGraph::Edge>
    355355    RedMatchingMap;
    356356    /// The type of the blue matching map
    357     typedef typename BpGraph::template BlueMap<typename BpGraph::Edge>
     357    typedef typename BpGraph::template BlueNodeMap<typename BpGraph::Edge>
    358358    BlueMatchingMap;
    359359
    360360  private:
     
    420420      BM = new BlueMatchingMap(*G, INVALID);
    421421     
    422422      int nodeCount = 0;
    423       for( RedIt n(*G); n != INVALID; ++n ){
     423      for( RedNodeIt n(*G); n != INVALID; ++n ){
    424424        Value max_C = 0;
    425425        bool start = true;
    426426        vector<Edge> maxEdges;
     
    446446        }
    447447        nodeCount++;
    448448      }
    449       for( BlueIt n(*G); n != INVALID; ++n ){
     449      for( BlueNodeIt n(*G); n != INVALID; ++n ){
    450450        Value minDif = 0;
    451451        bool start = true;
    452452        vector<Edge> minEdges;
     
    482482    HungAlgStatus step()
    483483    {
    484484      bool perfect = true;
    485       for( BlueIt n(*G); n != INVALID; ++n ){
     485      for( BlueNodeIt n(*G); n != INVALID; ++n ){
    486486        if( (*BM)[n] == INVALID ) {
    487487          perfect = false;
    488488          break;
    489489        }
    490490      }
    491       for( RedIt n(*G); n != INVALID; ++n ){
     491      for( RedNodeIt n(*G); n != INVALID; ++n ){
    492492        if( (*RM)[n] == INVALID ) {
    493493          perfect = false;
    494494          break;
    495495        }
    496496      }
    497497      if( perfect ) return HUNGALG_SUCCESS;
    498       queue<Node> sources;
     498      queue<RedNode> sources;
    499499      BoolNodeMap _processed(*G, false);
    500500      EdgeNodeMap _pred(*G, INVALID);
    501501      BoolNodeMap _reached(*G, false);
    502       vector<Node> H;
     502      vector<RedNode> H;
    503503      bool isAlternatePath = false;
    504       for( RedIt n(*G); n != INVALID; ++n ){
     504      for( RedNodeIt n(*G); n != INVALID; ++n ){
    505505        if( (*RM)[n] == INVALID ){
    506506          sources.push( n );
    507507        }
    508508      }
    509509     
    510510      while ( !sources.empty() && !isAlternatePath ){
    511         Node s = sources.front();
     511        RedNode s = sources.front();
    512512        if(_processed[s]) {sources.pop(); continue;}
    513513        _processed[s] = true;
    514514        _reached[s] = true;
    515515        H.push_back( s );
    516         Node m;
     516        BlueNode m;
    517517        for(IncEdgeIt e(*G,s);e!=INVALID;++e) {
    518518          if( (*c)[e] != PI[G->blueNode(e)] + PI[G->redNode(e)] ) continue;
    519519          if(!_reached[m=G->blueNode(e)]) {
    520520            _reached[m]=true;
    521521            _pred[m]=e;
    522522            if( (*BM)[m] != INVALID ) {
    523               Node n;
     523              RedNode n;
    524524              if (!_reached[n = G->redNode((*BM)[m])] ) {
    525525                sources.push( n );
    526526                _pred[n] = (*BM)[m];
     
    537537      }
    538538       
    539539      if( !isAlternatePath ) {
    540         vector<Node> GammaH;
    541         BoolBlueMap GammaH_map( *G, false );
    542         for (typename vector<Node>::iterator nit = H.begin();
     540        vector<BlueNode> GammaH;
     541        BoolBlueNodeMap GammaH_map( *G, false );
     542        for (typename vector<RedNode>::iterator nit = H.begin();
    543543             nit!=H.end(); ++nit){
    544544          for( IncEdgeIt e( *G, *nit ); e!=INVALID; ++e ){
    545545            if( (*c)[e] != PI[G->blueNode(e)] + PI[G->redNode(e)] ) continue;
    546             Node n = G->blueNode( e );
     546            BlueNode n = G->blueNode( e );
    547547            if( !GammaH_map[n] ){
    548548              GammaH.push_back(n);
    549549              GammaH_map[n] = true;
     
    552552        }
    553553        Value gamma = 0;
    554554        bool start = true;
    555         for (typename vector<Node>::iterator nit = H.begin();
     555        for (typename vector<RedNode>::iterator nit = H.begin();
    556556             nit!=H.end(); ++nit){
    557557          for( IncEdgeIt e( *G, *nit ); e!=INVALID; ++e ){
    558             Node n = G->oppositeNode( *nit, e );
     558            BlueNode n = G->oppositeNode( *nit, e );
    559559            if( !GammaH_map[ n ] ){
    560560              Value dif = PI[ G->u(e) ] + PI[ G->v(e) ] - (*c)[e];
    561561              if( start ){ gamma=dif; start=false; continue; }
     
    567567           
    568568        if(!gamma) return HUNGALG_ERROR;
    569569           
    570         for (typename vector<Node>::iterator nit = H.begin();
     570        for (typename vector<RedNode>::iterator nit = H.begin();
    571571             nit!=H.end(); ++nit){
    572572          PI[*nit] -= gamma;
    573573        }
    574         for (typename vector<Node>::iterator nit = GammaH.begin();
     574        for (typename vector<BlueNode>::iterator nit = GammaH.begin();
    575575             nit!=GammaH.end(); ++nit){
    576576          PI[*nit] += gamma;
    577577        }
     
    631631    {
    632632      Value retVal = 0;
    633633      Edge e;
    634       for( BlueIt n(*G); n != INVALID; ++n )
     634      for( BlueNodeIt n(*G); n != INVALID; ++n )
    635635        if( ( e = (*BM)[n] ) != INVALID ) retVal += (*c)[e];
    636636      return retVal;
    637637    }
     
    656656    /// \pre Either run() or start() must be called before using this function.
    657657    Edge matching(const Node& node) const
    658658    {
    659       return G->blue(node) ? (*BM)[node] : (*RM)[node];
     659      return G->blue(node) ? (*BM)[G->asBlueNodeUnsafe(node)] : (*RM)[G->asRedNodeUnsafe(node)];
    660660    }
    661661
    662662    /// \brief Return a const reference to the blue matching map.
     
    687687    {
    688688      Edge e;
    689689      if( G->blue(node) ){
    690         if( ( e = (*BM)[node]) != INVALID ) return G->redNode(e);
     690        if( ( e = (*BM)[G->asBlueNodeUnsafe(node)]) != INVALID ) return G->redNode(e);
    691691        else return INVALID;
    692692      }
    693693      else {
    694         if( ( e = (*RM)[node]) != INVALID ) return G->blueNode(e);
     694        if( ( e = (*RM)[G->asRedNodeUnsafe(node)]) != INVALID ) return G->blueNode(e);
    695695        else return INVALID;
    696696      }
    697697    }
     
    738738    /// The value type of the edge weights
    739739    typedef typename WeightMap::Value Value;
    740740    /// The type of the red matching map
    741     typedef typename BpGraph::template RedMap<typename BpGraph::Edge>
     741    typedef typename BpGraph::template RedNodeMap<typename BpGraph::Edge>
    742742    RedMatchingMap;
    743743    /// The type of the blue matching map
    744     typedef typename BpGraph::template BlueMap<typename BpGraph::Edge>
     744    typedef typename BpGraph::template BlueNodeMap<typename BpGraph::Edge>
    745745    BlueMatchingMap;
    746746   
    747747  private:
     
    750750   
    751751    typedef typename BpGraph::template NodeMap<Value> NodeMap;
    752752   
    753     typedef typename BpGraph::template RedMap<BlueNode> BlueRedMap;
     753    typedef typename BpGraph::template RedNodeMap<BlueNode> BlueRedMap;
    754754   
    755     typedef typename BpGraph::template BlueMap<RedNode> RedBlueMap;
     755    typedef typename BpGraph::template BlueNodeMap<RedNode> RedBlueMap;
    756756
    757757    typedef typename BpGraph::template NodeMap<Edge> EdgeNodeMap;
    758758   
     
    770770    RedBlueMap *RBM;
    771771    BlueRedMap *BRM;
    772772   
    773     void _processMins( bool &processedMins, queue<Node> &sources, NodeNodeMap &_pred, BoolNodeMap &_reached, BlueNode &first )
     773    void _processMins( bool &processedMins, queue<RedNode> &sources, NodeNodeMap &_pred, BoolNodeMap &_reached, BlueNode &first )
    774774    {
    775775      if( processedMins ) return;
    776776      processedMins = true;
    777       for( BlueIt m(*G); m!=INVALID; ++m ) {
     777      for( BlueNodeIt m(*G); m!=INVALID; ++m ) {
    778778        if( PI[m] == -MinPI ){
    779779          _reached[m]=true;
    780780          if( (*RBM)[m] != INVALID ) {
    781             Node n;
     781            RedNode n;
    782782            if (!_reached[n = (*RBM)[m]] ) {
    783783              sources.push( n );
    784784              _pred[n] = m;
     
    788788        }
    789789      }
    790790       
    791       for( RedIt m(*G); m!=INVALID; ++m ) {
     791      for( RedNodeIt m(*G); m!=INVALID; ++m ) {
    792792        if( PI[m] == MinPI && !_reached[ m ] && (*BRM)[m] == INVALID ) {
    793793          sources.push( m );
    794794          _pred[m] = INVALID;
     
    798798     
    799799    }
    800800   
    801     void _setMatching( NodeNodeMap &pred, Node n, BlueNode &first ) {
    802       Node node = n;
    803       Node prevNode = pred[n];
     801    void _setMatching( NodeNodeMap &pred, BlueNode n, BlueNode &first ) {
     802      BlueNode node = n;
     803      RedNode prevNode = G->asRedNodeUnsafe(pred[n]);
    804804      while( 1 ) {
    805805        if( prevNode == INVALID ){
    806806          if( PI[node] == -MinPI ){
     
    811811        else if( (*RBM)[node] != prevNode ) {
    812812          (*BRM)[prevNode] = node;
    813813          (*RBM)[node] = prevNode;
    814           node = pred[prevNode];
     814          node = G->asBlueNodeUnsafe(pred[prevNode]);
    815815        }
    816816        if( node == INVALID ) {
    817817          if( ( PI[prevNode] == MinPI && (*BRM)[prevNode] == INVALID ) || first == INVALID ) return;
    818818          else node = first;
    819819        }
    820         prevNode = pred[node];
     820        prevNode = G->asRedNodeUnsafe(pred[node]);
    821821      }
    822822    }
    823823   
     
    858858      BRM = new BlueRedMap(*G, INVALID);
    859859      RBM = new RedBlueMap(*G, INVALID);
    860860     
    861       for( BlueIt n(*G); n != INVALID; ++n )
     861      for( BlueNodeIt n(*G); n != INVALID; ++n )
    862862      {
    863863        Value max_C = 0;
    864         vector<Node> maxNodes;
     864        vector<RedNode> maxNodes;
    865865        for( IncEdgeIt e( *G, n ); e!=INVALID; ++e ) {
    866866          if( (*c)[e] > max_C ) {
    867867            max_C = (*c)[e];
     
    873873          }
    874874        }
    875875        PI[n] = max_C;
    876         for (typename vector<Node>::iterator eit = maxNodes.begin();
     876        for (typename vector<RedNode>::iterator eit = maxNodes.begin();
    877877          eit!=maxNodes.end(); ++eit)
    878878        {
    879879          if( (*BRM)[*eit] == INVALID )
     
    884884          }
    885885        }
    886886      }
    887       for( RedIt n(*G); n != INVALID; ++n ){
     887      for( RedNodeIt n(*G); n != INVALID; ++n ){
    888888        PI[n] = 0;
    889889      }
    890890    }
     
    901901      for( NodeIt n(*G); n != INVALID; ++n ){
    902902       
    903903        if( G->blue(n) ) {
    904           if( (*RBM)[n] == INVALID && PI[n] != -MinPI ){
     904          if( (*RBM)[G->asBlueNodeUnsafe(n)] == INVALID && PI[n] != -MinPI ){
    905905            Continue = true;
    906906          }
    907907        }
    908908        else {
    909           if( (*BRM)[n] == INVALID && PI[n] != MinPI ){
     909          if( (*BRM)[G->asRedNodeUnsafe(n)] == INVALID && PI[n] != MinPI ){
    910910            Continue = true;
    911911          }
    912912        }
    913913      }
    914914      if( !Continue ){
    915         for( RedIt n(*G); n != INVALID; ++n ) {
     915        for( RedNodeIt n(*G); n != INVALID; ++n ) {
    916916          PI[n] -= MinPI;
    917917         
    918918          for( IncEdgeIt e(*G,n); e != INVALID; ++e ) {
    919919            if( (*BRM)[n] == G->blueNode(e) ) (*RM)[n] = e;
    920920          }
    921921        }
    922         for( BlueIt n(*G); n != INVALID; ++n ) {
     922        for( BlueNodeIt n(*G); n != INVALID; ++n ) {
    923923          PI[n] += MinPI;
    924924         
    925925          for( IncEdgeIt e(*G,n); e != INVALID; ++e ) {
     
    929929       
    930930        return true;
    931931      }
    932       queue<Node> sources;
     932      queue<RedNode> sources;
    933933      BoolNodeMap _processed(*G, false);
    934934      NodeNodeMap _pred(*G, INVALID);
    935935      BoolNodeMap _reached(*G, false);
    936       vector<Node> H;
     936      vector<RedNode> H;
    937937      bool isAlternatePath = false;
    938938      bool notMinUncovered = false;
    939939      BlueNode first = INVALID;
    940940     
    941       for( BlueIt n(*G); n != INVALID; ++n ){
     941      for( BlueNodeIt n(*G); n != INVALID; ++n ){
    942942        if( (*RBM)[n] == INVALID && PI[n] != -MinPI ){
    943943          notMinUncovered = true;
    944944          break;
    945945        }
    946946      }
    947947     
    948       for( RedIt n(*G); n != INVALID; ++n ){
     948      for( RedNodeIt n(*G); n != INVALID; ++n ){
    949949        if( (*BRM)[n] == INVALID ){
    950950          if( notMinUncovered || PI[n] != MinPI ) {
    951951            sources.push( n );
     
    961961      }
    962962     
    963963      while ( !sources.empty() && !isAlternatePath ){
    964         Node s = sources.front();
     964        RedNode s = sources.front();
    965965        if(_processed[s]) { sources.pop(); continue; }
    966966        if(PI[s] == MinPI && (*BRM)[s] == INVALID ) _processMins( processedMins, sources, _pred, _reached, first );
    967967        _processed[s] = true;
    968968        _reached[s] = true;
    969969        H.push_back( s );
    970         Node m;
     970        BlueNode m;
    971971        for( IncEdgeIt e(*G,s); e!=INVALID; ++e ) {
    972972          if( (*c)[e] != PI[G->blueNode(e)] + PI[G->redNode(e)] ) continue;
    973973          if( _reached[m=G->blueNode(e)] ) continue;
    974974          _reached[m]=true;
    975975          _pred[m]=s;
    976976          if( (*RBM)[m] != INVALID ) {
    977             Node n;
     977            RedNode n;
    978978            if (!_reached[n = (*RBM)[m]] ) {
    979979              sources.push( n );
    980980              _pred[n] = m;
     
    994994      }
    995995     
    996996      if( !isAlternatePath ) {
    997         vector<Node> GammaH;
    998         BoolBlueMap GammaH_map( *G, false );
    999         for (typename vector<Node>::iterator nit = H.begin();
     997        vector<BlueNode> GammaH;
     998        BoolBlueNodeMap GammaH_map( *G, false );
     999        for (typename vector<RedNode>::iterator nit = H.begin();
    10001000             nit!=H.end(); ++nit){
    10011001          for( IncEdgeIt e( *G, *nit ); e!=INVALID; ++e ){
    10021002            if( (*c)[e] != PI[G->blueNode(e)] + PI[G->redNode(e)] ) continue;
    1003             Node n = G->blueNode( e );
     1003            BlueNode n = G->blueNode( e );
    10041004            if( !GammaH_map[n] ){
    10051005              GammaH.push_back(n);
    10061006              GammaH_map[n] = true;
     
    10081008          }
    10091009        }
    10101010        if( processedMins ) {
    1011           for( BlueIt n(*G); n != INVALID; ++n ) {
     1011          for( BlueNodeIt n(*G); n != INVALID; ++n ) {
    10121012            if( PI[n] == -MinPI && !GammaH_map[n] ) {
    10131013              GammaH.push_back(n);
    10141014              GammaH_map[n] = true;
     
    10181018       
    10191019        Value gamma = 0;
    10201020        bool start = true;
    1021         for (typename vector<Node>::iterator nit = H.begin();
     1021        for (typename vector<RedNode>::iterator nit = H.begin();
    10221022             nit!=H.end(); ++nit){
    10231023          for( IncEdgeIt e( *G, *nit ); e!=INVALID; ++e ){
    10241024            if((*c)[e]<0) continue;
    1025             Node n = G->oppositeNode( *nit, e );
     1025            BlueNode n = G->asBlueNodeUnsafe(G->oppositeNode( *nit, e ));
    10261026            if( !GammaH_map[ n ] ){
    10271027              Value dif = PI[ G->u(e) ] + PI[ G->v(e) ] - (*c)[e];
    10281028              if( start ){ gamma=dif; start=false; continue; }
     
    10331033        }
    10341034       
    10351035        if( processedMins ) {
    1036           for( BlueIt n(*G); n != INVALID; ++n ) {
     1036          for( BlueNodeIt n(*G); n != INVALID; ++n ) {
    10371037            if( !GammaH_map[n] && ( PI[n] + MinPI < gamma || !gamma ) ) gamma = PI[n] + MinPI;
    10381038          }
    10391039        }
    10401040           
    1041         for (typename vector<Node>::iterator nit = H.begin();
     1041        for (typename vector<RedNode>::iterator nit = H.begin();
    10421042             nit!=H.end(); ++nit){
    10431043          PI[*nit] -= gamma;
    10441044        }
    10451045        if( processedMins ) MinPI -= gamma;
    1046         for (typename vector<Node>::iterator nit = GammaH.begin();
     1046        for (typename vector<BlueNode>::iterator nit = GammaH.begin();
    10471047             nit!=GammaH.end(); ++nit){
    10481048          PI[*nit] += gamma;
    10491049        }
     
    10971097    {
    10981098      Value retVal = 0;
    10991099      Edge e;
    1100       for( BlueIt n(*G); n != INVALID; ++n ) {
     1100      for( BlueNodeIt n(*G); n != INVALID; ++n ) {
    11011101        if( ( e = (*BM)[n] ) != INVALID ) retVal += (*c)[e];
    11021102      }
    11031103      return retVal;
     
    11111111    int matchingSize() const
    11121112    {
    11131113      int size = 0;
    1114       for ( BlueIt n(*G); n != INVALID; ++n) {
     1114      for ( BlueNodeIt n(*G); n != INVALID; ++n) {
    11151115        if ( (*BM)[n] != INVALID) {
    11161116          ++size;
    11171117        }
     
    11391139    /// \pre Either run() or start() must be called before using this function.
    11401140    Edge matching( const Node& node ) const
    11411141    {
    1142       return G->blue(node) ? (*BM)[node] : (*RM)[node];
     1142      return G->blue(node) ? (*BM)[G->asBlueNodeUnsafe(node)] : (*RM)[G->asRedNodeUnsafe(node)];
    11431143    }
    11441144
    11451145    /// \brief Return a const reference to the blue matching map.
     
    11701170    {
    11711171      Edge e;
    11721172      if( G->blue(node) ){
    1173         if( ( e = (*BM)[node]) != INVALID ) return G->redNode(e);
     1173        if( ( e = (*BM)[G->asBlueNodeUnsafe(node)]) != INVALID ) return G->redNode(e);
    11741174        else return INVALID;
    11751175      }
    11761176      else {
    1177         if( ( e = (*RM)[node]) != INVALID ) return G->blueNode(e);
     1177        if( ( e = (*RM)[G->asRedNodeUnsafe(node)]) != INVALID ) return G->blueNode(e);
    11781178        else return INVALID;
    11791179      }
    11801180    }