public void proposeTree() throws OperatorFailedException {
  NodeRef i;
  double oldMinAge, newMinAge, newRange, oldRange, newAge, q;
  final int nodeCount=tree.getNodeCount();
  do {
    i=tree.getNode(MathUtils.nextInt(nodeCount));
  }
 while (tree.getRoot() == i);
  final NodeRef iP=tree.getParent(i);
  NodeRef j=tree.getNode(MathUtils.nextInt(nodeCount));
  NodeRef k=tree.getParent(j);
  while ((k != null && tree.getNodeHeight(k) <= tree.getNodeHeight(i)) || (i == j)) {
    j=tree.getNode(MathUtils.nextInt(nodeCount));
    k=tree.getParent(j);
  }
  if (j == tree.getRoot() || iP == tree.getRoot()) {
    throw new OperatorFailedException("Root changes not allowed!");
  }
  if (k == iP || j == iP || k == i)   throw new OperatorFailedException("move failed");
  final NodeRef CiP=getOtherChild(tree,iP,i);
  NodeRef PiP=tree.getParent(iP);
  newMinAge=Math.max(tree.getNodeHeight(i),tree.getNodeHeight(j));
  newRange=tree.getNodeHeight(k) - newMinAge;
  newAge=newMinAge + (MathUtils.nextDouble() * newRange);
  oldMinAge=Math.max(tree.getNodeHeight(i),tree.getNodeHeight(CiP));
  oldRange=tree.getNodeHeight(PiP) - oldMinAge;
  q=newRange / Math.abs(oldRange);
  tree.beginTreeEdit();
  if (j == tree.getRoot()) {
    tree.removeChild(iP,CiP);
    tree.removeChild(PiP,iP);
    tree.addChild(iP,j);
    tree.addChild(PiP,CiP);
    tree.setRoot(iP);
  }
 else   if (iP == tree.getRoot()) {
    tree.removeChild(k,j);
    tree.removeChild(iP,CiP);
    tree.addChild(iP,j);
    tree.addChild(k,iP);
    tree.setRoot(CiP);
  }
 else {
    tree.removeChild(k,j);
    tree.removeChild(iP,CiP);
    tree.removeChild(PiP,iP);
    tree.addChild(iP,j);
    tree.addChild(k,iP);
    tree.addChild(PiP,CiP);
  }
  tree.setNodeHeight(iP,newAge);
  tree.endTreeEdit();
  logq=Math.log(q);
}

public void proposeTree ( ) throws OperatorFailedException { NodeRef i ; double oldMinAge , newMinAge , newRange , oldRange , newAge , q ; final int nodeCount = tree . getNodeCount ( ) ; do { i = tree . getNode ( MathUtils . nextInt ( nodeCount ) ) ; } while ( tree . getRoot ( ) == i ) ; final NodeRef iP = tree . getParent ( i ) ; NodeRef j = tree . getNode ( MathUtils . nextInt ( nodeCount ) ) ; NodeRef k = tree . getParent ( j ) ; while ( ( k != null && tree . getNodeHeight ( k ) <= tree . getNodeHeight ( i ) ) || ( i == j ) ) { j = tree . getNode ( MathUtils . nextInt ( nodeCount ) ) ; k = tree . getParent ( j ) ; } if ( j == tree . getRoot ( ) || iP == tree . getRoot ( ) ) { throw new OperatorFailedException ( "Root changes not allowed!" ) ; } if ( k == iP || j == iP || k == i ) throw new OperatorFailedException ( "move failed" ) ; final NodeRef CiP = getOtherChild ( tree , iP , i ) ; NodeRef PiP = tree . getParent ( iP ) ; newMinAge = Math . max ( tree . getNodeHeight ( i ) , tree . getNodeHeight ( j ) ) ; newRange = tree . getNodeHeight ( k ) - newMinAge ; newAge = newMinAge + ( MathUtils . nextDouble ( ) * newRange ) ; oldMinAge = Math . max ( tree . getNodeHeight ( i ) , tree . getNodeHeight ( CiP ) ) ; oldRange = tree . getNodeHeight ( PiP ) - oldMinAge ; q = newRange / Math . abs ( oldRange ) ; tree . beginTreeEdit ( ) ; if ( j == tree . getRoot ( ) ) { tree . removeChild ( iP , CiP ) ; tree . removeChild ( PiP , iP ) ; tree . addChild ( iP , j ) ; tree . addChild ( PiP , CiP ) ; tree . setRoot ( iP ) ; } else if ( iP == tree . getRoot ( ) ) { tree . removeChild ( k , j ) ; tree . removeChild ( iP , CiP ) ; tree . addChild ( iP , j ) ; tree . addChild ( k , iP ) ; tree . setRoot ( CiP ) ; } else { tree . removeChild ( k , j ) ; tree . removeChild ( iP , CiP ) ; tree . removeChild ( PiP , iP ) ; tree . addChild ( iP , j ) ; tree . addChild ( k , iP ) ; tree . addChild ( PiP , CiP ) ; } tree . setNodeHeight ( iP , newAge ) ; tree . endTreeEdit ( ) ; logq = Math . log ( q ) ; }
warning : assumes strictly bifurcating tree .
