using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Intemi;
using Intemi.Query;
using Intemi.Classifiers.DT;
using Intemi.InTrees;
using Intemi.InTrees.Implements;

namespace InTreesPrg
{
    public class InTreesExpl
    {
        static protected string dataPath = 
            Environment.GetEnvironmentVariable("CI_DATA", EnvironmentVariableTarget.User);

        static void W(string title, string seriesSTR)
        {
            Console.WriteLine("{0}:\n{1}\n", title, seriesSTR);
        }
        static void W(string title, Series s)
        {
            W(title, s.ToStringAllSeries());
        }


        public static void TestyPorownawczeKlasyfikatorow(Project project)
        {
            IDictionary d = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User);
            ConfigBase dc = project.GetConfiguration("GM data loader");
            DataLoaderConfig dcfg = (DataLoaderConfig)dc.Configuration;
            //dcfg.InputFileName = dataPath + "MUSHROOM.DAT";
            //dcfg.InputFileName = dataPath + "Thyroid2.dat";
            //dcfg.InputFileName = dataPath + "heartNoMissing.dat";
            //dcfg.InputFileName = dataPath + "breast-cancer-wisconsin.dat";
            dcfg.InputFileName = dataPath + "iris.dat";
            Capsule dcaps = project.Create(dc);

            ConfigBase mtConfigBase =
                CITools.Repeater_CVConfig(project, dcaps, "Dataset");
            ((RepeaterConfig)mtConfigBase.Configuration).Count = 10;

            const int K = 8;
            int i;

            ConfigBase[] treeConfig = new ConfigBase[K];
            InTreeConfig[] ccConf = new InTreeConfig[K];
            Pruning2Config[] pConf = new Pruning2Config[K];
            ConfigBase[] testConfig = new ConfigBase[K];

            #region tree1
            i = 0;
            treeConfig[i] = project.GetConfiguration("INTREE");
            ccConf[i] = (InTreeConfig)treeConfig[i].Configuration;
            ccConf[i].Pruning = new Pruning2();
            ccConf[i].NodeTestGenerator = new BinaryTestGenerator();
            ccConf[i].NodeTestSelector = new Gini();
            ccConf[i].StoppingCriterium = new NaturalStoppingCriterium();
            ccConf[i].TargetSelector = new TargetSelector();
            ccConf[i].PruningMode = InTreeConfig.PRUNING_AUTO;

            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region tree2
            i = 1;
            treeConfig[i] = project.GetConfiguration("INTREE");
            ccConf[i] = (InTreeConfig)treeConfig[i].Configuration;
            ccConf[i].Pruning = new Pruning2();
            ccConf[i].NodeTestGenerator = new MultiSplitTestGenerator();
            ccConf[i].NodeTestSelector = new InfoGainNTS(true);
            ccConf[i].StoppingCriterium = new NaturalStoppingCriterium();
            ccConf[i].TargetSelector = new TargetSelector();
            ccConf[i].PruningMode = InTreeConfig.PRUNING_AUTO;

            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region tree3
            i = 2;
            treeConfig[i] = project.GetConfiguration("INTREE");
            ccConf[i] = (InTreeConfig)treeConfig[i].Configuration;
            ccConf[i].Pruning = new Pruning2();
            ccConf[i].NodeTestGenerator = new BinaryTestGenerator();
            ccConf[i].NodeTestSelector = new InfoGainNTS(true);
            ccConf[i].StoppingCriterium = new NaturalStoppingCriterium();
            ccConf[i].TargetSelector = new TargetSelector();
            ccConf[i].PruningMode = InTreeConfig.PRUNING_AUTO;

            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region tree4
            i = 3;
            treeConfig[i] = project.GetConfiguration("INTREE");
            ccConf[i] = (InTreeConfig)treeConfig[i].Configuration;
            ccConf[i].Pruning = new Pruning2();
            ccConf[i].NodeTestGenerator = new MultiSplitTestGenerator();
            ccConf[i].NodeTestSelector = new Gini();
            ccConf[i].StoppingCriterium = new NaturalStoppingCriterium();
            ccConf[i].TargetSelector = new TargetSelector();
            ccConf[i].PruningMode = InTreeConfig.PRUNING_AUTO;

            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region tree5
            i = 4;
            treeConfig[i] = project.GetConfiguration("INTREE");
            ccConf[i] = (InTreeConfig)treeConfig[i].Configuration;
            ccConf[i].Pruning = new Pruning2();
            ccConf[i].NodeTestGenerator = new MultiSplitTestGenerator();
            ccConf[i].NodeTestSelector = new InfoGainNTS(true);
            ccConf[i].StoppingCriterium = new NodePuritySC(0.8);
            ccConf[i].TargetSelector = new TargetSelector();
            ccConf[i].PruningMode = InTreeConfig.PRUNING_NONE;

            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region tree6
            i = 5;
            treeConfig[i] = project.GetConfiguration("INTREE");
            ccConf[i] = (InTreeConfig)treeConfig[i].Configuration;
            ccConf[i].Pruning = new Pruning2();
            ccConf[i].NodeTestGenerator = new BinaryTestGenerator();
            ccConf[i].NodeTestSelector = new Gini();

            List<IStoppingCriterion> criteriums = new List<IStoppingCriterion>();
            criteriums.Add(new MinNodeSizeSC(6));
            criteriums.Add(new NodePuritySC(0.7));
            ccConf[i].StoppingCriterium = new CommitteeSC(criteriums, CommitteeSC.OP_AND);

            ccConf[i].TargetSelector = new TargetSelector();
            ccConf[i].PruningMode = InTreeConfig.PRUNING_NONE;

            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region meta tree
            i = 6;
            treeConfig[i] = project.GetConfiguration("META TREE2");
            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region ssv
            i = 7;
            treeConfig[i] = project.GetConfiguration("Validated SSV decision tree");
            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            for (int j = 0; j < K; j++)
            {
                testConfig[j] =
                    project.GetConfiguration("Classification test", string.Format("Tree{0} Test", j + 1));
                testConfig[j].Inputs.BindParentInput("Dataset", "Test dataset");
                testConfig[j].Inputs.BindSiblingConfig("Classifier", j, "Classifier");
                testConfig[j].DeclareCommentator(new CorrectnessCommentator());
            }

            for (int j = 0; j < K; j++)
            {
                mtConfigBase.Subconfigurations[1].Subconfigurations.Add(j, treeConfig[j]);
                mtConfigBase.Subconfigurations[1].Subconfigurations.Add(j + K, testConfig[j]);
            }

            ((TTDistributionBoardConfig)mtConfigBase.Subconfigurations[0].Subconfigurations[0].Configuration).Count = 5;
            Capsule mt = project.Create(mtConfigBase);
            project.WaitAll();

            Query q, q1;
            Series[] s = new Series[K];

            for (int j = 0; j < K; j++)
            {
                q = new Query();
                q.Root = mt;
                q.AddMachineConfig(testConfig[j]);
                q.MainLabel = "Accuracy";
                s[j] = q.Series;
            }

            Console.WriteLine("-------------------------  PODSTAWOWE STATYSTYKI");

            for (int p = 0; p < K; p++)
            {
                for (int r = p + 1; r < K; r++)
                {
                    W(string.Format("N Test T{0} -- T{1}", p + 1, r + 1), (new NTest()).Transform(s[p], s[r]));
                }
            }

            for (int j = 0; j < K; j++)
            {
                s[j] = s[j].Group("Repetition").MAP(new BasicStatistics()).Ungroup();
                W(string.Format("T{0}", j + 1), s[j].Transform(new BasicStatistics()));
            }

            for (int p = 0; p < K; p++)
            {
                for (int r = p + 1; r < K; r++)
                {
                    W(string.Format("T{0} -- T{1}", p + 1, r + 1), s[p] - s[r]);
                }
            }

            
            Series sx;
            for (int p = 0; p < K; p++)
            {
                for (int r = p + 1; r < K; r++)
                {
                    Console.WriteLine(string.Format("------------------------- Wyniki testów dla drzew T{0} -- T{1}", p + 1, r + 1));

                    sx = (new TTestPaired()).Transform(s[p], s[r]);
                    W(string.Format("Sparowany T-test T{0} -- T{1}", p + 1, r + 1), sx);

                    sx = (new WilcoxonSignedRankTest()).Transform(s[p], s[r]);
                    W(string.Format("Test Wilcoxona T{0} -- T{1}", p + 1, r + 1), sx);

                    // -- McNemar !! --
                    q1 = new Query();
                    q1.Root = mt;
                    q1.AddMachineConfig(testConfig[p], testConfig[r]);
                    q1.MainLabel = "Correctness";
                    sx = q1.Series;

                    sx = sx.Group(Series.FamilyConfig);
                    sx = sx.MAP(new Unpack());
                    ISeriesTransformer mcNemarST = new McNemar();
                    sx = mcNemarST.Transform((Series)sx[0], (Series)sx[1]);
                    W(string.Format("Test McNemary T{0} -- T{1}", p + 1, r + 1), sx);

                    // -- Paired TTest of ACC-Std --
                    sx = (new TTestPaired()).Transform(
                        s[p] - s[p].GetSeries("Standard deviation"),
                        s[r] - s[r].GetSeries("Standard deviation"));
                    W(string.Format("Sparowany T-test of (ACC-Std) T{0} -- T{1}", p + 1, r + 1), sx);

                }
            }
        }

        /// <summary>
        /// Klasyfikacja z użyciem walidacji krzyżowej 
        /// z wykorzystaniem jednej z kilku predefiniowanych konfiguracji
        /// klasyfikatora z modułu InTrees
        /// </summary>
        /// <param name="project"></param>
        public static void MultiTreeTest_CV(Project project)
        {
            IDictionary d = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User);
            ConfigBase dc = project.GetConfiguration("GM data loader");
            DataLoaderConfig dcfg = (DataLoaderConfig)dc.Configuration;
            //dcfg.InputFileName = dataPath + "MUSHROOM.DAT";
            //dcfg.InputFileName = dataPath + "Thyroid2.dat";
            dcfg.InputFileName = dataPath + "iris.dat";
            //dcfg.InputFileName = dataPath + "breast-cancer-wisconsin.dat";
            Capsule dcaps = project.Create(dc);

            ConfigBase mtConfigBase =
                CITools.Repeater_CVConfig(project, dcaps, "Dataset");
            ((RepeaterConfig)mtConfigBase.Configuration).Count = 10;

            const int K = 8;
            int i;

            ConfigBase[] treeConfig = new ConfigBase[K];
            InTreeConfig[] ccConf = new InTreeConfig[K];
            Pruning2Config[] pConf = new Pruning2Config[K];
            ConfigBase[] testConfig = new ConfigBase[K];

            #region tree1
            i = 0;
            treeConfig[i] = project.GetConfiguration("INTREE");
            ccConf[i] = (InTreeConfig)treeConfig[i].Configuration;
            ccConf[i].Pruning = new Pruning2();
            ccConf[i].NodeTestGenerator = new BinaryTestGenerator();
            ccConf[i].NodeTestSelector = new Gini();
            ccConf[i].StoppingCriterium = new NaturalStoppingCriterium();
            ccConf[i].TargetSelector = new TargetSelector();
            ccConf[i].PruningMode = InTreeConfig.PRUNING_AUTO;

            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region tree2
            i = 1;
            treeConfig[i] = project.GetConfiguration("INTREE");
            ccConf[i] = (InTreeConfig)treeConfig[i].Configuration;
            ccConf[i].Pruning = new Pruning2();
            ccConf[i].NodeTestGenerator = new MultiSplitTestGenerator();
            ccConf[i].NodeTestSelector = new InfoGainNTS(true);
            ccConf[i].StoppingCriterium = new NaturalStoppingCriterium();
            ccConf[i].TargetSelector = new TargetSelector();
            ccConf[i].PruningMode = InTreeConfig.PRUNING_AUTO;

            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region tree3
            i = 2;
            treeConfig[i] = project.GetConfiguration("INTREE");
            ccConf[i] = (InTreeConfig)treeConfig[i].Configuration;
            ccConf[i].Pruning = new Pruning2();
            ccConf[i].NodeTestGenerator = new BinaryTestGenerator();
            ccConf[i].NodeTestSelector = new InfoGainNTS(true);
            ccConf[i].StoppingCriterium = new NaturalStoppingCriterium();
            ccConf[i].TargetSelector = new TargetSelector();
            ccConf[i].PruningMode = InTreeConfig.PRUNING_AUTO;

            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region tree4
            i = 3;
            treeConfig[i] = project.GetConfiguration("INTREE");
            ccConf[i] = (InTreeConfig)treeConfig[i].Configuration;
            ccConf[i].Pruning = new Pruning2();
            ccConf[i].NodeTestGenerator = new MultiSplitTestGenerator();
            ccConf[i].NodeTestSelector = new Gini();
            ccConf[i].StoppingCriterium = new NaturalStoppingCriterium();
            ccConf[i].TargetSelector = new TargetSelector();
            ccConf[i].PruningMode = InTreeConfig.PRUNING_AUTO;

            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region tree5
            i = 4;
            treeConfig[i] = project.GetConfiguration("INTREE");
            ccConf[i] = (InTreeConfig)treeConfig[i].Configuration;
            ccConf[i].Pruning = new Pruning2();
            ccConf[i].NodeTestGenerator = new MultiSplitTestGenerator();
            ccConf[i].NodeTestSelector = new InfoGainNTS(true);
            ccConf[i].StoppingCriterium = new NodePuritySC(0.8);
            ccConf[i].TargetSelector = new TargetSelector();
            ccConf[i].PruningMode = InTreeConfig.PRUNING_NONE;

            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region tree6
            i = 5;
            treeConfig[i] = project.GetConfiguration("INTREE");
            ccConf[i] = (InTreeConfig)treeConfig[i].Configuration;
            ccConf[i].Pruning = new Pruning2();
            ccConf[i].NodeTestGenerator = new BinaryTestGenerator();
            ccConf[i].NodeTestSelector = new Gini();

            List<IStoppingCriterion> criteriums = new List<IStoppingCriterion>();
            criteriums.Add(new MinNodeSizeSC(6));
            criteriums.Add(new NodePuritySC(0.7));
            ccConf[i].StoppingCriterium = new CommitteeSC(criteriums, CommitteeSC.OP_AND);

            ccConf[i].TargetSelector = new TargetSelector();
            ccConf[i].PruningMode = InTreeConfig.PRUNING_NONE;

            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region meta tree
            i = 6;
            treeConfig[i] = project.GetConfiguration("META TREE2");
            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            #region ssv
            i = 7;
            treeConfig[i] = project.GetConfiguration("Validated SSV decision tree");
            treeConfig[i].Inputs.BindParentInput("Dataset", "Training dataset");
            #endregion

            CITools.CVTest(treeConfig[5], project, dcaps, "Dataset",1,10,10);
            
            
        }

        /// <summary>
        /// Klasyfikacja z użyciem walidacji krzyżowej 
        /// z wykorzystaniem konfiguracji użytkownika
        /// </summary>
        /// <param name="project"></param>
        public static void TreeTest_CV(Project project)
        {
            // ładowanie pliku z danymi
            ConfigBase dc = project.GetConfiguration("GM data loader");
            DataLoaderConfig dcfg = (DataLoaderConfig)dc.Configuration;
            //dcfg.InputFileName = dataPath + "breast-cancer-wisconsin.dat";
            //dcfg.InputFileName = dataPath + "thyroid-trs.dat";
            //dcfg.InputFileName = dataPath + "iris.dat";
            //dcfg.InputFileName = dataPath + "heartNoMissing.dat";
            //dcfg.InputFileName = dataPath + "credit-a.dat";
            //dcfg.InputFileName = dataPath + "gracjan.dat";
            dcfg.InputFileName = dataPath + "mushroom.dat";
            //dcfg.InputFileName = dataPath + "thyroid-trs.dat";
            Capsule dcaps = project.Create(dc);

            ConfigBase treeConfig = project.GetConfiguration("INTREE");
            InTreeConfig ccConf = (InTreeConfig)treeConfig.Configuration;

            /* ---------------------- konfiguracja parametrów drzewa ----------------- */
          
            /* kryterium generowania podziałów */
            //ccConf.NodeTestGenerator = new BinaryTestGenerator();
            ccConf.NodeTestGenerator = new MultiSplitTestGenerator();

            /* kryterium wyboru najlepszego podziału */
            //ccConf.NodeTestSelector = new Gini();
            ccConf.NodeTestSelector = new InfoGainNTS(true);

            /* kryterium stopu */
            ccConf.StoppingCriterium = new NaturalStoppingCriterium();
            //ccConf.StoppingCriterium = new MinNodeSizeSC(10);
            //ccConf.StoppingCriterium = new NodePuritySC(0.88);

            //List<IStoppingCriterium> criteriums = new List<IStoppingCriterium>();
            //criteriums.Add(new MinNodeSizeSC(100));
            //criteriums.Add(new NodePuritySC(0.88));
            //ccConf.StoppingCriterium = new CommitteeSC(criteriums, CommitteeSC.OP_AND);

            /* sposób wyboru etykiety domyślnej */
            ccConf.TargetSelector = new TargetSelector();

            /* konfiguracja przycinania */
            ccConf.Pruning = new Pruning2();
            ccConf.PruningMode = InTreeConfig.PRUNING_AUTO;
            Pruning2Config p2conf = new Pruning2Config();
            p2conf.NodeCount = 4;  
            ccConf.PruningConfig = p2conf;

            /* ---------------------- koniec konfiguracji---------------------------- */

            CITools.CVTest(treeConfig, project, dcaps, "Dataset", 10, 10,10);

        }
    }

}
