//Dado un elemento y una lista de clusters devuelve la posicion del cluster mas similar private int ClusterProcessedElement(Element e, List <Cluster> l) { //Esto es asi ya que estamos tratando con dissimilitud, es decir mientras mas pequeno mas cerca estan double minDist = double.MaxValue; int bestCluster = 0; for (int i = 0; i < ClustersCount; i++) { double dist = Proximity.CalculateProximity(e, l[i].Centroid); if (dist < minDist) { minDist = dist; bestCluster = i; } } return(bestCluster); }
private string BuildInputFile(ref int acurrent) { string folderpath = Utils.ExesFolderPath; string filename = "inputgraph" + Utils.GetUniqueID + ".config"; string filepath = folderpath + Path.DirectorySeparatorChar + filename; if (File.Exists(filepath)) { File.Delete(filepath); } FileStream fs = new FileStream(filepath, FileMode.CreateNew, FileAccess.ReadWrite); StreamWriter sw = new StreamWriter(fs); //First Line #vertex , #edges , #code int vertices = Set.ElementsCount; int edges = (vertices * (vertices - 1)) / 2; int code = 1; string firstLine = vertices + " " + edges + " " + code; sw.WriteLine(firstLine); int edgesZero = 0;//Este es un numero par ya que si (i,j)=0 entonces tbn sera cero (j,i)=0 //n-lines, where n is the amount of vertices, the vertices start in 1 StringBuilder line; for (int i = 0; i < Set.ElementsCount; i++) { line = new StringBuilder(); for (int j = 0; j < Set.ElementsCount; j++) { if (i != j) { int adj = j + 1; double edgeweight = Proximity.CalculateProximity(Set[i], Set[j]); //Codigo Chiki string number = (edgeweight * 100000).ToString(); string[] parts = number.Split('.'); int temp = 0; if (!int.TryParse(parts[0], out temp)) { temp = int.MaxValue; } //hasta aqui if (temp != 0) { line.Append(adj + " " + temp + " "); } else { edgesZero++; } } } //Write the line for the vertex i+1 sw.WriteLine(line); } sw.Flush(); //Actualizar la cantidad de aristas ya que pudo haber aristas con costo cero //las cuales no pertenecen al grafo ya que segun la especificacion del fichero de entrada //el costo de las aristas debe ser mayor estricto que cero if (edgesZero > 0) { fs.Seek(0, SeekOrigin.Begin); string newFirstLine = vertices + " " + (edges - edgesZero / 2) + " " + code; int lengthNewFirstLine = newFirstLine.Length; int lengthOldFirstLine = firstLine.Length; byte[] arr = new byte[lengthOldFirstLine]; for (int i = 0; i < lengthNewFirstLine; i++) { arr[i] = (byte)newFirstLine[i]; } if (lengthNewFirstLine < lengthOldFirstLine) { byte white = (byte)' '; for (int i = lengthNewFirstLine; i < lengthOldFirstLine; i++) { arr[i] = white; } } fs.Write(arr, 0, lengthOldFirstLine); fs.Flush(); } sw.Close(); fs.Close(); return(filename); }
public override Structuring BuildStructuring() { try { if (Set == null) { throw new NullReferenceException(); } int _current = 1; int _max = Set.ElementsCount; if (IContainerProgressBar != null) { IContainerProgressBar.ResetProgressBar(1, _max, true); IContainerProgressBar.UpdateProgressBar(1, "Running Hierarchical agglomerative algorithm...", true); } if (ClustersCount > Set.ElementsCount) { ClustersCount = Set.ElementsCount; } if (ClustersCount <= 0) { throw new Exception("La cantidad de clusters debe ser mayor que cero"); } 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++) { if (IContainerProgressBar != null) { IContainerProgressBar.UpdateProgressBar(_current++, "Running Hierarchical agglomerative algorithm...", false); } temp.Add(Set[i]); } dic_clus.Add(name, new Cluster(name) { Elements = temp }); Structuring = new Partition() { Clusters = dic_clus, Proximity = Proximity }; if (IContainerProgressBar != null) { IContainerProgressBar.FinishProgressBar(); } return(Structuring); } double AlfaI = 0, AlfaJ = 0, Beta = 0, Gamma = 0; //Al inicio cada elemento es un cluster double[,] DMatrix = new double[Set.Elements.Count, Set.Elements.Count]; List <Cluster> clusters = new List <Cluster>(); bool[] des = new bool[Set.Elements.Count];//true si ese elemento ya no es representativo for (int i = 0; i < Set.Elements.Count; i++) { List <Element> l = new List <Element>(); l.Add(Set[i]); clusters.Add(new Cluster("C-" + i, l)); } //Construir para cada cluster una cola con prioridad //con las disimilitudes de el con el resto de los clusters //y la matriz de todas las disimilitudes O(n2*log n) List <HeapArray <Container> > lh = new List <HeapArray <Container> >(); for (int i = 0; i < Set.Elements.Count; i++) { lh.Add(new HeapArray <Container>(Set.Elements.Count - 1));//No se pone la diss de un elemento con el mismo } for (int i = 0; i < Set.Elements.Count; i++) { for (int j = i + 1; j < Set.Elements.Count; j++) { double temp_diss = Proximity.CalculateProximity(Set.Elements[i], Set.Elements[j]); DMatrix[i, j] = temp_diss; DMatrix[j, i] = temp_diss; lh[i].Add(new Container { Rank = temp_diss, Name = i, Cluster = j }); lh[j].Add(new Container { Rank = temp_diss, Name = j, Cluster = i }); } } //Algoritmo O(n2*log n) for (int i = Set.Elements.Count; i > ClustersCount; i--) { if (IContainerProgressBar != null) { IContainerProgressBar.UpdateProgressBar(_current++, "Running Hierarchical agglomerative algorithm...", false); } //Seleccionar los 2 clusters mas similares O(n) double min = double.MaxValue; int cluster_i = 0, cluster_j = 0; int pos_cluster_i = 0, pos_cluster_j = 0; for (int j = lh.Count - 1; j >= 0; j--) { if (lh[j].First.Rank < min) { min = lh[j].First.Rank; cluster_i = lh[j].First.Name; cluster_j = lh[j].First.Cluster; pos_cluster_i = j; } } for (int j = 0; j < lh.Count; j++) { if (lh[j].First != null && lh[j].First.Name == cluster_j) { pos_cluster_j = j; break; } } //Calcular posiciones para borrar y guardar int erase_pos = 0, final_pos = 0; erase_pos = pos_cluster_i > pos_cluster_j ? pos_cluster_i : pos_cluster_j; final_pos = pos_cluster_i < pos_cluster_j ? pos_cluster_i : pos_cluster_j; lh.RemoveAt(erase_pos); //Actualizar los parametros AlfaI, AlfaJ, Beta y Gamma double cluster_i_count = clusters[erase_pos].ElementsCount; double cluster_j_count = clusters[final_pos].ElementsCount; AlfaI = UpdateAlfaI(cluster_i_count, cluster_j_count); AlfaJ = UpdateAlfaJ(cluster_i_count, cluster_j_count); Beta = UpdateBeta(cluster_i_count, cluster_j_count); Gamma = UpdateGamma(cluster_i_count, cluster_j_count); //Unir los clusters foreach (Element item in clusters[erase_pos].Elements) { clusters[final_pos].AddElement(item); } clusters.RemoveAt(erase_pos); //Actualizar DMatrix con la disimilitud del nuevo cluster //y el resto de los clusters O(n) //Formula que se usa segun el algoritmo //La posicion del cluster i en Dmatrix es cluster_i //La posicion del cluster j en Dmatrix es cluster_j int pos_h = -1; int pos_i = cluster_i; int pos_j = cluster_j; if (erase_pos == pos_cluster_i) { des[cluster_i] = true; pos_h = cluster_j; } else { des[cluster_j] = true; pos_h = cluster_i; } for (int k = 0; k < DMatrix.GetLength(0); k++) { DMatrix[pos_h, k] = AlfaI * DMatrix[pos_i, k] + AlfaJ * DMatrix[pos_j, k] + Beta * DMatrix[pos_i, pos_j] + Gamma * Math.Abs(DMatrix[pos_i, k] - DMatrix[pos_j, k]); DMatrix[k, pos_h] = DMatrix[pos_h, k]; } //Actualizar array de Heaps con la disimilitud del nuevo cluster //y el resto de los clusters O(n*log n) lh[final_pos] = new HeapArray <Container>(Set.Elements.Count - 1); for (int j = 0; j < lh.Count; j++) { Container[] lc = lh[j].ToArray; lh[j] = new HeapArray <Container>(Set.Elements.Count - 1); for (int k = 1; k < lc.Length; k++) { if (lc[k] == null) { break; } if (lc[k].Cluster != cluster_i && lc[k].Cluster != cluster_j) { lh[j].Add(lc[k]); } } if (j != final_pos && lh[j].First != null) { lh[j].Add(new Container { Rank = DMatrix[pos_h, lh[j].First.Name], Name = lh[j].First.Name, Cluster = pos_h }); } } for (int j = 0; j < DMatrix.GetLength(0); j++) { if (pos_h != j && pos_j != j && pos_i != j && !des[j]) { lh[final_pos].Add(new Container { Rank = DMatrix[pos_h, j], Name = pos_h, Cluster = j }); } } } //Crear Dictionary<string,Cluster> para construir la particion Dictionary <string, Cluster> dic_clusters = new Dictionary <string, Cluster>(); int cont = 0; for (int i = 0; i < clusters.Count; i++) { if (clusters[i] != null) { clusters[i].Name = "C-" + cont; dic_clusters.Add(clusters[i].Name, clusters[i]); cont++; } } Structuring = new Partition() { Clusters = dic_clusters, Proximity = Proximity }; if (IContainerProgressBar != null) { IContainerProgressBar.FinishProgressBar(); } return(Structuring); } catch { if (IContainerProgressBar != null) { IContainerProgressBar.ShowError("Error occurred in Hierarchical agglomerative algorithm."); } return(null); } }