//Добавляет кластер к ближайшему кластеру public void AddToClosestCluster(Cluster cl) { Graph temp = new Graph(G.V); for (int i = 0; i < temp.V.Count; i++) { for (int j = i + 1; j < temp.V.Count; j++) { temp.E.Add(new Edge(temp.V[i], temp.V[j])); } } Vertex neighbour = G.V[0]; double shortestedgeweight = double.MaxValue; for (int j = 0; j < cl.Data.Count; j++)//перебор вершин кластера { for (int i = 0; i < temp.E.Count; i++)//перебор связанных с вершиной рёбер { if (temp.E[i].V1 == cl.Data[j]) { if (temp.E[i].Weight < shortestedgeweight) { bool access = true; for (int q = 0; q < cl.Data.Count; q++) { if (temp.E[i].V2 == cl.Data[q] && q != j) { access = false; } } if (access) { shortestedgeweight = temp.E[i].Weight; neighbour = temp.E[i].V2; } } } else { if (temp.E[i].V2 == cl.Data[j]) { if (temp.E[i].Weight < shortestedgeweight) { bool access = true; for (int q = 0; q < cl.Data.Count; q++) { if (temp.E[i].V1 == cl.Data[q] && q != j) { access = false; } } if (access) { shortestedgeweight = temp.E[i].Weight; neighbour = temp.E[i].V1; } } } } } } for (int i = 0; i < C.Count; i++)//перебор имеющихся кластеров { bool tobreak = false; for (int j = 0; j < C[i].Data.Count; j++)//перебор вершин в кластере i { if (C[i].Data[j] == neighbour) { for (int q = 0; q < cl.Data.Count; q++) { C[i].Data.Add(cl.Data[q]); } C.Remove(cl); tobreak = true; break; } } if (tobreak) break; } }
public Clusters(double[,] A, Tags[] texts, Tags[] words) { textTitles = texts; C = new List<Cluster>(); G = new Graph(); Texts = new Cluster(); double[] W = new double[A.GetLength(0)]; double[,] U = new double[A.GetLength(0), A.GetLength(1)]; double[,] VT = new double[A.GetLength(1), A.GetLength(1)]; alglib.rmatrixsvd(A, A.GetLength(0), A.GetLength(1), 1, 1, 0, out W, out U, out VT); #region /************************************************************************* Singular value decomposition of a rectangular matrix. The algorithm calculates the singular value decomposition of a matrix of size MxN: A = U * S * V^T The algorithm finds the singular values and, optionally, matrices U and V^T. The algorithm can find both first min(M,N) columns of matrix U and rows of matrix V^T (singular vectors), and matrices U and V^T wholly (of sizes MxM and NxN respectively). Take into account that the subroutine does not return matrix V but V^T. Input parameters: A - matrix to be decomposed. Array whose indexes range within [0..M-1, 0..N-1]. M - number of rows in matrix A. N - number of columns in matrix A. UNeeded - 0, 1 or 2. See the description of the parameter U. VTNeeded - 0, 1 or 2. See the description of the parameter VT. AdditionalMemory - If the parameter: * equals 0, the algorithm doesn’t use additional memory (lower requirements, lower performance). * equals 1, the algorithm uses additional memory of size min(M,N)*min(M,N) of real numbers. It often speeds up the algorithm. * equals 2, the algorithm uses additional memory of size M*min(M,N) of real numbers. It allows to get a maximum performance. The recommended value of the parameter is 2. Output parameters: W - contains singular values in descending order. U - if UNeeded=0, U isn't changed, the left singular vectors are not calculated. if Uneeded=1, U contains left singular vectors (first min(M,N) columns of matrix U). Array whose indexes range within [0..M-1, 0..Min(M,N)-1]. if UNeeded=2, U contains matrix U wholly. Array whose indexes range within [0..M-1, 0..M-1]. VT - if VTNeeded=0, VT isn’t changed, the right singular vectors are not calculated. if VTNeeded=1, VT contains right singular vectors (first min(M,N) rows of matrix V^T). Array whose indexes range within [0..min(M,N)-1, 0..N-1]. if VTNeeded=2, VT contains matrix V^T wholly. Array whose indexes range within [0..N-1, 0..N-1]. *************************************************************************/ #endregion //Добавление вершин из матриц for (int i = 0; i < U.GetLength(0); i++) { G.V.Add(new Vertex(words[i], U[i, 0], U[i, 1], U[i, 2])); } for (int i = 0; i < VT.GetLength(1); i++) { G.V.Add(new Vertex(texts[i], VT[0, i], VT[1, i], VT[2, i])); } //добавление рёбер for (int i = 0; i < G.V.Count; i++) { for (int j = i + 1; j < G.V.Count; j++) { G.E.Add(new Edge(G.V[i], G.V[j])); } } for (int i = 0; i < texts.Length; i++) { for (int j = 0; j < G.V.Count; j++) { if (texts[i].GetTag == G.V[j].Data.GetTag) { Texts.Data.Add(G.V[j]); } } } }
//Добавляет вершину к ближайшему кластеру public void AddToClosestCluster(Vertex v) { Graph temp = new Graph(G.V); for (int i = 0; i < temp.V.Count; i++) { for (int j = i + 1; j < temp.V.Count; j++) { temp.E.Add(new Edge(temp.V[i], temp.V[j])); } } Vertex neighbour = G.V[0]; double shortestedgeweight = double.MaxValue; for(int i = 0; i < temp.E.Count; i++) { if (temp.E[i].V1 == v) { if (temp.E[i].Weight < shortestedgeweight) { shortestedgeweight = temp.E[i].Weight; neighbour = temp.E[i].V2; } } else { if (temp.E[i].V2 == v) { if (temp.E[i].Weight < shortestedgeweight) { shortestedgeweight = temp.E[i].Weight; neighbour = temp.E[i].V1; } } } } for (int i = 0; i < C.Count; i++) { for (int j = 0; j < C[i].Data.Count; j++) { if (C[i].Data[j] == neighbour) { C[i].Data.Add(v); } } } }