Tree runID3(IEnumerable<XElement> examples, XName target_attribute
     , List<XName> attribute_list, string exp) {
     Tree root = new Tree();
     if (Entropy(examples) == 0.0) {
         if (getPercentPositive() == 1.0) {
             _expressions.Add("(" + exp.Remove(0, 3) + ")");
             root.setAttributeName("Yes");
         } else root.setAttributeName("No");
         return root;
     }
     if (attribute_list.Count == 0) {
         //only target attribute exists
         if (getPercentPositive() >= 0.5) {
             _expressions.Add("(" + exp.Remove(0, 3) + ")");
             root.setAttributeName("Yes");
         } else root.setAttributeName("No");
         return root;
     }
     //now do main work of algorithm
     XName best = getBestAttribute(examples, attribute_list);
     List<string> p = _dataSet.getPossibleAttributeValues(best);
     root.setAttributeName(best.ToString());
     attribute_list = removeBestAttribute(attribute_list, best);
     exp += " ^ " + best.ToString() + " = ";
     foreach (string s in p) {
         IEnumerable<XElement> subset = _dataSet.refineQuery(examples, best, s);
         Tree t = runID3(subset, target_attribute, attribute_list, (exp + s));
         t.setAttributeValue(s);
         root.Nodes.Add(t);
     }
     return root;
 }