//========================================================================
// Copyright(C): RFAI France
//
// CLR Version : 4.0.30319.18052
// NameSpace : Matching
// FileName : FGMESignature.cs
//
// Created by : JC (jiangchar@gamil.com) at 1/1/2014 10:04:19 PM
//
//========================================================================
#region Using directives

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

#endregion

namespace Matching
{
    /// <summary>
    /// Cette classe va gérer une base de graphe
    /// l'ordre de fonction est:GetAsemblance(vérifier type)--Extraitclique
    /// --AnalyseAttribut(créer 4 tableaux à partir de lequels on fait un modèle dans la phase de graph2Vector)
    /// --Graph2Vector
    /// </summary>
    public class FMGESignature
    {
        /***************************************************************/
        /*************************Attributs*****************************/
        /***************************************************************/

        #region Attributs

        //l'objet qui va gérer l'embedding
        FMGEEmbedding embedding;
        //liste de tout les graphes avec Ressemblance et noeud degré
        //List<Graph> listGraphs;
        //liste de tout les cliques avec Ressemblance et noeud degré
        List<List<Graph>> listAllClique;

        //-------------------element de la table d'indexation-----------
        List<int> listClusterLabel;

        string GXLFileGraphName;

        List<string> listDirectoryGraph;

        List<string> listGraphName;

        List<VectorFMGE> listVectorFGME;

        int maxNumberClique;

        //-------------------fin de table d'indexation------------------

        public const int LoadBins = 1;
        public const int LearnBins = 0;

        #endregion

        /***************************************************************/
        /*************************Accesseurs****************************/
        /***************************************************************/

        #region Accesseurs

        //liste de clique de tous les graphes
        public List<List<Graph>> ListAllClique
        {
            get { return listAllClique; }
            set { listAllClique = value; }
        }

        //liste de vecteur de tous les graphes
        public List<VectorFMGE> ListVectorFGME
        {
            get { return listVectorFGME; }
            set { listVectorFGME = value; }
        }

        //public int MaxNumberAttribute
        //{
        //    get { return Math.Max(DicAnaFMG_TableNumericEdge.Count + DicAnaFMG_TableSybmolicEdge.Count,
        //        DicAnaFMG_TableNumericNode.Count + DicAnaFMG_TableSybmolicNode.Count);
        //    }
        //    set { maxNumberAttribute = value; }
        //}

        public int MaxNumberClique
        {
            get { return maxNumberClique; }
            set { maxNumberClique = value; }
        }

        public List<string> ListGraphName
        {
            get { return listGraphName; }
            set { listGraphName = value; }
        }

        public List<int> ListLabel
        {
            get { return listClusterLabel; }
            set { listClusterLabel = value; }
        }

        #endregion

        /***************************************************************/
        /************************Constructeurs**************************/
        /***************************************************************/

        #region Constructeurs

        public FMGESignature()
        {
            embedding = new FMGEEmbedding();

            listAllClique = new List<List<Graph>>();

            //listGraphs = new List<Graph>();

            listClusterLabel = new List<int>();

            listGraphName = new List<string>();

            listVectorFGME = new List<VectorFMGE>();

            listDirectoryGraph = new List<string>();

            maxNumberClique = 0;
        }

        /// <summary>
        /// Constructeurs
        /// </summary>
        /// <param name="StrDictonary">La répertoire de la base de graphe</param>
        public FMGESignature(string StrDictonary)
        {
            embedding = new FMGEEmbedding();

            //tout les cliques de tout les graphes de base de graphe

            listAllClique = new List<List<Graph>>();

            //-----4 tableaux d'indexation-------

            listClusterLabel = new List<int>();

            listGraphName = new List<string>();

            listVectorFGME = new List<VectorFMGE>();

            listDirectoryGraph = new List<string>();

            //-----------------------------------

            GXLFileGraphName = StrDictonary;

            maxNumberClique = 0;
        }

        #endregion

        /***************************************************************/
        /*********************Méthodes publics**************************/
        /***************************************************************/

        #region Méthodes publics


        /// <summary>
        /// pour chaque clique, créer un FGMEEmbedding et remplir les tableaux du FGMESignature
        /// </summary>
        /// <param name="part1">s'il contient du graph level information</param>
        /// <param name="part2">s'il contient du structure level information</param>
        /// <param name="part3">s'il contient du elementary level information</param>
        /// <param name="getBins">s'il lire des bins et créer des bins</param>
        /// <param name="directionary">la répértoire du fichier bins.</param>
        public void FillTable(bool part1, bool part2, bool part3, int getBins, string directionary)
        {
            List<Graph> listAll = new List<Graph>();
            foreach (List<Graph> listGraph in listAllClique)
            {
                listAll = listAll.Concat(listGraph).ToList();
            }
            //phase d'apprentissage
            if (getBins == LearnBins)
                embedding.LearnBins(listAll);
            else
            {
                if (directionary == "")
                {
                    throw new Exception("donner une répertoire de données d'apprentissage");
                }
                else
                    embedding.LoadBins(directionary);
            }
            foreach (Graph g in listAll)
            {
                VectorFMGE Vec = embedding.Graph2Vector(g, part1, part2, part3);
                listVectorFGME.Add(Vec);
                listGraphName.Add(g.Id);
            }
        }
        /*
        /// <summary>
        /// transformer un objet de graphe à un objet de vectorFMGE.
        /// au début, construire une modèle de vecteur à partir de tableaux dans la phase d'appentissage,
        /// après grâce à une filtre, on supprime les attributs inutile(parte1 ou partie2 ou partie3),
        /// pour chaque attribut dans le graphe, s'il y a une place dans le vecteur modèle, on l'ajoute.
        /// Erreur: quand il existe un attribut numerique mais il ne peut pas convertir en un chiffre. throw un exception;
        /// </summary>
        /// <param name="GraphIn">un graphe à convertir à un vecteur</param>
        /// <returns>un nouveau vecteurFMGE supprimant les parties designés</returns>
        public  override VectorFGME Graph2Vector(Graph GraphIn, bool part1, bool part2, bool part3)
        {
            //on ne peut pas avoir un vecteur sans les 3 intervalles en le même temps
            if (part1 == false && part2 == false && part3 == false)
                throw new Exception("at least choose one Interval. ");

            VectorFGME VecGraFMG = new VectorFGME();
            VecGraFMG.FSMFV.Add("graph order", GraphIn.ListNodes.Count);
            VecGraFMG.FSMFV.Add("graph size", GraphIn.ListEdges.Count);

            //**************************************************************************************************************
            //*****************Construire une modèle de vecteur avec tous les attributs*************************************
            //*****************pour les attributs qu'on ne veut pas garder, on les supprime après***************************
            //**************************************************************************************************************

            foreach (KeyValuePair<string, List<double>> k in DicAnaFMG_TableNumericEdge)
            {
                //pour chaque attribut numerique, il existe forcement 3 intervals
                if (!VecGraFMG.FSMFV.ContainsKey(k.Key + "_1"))
                {
                    string str = k.Key;
                    //pour chaque attribut, on compte le nombre de fois qu'il apprait, au début, c'est zéro.
                    //pour une valeur numerique, il y a " interval.
                    VecGraFMG.FSMFV.Add(str + "_1", 0);
                    VecGraFMG.FSMFV.Add(str + "_2", 0);
                    VecGraFMG.FSMFV.Add(str + "_3", 0);
                }
            }

            foreach (KeyValuePair<string, List<string>> k in DicAnaFMG_TableSybmolicEdge)
            {
                foreach (string s in k.Value)
                {
                    string str = k.Key;
                    //pour chaque attribut numerique, il existe forcement 3 intervals
                    if (!VecGraFMG.FSMFV.ContainsKey(str + "_" + s))
                    {
                        //pour chaque attribut, on compte le nombre de fois qu'il apprait, au début, c'est zéro.
                        //pour une valeur numerique, il y a " interval.
                        VecGraFMG.FSMFV.Add(str + "_" + s, 0);
                    }
                }

            }
            foreach (KeyValuePair<string, List<double>> k in DicAnaFMG_TableNumericNode)
            {
                string str = k.Key;
                //pour chaque attribut numerique, il existe forcement 3 intervals
                if (!VecGraFMG.FSMFV.ContainsKey(str + "_1"))
                {
                    //pour chaque attribut, on compte le nombre de fois qu'il apprait, au début, c'est zéro.
                    //pour une valeur numerique, il y a " interval.
                    VecGraFMG.FSMFV.Add(str + "_1", 0);
                    VecGraFMG.FSMFV.Add(str + "_2", 0);
                    VecGraFMG.FSMFV.Add(str + "_3", 0);
                }
            }
            foreach (KeyValuePair<string, List<string>> k in DicAnaFMG_TableSybmolicNode)
            {
                foreach (string s in k.Value)
                {
                    string str = k.Key;
                    //pour chaque attribut numerique, il existe forcement 3 intervals
                    if (!VecGraFMG.FSMFV.ContainsKey(str + "_" + s))
                    {
                        //pour chaque attribut, on compte le nombre de fois qu'il apprait, au début, c'est zéro.
                        //pour une valeur numerique, il y a " interval.
                        VecGraFMG.FSMFV.Add(str + "_" + s, 0);
                    }
                }
            }
            //**************************************************************************************************************
            //*****************Construction de la modèle fini***************************************************************
            //**************************************************************************************************************

            //filtre pour supprimer les attributs qu'on ne veut pas garder
            VecGraFMG.FSMFV = FilterAttribute(VecGraFMG.FSMFV, part1, part2, part3);

            //**************************************************************************************************************
            //**************************************************pour les noeuds*********************************************
            //**************************************************************************************************************
            foreach (Node node in GraphIn.ListNodes)
            {
                foreach (AttributeGXL attributeGXL in node.AttributesGXL)
                {
                    //si la valeur d'attribut est numerique
                    if (String.Compare(attributeGXL.Type, "int", true) == 0 ||
                        String.Compare(attributeGXL.Type, "float", true) == 0||
                        String.Compare(attributeGXL.Type, "integer", true) == 0)
                    {
                        double DouGraFMG_Val;
                        try
                        {
                            DouGraFMG_Val = Convert.ToDouble(attributeGXL.Value);
                        }
                        catch(Exception e)
                        {
                            Console.Write(e.Message);
                            throw new Exception("Type of value error. ", e);
                        }
                        //pour chaque attribut numerique, il existe forcement 3 intervals
                        //if (!VecGraFMG.FSMFV.ContainsKey(attributeGXL.Name + "_1"))
                        //{
                        //    //pour chaque attribut, on compte le nombre de fois qu'il apprait, au début, c'est zéro.
                        //    //pour une valeur numerique, il y a " interval.
                        //    VecGraFMG.FSMFV.Add(attributeGXL.Name + "_1", 0);
                        //    VecGraFMG.FSMFV.Add(attributeGXL.Name + "_2", 0);
                        //    VecGraFMG.FSMFV.Add(attributeGXL.Name + "_3", 0);
                        //}

                        //si cette valeur n'est pas dans le tableau d'apprentissage, retourner false
                        if (!DicAnaFMG_TableNumericNode.ContainsKey(attributeGXL.Name))
                            return null;
                        //s'il n'est pas être supprimer par la filtre
                        if (VecGraFMG.FSMFV.ContainsKey(attributeGXL.Name + "_1"))
                        {
                            //decider la longeur de pas
                            double DouGraFMG_Pas = (DicAnaFMG_TableNumericNode[attributeGXL.Name][1] -
                                DicAnaFMG_TableNumericNode[attributeGXL.Name][0]) / 3;
                            //s'il est dans la premiere groupe
                            if (DouGraFMG_Val < DicAnaFMG_TableNumericNode[attributeGXL.Name][0] + DouGraFMG_Pas)
                                VecGraFMG.FSMFV[attributeGXL.Name + "_1"] += 1;
                            //s'il est dans la deuxieme groupe
                            else if (DouGraFMG_Val < (DicAnaFMG_TableNumericNode[attributeGXL.Name][0] + DouGraFMG_Pas * 2))
                                VecGraFMG.FSMFV[attributeGXL.Name + "_2"] += 1;
                            else
                                VecGraFMG.FSMFV[attributeGXL.Name + "_3"] += 1;
                        }
                    }
                    //si la valeur d'attribut est symbolique
                    else
                    {
                        //si cette valeur n'est pas dans ce tableau qui est le resultat de learn phase, retourner null
                        if (!DicAnaFMG_TableSybmolicNode.ContainsKey(attributeGXL.Name))
                            return null;
                        //if (!VecGraFMG.FSMFV.ContainsKey(attributeGXL.Name + "_" + attributeGXL.Value))
                        //{
                        //    //pour chaque attribut, on compte le nombre de fois qu'il apprait, au début, c'est zéro.
                        //    //pour un attribut d'une valeur symbolique, il y a 1 interval.
                        //    for (int i = 0; i < DicAnaFMG_TableSybmolicNode[attributeGXL.Name].Count; i++)
                        //    {
                        //        VecGraFMG.FSMFV.Add(attributeGXL.Name + "_" + DicAnaFMG_TableSybmolicNode[attributeGXL.Name][i], 0);
                        //    }
                        //}
                        if (VecGraFMG.FSMFV.ContainsKey(attributeGXL.Name + "_" + attributeGXL.Value))
                            VecGraFMG.FSMFV[attributeGXL.Name + "_" + attributeGXL.Value] += 1;
                    }
                }
            }
            //**************************************************************************************************************
            //**************************************************pour les arcs***********************************************
            //**************************************************************************************************************
            foreach (Edge edge in GraphIn.ListEdges)
            {
                foreach (AttributeGXL attributeGXL in edge.AttributesGXL)
                {
                    //si la valeur d'attribut est numerique
                    if (String.Compare(attributeGXL.Type, "int", true) == 0 ||
                        String.Compare(attributeGXL.Type, "float", true) == 0 ||
                        String.Compare(attributeGXL.Type, "integer", true) == 0
                        )
                    {
                        double DouGraFMG_Val;
                        try
                        {
                            DouGraFMG_Val = Convert.ToDouble(attributeGXL.Value);
                        }
                        catch (Exception e)
                        {
                            Console.Write(e.Message);
                            throw new Exception("Type of value error. ", e);
                        }

                        //if (!VecGraFMG.FSMFV.ContainsKey(attributeGXL.Name + "_1"))
                        //{
                        //    //pour chaque attribut, on compte le nombre de fois qu'il apprait, au début, c'est zéro.
                        //    //pour une valeur numerique, il y a " interval.
                        //    VecGraFMG.FSMFV.Add(attributeGXL.Name + "_1", 0);
                        //    VecGraFMG.FSMFV.Add(attributeGXL.Name + "_2", 0);
                        //    VecGraFMG.FSMFV.Add(attributeGXL.Name + "_3", 0);
                        //}
                        //si cette valeur n'est pas dans ce tableau, retourner null
                        if (!DicAnaFMG_TableNumericEdge.ContainsKey(attributeGXL.Name))
                            return null;
                        if (VecGraFMG.FSMFV.ContainsKey(attributeGXL.Name + "_1"))
                        //decider la longeur de pas
                        {
                            double DouGraFMG_Pas = (DicAnaFMG_TableNumericEdge[attributeGXL.Name][1] - 
                                DicAnaFMG_TableNumericEdge[attributeGXL.Name][0]) / 3;
                            //s'il est dans la premiere groupe
                            if (DouGraFMG_Val < DicAnaFMG_TableNumericEdge[attributeGXL.Name][0] + DouGraFMG_Pas)
                                VecGraFMG.FSMFV[attributeGXL.Name + "_1"] += 1;
                            //s'il est dans la deuxieme groupe
                            else if (DouGraFMG_Val < (DicAnaFMG_TableNumericEdge[attributeGXL.Name][0] + DouGraFMG_Pas * 2))
                                VecGraFMG.FSMFV[attributeGXL.Name + "_2"] += 1;
                            else
                                VecGraFMG.FSMFV[attributeGXL.Name + "_3"] += 1;
                        }
                    }
                    else
                    {
                        //si cette valeur n'est pas dans ce tableau, retourner null
                        if (!DicAnaFMG_TableSybmolicEdge.ContainsKey(attributeGXL.Name))
                            return null;
                        //if (!VecGraFMG.FSMFV.ContainsKey(attributeGXL.Name + "_" + attributeGXL.Value))
                        //{
                        //    //pour chaque attribut, on compte le nombre de fois qu'il apprait, au début, c'est zéro.
                        //    //pour un attribut d'une valeur symbolique, il y a 1 interval.
                        //    for (int i = 0; i < DicAnaFMG_TableSybmolicEdge[attributeGXL.Name].Count; i++)
                        //    {
                        //        VecGraFMG.FSMFV.Add(attributeGXL.Name + "_" + DicAnaFMG_TableSybmolicEdge[attributeGXL.Name][i], 0);
                        //    }
                        //}
                        if (VecGraFMG.FSMFV.ContainsKey(attributeGXL.Name + "_" + attributeGXL.Value))
                            VecGraFMG.FSMFV[attributeGXL.Name + "_" + attributeGXL.Value] += 1;
                    }
                }
            }
            listVectorFGME.Add(VecGraFMG);
            listGraph.Add(GraphIn.Id);
            return VecGraFMG;
        }*/
        //--------------------------------------fin de FillTable------------------------------------------------------------

        /// <summary>
        /// extraire les cliques d'un graphe et à la fin les rengistrer dans un tableau ListAllClique.
        /// </summary>
        /// <param name="GraphIn">Graphe a extraire</param>
        /// <param name="GraphName">Graphe a extraire</param>
        /// <param name="IsDirected">Graphe orienté ou pas, pour l'instant, seulement les graphes non orientés supportés</param>
        public void ExtractClique(Graph GraphIn, string GraphName, bool IsDirected)
        {
            //avant de calculer le clique, on doit calculer la ressemblance!
            Graph GraphWithDegree =embedding.GetNodeDegree(GraphIn);
            Graph GraphWithAss = embedding.GetRessemblance(GraphWithDegree);

            //listGraphs.Add(GraphWithAss);

            List<Graph> LisGraExtFMG = new List<Graph>();
            foreach (Edge edge in GraphWithAss.ListEdges)
            {
                maxNumberClique += 1;
                Graph GraExtFMG = new Graph(GraphName + "$" + edge.Id, "", IsDirected);
                Node NodExtFMGSor = new Node(edge.NodeSource.Id);
                Node NodExtFMGTar = new Node(edge.NodeTarget.Id);
                Edge EdgExtFMG = new Edge(edge.Id);

                //ajouter les attributs de noeud 1
                foreach (AttributeGXL attributeGXL in edge.NodeSource.AttributesGXL)
                {
                    AttributeGXL AttExtFMG = new AttributeGXL();
                    AttExtFMG.Name = attributeGXL.Name;
                    AttExtFMG.Type = attributeGXL.Type;
                    AttExtFMG.Value = attributeGXL.Value;
                    NodExtFMGSor.AttributesGXL.Add(AttExtFMG);
                    //listResemblanceWithValue.Add(new KeyValuePair<string, string>(att.Name, att.Type), att.Value);
                }

                //ajouter les attributs de noeud 2
                foreach (AttributeGXL attributeGXL in edge.NodeTarget.AttributesGXL)
                {
                    AttributeGXL AttExtFMG = new AttributeGXL();
                    AttExtFMG.Name = attributeGXL.Name;
                    AttExtFMG.Type = attributeGXL.Type;
                    AttExtFMG.Value = attributeGXL.Value;
                    NodExtFMGTar.AttributesGXL.Add(AttExtFMG);
                }

                //ajouter les autres attributs d'arc
                foreach (AttributeGXL attributeGXL in edge.AttributesGXL)
                {
                    AttributeGXL AttExtFMG = new AttributeGXL();
                    AttExtFMG.Name = attributeGXL.Name;
                    AttExtFMG.Type = attributeGXL.Type;
                    AttExtFMG.Value = attributeGXL.Value;
                    EdgExtFMG.AttributesGXL.Add(AttExtFMG);
                }
                EdgExtFMG.NodeSource = NodExtFMGSor;
                EdgExtFMG.NodeTarget = NodExtFMGTar;

                GraExtFMG.addNode(NodExtFMGSor);
                GraExtFMG.addNode(NodExtFMGTar);
                GraExtFMG.addEdge(EdgExtFMG);

                foreach (Node nodeInner in GraExtFMG.ListNodes)
                {
                    GenericLabel labelNode = new GenericLabel();
                    Type typeNode = labelNode.GetType();
                    object obj = Activator.CreateInstance(typeNode);
                    nodeInner.Label = (Graphs.Label)obj;
                    nodeInner.Label.Id = nodeInner.Id;
                    nodeInner.Label.fromAttributes(nodeInner.AttributesGXL);
                }

                foreach (Edge edgeInner in GraExtFMG.ListEdges)
                {
                    GenericLabel labelEdge = new GenericLabel();
                    Type typeEdge = labelEdge.GetType();
                    object obj = Activator.CreateInstance(typeEdge);
                    edgeInner.Label = (Graphs.Label)obj;
                    edgeInner.Label.Id = edgeInner.Id;
                    edgeInner.Label.fromAttributes(edgeInner.AttributesGXL);
                }
                LisGraExtFMG.Add(GraExtFMG);
                listDirectoryGraph.Add(GXLFileGraphName + "\\" + GraphName);
            }
            listAllClique.Add(LisGraExtFMG);
        }
        //--------------------------------------fin de ExtraitClique-----------------------------------------------------------

        /*
        /// <summary>
        /// calcule les attributs supplimentaires et les ajoute dans un nouveau graphe.
        /// ce processus n'est pas obligatoire.
        /// Erreur:quand il existe une type int ou float mais la valeur ne peut pas être converti à une valeur numerique
        /// </summary>
        /// <param name="GrapnIn">Graphe à calculer</param>
        /// <returns>Graphe avec ressemblance </returns>
        public Graph GetRessemblance(Graph GraphIn)
        {
            int numberAttribute = 0;
            Graph GraphOut = new Graph();
            GraphOut = GraphCopy(GraphIn);
            //**************************************************************************************************************
            //**************************************************pour les arcs***********************************************
            //**************************************************************************************************************
            //pour chaque arc, on prend en compte les attributs de noeud source et les attributs de noeud destination, s'il existe
            //des attributs similaire, on ajoute un attrubut <resemblance>
            foreach (Edge edge in GraphIn.ListEdges)
            {
                Dictionary<KeyValuePair<string, string>, string> DicStrStrStrGetFMG =
                    new Dictionary<KeyValuePair<string, string>, string>();
                maxNumberClique += 1;
                numberAttribute = 0;
                foreach (AttributeGXL attributeGXL in edge.NodeSource.AttributesGXL)
                {
                    numberAttribute += 1;
                    DicStrStrStrGetFMG.Add(
                        new KeyValuePair<string, string>(attributeGXL.Name, attributeGXL.Type), attributeGXL.Value);
                }
                //pour garder le numbre d'attribut maximal
                if (numberAttribute > maxNumberAttribute) maxNumberAttribute = numberAttribute;

                numberAttribute = 0;
                foreach (AttributeGXL attributeGXL in edge.NodeTarget.AttributesGXL)
                {
                    numberAttribute += 1;
                    //s'il contient un même attribut avec le noeud 1, calcule min(s1, s2)/max(s1, s2) et l'ajoute sur l'arc
                    KeyValuePair<string, string> KeyGetFMG = 
                        new KeyValuePair<string, string>(attributeGXL.Name, attributeGXL.Type);
                    if (DicStrStrStrGetFMG.ContainsKey(KeyGetFMG))
                    {
                        AttributeGXL AttGetFMG = new AttributeGXL();

                        //-----------------------------------numerique valeur---------------------------------------------
                        if (String.Compare(attributeGXL.Type, "int", true) == 0 ||
                            String.Compare(attributeGXL.Type, "float", true) == 0 ||
                            String.Compare(attributeGXL.Type, "Integer", true) == 0 ||
                            String.Compare(attributeGXL.Type, "double", true) == 0)
                        {
                            double IntGetFMG_JudgeType;
                            try
                            {
                                IntGetFMG_JudgeType = Convert.ToDouble(attributeGXL.Value);
                            }
                            catch(Exception e)
                            {
                                Console.Write(e.Message);
                                throw new Exception("The type of value is wrong. \n", e);
                            }
                            // chercher la valeur dans le noeud 1
                            string StrGetFMG = DicStrStrStrGetFMG[KeyGetFMG];
                            AttGetFMG.Name = "Resemblance_" + attributeGXL.Name;
                            AttGetFMG.Type = "float";
                            double DouGetFMG;
                            //s'il n'est pas divisé par 0
                            if (Math.Max(Math.Abs(Convert.ToDouble(attributeGXL.Value)),
                                Math.Abs(Convert.ToDouble(StrGetFMG))) != 0.0)
                            {
                                DouGetFMG = Math.Min(Math.Abs(Convert.ToDouble(attributeGXL.Value)),
                                    Math.Abs(Convert.ToDouble(StrGetFMG))) /
                                    Math.Max(Math.Abs(Convert.ToDouble(attributeGXL.Value)),
                                    Math.Abs(Convert.ToDouble(StrGetFMG)));
                            }
                            //s'il est divisé par 0
                            else
                            {
                                DouGetFMG = 0.0;
                            }
                            AttGetFMG.Value = DouGetFMG.ToString();
                        }
                        //-----------------------------------symbolique valeur-------------------------------------------
                        else
                        {
                            AttGetFMG.Name = "Resemblance_" + attributeGXL.Name;
                            AttGetFMG.Type = "float";
                            if (attributeGXL.Value.Equals(DicStrStrStrGetFMG[KeyGetFMG]))
                                AttGetFMG.Value = "1";
                            else
                                AttGetFMG.Value = "0";
                        }
                        Edge EdgeInGraphOut = GraphOut.findEdge(edge.Id);
                        EdgeInGraphOut.AttributesGXL.Add(AttGetFMG);
                    }
                }
                //pour garder le numbre d'attribut maximal
                if (numberAttribute > maxNumberAttribute) maxNumberAttribute = numberAttribute;
            }
            //**************************************************************************************************************
            //**************************************************pour les noeuds*********************************************
            //**************************************************************************************************************
            //pour chaque noeud, on prend en compte les attributs de tous les arcs sortie, s'il existe
            //des attributs similaire, on ajoute un attrubut <resemblance>, s'il y a un noeud connecté plusieurs arcs,
            //pour chaque paire, on calcule une resemblance et calcule ensuite le moyen de ces resemblances.
            foreach (Node node in GraphIn.ListNodes)
            {
                List<List<AttributeGXL>> LisLisAttGetFMG_Table = new List<List<AttributeGXL>>();
                //pour ajouter les attribut de resemblance, il faut au moins 2 arcs
                if (node.ListEdgesOut.Count > 1)
                {
                    //pour un graphe non orienté, tous les arcs sont dans la listOut.
                    for (int edge1 = 0; edge1 <= node.ListEdgesOut.Count - 2; edge1++)
                    {
                        for (int edge2 = edge1 + 1; edge2 <= node.ListEdgesOut.Count - 1; edge2++)
                        {
                            Dictionary<KeyValuePair<string, string>, string> DicStrStrStrGetFMG =
                                new Dictionary<KeyValuePair<string, string>, string>();
                            //stocker les attributs pour chaque pair d'arc
                            List<AttributeGXL> LisAttGetFMG_Cell = new List<AttributeGXL>();
                            //pour tous les attributs d'arc 1
                            foreach (AttributeGXL attributeGXL in node.ListEdgesOut[edge1].AttributesGXL)
                            {
                                if (attributeGXL.Name.IndexOf("Resemblance_") != 0)
                                    DicStrStrStrGetFMG.Add(
                                        new KeyValuePair<string, string>(attributeGXL.Name, attributeGXL.Type),
                                                                         attributeGXL.Value);
                            }
                            foreach (AttributeGXL attributeGXL in node.ListEdgesOut[edge2].AttributesGXL)
                            {
                                //s'il contient un même attribut avec le noeud 1, calcule min(s1, s2)/max(s1, s2) et l'ajoute sur l'arc
                                KeyValuePair<string, string> KeyGetFMG = new KeyValuePair<string, string>(attributeGXL.Name,
                                    attributeGXL.Type);
                                if (DicStrStrStrGetFMG.ContainsKey(KeyGetFMG))
                                {
                                    AttributeGXL attributeNode = new AttributeGXL();
                                    //-----------------------------------numerique valeur---------------------------------------------
                                    if (String.Compare(attributeGXL.Type, "int", true) == 0 ||
                                        String.Compare(attributeGXL.Type, "float", true) == 0 ||
                                        String.Compare(attributeGXL.Type, "Integer", true) == 0 ||
                                        String.Compare(attributeGXL.Type, "double", true) == 0
                                        )
                                    {
                                        double IntGetFMG_JudgeType;
                                        try
                                        {
                                             IntGetFMG_JudgeType = Convert.ToDouble(attributeGXL.Value);
                                        }
                                        catch(Exception e)
                                        {
                                            Console.Write(e.Message);
                                            throw new Exception("The type of value is wrong. \n", e);
                                        }
                                        // chercher la valeur dans le noeud 1
                                        string StrGetFMG = DicStrStrStrGetFMG[KeyGetFMG];
                                        attributeNode.Name = "Resemblance_" + attributeGXL.Name;
                                        attributeNode.Type = "float";
                                        double doubleValue;
                                        //s'il n'est pas divisé par 0
                                        if (Math.Max(Math.Abs(Convert.ToDouble(attributeGXL.Value)),
                                            Math.Abs(Convert.ToDouble(StrGetFMG))) != 0.0)
                                        {
                                            doubleValue = Math.Min(Math.Abs(Convert.ToDouble(attributeGXL.Value)),
                                                Math.Abs(Convert.ToDouble(StrGetFMG))) /
                                                Math.Max(Math.Abs(Convert.ToDouble(attributeGXL.Value)),
                                                Math.Abs(Convert.ToDouble(StrGetFMG)));
                                        }
                                        //s'il est divisé par 0
                                        else
                                        {
                                            doubleValue = 0.0;
                                        }
                                        attributeNode.Value = doubleValue.ToString();
                                    }
                                    //-----------------------------------symbolique valeur-------------------------------------------
                                    else
                                    {
                                        attributeNode.Name = "Resemblance_" + attributeGXL.Name;
                                        attributeNode.Type = "float";
                                        if (attributeGXL.Value.Equals(DicStrStrStrGetFMG[KeyGetFMG]))
                                            attributeNode.Value = "1";
                                        else
                                            attributeNode.Value = "0";
                                    }
                                    LisAttGetFMG_Cell.Add(attributeNode);
                                }
                            }
                            LisLisAttGetFMG_Table.Add(LisAttGetFMG_Cell);
                        }
                    }

                    //verifier si le nombre d'attribut de noeud source et de noeud destination des arcs sont different, on retourne false
                    //normalement, le nombre d'assemblance pour chaque paire de noeuds sont egale à attributeTable[0].Count
                    foreach (List<AttributeGXL> listAttributeGXL in LisLisAttGetFMG_Table)
                    {
                        if (LisLisAttGetFMG_Table[0].Count != listAttributeGXL.Count)
                            throw new FormatException(
                                "The number of attribute in different edge connected in a same node isn't the same");
                    }
                    int nbAttributeInCell = LisLisAttGetFMG_Table.Count;
                    //Attribut à ajouter
                    //apres parcourir tous les pairs, on calcule le moyen d'attribut
                    for (int int_elementInCell = 0; int_elementInCell <= LisLisAttGetFMG_Table[0].Count - 1; int_elementInCell++)
                    {
                        AttributeGXL AttGetFMG_newAtt = new AttributeGXL();
                        double DouGetFMG = 0.0;
                        //la valeur dans LisLisAttGetFMG_Table[int_nbCell][int_elementInCell].Value est forcement numerique
                        for (int int_nbCell = 0; int_nbCell <= LisLisAttGetFMG_Table.Count - 1; int_nbCell++)
                        {
                            try
                            {
                                DouGetFMG += Convert.ToDouble(LisLisAttGetFMG_Table[int_nbCell][int_elementInCell].Value);
                            }
                            catch
                            {
                                throw new FormatException("Value error");
                            }
                        }
                        AttGetFMG_newAtt.Value = (DouGetFMG / nbAttributeInCell).ToString();
                        AttGetFMG_newAtt.Name = LisLisAttGetFMG_Table[0][int_elementInCell].Name;
                        AttGetFMG_newAtt.Type = LisLisAttGetFMG_Table[0][int_elementInCell].Type;
                        Node NodGetFMG_Out = GraphOut.findNode(node.Id);
                        NodGetFMG_Out.AttributesGXL.Add(AttGetFMG_newAtt);
                    }
                }
            }
            return GraphOut;
        }
        //--------------------------------------fin de GetAssemblance----------------------------------------------------------

        /// <summary>
        /// Calcule et ajoute le degré de noeud dans un nouveau graphe(copy).
        /// Ce processus est obligatoire.
        /// </summary>
        /// <param name="GraphIn">Graphe à calculer</param>
        /// <returns>Graphe avec noeud degré</returns>
        public Graph GetNodeDegree(Graph GraphIn)
        {
            Graph GraphOut = new Graph();
            GraphOut = GraphCopy(GraphIn);
            foreach (Node node in GraphOut.ListNodes)
            {
                AttributeGXL AttAddFMG = new AttributeGXL();
                AttAddFMG.Name = "degree";
                AttAddFMG.Type = "int";
                AttAddFMG.Value = node.ListEdgesOut.Count.ToString();
                node.AttributesGXL.Add(AttAddFMG);
            }
            return GraphOut;
        }
        //--------------------------------------fin de AddNodeDegree----------------------------------------------------------

        /// <summary>
        /// créer un nouveau graphe dans le mémoire
        /// </summary>
        /// <param name="GraphIn">le graphe à copier </param>
        /// <returns>nouveau graphe </returns>
        public Graph GraphCopy(Graph GraphIn)
        {
            Graph GraGraFMG_Out = new Graph();
            foreach (Node node in GraphIn.ListNodes)
            {
                Node NodGraFMG_Add = new Node(node.Id);
                foreach (AttributeGXL att in node.AttributesGXL)
                {
                    AttributeGXL newAttributeGXL = new AttributeGXL();
                    newAttributeGXL.Name = att.Name;
                    newAttributeGXL.Type = att.Type;
                    newAttributeGXL.Value = att.Value;
                    NodGraFMG_Add.AttributesGXL.Add(newAttributeGXL);
                }
                GraGraFMG_Out.addNode(NodGraFMG_Add);
            }

            foreach (Edge edge in GraphIn.ListEdges)
            {
                Edge EdgGraFMG_Add = new Edge(edge.Id);
                EdgGraFMG_Add.NodeSource = GraGraFMG_Out.findNode(edge.NodeSource.Id);
                EdgGraFMG_Add.NodeTarget = GraGraFMG_Out.findNode(edge.NodeTarget.Id);
                foreach (AttributeGXL att in edge.AttributesGXL)
                {
                    AttributeGXL newAttributeGXL = new AttributeGXL();
                    newAttributeGXL.Name = att.Name;
                    newAttributeGXL.Type = att.Type;
                    newAttributeGXL.Value = att.Value;
                    EdgGraFMG_Add.AttributesGXL.Add(newAttributeGXL);
                }
                GraGraFMG_Out.addEdge(EdgGraFMG_Add);
            }

            foreach (Node node in GraphIn.ListNodes)
            {
                foreach (Edge edge in node.ListEdgesIn)
                {
                    Node NodGraFMG_InGraphOut = GraGraFMG_Out.findNode(node.Id);
                    NodGraFMG_InGraphOut.ListEdgesIn.Add(GraGraFMG_Out.findEdge(edge.Id));
                }
                foreach (Edge edge in node.ListEdgesOut)
                {
                    Node NodGraFMG_InGraphOut = GraGraFMG_Out.findNode(node.Id);
                    NodGraFMG_InGraphOut.ListEdgesIn.Add(GraGraFMG_Out.findEdge(edge.Id));
                }
            }

            foreach (Node node in GraGraFMG_Out.ListNodes)
            {
                GenericLabel labelNode = new GenericLabel();
                Type typeNode = labelNode.GetType();
                object obj = Activator.CreateInstance(typeNode);
                node.Label = (Label)obj;
                node.Label.Id = node.Id;
                node.Label.fromAttributes(node.AttributesGXL);
            }

            foreach (Edge edge in GraGraFMG_Out.ListEdges)
            {
                GenericLabel labelEdge = new GenericLabel();
                Type typeEdge = labelEdge.GetType();
                object obj = Activator.CreateInstance(typeEdge);
                edge.Label = (Label)obj;
                edge.Label.Id = edge.Id;
                edge.Label.fromAttributes(edge.AttributesGXL);
            }
            return GraGraFMG_Out;
        }
        //--------------------------------------fin de GraphCopy---------------------------------------------------------------
        */
        /*
        #region off-line learn phase
        /// <summary>
        /// cette fonction va parcourir tous les graphes dans la base de graphes
        /// pour les valeurs numeriques dans listAllClique, chercher un interval et calcule l'interval que chaque clique se situe.
        /// cette fonction doit être appellé après la méthode ExtraitClique.
        /// la sortie est deux fichier txt qui contient les tableaux pour les attributs numeriques et les attributs symboliques
        /// </summary>
        /// <param name="isSave">si on a besoin de stocker le fichier d'apprentissage</param>
        /// <param name="strDic">le répertoire du fichier d'apprentissage</param>
        /// <returns>faux:si il manque la phase d'extraire de clique</returns>
        public bool AnalyseNodeAttribute(bool isSave, string strDic)
        {
            DicAnaFMG_TableNumericNode = new Dictionary<string, List<double>>(StringComparer.OrdinalIgnoreCase);
            DicAnaFMG_TableSybmolicNode = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
            //AnalyseNodeAttribute doit être appellé après la méthode ExtraitClique
            if (listAllClique.Count == 0)
            {
                Console.WriteLine("Your clique table hasn't been built, utilize ExtraitClique first.");
                return false;
            }

            foreach (List<Graph> listClique in listAllClique)
            {
                foreach (Graph clique in listClique)
                {
                    foreach (Node node in clique.ListNodes)
                    {
                        foreach (AttributeGXL attributeGXL in node.AttributesGXL)
                        {
                            // verifier s'il est numerique ou symbolique
                            if (String.Compare(attributeGXL.Type, "int", true) == 0 ||
                                String.Compare(attributeGXL.Type, "float", true) == 0 ||
                                String.Compare(attributeGXL.Type, "Integer", true) == 0 ||
                                String.Compare(attributeGXL.Type, "double", true) == 0)
                            {
                                double IntGetFMG_Value;
                                try
                                {
                                    IntGetFMG_Value = Convert.ToDouble(attributeGXL.Value);
                                }
                                catch (Exception e)
                                {
                                    Console.Write(e.Message);
                                    throw new Exception("Type of value error. ", e);
                                }
                                //si l'attribut est déja existé
                                if (DicAnaFMG_TableNumericNode.ContainsKey(attributeGXL.Name))
                                {
                                    if (IntGetFMG_Value < DicAnaFMG_TableNumericNode[attributeGXL.Name][0])
                                    {
                                        DicAnaFMG_TableNumericNode[attributeGXL.Name][0] = IntGetFMG_Value;
                                    }
                                    if (IntGetFMG_Value > DicAnaFMG_TableNumericNode[attributeGXL.Name][1])
                                        DicAnaFMG_TableNumericNode[attributeGXL.Name][1] = IntGetFMG_Value;
                                }
                                else
                                {
                                    List<double> LisAnaFMG_New = new List<double>();
                                    //stocker la valeur courant comme la valeur minimal et maximal
                                    LisAnaFMG_New.Add(IntGetFMG_Value);
                                    LisAnaFMG_New.Add(IntGetFMG_Value);
                                    DicAnaFMG_TableNumericNode.Add(attributeGXL.Name, LisAnaFMG_New);
                                }
                            }
                            //s'il est symbolique
                            else
                            {
                                string IntGetFMG_Value = attributeGXL.Value;
                                //si l'attribut est déja existé
                                if (DicAnaFMG_TableSybmolicNode.ContainsKey(attributeGXL.Name))
                                {
                                    //si la valeur n'existe pas
                                    if (DicAnaFMG_TableSybmolicNode[attributeGXL.Name].IndexOf(attributeGXL.Value) == -1)
                                    {
                                        DicAnaFMG_TableSybmolicNode[attributeGXL.Name].Add(attributeGXL.Value);
                                    }
                                }
                                else
                                {
                                    DicAnaFMG_TableSybmolicNode.Add(attributeGXL.Name, new List<string>() { attributeGXL.Value });
                                }
                            }
                        }
                    }
                }
            }
            if (isSave == true)
            {
                try
                {
                    //**************************************************************************************************************
                    //**************************************************pour les attributs numerique********************************
                    //**************************************************************************************************************
                    using (System.IO.StreamWriter SysAnaFMG_OutFile = new System.IO.StreamWriter(strDic + "\\node_numeric.txt"))
                    {
                        foreach (KeyValuePair<string, List<double>> KeyAnaFMG in DicAnaFMG_TableNumericNode)
                        {
                            string StrAnaFMG = KeyAnaFMG.Key + ": ";
                            foreach (double DouAnaFMG in KeyAnaFMG.Value)
                            {
                                StrAnaFMG += " <" + DouAnaFMG.ToString() + ">";
                            }
                            SysAnaFMG_OutFile.WriteLine(StrAnaFMG);
                        }
                    }
                    //**************************************************************************************************************
                    //**************************************************pour les attributs symboliques******************************
                    //**************************************************************************************************************
                    using (System.IO.StreamWriter SysAnaFMG_OutFile = new System.IO.StreamWriter(strDic + "\\node_symbolic.txt"))
                    {
                        foreach (KeyValuePair<string, List<string>> KeyAnaFMG in DicAnaFMG_TableSybmolicNode)
                        {
                            string StrAnaFMG_Out = KeyAnaFMG.Key + ": ";
                            foreach (string StrAnaFMG in KeyAnaFMG.Value)
                            {
                                StrAnaFMG_Out += " <" + StrAnaFMG.ToString() + ">  .";
                            }
                            SysAnaFMG_OutFile.WriteLine(StrAnaFMG_Out);
                        }
                    }
                }
                catch (Exception ExcAnaFMG)
                {
                    Console.WriteLine("fail to write file.");
                    throw ExcAnaFMG;
                }
            }
            return true;
        }
        //-------------------------------fin de AnalyseNodeAttribute-----------------------------------------------------------

        /// <summary>
        /// cette fonction va parcourir tous les graphes dans la base de graphes
        /// pour les valeurs numeriques dans listAllClique, chercher un interval et calcule l'interval que chaque clique se situe.
        /// cette fonction doit être appellé après la méthode ExtraitClique.
        /// la sortie est deux fichier txt qui contient les tableaux pour les attributs numeriques et les attributs symboliques.
        /// si la deuxieme variable est vide, le fichier est stocké dans la répertoire courant.
        /// </summary>
        /// <param name="isSave">si on a besoin de stocker le fichier d'apprentissage</param>
        /// <param name="strDic">le répertoire du fichier d'apprentissage</param>
        /// <returns>faux:si il manque la phase d'extraire de clique</returns>
        public bool AnalyseEdgeAttribute(bool isSave, string strDic)
        {
            DicAnaFMG_TableNumericEdge = new Dictionary<string, List<double>>(StringComparer.OrdinalIgnoreCase);
            DicAnaFMG_TableSybmolicEdge = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);

            //AnalyseNodeAttribute doit être appellé après la méthode ExtraitClique
            if (listAllClique.Count == 0)
            {
                Console.WriteLine("Your clique table hasn't been built, utilize ExtraitClique first.");
                return false;
            }

            foreach (List<Graph> listClique in listAllClique)
            {
                foreach (Graph clique in listClique)
                {
                    foreach (Edge edge in clique.ListEdges)
                    {
                        foreach (AttributeGXL attributeGXL in edge.AttributesGXL)
                        {
                            // verifier s'il est numerique ou symbolique
                            if (String.Compare(attributeGXL.Type, "int", true) == 0 ||
                                String.Compare(attributeGXL.Type, "float", true) == 0 ||
                                String.Compare(attributeGXL.Type, "Integer", true) == 0 ||
                                String.Compare(attributeGXL.Type, "double", true) == 0)
                            {
                                double IntGetFMG_Value;
                                try
                                {
                                    IntGetFMG_Value = Convert.ToDouble(attributeGXL.Value);
                                }
                                catch (Exception e)
                                {
                                    Console.Write(e.Message);
                                    throw new Exception("Type of value error. ", e);
                                }
                                
                                //si l'attribut est déja existé
                                if (DicAnaFMG_TableNumericEdge.ContainsKey(attributeGXL.Name))
                                {
                                    if (IntGetFMG_Value < DicAnaFMG_TableNumericEdge[attributeGXL.Name][0])
                                        DicAnaFMG_TableNumericEdge[attributeGXL.Name][0] = IntGetFMG_Value;
                                    if (IntGetFMG_Value > DicAnaFMG_TableNumericEdge[attributeGXL.Name][1])
                                        DicAnaFMG_TableNumericEdge[attributeGXL.Name][1] = IntGetFMG_Value;
                                }
                                else
                                {
                                    List<double> LisAnaFMG_New = new List<double>();
                                    //stocker la valeur courant comme la valeur minimal et maximal
                                    LisAnaFMG_New.Add(IntGetFMG_Value);
                                    LisAnaFMG_New.Add(IntGetFMG_Value);
                                    DicAnaFMG_TableNumericEdge.Add(attributeGXL.Name, LisAnaFMG_New);
                                }
                            }
                            //s'il est symbolique
                            else
                            {
                                string IntGetFMG_Value = attributeGXL.Value;
                                //si l'attribut est déja existé
                                if (DicAnaFMG_TableSybmolicEdge.ContainsKey(attributeGXL.Name))
                                {
                                    //si la valeur n'existe pas
                                    if (DicAnaFMG_TableSybmolicEdge[attributeGXL.Name].IndexOf(attributeGXL.Value) == -1)
                                    {
                                        DicAnaFMG_TableSybmolicEdge[attributeGXL.Name].Add(attributeGXL.Value);
                                    }
                                }
                                else
                                {
                                    DicAnaFMG_TableSybmolicEdge.Add(attributeGXL.Name, new List<string>() { attributeGXL.Value });
                                }
                            }
                        }
                    }
                }
            }
            if (isSave == true)
            {
                try
                {
                    //**************************************************************************************************************
                    //**************************************************pour les attributs numerique********************************
                    //**************************************************************************************************************
                    using (System.IO.StreamWriter SysAnaFMG_OutFile = new System.IO.StreamWriter(strDic + "\\edge_numeric.txt"))
                    {
                        foreach (KeyValuePair<string, List<double>> KeyAnaFMG in DicAnaFMG_TableNumericEdge)
                        {
                            string StrAnaFMG = KeyAnaFMG.Key + ": ";
                            foreach (double DouAnaFMG in KeyAnaFMG.Value)
                            {
                                StrAnaFMG += " <" + DouAnaFMG.ToString() + ">";
                            }
                            SysAnaFMG_OutFile.WriteLine(StrAnaFMG);
                        }
                    }
                    //**************************************************************************************************************
                    //**************************************************pour les attributs symboliques******************************
                    //**************************************************************************************************************
                    using (System.IO.StreamWriter SysAnaFMG_OutFile = new System.IO.StreamWriter(strDic + "\\edge_symbolic.txt"))
                    {
                        foreach (KeyValuePair<string, List<string>> KeyAnaFMG in DicAnaFMG_TableSybmolicEdge)
                        {
                            string StrAnaFMG_Out = KeyAnaFMG.Key + ": ";
                            foreach (string StrAnaFMG in KeyAnaFMG.Value)
                            {
                                StrAnaFMG_Out += " <" + StrAnaFMG.ToString() + "> Value :" +
                                    KeyAnaFMG.Value.IndexOf(StrAnaFMG).ToString() + " .";
                            }
                            SysAnaFMG_OutFile.WriteLine(StrAnaFMG_Out);
                        }
                    }
                }
                catch (Exception ExcAnaFMG)
                {
                    Console.WriteLine("fail to write file.");
                    throw ExcAnaFMG;
                }
            }

            return true;
        }
        //-------------------------------fin de AnalyseEdgeAttribute-----------------------------------------------------------
        #endregion
        */     
        #region traitement XML

        /// <summary>
        /// Créer l'index d'une base de graphe
        /// Ecrire le tableau(indexation)
        /// Erreur:quand on n'arrive pas à ecrire le fichier XML
        /// </summary>
        /// <param name="StrDictionary">répertoire de la fichier xml</param>
        public void WriteXML(string StrDictionary)
        {
            //ecrire les fichiers d'apprentissage
            embedding.SaveBins(StrDictionary);

            //verifier que tout les processuss sont fini.
            if (listGraphName.Count == 0)
            {
                Console.Write("There isn't any graph gxl in your directonary. \n");
                return;
            }
            if (listVectorFGME.Count == 0)
            {
                Console.Write("You should call Graph2Vector first. \n");
                return;
            }
            if (listClusterLabel.Count == 0)
            {
                Console.Write("Your should do clustering first. \n");
                return;
            }
            //on commence à ecrire
            try
            {
                XmlDocument XmlWriFGM = new XmlDocument();
                XmlElement rootElement = XmlWriFGM.CreateElement("Cliques");
                XmlWriFGM.AppendChild(rootElement);
                for (int i = 0; i < listGraphName.Count; i++)
                {
                    XmlElement XmlWriFGM_1 = XmlWriFGM.CreateElement("Clique");
                    XmlWriFGM_1.SetAttribute("Clique", listGraphName[i]);
                    rootElement.AppendChild(XmlWriFGM_1);
                    XmlWriFGM_1.SetAttribute("Directory", listDirectoryGraph[i]);
                    XmlElement XmlWriFGM_1_1 = XmlWriFGM.CreateElement("Vector");
                    XmlWriFGM_1_1.InnerText = listVectorFGME[i].GetString();
                    XmlWriFGM_1.AppendChild(XmlWriFGM_1_1);
                    XmlElement XmlWriFGM_1_2 = XmlWriFGM.CreateElement("Label");
                    XmlWriFGM_1_2.InnerText = listClusterLabel[i].ToString();
                    XmlWriFGM_1.AppendChild(XmlWriFGM_1_2);
                }
                XmlWriFGM.Save(StrDictionary + "\\indexation.xml");

            }
            catch(Exception e)
            {
                Console.Write(e.Message);
                throw new Exception("Fail to write into XML. \n", e);
            }
        }
        //--------------------------------------fin de WriteXML------------------------------------------------------------------

        /// <summary>
        /// Reilitialise une signature et le repmlit par un fichier XML
        /// </summary>
        /// <param name="StrDictionary"></param>
        public void ReadXML(string StrDictionary)
        {

            listClusterLabel = new List<int>();

            //listGraphs = new List<Graph>();

            listGraphName = new List<string>();

            listVectorFGME = new List<VectorFMGE>();

            listDirectoryGraph = new List<string>();

            XmlDocument XmlReaFGM = new XmlDocument();
            try
            {
                XmlReaFGM.Load(StrDictionary);
            }
            catch (Exception e)
            {
                Console.Write(e.Message);
                throw new Exception("Fail to read XML. \n", e);
            }
            //trouver la racine
            XmlNode XmlReaFGM_root = XmlReaFGM.SelectSingleNode("Cliques");
            //trouver la liste de filles de la racine
            XmlNodeList XmlReaFGM_NodeList = XmlReaFGM_root.ChildNodes;
            foreach (XmlNode node in XmlReaFGM_NodeList)
            {
                XmlElement XmlEeaFGM_Elem = (XmlElement)node;
                XmlElement XmlEeaFGM_Vector = (XmlElement)node.FirstChild;
                XmlElement XmlEeaFGM_Label = (XmlElement)node.LastChild;
                listGraphName.Add(XmlEeaFGM_Elem.GetAttribute("Clique"));
                listDirectoryGraph.Add(XmlEeaFGM_Elem.GetAttribute("Directory"));

                listVectorFGME.Add(new VectorFMGE(XmlEeaFGM_Vector.InnerText));
                listClusterLabel.Add(Convert.ToInt32(XmlEeaFGM_Label.InnerText));
            }
        }
        //--------------------------------------fin de ReadXML-------------------------------------------------------------------


        #endregion

        #endregion
    }
}
