/// <summary>
        ///   Post-order tree traversal method.
        /// </summary>
        ///
        /// <remarks>
        ///   Adapted from John Cowan (1998) recommendation.
        /// </remarks>
        ///
        public static IEnumerator <DecisionNode> PostOrder(DecisionNode tree)
        {
            var cursor = new Dictionary <DecisionNode, int>();

            DecisionNode currentNode = tree;

            while (currentNode != null)
            {
                // Move down to first child
                DecisionNode nextNode = null;
                if (currentNode.Branches != null)
                {
                    nextNode = currentNode.Branches.FirstOrDefault();
                }

                if (nextNode != null)
                {
                    currentNode = nextNode;
                    continue;
                }

                // No child nodes, so walk tree
                while (currentNode != null)
                {
                    yield return(currentNode); // post order

                    // Move to sibling if possible.
                    nextNode = GetNextSibling(cursor, currentNode);

                    if (nextNode != null)
                    {
                        currentNode = nextNode;
                        break;
                    }

                    // Move up
                    if (currentNode == nextNode)
                    {
                        currentNode = null;
                    }
                    else
                    {
                        currentNode = currentNode.Parent;
                    }
                }
            }
        }
        private void create(DecisionNode node, int depth)
        {
            string indent = new string(' ', depth * 4);

            if (!node.IsLeaf)
            {
                int attributeIndex = node.Branches.AttributeIndex;

                // Create all comparison expressions
                for (int i = 0; i < node.Branches.Count; i++)
                {
                    DecisionNode child = node.Branches[i];
                    string       cmp   = ComparisonExtensions.ToString(child.Comparison);

                    if (i == 0)
                    {
                        writer.Write(indent + "if ");
                    }
                    else
                    {
                        writer.Write(indent + "else if ");
                    }

                    writer.Write("(input[{0}] {1} {2}) {{", attributeIndex, cmp, child.Value);
                    writer.WriteLine();
                    create(child, depth + 1);
                    writer.WriteLine(indent + "}");
                }

                writer.WriteLine(indent + "else throw new ArgumentException(\"input\", \"Unexpected value at position " + attributeIndex + ".\");");
            }

            else // node is a leaf
            {
                if (node.Output.HasValue)
                {
                    writer.WriteLine(indent + "return " + node.Output.Value + ";");
                }
                else
                {
                    writer.WriteLine(indent + "return -1;");
                }
            }
        }
        /// <summary>
        ///   Depth-first traversal method.
        /// </summary>
        ///
        public static IEnumerator <DecisionNode> DepthFirst(DecisionNode tree)
        {
            if (tree == null)
            {
                yield break;
            }

            var stack = new Stack <DecisionNode>(new[] { tree });

            while (stack.Count != 0)
            {
                DecisionNode current = stack.Pop();

                yield return(current);

                if (current.Branches != null)
                {
                    for (int i = current.Branches.Count - 1; i >= 0; i--)
                    {
                        stack.Push(current.Branches[i]);
                    }
                }
            }
        }
        /// <summary>
        ///   Breadth-first traversal method.
        /// </summary>
        ///
        public static IEnumerator <DecisionNode> BreadthFirst(DecisionNode tree)
        {
            if (tree == null)
            {
                yield break;
            }

            var queue = new Queue <DecisionNode>(new[] { tree });

            while (queue.Count != 0)
            {
                DecisionNode current = queue.Dequeue();

                yield return(current);

                if (current.Branches != null)
                {
                    foreach (var child in current.Branches)
                    {
                        queue.Enqueue(child);
                    }
                }
            }
        }
        internal static DecisionNode GetNextSibling(Dictionary <DecisionNode, int> cursors, DecisionNode node)
        {
            var parent = node.Parent;

            if (parent == null)
            {
                return(null);
            }

            // Get current node index
            int index;

            if (!cursors.TryGetValue(node, out index))
            {
                cursors[node] = index = 0;
            }

            int nextIndex = index + 1;

            if (nextIndex < parent.Branches.Count)
            {
                var sibling = parent.Branches[nextIndex];
                cursors[sibling] = nextIndex;
                return(sibling);
            }

            return(null);
        }
Exemple #6
0
        private Expression create(DecisionNode node)
        {
            if (!node.IsLeaf)
            {
                int attributeIndex = node.Branches.AttributeIndex;

                // Create all comparison expressions
                BinaryExpression[] comparisons     = new BinaryExpression[node.Branches.Count];
                Expression[]       childExpression = new Expression[node.Branches.Count];

                for (int i = 0; i < comparisons.Length; i++)
                {
                    DecisionNode child = node.Branches[i];

                    var expr = Expression.ArrayIndex(inputs, Expression.Constant(attributeIndex));
                    var cons = Expression.Constant(child.Value);

                    switch (child.Comparison)
                    {
                    case ComparisonKind.Equal:
                        comparisons[i] = Expression.Equal(expr, cons); break;

                    case ComparisonKind.GreaterThan:
                        comparisons[i] = Expression.GreaterThan(expr, cons); break;

                    case ComparisonKind.GreaterThanOrEqual:
                        comparisons[i] = Expression.GreaterThanOrEqual(expr, cons); break;

                    case ComparisonKind.LessThan:
                        comparisons[i] = Expression.LessThan(expr, cons); break;

                    case ComparisonKind.LessThanOrEqual:
                        comparisons[i] = Expression.LessThanOrEqual(expr, cons); break;

                    case ComparisonKind.NotEqual:
                        comparisons[i] = Expression.NotEqual(expr, cons); break;

                    default:
                        throw new InvalidOperationException("Unexpected node comparison type.");
                    }


                    childExpression[i] = create(node.Branches[i]);
                }

                // Create expression for else expressions
                ConstructorInfo ex = typeof(ArgumentException).GetConstructor(new[] { typeof(string), typeof(string) });

                var lastElse = Expression.IfThenElse(comparisons[comparisons.Length - 1],
                                                     childExpression[comparisons.Length - 1],
                                                     Expression.Throw(Expression.New(ex,
                                                                                     Expression.Constant("Input contains a value outside of expected ranges."),
                                                                                     Expression.Constant("input"))));

                ConditionalExpression currentIf = null;
                for (int i = comparisons.Length - 2; i >= 0; i--)
                {
                    currentIf = Expression.IfThenElse(comparisons[i],
                                                      childExpression[i], lastElse);
                    lastElse = currentIf;
                }

                return(currentIf);
            }

            else // node is a leaf
            {
                if (node.Output.HasValue)
                {
                    return(Expression.Return(label, Expression.Constant(node.Output.Value), typeof(int)));
                }
                return(Expression.Return(label, Expression.Constant(-1), typeof(int)));
            }
        }