/// <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;
                    }
                }
            }
        }
Beispiel #2
0
        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 ");
                    }

                    string value = child.Value.Value.ToString(CultureInfo.InvariantCulture);

                    writer.Write("(input[{0}] {1} {2}) {{", attributeIndex, cmp, 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)
                {
                    string value = node.Output.Value.ToString(CultureInfo.InvariantCulture);
                    writer.WriteLine(indent + "return " + 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);
        }