Example #1
0
        private void btnCheat_Click(object sender, EventArgs e)
        {
            //generate 15 random answers
            for (int n = 0; n < 15; n++)
            {
                string[] simulations = new string[10];
                for (int q = 0; q < 10; q++)
                {
                    List <string> possibilities = set1.Possibilities[q];
                    int           randomIndex   = r.Next(possibilities.Count);
                    string        generatedAnswer;
                    if (possibilities.Count != 0)
                    {
                        generatedAnswer = possibilities[randomIndex];
                    }
                    else
                    {
                        generatedAnswer = "random free answer";
                    }
                    if (q == 0)
                    {
                        simulations[q] = "SUNNY";
                    }
                    else
                    {
                        simulations[q] = generatedAnswer;
                    }
                }
                Answer ans = new Answer(set1, simulations);
                answers.Add(ans);
                AddAnswerRow(ans);

                lblNumberCount.Text = answers.Count.ToString();
            }
            lblNumberCount.Text = answers.Count.ToString();
            //if (answers.Count > 0) lblNumberCount.Text = answers[answers.Count-1].entries[0];

            inputs = new string[10];

            if (answers.Count >= 15)
            {
                decisionTree      = new Tree();
                decisionTree.Root = Tree.Learn(answersTable, "");
                currentNode       = decisionTree.Root;
                id3enabled        = true;
            }

            if (!id3enabled)
            {
                CurrentQuestionIndex = 0;
            }
            else
            {
                CurrentQuestionIndex = IndexFromFactor(currentNode.Name);
            }
        }
Example #2
0
 private DecisionTree.TreeNode NextNodeFromAnswer(string answer, DecisionTree.TreeNode parentNode)
 {
     foreach (DecisionTree.TreeNode n in parentNode.ChildNodes)
     {
         if (n.Edge == answer)
         {
             return(n);
         }
     }
     return(new DecisionTree.TreeNode(true, "newpath", "")); //if this is a new case
 }
Example #3
0
        /// <summary>
        /// Recursive down the decision tree using the example's attributes
        /// until we hit a leaf node, which has the class label
        /// </summary>
        private static string GetClassLabel(TreeNode decisionTree, Example testExample)
        {
            if (decisionTree.ClassLabel != null)
            {
                return decisionTree.ClassLabel;
            }

            var exampleAttrVal = testExample.Attributes[decisionTree.ColNum];

            var subTree = decisionTree.Children[exampleAttrVal];

            return GetClassLabel(subTree, testExample);
        }
Example #4
0
        /// <summary>
        /// Recursively construct decision tree from examples and attributes
        /// </summary>
        private static TreeNode LearnInternal(ICollection<Example> examples, ICollection<DataAttribute> attributes, IEnumerable<Example> parentExamples)
        {
            // if no examples, use parent plurality
            if (examples.Count == 0)
            {
                return PluralityValue(parentExamples);
            }

            // if all examples have same classification, use it
            if (examples.Select(x => x.ClassLabel).Distinct().Count() == 1)
            {
                return new TreeNode
                    {
                        ClassLabel = examples.First().ClassLabel,
                    };
            }

            // if no attributes, use plurality
            if (attributes.Count == 0)
            {
                return PluralityValue(examples);
            }

            // pick most important attribute
            var attr = attributes.OrderByDescending(x => Importance(examples, x)).First();

            // get other attributes
            var remainingAttrs = attributes.Where(x => x != attr).ToList();

            // group the examples by their value for selected attribute
            var examplesByAttrValue = examples.ToLookup(x => x.Attributes[attr.ColNum]);

            // construct a decision tree for this attribute
            var tree = new TreeNode
                {
                    ColNum = attr.ColNum,
                };

            // for each value, recursively construct a sub-tree
            foreach (var attrValue in attr.Values)
            {
                var childExamples = examplesByAttrValue[attrValue].ToList();

                var subTree = LearnInternal(childExamples, remainingAttrs, examples);

                tree.Children.Add(attrValue, subTree);
            }

            return tree;
        }
Example #5
0
        /// <summary>
        /// Serializes the decision tree and writes it into the classifier main program
        /// </summary>
        private static void ReplaceSerializedTreeLine(string mainFilePath, TreeNode decisionTree)
        {
            // double serialize the tree to escape " characters
            var serializedTree = JsonConvert.SerializeObject(JsonConvert.SerializeObject(decisionTree));

            // find the line in the file where we should stick the serialized tree
            const string serializedTreeLine = @"const string serializedDecisionTree = ";

            var fileContents = File.ReadAllText(mainFilePath);
            var lineToReplace = fileContents.Split(new[] { "\r\n" }, StringSplitOptions.None).Single(x => x.Contains(serializedTreeLine));

            // stick the serialized tree in that line
            var newLine = lineToReplace.Substring(0, lineToReplace.IndexOf(serializedTreeLine) + serializedTreeLine.Length) + serializedTree + ";";
            var newContents = fileContents.Replace(lineToReplace, newLine);
            File.WriteAllText(mainFilePath, newContents);
        }
Example #6
0
        private void newAnswer()
        {
            usedQuestions.Clear();
            Answer newAnswer = new Answer(set1, inputs);

            bool IsNewAnswer = true;

            foreach (Answer a in answers)
            {
                if (a.IsSameAnswer(newAnswer))
                {
                    IsNewAnswer = false;
                }
            }

            if (IsNewAnswer)
            {
                answers.Add(newAnswer);
                AddAnswerRow(newAnswer);
                lblNumberCount.Text = answers.Count.ToString();
            }
            //if (answers.Count > 0) lblNumberCount.Text = answers[answers.Count-1].entries[0];

            inputs = new string[10];

            if (answers.Count >= 15)
            {
                decisionTree      = new Tree();
                decisionTree.Root = Tree.Learn(answersTable, "");
                currentNode       = decisionTree.Root;
                id3enabled        = true;
            }

            if (!id3enabled)
            {
                CurrentQuestionIndex = 0;
            }
            else
            {
                CurrentQuestionIndex = IndexFromFactor(currentNode.Name);
            }
        }
Example #7
0
        /// <summary>
        /// Creates a DecisionTreeClassifier.exe from a decision tree, returning the file path of the new exe
        /// </summary>
        public static string CompileClassifier(TreeNode decisionTree)
        {
            var assemblyLocation = Assembly.GetExecutingAssembly().Location;
            var assemblyDirectory = new FileInfo(assemblyLocation).DirectoryName ?? "";

            var classifierDir = Path.Combine(assemblyDirectory, "DecisionTreeClassifier");

            var projFullPath = Path.Combine(classifierDir, "DecisionTreeClassifier.csproj");
            var mainFullPath = Path.Combine(classifierDir, "Program.cs");

            ReplaceSerializedTreeLine(mainFullPath, decisionTree);

            // load up the classifier project
            var proj = new Project(projFullPath);

            // set project to compile special DecisionTree config
            proj.SetProperty("Configuration", "DecisionTree");

            // set the output path
            proj.SetProperty("DecisionTreeOutputPath", assemblyDirectory);

            // make a logger to catch possible build errors
            var logger = new SimpleBuildLogger();

            // if we failed to build the classifier, we're screwed
            if (!proj.Build(logger))
            {
                var sb = new StringBuilder();
                sb.AppendLine("***************************************");
                sb.AppendLine("**** Failed To Compile Classifier! ****");
                sb.AppendLine("***************************************");
                foreach (var error in logger.Errors)
                {
                    sb.AppendLine(error.Message + " " + error.File + ": " + error.LineNumber);
                }
                throw new Exception(sb.ToString());
            }

            // return the executable name
            var exeFileName = proj.GetProperty("AssemblyName").EvaluatedValue + ".exe";
            return Path.Combine(assemblyDirectory, exeFileName);
        }
Example #8
0
        /// <summary>
        /// Classifies test data examples using decision tree, and outputs results to stdout.
        /// </summary>
        public static void Run(TreeNode decisionTree, DataSet testData)
        {
            try
            {
                Console.WriteLine();

                foreach (var example in testData.Examples)
                {
                    var classLabel = GetClassLabel(decisionTree, example);

                    var attrs = example.Attributes.OrderBy(x => x.Key).Select(x => x.Value);

                    Console.WriteLine("{0}   ==> {1}", string.Join(",", attrs), classLabel);
                }
            }
            catch // we will only get an exception if the inputs were invalid
            {
                throw new Exception("Test data cannot be used with decision tree - one of them is invalid.");
            }
        }
Example #9
0
        private void stepButton_Click(object sender, EventArgs e)
        {
            inputs[CurrentQuestionIndex] = cbAnswers.Text;

            if (CurrentQuestionIndex == 9)
            {
                if (id3enabled && cbAnswers.Text != currentNode.Name)
                {
                    AskNextRemainingQuestion();
                    id3enabled = false;
                }//if the final answer is not the one in the tree
                else
                {
                    newAnswer();
                }
            }
            else if (!id3enabled)
            {
                AskNextRemainingQuestion();
            }
            else
            {
                DecisionTree.TreeNode nextNode = NextNodeFromAnswer(inputs[CurrentQuestionIndex], currentNode);
                if (nextNode.IsLeaf && nextNode.Name != "newpath")
                {
                    CurrentQuestionIndex = 9;
                }
                else if (nextNode.Name == "newpath")
                {
                    AskNextRemainingQuestion();
                    id3enabled = false;
                }
                else
                {
                    CurrentQuestionIndex = IndexFromFactor(nextNode.Name);
                }
                currentNode = nextNode;
            }
            stepButton.Enabled = false;
        }
        public double Compute(double[] inputVals)
        {
            currentNode = rootNode;

            foreach (var val in inputVals)
            {
                //if they're equal then use this child...
                var sameValNode = currentNode.Children.FirstOrDefault(n => n.Value == val);
                if (sameValNode != null)
                    currentNode = sameValNode;
                else
                {
                    //if not get the child with the closest value...
                    //order the set by difference first, then whether or not the tree node is observed.
                    var closestNode = (from node in currentNode.Children
                                       select new { Node = node, Diff = Math.Abs(node.Value - val), IsObserved = node is ObservedTreeNode })
                                       .OrderBy(a => a.Diff)
                                       .OrderByDescending(a=>a.IsObserved)
                                       .First();

                    currentNode = closestNode.Node;
                }
            }

            //return the child of the last node...there should be exactly one child...
            if (currentNode.Children.Count == 1)
                return currentNode.Children.First().Value;
            else
                throw new Exception("This tree ain't right.");
        }
        public bool AddBranch(double[] newVals, double answer, bool isObserved)
        {
            currentNode = rootNode;
            foreach (var val in newVals)
            {
                var childCount = currentNode.Children.Count;
                bool addNewNode = false;
                //if there are no current children in the branch then add the current branch as a child.
                if (childCount == 0)
                {
                    addNewNode = true;
                }
                else
                {
                    //if there exist a child with the same value then just move to the next value..
                    var sameValNode = currentNode.Children.FirstOrDefault(n => n.Value == val);
                    if (sameValNode != null)
                    {
                        if (isObserved)
                        {
                            if (sameValNode is ObservedTreeNode)
                                currentNode = sameValNode;
                            else
                            {
                                var newObserved = new ObservedTreeNode(sameValNode.Parent, sameValNode.Children.ToList(), val);
                                currentNode.Children.Remove(sameValNode);
                                currentNode.Children.Add(newObserved);
                                currentNode = newObserved;
                            }
                        }
                        else
                        {
                            currentNode = sameValNode;
                        }
                    }
                    else //otherwise add the new branch as a child...
                        addNewNode = true;
                }

                //add the node
                if (addNewNode)
                {
                    TreeNode newChild = null;
                    if (isObserved)
                        newChild = new ObservedTreeNode(currentNode, null, val);
                    else
                        newChild = new TrainedTreeNode(currentNode, null, val);

                    currentNode.Children.Add(newChild);
                    currentNode = newChild;
                }
            }

            //we're at the last value, so now we need to add the answer node...
            //if any answers already exist then we replace the current answer with this answer.
            currentNode.Children.Clear();
            if (isObserved)
                currentNode.Children.Add(new ObservedTreeNode(currentNode, null, answer));
            else
                currentNode.Children.Add(new TrainedTreeNode(currentNode, null, answer));

            return true;
        }
 public SimpleDecisionTree(TreeNode root)
 {
     rootNode = root;
     currentNode = rootNode;
 }