//classifies the dataset with ID = id
        public ActionResult Index(int id)
        {
            //remove any data from the trees and nodes tables
            foreach(var t in db.Trees.ToList())
            {
                db.Trees.Remove(t);
            }
            foreach(var n in db.Nodes.ToList())
            {
                db.Nodes.Remove(n);
            }
            db.SaveChanges();

            Models.DataSet dataset = db.DataSets.Single(i => i.ID == id);
            List<Instance> instances = db.Instances.Where(i => i.DataSetID == dataset.ID).ToList();
            List<Tree> decisionTrees = new List<Tree>();
            List<double> successRates = new List<double>();
            List<string> correctlyClassifiedInstances = new List<string>();
            Tree decisionTree;

            //stringwriter for exporting to CSV
            results = new StringWriter();
            results.WriteLine("\"Test No.\",\"Predicted Class\",\"Actual Class\"");
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add(new DataColumn("ID"));
            //performs the following sequence 10 times, as specified
            for (int j = 0; j < 10; j++)
            {
                decisionTree = new Tree { Name = dataset.Name + " Tree" };
                db.Trees.Add(decisionTree);
                db.SaveChanges();
                decisionTrees.Add(decisionTree);

                //generates testing and training lists from the datasets instances: 1/3 testing and 2/3 training
                int noOfTestingDataInstances = instances.Count / 3;
                List<Instance> testingInstances = new List<Instance>();
                List<Instance> trainingInstances = new List<Instance>();
                for (int i = 0; i < noOfTestingDataInstances; i++)
                {
                    var x = rnd.Next(instances.Count);
                    testingInstances.Add(instances.ElementAt(rnd.Next(instances.Count)));
                }
                trainingInstances = instances.Where(i => testingInstances.Contains(i) == false).ToList();

                //generates a decision tree based on the training instances
                attributesUsedSoFar = new List<string>();
                CreateDecisionTree(trainingInstances, new Node { EdgeValue = null }, decisionTree.ID, String.Empty, null);

                //classifies each test instance based on the current decision tree, and computes a list of success rates
                double successes = 0;
                double failures = 0;
                foreach (var i in testingInstances)
                {
                    string result = classifyInstance(i, decisionTree);
                    results.WriteLine("\"{0}\",\"{1}\",\"{2}\"", j+1, result, i.Class);
                    if (result == i.Class)
                        successes++;
                    else
                        failures++;
                }
                results.WriteLine();
                double successRate = successes / testingInstances.Count;
                successRate = Math.Round(successRate, 6);
                successRates.Add(successRate * 100);
                Math.Round(successes, 0);
                correctlyClassifiedInstances.Add(successes.ToString()+"/"+(testingInstances.Count.ToString()));
            }

            //outputs the success rates and the decision trees nodes to the view
            ViewBag.SuccessRates = successRates;
            ViewBag.CorrectlyClassifiedInstances = correctlyClassifiedInstances;
            ViewBag.TestInstances = (instances.Count / 3).ToString();
            ViewBag.TrainingInstances = (instances.Count - (instances.Count / 3)).ToString();
            ViewBag.TotalInstances = instances.Count.ToString();
            ViewBag.AverageSuccessRate = Math.Round(successRates.Average(),2);
            int decisionTreeId = decisionTrees.ElementAt(successRates.IndexOf(successRates.Max())).ID;
            List<Node> decisionTreeNodes = db.Nodes.Where(i => i.TreeID == decisionTreeId).OrderBy(i=>i.ID).ThenBy(i=>i.ParentID).ToList();
            return View(decisionTreeNodes);
        }
        //classifies an instance - returns "" if the instance cannot be classified
        private string classifyInstance(Instance instance, Tree tree)
        {
            Node selectedNode = db.Nodes.Single(i => i.ParentID < 1 && i.TreeID == tree.ID);

            while (db.Nodes.Where(i => i.ParentID == selectedNode.ID).Count() > 0)
            {
                Boolean result = false;
                List<Node> childNodes = db.Nodes.Where(i => i.ParentID == selectedNode.ID).ToList();

                int j = 0;
                while (result != true)
                {
                    if (j >= childNodes.Count)
                        return ""; // this is the case where the instance cannot be classified, this can happen occasionally with nominal data
                    Node childNode = childNodes.ElementAt(j);
                    result = checkBranch(instance, selectedNode, childNode);
                    if (result == true)
                    {
                        selectedNode = childNodes.ElementAt(j);
                    }
                    j++;
                }
            }
            return selectedNode.Attribute;
        }