/**
  * Rewrite expression tree to update the leaves.
  * @param root the root of the tree to fix
  * @param leafReorder a map from old leaf ids to new leaf ids
  * @return the fixed root
  */
 static ExpressionTree rewriteLeaves(ExpressionTree root,
                                     int[] leafReorder)
 {
     if (root.getOperator() == ExpressionTree.Operator.LEAF)
     {
         return(new ExpressionTree(leafReorder[root.getLeaf()]));
     }
     else if (root.getChildren() != null)
     {
         List <ExpressionTree> children = root.getChildren();
         for (int i = 0; i < children.Count; ++i)
         {
             children[i] = rewriteLeaves(children[i], leafReorder);
         }
     }
     return(root);
 }
 /**
  * Recursively explore the tree to find the leaves that are still reachable
  * after optimizations.
  * @param tree the node to check next
  * @param next the next available leaf id
  * @param leafReorder
  * @return the next available leaf id
  */
 static int compactLeaves(ExpressionTree tree, int next, int[] leafReorder)
 {
     if (tree.getOperator() == ExpressionTree.Operator.LEAF)
     {
         int oldLeaf = tree.getLeaf();
         if (leafReorder[oldLeaf] == -1)
         {
             leafReorder[oldLeaf] = next++;
         }
     }
     else if (tree.getChildren() != null)
     {
         foreach (ExpressionTree child in tree.getChildren())
         {
             next = compactLeaves(child, next, leafReorder);
         }
     }
     return(next);
 }
 /**
  * Rewrite expression tree to update the leaves.
  * @param root the root of the tree to fix
  * @param leafReorder a map from old leaf ids to new leaf ids
  * @return the fixed root
  */
 static ExpressionTree rewriteLeaves(ExpressionTree root,
                                     int[] leafReorder)
 {
     if (root.getOperator() == ExpressionTree.Operator.LEAF)
     {
         return new ExpressionTree(leafReorder[root.getLeaf()]);
     }
     else if (root.getChildren() != null)
     {
         List<ExpressionTree> children = root.getChildren();
         for (int i = 0; i < children.Count; ++i)
         {
             children[i] = rewriteLeaves(children[i], leafReorder);
         }
     }
     return root;
 }
 /**
  * Recursively explore the tree to find the leaves that are still reachable
  * after optimizations.
  * @param tree the node to check next
  * @param next the next available leaf id
  * @param leafReorder
  * @return the next available leaf id
  */
 static int compactLeaves(ExpressionTree tree, int next, int[] leafReorder)
 {
     if (tree.getOperator() == ExpressionTree.Operator.LEAF)
     {
         int oldLeaf = tree.getLeaf();
         if (leafReorder[oldLeaf] == -1)
         {
             leafReorder[oldLeaf] = next++;
         }
     }
     else if (tree.getChildren() != null)
     {
         foreach (ExpressionTree child in tree.getChildren())
         {
             next = compactLeaves(child, next, leafReorder);
         }
     }
     return next;
 }