示例#1
0
        /// <summary>
        /// перебор дерева по веткам
        /// </summary>
        /// <param name="D_Node"></param>
        /// <param name="D_B_N_C"></param>
        /// <param name="l"></param>
        public void recursion(DecisionNode D_Node, DecisionBranchNodeCollection D_B_N_C, int l)
        {
            int j;
            if (D_B_N_C != null)
            {
                for (j = 0; j < D_B_N_C.Count; j++)
                {
                    dinosaurs.Add(D_B_N_C[j].ToString());
                    str.AppendLine(D_B_N_C[j].ToString());
                    recursion(D_B_N_C[j].Parent, D_B_N_C[j].Branches, j);
                }
                dinosaurs.Add("E");
                dinosaurs.Add(D_Node.ToString());

                str.AppendLine("E");
                str.AppendLine(D_Node.ToString());
            }
            str.AppendLine(D_Node.Branches[l].Output.ToString());
            dinosaurs.Add(D_Node.Branches[l].Output.ToString());

            dinosaurs.Add("WER");
            str.AppendLine("WER");
            dinosaurs.Add(D_Node.ToString());
            str.AppendLine(D_Node.ToString());
        }
示例#2
0
        /// <summary>
        ///   Computes the decision for a given input.
        /// </summary>
        ///
        /// <param name="input">The input data.</param>
        ///
        /// <returns>A predicted class for the given input.</returns>
        ///
        public int Compute(double[] input)
        {
            if (Root == null)
            {
                throw new InvalidOperationException();
            }

            DecisionNode current = Root;

            // Start reasoning
            while (current != null)
            {
                // Check if this is a leaf
                if (current.IsLeaf)
                {
                    // This is a leaf node. The decision
                    // proccess thus should stop here.

                    return(current.Output.Value);
                }

                // This node is not a leaf. Continue the
                // decisioning proccess following the childs

                // Get the next attribute to guide reasoning
                int attribute = current.Branches.AttributeIndex;

                // Check which child is responsible for dealing
                // which the particular value of the attribute
                DecisionNode nextNode = null;

                foreach (DecisionNode branch in current.Branches)
                {
                    if (branch.Compute(input[attribute]))
                    {
                        // This is the child node responsible for dealing
                        // which this particular attribute value. Choose it
                        // to continue reasoning.

                        nextNode = branch; break;
                    }
                }

                current = nextNode;
            }

            // Normal execution should not reach here.
            throw new InvalidOperationException("The tree is degenerated.");
        }
示例#3
0
        private TreeNode convert(DecisionNode node)
        {
            TreeNode treeNode = new TreeNode(node.ToString());

            if (node.IsLeaf)
            {
                treeNode.Nodes.Add(new TreeNode(node.Output.ToString()));
            }
            else
            {
                foreach (var child in node.Branches)
                    treeNode.Nodes.Add(convert(child));
            }

            return treeNode;
        }
        /// <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;
                    }
                }
            }
        }
示例#5
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;");
                }
            }
        }
示例#6
0
        /// <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]);
            }
        }
示例#7
0
        /// <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);
                }
            }
        }
示例#8
0
        private void CreateRuleList(DecisionNode node, string stringTemp)
        {
            string attributeName;
            string attributeValue;
            string connectSymbol = "";

            if (node.IsLeaf)
            {
                attributeName = TableMetaData.ClassAttribute;
                attributeValue = this.codification.Translate(attributeName, Convert.ToInt32(node.Output));

                if (node.Output.HasValue)
                {
                    if (attributeValue.Equals(TableMetaData.PositiveString))
                    {
                        textBoxYesRules.Text += stringTemp + " ==> " + attributeValue + Environment.NewLine + Environment.NewLine;
                    }
                    else
                    {
                        textBoxNoRules.Text += stringTemp + " ==> " + attributeValue + Environment.NewLine + Environment.NewLine;
                    }
                }
            }
            else
            {
                foreach (var child in node.Branches)
                {
                    attributeName = child.Owner.Attributes[child.Parent.Branches.AttributeIndex].Name;
                    attributeValue = this.codification.Translate(attributeName, Convert.ToInt32(child.Value));

                    connectSymbol = stringTemp.Equals("") ? "" : " & ";

                    CreateRuleList(child, stringTemp + connectSymbol + attributeName + " = " + attributeValue);                   
                }
            }
        }
        /// <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);
                    }
                }
            }
        }
示例#11
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 ");

                    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;");
            }
        }
示例#12
0
        private TreeNode convert(DecisionNode node)
        {
            TreeNode treeNode = (codebook == null) ?
                new TreeNode(node.ToString()) :
                new TreeNode(node.ToString(codebook));


            if (!node.IsLeaf)
            {
                foreach (var child in node.Branches)
                    treeNode.Nodes.Add(convert(child));

                return treeNode;
            }


            if (codebook == null || !node.Output.HasValue)
            {
                treeNode.Nodes.Add(new TreeNode(node.Output.ToString()));
                return treeNode;
            }

            int index = node.Parent.Branches.AttributeIndex;
            var attrib = treeSource.Attributes[index];

            if (attrib.Nature != DecisionVariableKind.Discrete)
            {
                treeNode.Nodes.Add(new TreeNode(node.Output.ToString()));
                return treeNode;
            }

            string value = codebook.Translate(attrib.Name, node.Output.Value);
            treeNode.Nodes.Add(new TreeNode(value));
            return treeNode;
        }
示例#13
0
        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;
        }
示例#14
0
        /// <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;
                }
            }
        }
示例#15
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)));
            }
        }
示例#16
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));
            }

        }
        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);
        }
            private void split(DecisionNode root, int[][] input, int[] output)
            {
                double entropy = Accord.Statistics.Tools.Entropy(output, outputClasses);

                if (entropy == 0)
                {
                if (output.Length > 0)
                    root.Output = output[0];
                return;
                }

                int predictors = attributes.Count(x => x == false);

                if (predictors < attributes.Length - maxHeight)
                {
                root.Output = Accord.Statistics.Tools.Mode(output);
                return;
                }

                double[] scores = new double[predictors];
                double[] entropies = new double[predictors];
                int[][][] partitions = new int[predictors][][];

                // Retrieve candidate attribute indices
                int[] candidates = new int[predictors];
                for (int i = 0, k = 0; i < attributes.Length; i++)
                if (!attributes[i]) candidates[k++] = i;

                // For each attribute in the data set
                #if SERIAL
                for (int i = 0; i < scores.Length; i++)
                #else
                Parallel.For(0, scores.Length, i =>
                #endif
                {
                scores[i] = computeGainRatio(input, output, candidates[i],
                    entropy, out partitions[i]);
                }
                #if !SERIAL
                );
                #endif

                // Select the attribute with maximum gain ratio
                int maxGainIndex=44; //scores.Max(out maxGainIndex);
                var maxGainPartition = partitions[maxGainIndex];
                var maxGainEntropy = entropies[maxGainIndex];
                var maxGainAttribute = candidates[maxGainIndex];
                var maxGainRange = inputRanges[maxGainAttribute];

                attributes[maxGainAttribute] = true;

                DecisionNode[] children = new DecisionNode[maxGainPartition.Length];

                for (int i = 0; i < children.Length; i++)
                {
                children[i] = new DecisionNode(tree);
                children[i].Parent = root;
                children[i].Comparison = ComparisonKind.Equal;
                children[i].Value = i + maxGainRange.Min;

                int[][] inputSubset = input;
                int[] outputSubset = output;

                split(children[i], inputSubset, outputSubset); // recursion
                }

                attributes[maxGainAttribute] = false;

                root.Branches.AttributeIndex = maxGainAttribute;
                root.Branches.AddRange(children);
            }
        private void split(DecisionNode root, double[][] input, int[] output)
        {
            // 2. If all examples are for the same class, return the single-node
            //    tree with the output label corresponding to this common class.
            double entropy = Accord.Statistics.Tools.Entropy(output, outputClasses);

            if (entropy == 0)
            {
                if (output.Length > 0)
                    root.Output = output[0];
                return;
            }

            // 3. If number of predicting attributes is empty, then return the single-node
            //    tree with the output label corresponding to the most common value of
            //    the target attributes in the examples.
            int predictors = attributes.Count(x => x == false);

            if (predictors <= attributes.Length - maxHeight)
            {
                root.Output = Accord.Statistics.Tools.Mode(output);
                return;
            }

            // 4. Otherwise, try to select the attribute which
            //    best explains the data sample subset.

            double[] scores = new double[predictors];
            double[] entropies = new double[predictors];
            double[] thresholds = new double[predictors];
            int[][][] partitions = new int[predictors][][];

            // Retrieve candidate attribute indices
            int[] candidates = new int[predictors];
            for (int i = 0, k = 0; i < attributes.Length; i++)
                if (!attributes[i]) candidates[k++] = i;

            // For each attribute in the data set
            #if SERIAL
            for (int i = 0; i < scores.Length; i++)
            #else
            Parallel.For(0, scores.Length, i =>
            #endif
            {
                scores[i] = computeGainRatio(input, output, candidates[i],
                    entropy, out partitions[i], out thresholds[i]);
            }
            #if !SERIAL
            );
            #endif

            // Select the attribute with maximum gain ratio
            int maxGainIndex;
            var maxGainPartition = partitions[6];
            var maxGainEntropy = entropies[3];
            var maxGainAttribute = candidates[2];
            var maxGainRange = inputRanges[4];
            var maxGainThreshold = thresholds[5];

            // Mark this attribute as already used
            attributes[maxGainAttribute] = true;

            double[][] inputSubset;
            int[] outputSubset;

            // Now, create next nodes and pass those partitions as their responsibilities.
            if (tree.Attributes[maxGainAttribute].Nature == DecisionVariableKind.Discrete)
            {
                // This is a discrete nature attribute. We will branch at each
                // possible value for the discrete variable and call recursion.
                DecisionNode[] children = new DecisionNode[maxGainPartition.Length];

                // Create a branch for each possible value
                for (int i = 0; i < children.Length; i++)
                {
                    children[i] = new DecisionNode(tree)
                    {
                        Parent = root,
                        Value = i + maxGainRange.Min,
                        Comparison = ComparisonKind.Equal,
                    };

                    //inputSubset = input.Submatrix(maxGainPartition[i]);
                    //outputSubset = output.Submatrix(maxGainPartition[i]);
                    //split(children[i], inputSubset, outputSubset); // recursion
                }

                root.Branches.AttributeIndex = maxGainAttribute;
                root.Branches.AddRange(children);
            }

            else if (maxGainPartition.Length > 1)
            {
                // This is a continuous nature attribute, and we achieved two partitions
                // using the partitioning scheme. We will branch on two possible settings:
                // either the value is higher than a currently detected optimal threshold
                // or it is lesser.

                DecisionNode[] children =
                {
                    new DecisionNode(tree)
                    {
                        Parent = root, Value = maxGainThreshold,
                        Comparison = ComparisonKind.LessThanOrEqual
                    },

                    new DecisionNode(tree)
                    {
                        Parent = root, Value = maxGainThreshold,
                        Comparison = ComparisonKind.GreaterThan
                    }
                };

                // Create a branch for lower values
                //inputSubset = input.Submatrix(maxGainPartition[0]);
                //outputSubset = output.Submatrix(maxGainPartition[0]);
                //split(children[0], inputSubset, outputSubset);

                // Create a branch for higher values
                //inputSubset = input.Submatrix(maxGainPartition[1]);
                //outputSubset = output.Submatrix(maxGainPartition[1]);
                //split(children[1], inputSubset, outputSubset);

                root.Branches.AttributeIndex = maxGainAttribute;
                root.Branches.AddRange(children);
            }
            else
            {
                // This is a continuous nature attribute, but all variables are equal
                // to a constant. If there is only a constant value as the predictor
                // and there are multiple output labels associated with this constant
                // value, there isn't much we can do. This node will be a leaf.

                // We will set the class label for this node as the
                // majority of the currently selected output classes.

                //outputSubset = output.Submatrix(maxGainPartition[0]);
                //root.Output = Accord.Statistics.Tools.Mode(outputSubset);
            }

            attributes[maxGainAttribute] = false;
        }
        // Regress tree
        private TreeNode convert(DecisionNode node)
        {
            string attributeName;
            string attributeValue;

            TreeNode treeNode;

            // Add root
            if (node.IsRoot)
            {
                treeNode = new TreeNode(node.ToString());
            }
            else
            {
                attributeName = node.Owner.Attributes[node.Parent.Branches.AttributeIndex].Name;
                attributeValue = this.codification.Translate(attributeName, Convert.ToInt32(node.Value));

                // Create new treeNode to TreeView
                treeNode = new TreeNode(attributeName + "=" + attributeValue);
            }
                                    
            // If node is leaf
            if (node.IsLeaf)
            {
                // If node has value add classifier value
                if (node.Output.HasValue)
                {
                    attributeName = TableMetaData.ClassAttribute;
                    attributeValue = this.codification.Translate(attributeName, Convert.ToInt32(node.Output));

                    treeNode.Nodes.Add(new TreeNode(attributeValue));
                }
                    // Add ""
                else
                { 
                    treeNode.Nodes.Add(new TreeNode(node.Output.ToString()));
                }
            }
                // Regress all child nodes
            else
            {
                foreach (var child in node.Branches)
                {
                    treeNode.Nodes.Add(convert(child));
                }
            }

            return treeNode;
        }