private ExpressionNode optimize(ExpressionNode node, ContextIndex context) {
        if (node instanceof OperationNode) {
            Iterator<ExpressionNode> childIt = ((OperationNode)node).children().iterator();
            ExpressionNode ret = optimize(childIt.next(), context);

            Iterator<Operator> operIt = ((OperationNode)node).operators().iterator();
            while (childIt.hasNext() && operIt.hasNext()) {
                ret = OperationNode.resolve(ret, operIt.next(), optimize(childIt.next(), context));
            }
            return ret;
        }
        if (node instanceof IfNode) {
            return createGBDTNode((IfNode)node, context);
        }
        return node;
    }
<p>Recursively optimize nodes of the form ArithmeticNode(IfNode,ArithmeticNode(IfNode)) etc., ignore
anything else.</p>

<p>Each condition node is converted to the double sequence [(OperatorIsEquals ? GBDTNode.MAX_VARIABLES : 0) +
IndexOfLeftComparisonFeature+GBDTNode.MAX_LEAF_VALUE, ValueOfRightComparisonValue,#OfValuesInTrueBranch,true
branch values,false branch values]</p>

<p>Each value node is converted to the double value of the value node itself.</p>

@return the optimized expression
searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/gbdtoptimization/GBDTOptimizer.java