/// <summary>
        ///
        /// </summary>
        /// <param name="rawCouples">unclustered array of PredictionCouples having each a similarity assigned to it</param>
        /// <param name="clusterWidth"> the width of the cluster grouping this PredictionCouples ex: 0.1 </param>
        /// <returns></returns>
        public static List <Cluster> Cluster(IEnumerable <PredictionCouple> rawCouples, double clusterWidth)
        {
            /// TODO : optimize Function
            List <Cluster> finalList     = new List <Cluster>();
            double         startingBound = 0;
            var            sortedData    = from item in rawCouples
                                           orderby item.Similarity descending
                                           select item;

            if (clusterWidth > 1)
            {
                clusterWidth = 1;
            }

            while (startingBound <= 1 - clusterWidth)
            {
                Cluster cluster = new Cluster(startingBound, startingBound + clusterWidth);
                ///TODO : optimize this piece of code to not traverse all sortedData everyTime
                foreach (PredictionCouple item in sortedData)
                {
                    /// add element if he had similarity in this cluster
                    cluster.AddElement(item);
                }

                finalList.Add(cluster);

                startingBound += clusterWidth;
            }


            return(finalList);
        }
        public override Structuring TurnOffReduction(Set dataSet, Structuring partition)
        {
            if (partition is ReductionPartition)
            {
                return(((ReductionPartition)partition).Partition);
            }
            else
            {
                Dictionary <string, Cluster> _dic = new Dictionary <string, Cluster>();

                foreach (var item in partition.Clusters)
                {
                    Cluster _cluster    = item.Value;
                    Cluster _newCluster = new Cluster(_cluster.Name, new List <Element>());
                    foreach (var _e in _cluster.Elements)
                    {
                        foreach (var _object in _e.Values)
                        {
                            _newCluster.AddElement((Element)_object);
                        }
                    }
                    _dic.Add(_newCluster.Name, _newCluster);
                }

                return(new Partition()
                {
                    Clusters = _dic, Proximity = partition.Proximity
                });
            }
        }
        public override Structuring BuildStructuring()
        {
            if (Structurings == null || Set == null)
            {
                throw new NullReferenceException();
            }

            if (IContainerProgressBar != null)
            {
                IContainerProgressBar.ResetProgressBar(1, 1, true);
                IContainerProgressBar.UpdateProgressBar(0, "Running QMI algorithm...", true);
            }

            List <Attribute> list_att = new List <Attribute>();
            int cont = 0;

            foreach (Structuring s in Structurings)
            {
                foreach (Cluster c in s.Clusters.Values)
                {
                    Attribute att = new Attribute("x" + cont, null);
                    cont++;

                    att.AttributeType = AttributeType.Numeric;
                    list_att.Add(att);
                }
            }

            Set newset = new Set("Artificial");

            newset.Attributes  = new Attributes(list_att);
            newset.ElementType = ElementType.Numeric;


            foreach (Element e in Set.Elements)
            {
                List <object> values = new List <object>();
                foreach (Structuring s in Structurings)
                {
                    foreach (Cluster c in s.Clusters.Values)
                    {
                        double temp = c.HaveElement(e) ? 1 : 0;
                        temp = temp - ((double)c.ElementsCount / (double)Set.ElementsCount);
                        values.Add(temp);
                    }
                }
                Element newelement = new Element(newset, values);
                newelement.Name  = e.Name;
                newelement.Index = e.Index;

                newset.AddElement(newelement);
            }

            KMeans kms = new KMeans(newset, new EuclideanDistance()
            {
                AttributesToCalculateProximity = newset.Attributes.Values
            });

            kms.ClustersCount   = ClusterCount;
            kms.IterationsCount = IterationsCount;
            kms.Seed            = Environment.TickCount;

            kms.IContainerProgressBar = IContainerProgressBar;

            Structuring art_struct = kms.BuildStructuring();

            List <Cluster> clusters = new List <Cluster>();

            cont = 0;
            foreach (Cluster c in art_struct.Clusters.Values)
            {
                Cluster temp = new Cluster("C-" + cont);
                cont++;
                foreach (Element item in c.Elements)
                {
                    temp.AddElement(Set[item.Index]);
                }
                clusters.Add(temp);
            }

            Dictionary <string, Cluster> temp_dic = new Dictionary <string, Cluster>();

            foreach (Cluster item in clusters)
            {
                temp_dic.Add(item.Name, item);
            }

            Structuring real_struct = new Partition()
            {
                Clusters = temp_dic
            };

            return(real_struct);
        }
示例#4
0
        public override Structuring BuildStructuring()
        {
            try
            {
                if (Set == null || Structurings == null)
                {
                    throw new NullReferenceException();
                }

                int _current = 1, _max = IterationsCount;
                if (IContainerProgressBar != null)
                {
                    IContainerProgressBar.ResetProgressBar(1, _max, true);
                    IContainerProgressBar.UpdateProgressBar(0, "Running Simulated Annealing MeetJoinClusters algorithm...", true);
                }

                int random_pos = new Random(Environment.TickCount).Next(0, StructuringsCount);
                //EuclideanDistance _eu = new EuclideanDistance();
                //_eu.AttributesToCalculateProximity = Set.Attributes.Values;
                //KMeans _kmeans = new KMeans(Set, _eu);
                //_kmeans.ClustersCount =3;
                //_kmeans.Seed = Environment.TickCount;
                //_kmeans.IterationsCount = 100;

                //Structuring initial = Structurings[random_pos];

                BOK bok = new BOK(Set, Structurings)
                {
                    GenericDistances = new MirkinDistance()
                };
                Structuring initial = UseBOK ? bok.BuildStructuring() : Structurings[0];

                string[] initial_sol = new string[Set.ElementsCount];
                for (int i = 0; i < Set.ElementsCount; i++)
                {
                    initial_sol[i] = initial.Elements[Set[i]][0];
                }

                int _maxCluster = initial.ClustersCount;

                List <string[]> labels_List = new List <string[]>();
                //Convertir todas las particiones a arreglo de string, donde en cada posicion
                //esta la etiqueta del cluster al que pertenece el elemento j
                for (int i = 0; i < Structurings.Count; i++)
                {
                    string[] _temp = new string[Set.ElementsCount];
                    labels_List.Add(_temp);
                    for (int j = 0; j < Set.ElementsCount; j++)
                    {
                        _temp[j] = Structurings[i].Elements[Set[j]][0];
                    }
                }

                string[] _result_labels = SA <string[]> .RunSAOMNewNeighbor(Set, initial_sol, labels_List, Temperature, .99, 50, 1.05, 10, .5, IterationsCount, IContainerProgressBar, _current, GenericDistances, ref _maxCluster);

                Dictionary <string, Cluster> dic_clusters = new Dictionary <string, Cluster>();
                for (int i = 0; i < Set.ElementsCount; i++)
                {
                    if (dic_clusters.ContainsKey(_result_labels[i]))
                    {
                        dic_clusters[_result_labels[i]].AddElement(Set[i]);
                    }
                    else
                    {
                        Cluster c = new Cluster(_result_labels[i]);
                        c.AddElement(Set[i]);
                        dic_clusters.Add(c.Name, c);
                    }
                }

                if (IContainerProgressBar != null)
                {
                    IContainerProgressBar.FinishProgressBar();
                }

                Structuring = new Partition()
                {
                    Clusters = dic_clusters
                };
                return(Structuring);
            }
            catch
            {
                if (IContainerProgressBar != null)
                {
                    IContainerProgressBar.ShowError("Error occurred in Simulated Annealing MeetJoinClusters algorithm.");
                }
                return(null);
            }
        }
        public override Structuring BuildStructuring()
        {
            try
            {
                if (Set == null || Structurings == null)
                {
                    throw new NullReferenceException();
                }

                int _current = 1, _maxpb = Set.ElementsCount * Structurings.Count;
                if (IContainerProgressBar != null)
                {
                    IContainerProgressBar.ResetProgressBar(1, _maxpb, true);
                    IContainerProgressBar.UpdateProgressBar(1, "Running HGPA algorithm...", true);
                }

                if (ClustersCount <= 0)
                {
                    throw new Exception("La cantidad de clusters debe ser mayor que cero");
                }
                else if (ClustersCount == 1)
                {
                    Dictionary <string, Cluster> dic_clus = new Dictionary <string, Cluster>();
                    string         name = "C-0";
                    List <Element> temp = new List <Element>();

                    for (int i = 0; i < Set.ElementsCount; i++)
                    {
                        temp.Add(Set[i]);
                    }

                    dic_clus.Add(name, new Cluster(name)
                    {
                        Elements = temp
                    });

                    Structuring = new Partition()
                    {
                        Clusters = dic_clus
                    };

                    if (IContainerProgressBar != null)
                    {
                        IContainerProgressBar.FinishProgressBar();
                    }

                    return(Structuring);
                }
                else
                {
                    #region Algorithm
                    //Construir un conjunto de elementos donde ahora cada elemento es un label,
                    //o lo que es lo mismo una hyperedge. Este seria el meta-grafo
                    Set hyperedgeSet = new Set("HyperEdge Set");

                    int dimH = 0;
                    foreach (Structuring s in Structurings)
                    {
                        dimH += s.ClustersCount;
                    }

                    byte[,] metagraph = new byte[Set.ElementsCount, dimH];

                    //Ahora por cada label annadir un nuevo elemento al conjunto, recordar que cada label
                    //seria cada hyperedges, lo que ahora cada hyperedges estaria representada por la clase Element
                    //pero la lista de Values seria el vector binario o mejor dicho los elementos que pertenecen
                    //a la hyperedges.
                    //La matriz metagraph es la representacion en vectores binarios del conjunto hyperedges.

                    // Ojo esto ya  ///////Es mejor representar cada hyperedges de esta forma es decir con los elementos que pertenecen
                    // no se hace   ///////a dicha hyperedges ya que si se representa por el vector binario entonces necesitariamos mucha memoria.
                    int index = 0;
                    foreach (Structuring structuring in Structurings)
                    {
                        foreach (Cluster cluster in structuring.Clusters.Values)
                        {
                            Element element = new Element();
                            element.Index = index;
                            element.Name  = "hyperedge-" + index;
                            foreach (Element temp in cluster.Elements)
                            {
                                metagraph[temp.Index, index] = 1;

                                if (IContainerProgressBar != null)
                                {
                                    IContainerProgressBar.UpdateProgressBar(_current++, "Running HGPA algorithm...", false);
                                }
                            }

                            hyperedgeSet.AddElement(element);
                            index++;
                        }
                    }

                    if (IContainerProgressBar != null)
                    {
                        IContainerProgressBar.UpdateProgressBar(_maxpb, "Running HGPA algorithm...", true);
                    }

                    Similarity _sim = new BinaryJaccardMeasure(metagraph);

                    ClusterAlgorithm ca = new Metis(hyperedgeSet, _sim);

                    ca.ClustersCount = ClustersCount;
                    ca.BuildStructuring();

                    Partition metaClusters = (Partition)ca.Structuring;

                    //Asignar cada elemento original a su metacluster correspondiente

                    //double[] va a tener dimension igual a la cantidad de elementos iniciales y en cada posicion va a estar un numero entre 0 y 1
                    List <double[]> _meta_hyperedges = new List <double[]>();
                    foreach (Cluster _c in metaClusters.Clusters.Values)
                    {
                        double[] _meta_hyperedge = new double[metagraph.GetLength(0)];
                        foreach (Element _e in _c.Elements)
                        {
                            //_e.Index es la columna de la matrix metgraph, que dicha columna representa a ese elemento
                            for (int row = 0; row < metagraph.GetLength(0); row++)
                            {
                                _meta_hyperedge[row] += metagraph[row, _e.Index];
                            }
                        }

                        //LLevar cada posicion a un valor enre 0 y 1
                        for (int i = 0; i < _meta_hyperedge.Length; i++)
                        {
                            _meta_hyperedge[i] = _meta_hyperedge[i] / _c.ElementsCount;
                        }

                        _meta_hyperedges.Add(_meta_hyperedge);
                    }

                    //Construir la particion final
                    Dictionary <string, Cluster> _dic_clusters = new Dictionary <string, Cluster>();

                    for (int i = 0; i < Set.ElementsCount; i++)
                    {
                        Element _e = Set[i];

                        double _max            = -1;
                        int    _meta_hyperedge = -1;
                        for (int j = 0; j < _meta_hyperedges.Count; j++)
                        {
                            if (_meta_hyperedges[j][_e.Index] > _max)
                            {
                                _max            = _meta_hyperedges[j][_e.Index];
                                _meta_hyperedge = j;
                            }
                        }

                        string _nameOfCluster = "C-" + _meta_hyperedge;
                        if (_dic_clusters.ContainsKey(_nameOfCluster))
                        {
                            _dic_clusters[_nameOfCluster].AddElement(_e);
                        }
                        else
                        {
                            Cluster c = new Cluster(_nameOfCluster);
                            c.AddElement(_e);
                            _dic_clusters.Add(_nameOfCluster, c);
                        }
                    }


                    Structuring = new Partition()
                    {
                        Clusters = _dic_clusters
                    };

                    if (IContainerProgressBar != null)
                    {
                        IContainerProgressBar.FinishProgressBar();
                    }

                    return(Structuring);

                    #endregion
                }
            }
            catch
            {
                if (IContainerProgressBar != null)
                {
                    IContainerProgressBar.ShowError("Error occurred in MCLA algorithm.");
                }
                return(null);
            }
        }
        //OJO Excepciones porque dice que no puede acceder al fichero porque esta siendo usado por otro proceso
        //tbn da Excepcion porque dice que no existe el fichero.
        //Parece que el metis se demora un poco creandolo, debe ser algo de eso, y lo crea pero despues parece que empieza
        //a escribir sobre el y entonces es que me da la otra excepcion de que esta siendo usado por otra persona, es que todo
        //ocurre muy rapido, NUNCA ME HA DADO EXCEPCION EN EL MODO DEBUG
        public static Structuring BuildStructuringFromOutputFile(string inputfilename, Set Set, int ClustersCount, Proximity Proximity)
        {
            try
            {
                string folderpath = Utils.ExesFolderPath;
                string filename = inputfilename + ".part." + ClustersCount;
                string filepath = folderpath + Path.DirectorySeparatorChar + filename;

                //Dar tiempo a que el algoritmo Metis cree el fichero
                while (!File.Exists(filepath))
                {
                }

                FileStream fs = null;
                bool ok = false;
                //Dar tiempo a que el algoritmo Metis termine de escribir sobre el fichero de salida
                while (!ok)
                {
                    try
                    {
                        fs = new FileStream(filepath, FileMode.Open, FileAccess.Read);
                        ok = true;
                    }
                    catch
                    { }
                }

                StreamReader sr = new StreamReader(fs);
                Dictionary<string, Cluster> dic_clusters;
                try
                {
                    //Crear Dictionary<string,Cluster> para poder construir la particion
                    dic_clusters = new Dictionary<string, Cluster>();
                    string line;
                    int vertex = 0;
                    while ((line = sr.ReadLine()) != null)
                    {
                        int cluster = int.Parse(line);
                        string nameOfCluster = "C-" + cluster;
                        if (dic_clusters.ContainsKey(nameOfCluster))
                        {
                            dic_clusters[nameOfCluster].AddElement(Set[vertex]);
                        }
                        else
                        {
                            Cluster c = new Cluster(nameOfCluster);
                            c.AddElement(Set[vertex]);
                            dic_clusters.Add(nameOfCluster, c);
                        }
                        vertex++;
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("Formato incorrecto del fichero de salida del algoritmo METIS \r\nInformacion Adicional: " + ex.Message);
                }
                finally
                {
                    sr.Close();
                    fs.Close();

                    //Eliminar el fichero de entrada
                    File.Delete(ExesFolderPath + Path.DirectorySeparatorChar + inputfilename);

                    //Eliminar el fichero de salida
                    File.Delete(filepath);
                }

                //Los numeros de las particiones comienzan con cero hasta el numero de particiones menos uno[0,...,P-1]
                return new Partition() { Clusters = dic_clusters, Proximity = Proximity };
            }
            catch
            {
                return null;
            }
        }
示例#7
0
        private void Crossover(Pair parents)
        {
            parents.P1 = Utils.Clone((Structuring)parents.P1);
            parents.P2 = Utils.Clone((Structuring)parents.P2);

            Cluster new_c1 = new Cluster(parents.C1.Name);
            Cluster new_c2 = new Cluster(parents.C2.Name);

            List <Element> un_el_p1 = new List <Element>();
            List <Element> un_el_p2 = new List <Element>();

            foreach (Element item in parents.C1.Elements)
            {
                if (parents.C2.HaveElement(item))
                {
                    new_c2.AddElement(item);
                }

                //else if (!parents.P2.Clusters.Values.ToList().Exists(c => c.HaveElement(item)))
                //    new_c2.AddElement(item);
                //else
                //{
                //    //Si entra aki, el problema es que un elemento de C1, no pertenece a C2 (C2 es un de la P2), ni tampoco
                //    //pertenece a algun otro cluster de P2, por lo tanto ese elemento no esta en la particion P2, y P2 y P1
                //    //son particiones de un mismo conjunto. Este caso solamente se debe dar cuando P2 tiene elementos no asignados
                //    //y este elemento que estoy analizando puede estar no asignado, ahi en P2.
                //    throw new Exception("no puede entrara aki, siginificaria que cada particion tiene conjuntos distintos.");

                //    string c_temp = parents.P2.Elements[item][0];
                //    parents.P2.Clusters[c_temp].Elements.Remove(item);
                //    parents.P2.Elements.Remove(item);
                //    un_el_p2.Add(item);
                //}
            }

            foreach (Element item in parents.C2.Elements)
            {
                if (parents.C1.HaveElement(item))
                {
                    new_c1.AddElement(item);
                }

                //else if (!parents.P1.Clusters.Values.ToList().Exists(c => c.HaveElement(item)))
                //    new_c1.AddElement(item);
                //else
                //{
                //    for (int i = 0; i < parents.P1.Clusters.Values.ToList().Count; i++)
                //    {
                //        Cluster _ccc = parents.P1.Clusters.Values.ToList()[i];
                //        for (int ii = 0; ii < _ccc.ElementsCount; ii++)
                //        {
                //            if (_ccc[ii].Index == item.Index)
                //            {
                //            }
                //        }
                //    }
                //    //Si entra aki, el problema es que un elemento de C1, no pertenece a C2 (C2 es un de la P2), ni tampoco
                //    //pertenece a algun otro cluster de P2, por lo tanto ese elemento no esta en la particion P2, y P2 y P1
                //    //son particiones de un mismo conjunto. Este caso solamente se debe dar cuando P2 tiene elementos no asignados
                //    //y este elemento que estoy analizando puede estar no asignado, ahi en P2.
                //    throw new Exception("no puede entrara aki, siginificaria que cada particion tiene conjuntos distintos.");

                //    string c_temp = parents.P1.Elements[item][0];
                //    parents.P1.Clusters[c_temp].Elements.Remove(item);
                //    parents.P1.Elements.Remove(item);
                //    un_el_p1.Add(item);
                //}
            }

            foreach (var item in new_c1.Elements)
            {
                parents.P1.Elements[item] = new List <string>()
                {
                    new_c1.Name
                };
            }

            foreach (var item in new_c2.Elements)
            {
                parents.P2.Elements[item] = new List <string>()
                {
                    new_c2.Name
                };
            }

            parents.P1.Clusters[new_c1.Name] = new_c1;
            parents.P2.Clusters[new_c2.Name] = new_c2;

            if (parents.P1.UnassignedElements != null)
            {
                parents.P1.UnassignedElements.AddRange(un_el_p1);
            }
            else
            {
                parents.P1.UnassignedElements = un_el_p1;
            }

            if (parents.P2.UnassignedElements != null)
            {
                parents.P2.UnassignedElements.AddRange(un_el_p2);
            }
            else
            {
                parents.P2.UnassignedElements = un_el_p2;
            }
        }
        private void Crossover(Pair parents)
        {
            parents.P1 = Utils.Clone((Structuring)parents.P1);
            parents.P2 = Utils.Clone((Structuring)parents.P2);

            Cluster new_c1 = new Cluster(parents.C1.Name);
            Cluster new_c2 = new Cluster(parents.C2.Name);

            List<Element> un_el_p1=new List<Element>();
            List<Element> un_el_p2=new List<Element>();

            foreach (Element item in parents.C1.Elements)
            {
                if (parents.C2.HaveElement(item))
                    new_c2.AddElement(item);

                //else if (!parents.P2.Clusters.Values.ToList().Exists(c => c.HaveElement(item)))
                //    new_c2.AddElement(item);
                //else
                //{
                //    //Si entra aki, el problema es que un elemento de C1, no pertenece a C2 (C2 es un de la P2), ni tampoco
                //    //pertenece a algun otro cluster de P2, por lo tanto ese elemento no esta en la particion P2, y P2 y P1
                //    //son particiones de un mismo conjunto. Este caso solamente se debe dar cuando P2 tiene elementos no asignados
                //    //y este elemento que estoy analizando puede estar no asignado, ahi en P2.
                //    throw new Exception("no puede entrara aki, siginificaria que cada particion tiene conjuntos distintos.");
                    
                //    string c_temp = parents.P2.Elements[item][0];
                //    parents.P2.Clusters[c_temp].Elements.Remove(item);
                //    parents.P2.Elements.Remove(item);
                //    un_el_p2.Add(item);
                //}       
                
            }            

            foreach (Element item in parents.C2.Elements)
            {
                if (parents.C1.HaveElement(item))
                    new_c1.AddElement(item);

                //else if (!parents.P1.Clusters.Values.ToList().Exists(c => c.HaveElement(item)))
                //    new_c1.AddElement(item);
                //else
                //{
                //    for (int i = 0; i < parents.P1.Clusters.Values.ToList().Count; i++)
                //    {
                //        Cluster _ccc = parents.P1.Clusters.Values.ToList()[i];
                //        for (int ii = 0; ii < _ccc.ElementsCount; ii++)
                //        {
                //            if (_ccc[ii].Index == item.Index)
                //            { 
                //            }
                //        }
                //    }
                //    //Si entra aki, el problema es que un elemento de C1, no pertenece a C2 (C2 es un de la P2), ni tampoco
                //    //pertenece a algun otro cluster de P2, por lo tanto ese elemento no esta en la particion P2, y P2 y P1
                //    //son particiones de un mismo conjunto. Este caso solamente se debe dar cuando P2 tiene elementos no asignados
                //    //y este elemento que estoy analizando puede estar no asignado, ahi en P2.
                //    throw new Exception("no puede entrara aki, siginificaria que cada particion tiene conjuntos distintos.");

                //    string c_temp = parents.P1.Elements[item][0];
                //    parents.P1.Clusters[c_temp].Elements.Remove(item);
                //    parents.P1.Elements.Remove(item);
                //    un_el_p1.Add(item);
                //}

            }

            foreach (var item in new_c1.Elements)
            {
                parents.P1.Elements[item] = new List<string>() { new_c1.Name };
            }

            foreach (var item in new_c2.Elements)
            {
                parents.P2.Elements[item] = new List<string>() { new_c2.Name };
            }

            parents.P1.Clusters[new_c1.Name] = new_c1;
            parents.P2.Clusters[new_c2.Name] = new_c2;

            if (parents.P1.UnassignedElements != null)
                parents.P1.UnassignedElements.AddRange(un_el_p1);
            else
                parents.P1.UnassignedElements = un_el_p1;

            if (parents.P2.UnassignedElements != null)
                parents.P2.UnassignedElements.AddRange(un_el_p2);
            else
                parents.P2.UnassignedElements = un_el_p2;

        }
        public override Structuring BuildStructuring()
        {
            if (Structurings == null || Set == null)
                throw new NullReferenceException();

            if (IContainerProgressBar != null)
            {
                IContainerProgressBar.ResetProgressBar(1, 1, true);
                IContainerProgressBar.UpdateProgressBar(0, "Running QMI algorithm...", true);
            }

            List<Attribute> list_att = new List<Attribute>();
            int cont = 0;
            foreach (Structuring s in Structurings)
            {
                foreach (Cluster c in s.Clusters.Values)
                {
                    Attribute att = new Attribute("x" + cont, null);
                    cont++;

                    att.AttributeType = AttributeType.Numeric;
                    list_att.Add(att);
                }
            }

            Set newset = new Set("Artificial");
            newset.Attributes = new Attributes(list_att);
            newset.ElementType = ElementType.Numeric;

            
            foreach (Element e in Set.Elements)
            {
                List<object> values = new List<object>();
                foreach (Structuring s in Structurings)
                {
                    foreach (Cluster c in s.Clusters.Values)
                    {
                        double temp = c.HaveElement(e) ? 1 : 0;
                        temp = temp - ((double)c.ElementsCount / (double)Set.ElementsCount);
                        values.Add(temp);
                    }
                }
                Element newelement = new Element(newset, values);                
                newelement.Name = e.Name;
                newelement.Index = e.Index;
                
                newset.AddElement(newelement);
            }

            KMeans kms = new KMeans(newset, new EuclideanDistance() { AttributesToCalculateProximity = newset.Attributes.Values });
            kms.ClustersCount = ClusterCount;
            kms.IterationsCount = IterationsCount;
            kms.Seed = Environment.TickCount;

            kms.IContainerProgressBar = IContainerProgressBar;

            Structuring art_struct = kms.BuildStructuring();

            List<Cluster> clusters = new List<Cluster>();
            cont = 0;
            foreach (Cluster c in art_struct.Clusters.Values)
            {
                Cluster temp = new Cluster("C-" + cont);
                cont++;
                foreach (Element item in c.Elements)
                {
                    temp.AddElement(Set[item.Index]);
                }
                clusters.Add(temp);
            }

            Dictionary<string, Cluster> temp_dic=new Dictionary<string,Cluster>();
            foreach (Cluster item in clusters)
            {
                temp_dic.Add(item.Name, item); 
            }

            Structuring real_struct = new Partition() { Clusters = temp_dic };
            return real_struct;            
        }
        public override List <Structuring> GetReduction(Set dataSet, List <Structuring> realPartitions, out Set anewSet)
        {
            if (dataSet == null || realPartitions == null)
            {
                throw new ArgumentNullException();
            }

            // Calculamos la matriz de adyacencia
            bool[,] adjMatrix = new bool[dataSet.ElementsCount, dataSet.ElementsCount];
            int[] visited = new int[dataSet.ElementsCount];
            int   ccCount = 0;

            for (int i = 0; i < dataSet.ElementsCount - 1; i++)
            {
                for (int j = i + 1; j < dataSet.ElementsCount; j++)
                {
                    int jointCount     = 0;
                    int halfPartitions = (int)Math.Floor(realPartitions.Count / 2.0);
                    foreach (var partition in realPartitions)
                    {
                        if (partition.BeSameCluster(dataSet[i], dataSet[j]))
                        {
                            jointCount++;
                        }
                        if (jointCount > halfPartitions)
                        {
                            adjMatrix[i, j] = adjMatrix[j, i] = true;
                            break;
                        }
                    }
                }
            }

            for (int i = 0; i < dataSet.ElementsCount; i++)
            {
                if (visited[i] == 0)
                {
                    ccCount++;
                    DFS(i, adjMatrix, visited, ccCount);
                }
            }

            fragments = new Dictionary <string, List <object> >();

            for (int i = 1; i <= ccCount; i++)
            {
                fragments.Add("OurFragment-" + i, new List <object>());
            }

            for (int i = 0; i < dataSet.ElementsCount; i++)
            {
                fragments["OurFragment-" + visited[i]].Add(dataSet[i]);
            }


            // La transformación
            List <Element> _elements = new List <Element>();
            Set            _newSet   = new Set(dataSet.RelationName + "(Reduction-Set)", _elements, dataSet.Attributes);

            foreach (var item in fragments)
            {
                Element _e = new Element(_newSet, item.Value);
                _e.Name = item.Key;
                _elements.Add(_e);
            }
            anewSet = _newSet;
            List <Structuring> partitions = new List <Structuring>();

            //Build partitions
            //First Partition
            Dictionary <string, Cluster> dic_clusters = new Dictionary <string, Cluster>();

            for (int i = 0; i < anewSet.ElementsCount; i++)
            {
                Cluster _c = new Cluster("C-" + i);
                _c.AddElement(anewSet[i]);
                dic_clusters.Add(_c.Name, _c);
            }
            partitions.Add(new Partition()
            {
                Clusters = dic_clusters
            });

            //realPartitions.ForEach(rp => partitions.Add(new ReductionPartition(rp, _newSet, fragments)));

            return(partitions);
        }