/// <summary>
        /// Filters a tree to get the leaf node.
        /// </summary>
        /// <param name="node">The first node of the tree.</param>
        /// <param name="questions">A Dictionary to contains all the Question used by the tree.</param>
        /// <param name="label">The given label.</param>
        /// <returns>The leaf node which match the label.</returns>
        public static DecisionTreeNode FilterTree(DecisionTreeNode node, IDictionary<string, Question> questions, Label label)
        {
            while (node.NodeType != DecisionTreeNodeType.Leaf)
            {
                Question question = questions[node.QuestionName];

                // If the value set of question contains the feature value, it means matched with question mark.
                if (MatchHtsQuestion(question.ValueSet, label.GetFeatureValue(question.FeatureName)))
                {
                    node = node.RightChild;
                }
                else
                {
                    node = node.LeftChild;
                }
            }

            return node;
        }
示例#2
0
        /// <summary>
        /// Compare the DecisionTreeNode, used by List.Sort() method.
        /// </summary>
        /// <param name="firstNode">Source DecisionTreeNode.</param>
        /// <param name="secondNode">Destination DecisionTreeNode.</param>
        /// <returns>Positive for x greater than y, 0 for equal and negative for x less than y.</returns>        
        private static int Compare(DecisionTreeNode firstNode, DecisionTreeNode secondNode)
        {
            Helper.ThrowIfNull(firstNode);
            Helper.ThrowIfNull(secondNode);

            // give leaf node a very low ID to ensure leaf node was put in the end.
            int firstId = int.MinValue / 2;
            int secondId = int.MinValue / 2;
            if (firstNode.NodeType == DecisionTreeNodeType.NonLeaf)
            {
                firstId = int.Parse(firstNode.Name, CultureInfo.InvariantCulture);
            }

            if (secondNode.NodeType == DecisionTreeNodeType.NonLeaf)
            {
                secondId = int.Parse(secondNode.Name, CultureInfo.InvariantCulture);
            }

            return secondId - firstId;
        }
示例#3
0
        /// <summary>
        /// Load the decision tree.
        /// </summary>
        /// <param name="treeLines">Multiple lines to contain the tree information.</param>
        public void Load(Collection<string> treeLines)
        {
            Helper.ThrowIfNull(treeLines);

            // Verify treeLines' format
            if (!(treeLines.Count == 2 || (treeLines.Count >= 4 && treeLines[1].Equals(StartSymbol) &&
                treeLines[treeLines.Count - 1].Equals(EndSymbol))))
            {
                throw new InvalidDataException(Helper.NeutralFormat(
                    "Tree \"{0}\" has invalidate format", treeLines[0]));
            }

            Dictionary<string, DecisionTreeNode> nameNodeMap = new Dictionary<string, DecisionTreeNode>();
            Name = treeLines[0].Trim();

            // Standard format
            if (treeLines.Count >= 4)
            {
                // add non-leaf node in the beginning
                for (int i = 2; i < treeLines.Count - 1; i++)
                {
                    DecisionTreeNode node = new DecisionTreeNode();
                    _nodeList.Add(node);
                    nameNodeMap.Add(NodeIdxToName(i - 2), node);
                }

                for (int i = 2; i < treeLines.Count - 1; i++)
                {
                    string line = treeLines[i];
                    string[] infos = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
                    if (infos.Length != 4)
                    {
                        throw new InvalidDataException(Helper.NeutralFormat(
                            "Tree node format should be \"Name Question NoChild YesChild\": {0}", line));
                    }

                    Debug.Assert(infos[0].Equals(NodeIdxToName(i - 2)));

                    // pick up non-leaf node
                    DecisionTreeNode node = nameNodeMap[infos[0]];
                    node.Name = infos[0];
                    node.QuestionName = infos[1];
                    node.NodeType = DecisionTreeNodeType.NonLeaf;
                    if (infos[2].IndexOf('-') == 0)
                    {
                        // non leaf node
                        Debug.Assert(nameNodeMap.ContainsKey(infos[2]));
                        DecisionTreeNode childNode = nameNodeMap[infos[2]];
                        node.LeftChild = childNode;
                        childNode.Parent = node;
                    }
                    else
                    {
                        // leaf node
                        Debug.Assert(infos[2].IndexOf(LeafNameChar) == 0);
                        DecisionTreeNode leafNode = new DecisionTreeNode();
                        leafNode.Name = infos[2].Trim(LeafNameChar);
                        leafNode.NodeType = DecisionTreeNodeType.Leaf;
                        leafNode.Parent = node;
                        node.LeftChild = leafNode;
                        _leafNodeMap.Add(leafNode.Name, leafNode);
                        _nodeList.Add(leafNode);
                    }

                    if (infos[3].IndexOf('-') == 0)
                    {
                        // non leaf node
                        Debug.Assert(nameNodeMap.ContainsKey(infos[3]));
                        DecisionTreeNode childNode = nameNodeMap[infos[3]];
                        node.RightChild = childNode;
                        childNode.Parent = node;
                    }
                    else
                    {
                        // leaf node
                        Debug.Assert(infos[3].IndexOf(LeafNameChar) == 0);
                        DecisionTreeNode leafNode = new DecisionTreeNode();
                        leafNode.Name = infos[3].Trim(LeafNameChar);
                        leafNode.NodeType = DecisionTreeNodeType.Leaf;
                        leafNode.Parent = node;
                        node.RightChild = leafNode;
                        _leafNodeMap.Add(leafNode.Name, leafNode);
                        _nodeList.Add(leafNode);
                    }
                }
            }
            else
            {
                // one leaf node format
                DecisionTreeNode leafNode = new DecisionTreeNode();
                leafNode.Name = treeLines[1].Trim(LeafNameChar);
                leafNode.NodeType = DecisionTreeNodeType.Leaf;
                _leafNodeMap.Add(leafNode.Name, leafNode);
                _nodeList.Add(leafNode);
            }
        }
示例#4
0
        /// <summary>
        /// Assign a id to certain node and its children.
        /// </summary>
        /// <param name="node">Tree node to visit.</param>
        /// <param name="seq">Node id sequence.</param>
        /// <returns>The next id.</returns>
        private static int TravelOneNode(DecisionTreeNode node, int seq)
        {
            if (node.NodeType == DecisionTreeNodeType.NonLeaf)
            {
                node.Name = NodeIdxToName(seq);
                seq++;
                seq = TravelOneNode(node.LeftChild, seq);
                seq = TravelOneNode(node.RightChild, seq);
            }

            return seq;
        }
示例#5
0
        /// <summary>
        /// PreOrder decision tree traversal.
        /// </summary>
        /// <param name="node">Start node for traversal.</param>
        /// <param name="visitor">Visitor funclet.</param>
        /// <returns>True if the visitor needs continue at current node; false otherwise.</returns>
        public static bool PreOrderVisit(DecisionTreeNode node, Func<DecisionTreeNode, bool> visitor)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }

            if (visitor == null)
            {
                throw new ArgumentNullException("visitor");
            }

            var needContinue = visitor(node);

            if (needContinue && node.NodeType == DecisionTreeNodeType.NonLeaf)
            {
                needContinue = PreOrderVisit(node.LeftChild, visitor);
            }

            if (needContinue && node.NodeType == DecisionTreeNodeType.NonLeaf)
            {
                needContinue = PreOrderVisit(node.RightChild, visitor);
            }

            return needContinue;
        }