public OptimalSolution <T> FindBestPartition(List <T> rows)
        {
            OptimalSolution <T> solution = new OptimalSolution <T>();
            double    bestGain           = 0;
            Query <T> bestQuery          = null;
            double    currentImpurity    = this.Gini(rows);

            Console.WriteLine("Rows: " + rows.Count + "\nGini: " + currentImpurity);

            int attributesN = rows.ElementAt(0).getAttributes().Length - 1;

            for (int i = 0; i < attributesN; i++)
            {
                List <String> attributesValue = new List <string>();

                foreach (T row in rows)
                {
                    String val = row.getAttributes()[i];

                    /*foreach (String val in attributesValue)
                     * {*/
                    Query <T> query = new Query <T>(i, val);

                    List <T>[] partition = this.Partition(rows, query);

                    if (partition[0].Count > 0 && partition[1].Count > 0)
                    {
                        double gain = InformationGain(partition[0], partition[1], currentImpurity);
                        if (gain >= bestGain)
                        {
                            bestGain  = gain;
                            bestQuery = query;

                            solution.SetGain(gain);
                            solution.SetQuery(query);
                        }

                        /*}*/
                    }
                }
            }

            //Console.WriteLine("Gain -> "+solution.GetGain()+"\nQuery -> "+solution.GetQuery());
            return(solution);
        }
        public Node <T> BuildTree(List <T> rows)
        {
            OptimalSolution <T> solution = this.FindBestPartition(rows);

            //Console.WriteLine("Solution - >"+solution.GetGain());

            if (solution.GetGain() == 0)
            {
                return(new Node <T>(this.CountLabelDistribution(rows)));
            }

            List <T>[] partition = this.Partition(rows, solution.GetQuery());

            //Console.WriteLine("AAAAAAAHH - > "+partition[0].Count+"\nBEEEEHH - > "+partition[1].Count);

            Node <T> trueBranch  = BuildTree(partition[0]);
            Node <T> falseBranch = BuildTree(partition[1]);

            return(new Node <T>(solution.GetQuery(), trueBranch, falseBranch));
        }