/// <summary>
        /// Gets the selective tri-phone for each leaf nodes in the tree.
        /// </summary>
        /// <param name="nodeToTriphone">The selective tri-phone for first node in decision tree. The key is the leaf node, and the tri-phone pair set is the value.</param>
        /// <param name="questions">The related questions.</param>
        private static void GetSelectiveTriphone(Dictionary<DecisionTreeNode, TriphoneSet> nodeToTriphone,
            IDictionary<string, Question> questions)
        {
            while (true)
            {
                // Check whether there are some non-leaf nodes?
                IEnumerable<DecisionTreeNode> list = nodeToTriphone.Keys.Where(o => o.NodeType == DecisionTreeNodeType.NonLeaf);
                if (list.Count() == 0)
                {
                    // All the data are leaf nodes, just break to return them.
                    break;
                }

                // Process the first non-leaf node.
                DecisionTreeNode node = list.First();
                TriphoneSet parentSet = nodeToTriphone[node];
                nodeToTriphone.Remove(node);
                Question question = questions[node.QuestionName];

                // Check the question of this node.
                // Copy from parent.
                TriphoneSet leftChildSet = parentSet;
                TriphoneSet rightChildSet = new TriphoneSet(parentSet);
                switch (question.FeatureName)
                {
                    case LabelFeatureNameSet.CentralPhonemeFeatureName:
                        // It is central phone question.
                        // Right child (YES child) will only contains the ones which occur simultaneously in the question set and parent set.
                        // Left child (NO child) will contains the ones which in parent set but not in question set.
                        rightChildSet.CentralPhones.IntersectWith(question.ValueSet);
                        leftChildSet.CentralPhones.ExceptWith(question.ValueSet);
                        break;
                    case LabelFeatureNameSet.LeftPhonemeFeatureName:
                        // Left phone question.
                        // Right child (YES child) will only contains the ones which occur simultaneously in the question set and parent set.
                        // Left child (NO child) will contains the ones which in parent set but not in question set.
                        rightChildSet.LeftPhones.IntersectWith(question.ValueSet);
                        leftChildSet.LeftPhones.ExceptWith(question.ValueSet);
                        break;
                    case LabelFeatureNameSet.RightPhonemeFeatureName:
                        // Right phone question.
                        // Right child (YES child) will only contains the ones which occur simultaneously in the question set and parent set.
                        // Left child (NO child) will contains the ones which in parent set but not in question set.
                        rightChildSet.RightPhones.IntersectWith(question.ValueSet);
                        leftChildSet.RightPhones.ExceptWith(question.ValueSet);
                        break;
                    default:
                        // This question have nothing about phone. Just copy the set from parent.
                        break;
                }

                // Add the two children.
                nodeToTriphone.Add(node.LeftChild, leftChildSet);
                nodeToTriphone.Add(node.RightChild, rightChildSet);
            }
        }
 /// <summary>
 /// Initializes a new instance of the TriphoneSet class as a copy of the given instance.
 /// </summary>
 /// <param name="set">The set to copied.</param>
 public TriphoneSet(TriphoneSet set)
 {
     LeftPhones = new HashSet<string>(set.LeftPhones.OrderBy(p => p));
     CentralPhones = new HashSet<string>(set.CentralPhones.OrderBy(p => p));
     RightPhones = new HashSet<string>(set.RightPhones.OrderBy(p => p));
 }
        /// <summary>
        /// Gets the selective tri-phone for each leaf nodes in the tree.
        /// </summary>
        /// <param name="tree">The given tree.</param>
        /// <param name="questions">The related questions.</param>
        /// <param name="phonemes">The whole set of phoneme, which is used to initialize the tri-phone pairs.</param>
        /// <returns>The selective tri-phone for each leaf node in decision tree.
        /// The key is the leaf node, and the tri-phone pair set is the value.</returns>
        private static Dictionary<DecisionTreeNode, TriphoneSet> GetSelectiveTriphone(DecisionTree tree, IDictionary<string, Question> questions, HashSet<string> phonemes)
        {
            Dictionary<DecisionTreeNode, TriphoneSet> nodeToTriphone = new Dictionary<DecisionTreeNode, TriphoneSet>();

            // Firstly, generate a whole tri-phone set.
            TriphoneSet set = new TriphoneSet(phonemes);

            // Phone-dependent tree should resize the central phone set.
            string phone = tree.Phone;
            if (!Phoneme.IsAnyPhone(phone))
            {
                set.CentralPhones.Clear();
                set.CentralPhones.Add(phone);
            }

            // Assign the tri-phone set to the root of the tree.
            nodeToTriphone.Add(tree.NodeList[0], set);

            GetSelectiveTriphone(nodeToTriphone, questions);
            return nodeToTriphone;
        }