using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Simple_Kmeans_example_AlgLib
{
    class Program
    {


        public static int Main(string[] args)
        {
            // L'exemple de clusterisation ici est très simple
            //
            // Nous avons un ensemble de points dans l'espace 2D:
            //     (P0,P1,P2,P3,P4) = ((1,1),(1,2),(4,1),(2,3),(4,1.5))
            //
            //  |
            //  |     P3
            //  |
            //  | P1          
            //  |             P4
            //  | P0          P2
            //  |-------------------------
            //
            // Nous voulons effectuer une classification k-means avec K = 2.
            //
            // Pour ce faire, nous:
            // * Créons une classification (clusterizer) avec clusterizercreate ()
            // * Fixons la collection de points  XY et la métrique utilisée (elle doit être euclidienne, donc distype = 2) 
            //   avec clusterizersetpoints ()
            // * Optionnellement nous pouvons fixer un nombre de Série de redémarrage
            //   à partir de positions aléatoires (ici jusqu'à 5 bien sûr) 
            // * Exécuter l'algorithme du k-means avec la méthode clusterizerrunkmeans ()

            const int k = 2;

            // Vous pouvez voir que clusterisation en elle-même n'est pas la partie prépondérante de l'exemple,
            // Il y a surtout des commentaires  :)


            alglib.clusterizerstate s;
            alglib.kmeansreport rep;
            double[,] xy = new double[,] { { 1, 1 }, { 1, 2 }, { 4, 1 }, { 2, 3 }, { 4, 1.5 } };

            alglib.clusterizercreate(out s);
            alglib.clusterizersetpoints(s, xy, 2);
            alglib.clusterizersetkmeanslimits(s, 5, 0);
            alglib.clusterizerrunkmeans(s, k, out rep);

            //
            // Nous avons effectué une classification qui a réussi (code de fin est +1).
            //
            // Maintenant, le premier centre est stocké dans la première rangée de rep.c, et le deuxième est stocké
            // dans la deuxième rangée. 
            // rep.cidx peut être utilisé pour déterminer le centre qui est 
            // le plus proche de chaque point de l'ensemble des données.
            //


            System.Console.WriteLine("{0}", rep.terminationtype); // ATTENDU : 1

            System.Console.Write("X=");
            System.Console.Write(rep.c[0, 0]);
            System.Console.Write(", Y=");
            System.Console.WriteLine(rep.c[0, 1]);

            System.Console.Write("X=");
            System.Console.Write(rep.c[1, 0]);
            System.Console.Write(", Y=");
            System.Console.WriteLine(rep.c[1, 1]);

                ;

            // Nous avons appelé clusterizersetpoints () avec disttype = 2 parce que 
            // l'algorithme k-means ++ ne supporte pas des métriques non euclidiennes. 


            // Essayons maintenant d'utiliser une autre métrique.
            // Nous changeons de type métrique en appelant clusterizersetpoints () une fois de plus 
            // en essayez d'exécuter k-means une nouvelle fois. Il échoue.
            //

            alglib.clusterizersetpoints(s, xy, 0);
            alglib.clusterizerrunkmeans(s, k, out rep);
            System.Console.WriteLine("{0}", rep.terminationtype); // ATTENDU : -5
            System.Console.ReadLine();
            return 0;
        }
        
    }
}
