public double narrow() throws OperatorFailedException {
  NodeRef i=null, iP=null, j=null, jP=null;
  int tries=0;
  int beforeMoves=getAllValidNarrowMoves();
  while (tries < MAX_TRIES) {
    i=tree.getNode(MathUtils.nextInt(tree.getNodeCount()));
    while (tree.getRoot() == i || tree.getParent(i,0) == tree.getRoot() || tree.getParent(i,1) == tree.getRoot()) {
      i=tree.getNode(MathUtils.nextInt(tree.getNodeCount()));
    }
    iP=tree.getParent(i,0);
    if (tree.isReassortment(i) && MathUtils.nextBoolean())     iP=tree.getParent(i,1);
    jP=tree.getParent(iP,0);
    if (tree.isReassortment(iP) && MathUtils.nextBoolean())     jP=tree.getParent(iP,1);
    j=tree.getChild(jP,0);
    if (j == iP) {
      j=tree.getChild(jP,1);
    }
    if (j != iP && i != j && (tree.getNodeHeight(j) < tree.getNodeHeight(iP)) && (tree.getNodeHeight(i) < tree.getNodeHeight(jP))) {
      break;
    }
    tries+=1;
  }
  if (tries < MAX_TRIES) {
    eupdateARG(i,j,iP,jP);
    tree.pushTreeChangedEvent(iP);
    tree.pushTreeChangedEvent(jP);
  }
 else   throw new OperatorFailedException("Couldn't find valid narrow move on this tree!!");
  return Math.log((double)beforeMoves / getAllValidNarrowMoves());
}

public double narrow ( ) throws OperatorFailedException { NodeRef i = null , iP = null , j = null , jP = null ; int tries = 0 ; int beforeMoves = getAllValidNarrowMoves ( ) ; while ( tries < MAX_TRIES ) { i = tree . getNode ( MathUtils . nextInt ( tree . getNodeCount ( ) ) ) ; while ( tree . getRoot ( ) == i || tree . getParent ( i , 0 ) == tree . getRoot ( ) || tree . getParent ( i , 1 ) == tree . getRoot ( ) ) { i = tree . getNode ( MathUtils . nextInt ( tree . getNodeCount ( ) ) ) ; } iP = tree . getParent ( i , 0 ) ; if ( tree . isReassortment ( i ) && MathUtils . nextBoolean ( ) ) iP = tree . getParent ( i , 1 ) ; jP = tree . getParent ( iP , 0 ) ; if ( tree . isReassortment ( iP ) && MathUtils . nextBoolean ( ) ) jP = tree . getParent ( iP , 1 ) ; j = tree . getChild ( jP , 0 ) ; if ( j == iP ) { j = tree . getChild ( jP , 1 ) ; } if ( j != iP && i != j && ( tree . getNodeHeight ( j ) < tree . getNodeHeight ( iP ) ) && ( tree . getNodeHeight ( i ) < tree . getNodeHeight ( jP ) ) ) { break ; } tries += 1 ; } if ( tries < MAX_TRIES ) { eupdateARG ( i , j , iP , jP ) ; tree . pushTreeChangedEvent ( iP ) ; tree . pushTreeChangedEvent ( jP ) ; } else throw new OperatorFailedException ( "Couldn't find valid narrow move on this tree!!" ) ; return Math . log ( ( double ) beforeMoves / getAllValidNarrowMoves ( ) ) ; }
warning : assumes strictly bifurcating tree .
