/// <summary> /// Выполняет одну итерацю кластеризации и рисует кластеры /// </summary> public static void DrawNextIteration(int i, int n, List <List <string> > clusts, List <string> vert, ref List <int> prevAmount, ref List <double> prevAverage, List <Tuple <string, string, string, int> > arr, double average, PictureBox pb, Pen pen) { int indexFirst = i % n; //индекс кластера, в котором вершина находится в начале string v = vert[i]; //пересоздаем новые средние кластеров List <double> newAverage = new List <double>(); List <int> newAmount = new List <int>(); for (int k = 0; k < n; k++) { if (k == indexFirst) { clusts[k].Remove(v); //удаляем вершину из того кластера, где она была } clusts[k].Add(v); //добавляем в конец //теперь вершина, от которой нужно посчитать //количество новых ребер с остальными и их суммарный вес, //находится в конце //считаем новый средний вес ребер int newAmountEdg; newAverage.Add(PropertiesHelper.AverWeightLastVertex(prevAmount[k], out newAmountEdg, prevAverage[k], clusts[k], arr)); //добавляем новое количество newAmount.Add(newAmountEdg); //удаляем последнюю clusts[k].RemoveAt(clusts[k].Count - 1); } newAverage = newAverage.Select(x => x - average).ToList(); int indexSecond = newAverage.IndexOf(newAverage.Min()); clusts[indexSecond].Add(v); //добавляем в конец нужного кластера //меняем старый список на новый prevAverage = new List <double>(); foreach (double aver in newAverage) { prevAverage.Add(aver); } prevAmount = new List <int>(); foreach (int amount in newAmount) { prevAmount.Add(amount); } Image img = new Bitmap(pb.Width, pb.Height); pb.Image = img; DrawGroups(clusts, pb, pen); }
/// <summary> /// Рисует граф по вершинам /// </summary> public static void DrawGraphRandom (List <Tuple <string, string, string, int> > arr, PictureBox pb, Pen pen) { Graphics gr = Graphics.FromImage(pb.Image); gr.Clear(Color.White); List <string> vertexes = PropertiesHelper.Vertexes(arr); //список вершин List <Tuple <string, int> > vals = PropertiesHelper.Valences(arr); List <Tuple <string, Point, Color> > points = new List <Tuple <string, Point, Color> >(); int maxVal = PropertiesHelper.MaxValence(arr); double norm; norm = 255.0 / maxVal; //может быть и меньше единицы //распределяем точки for (int i = 0; i < vertexes.Count; i++) { points.Add(new Tuple <string, Point, Color> (vertexes[i], new Point(rnd.Next(pb.Width), rnd.Next(pb.Height)), Color.FromArgb((255 - (int)(vals[i].Item2 * norm)), (255 - (int)(vals[i].Item2 * norm)), (255 - (int)(vals[i].Item2 * norm))) ) );; } //рисуем все ребра for (int i = 0; i < arr.Count; i++) { //находим первую точку Tuple <string, Point, Color> t1 = points.Find(x => x.Item1 == arr[i].Item1); //находим вторую точку Tuple <string, Point, Color> t2 = points.Find(x => x.Item1 == arr[i].Item2); Point p1 = t1.Item2; Point p2 = t2.Item2; gr.DrawLine(pen, p1, p2); Color c1 = t1.Item3; Color c2 = t2.Item3; DrawVertex(p1, gr, c1, 10); DrawVertex(p2, gr, c2, 10); } }
/// <summary> /// Получаем список всех вершин /// </summary> public static List <string> Vertexes(List <Tuple <string, string, string, int> > arr) { List <string> vert1 = PropertiesHelper.Vertexes1(arr); List <string> vert2 = PropertiesHelper.Vertexes2(arr); foreach (string s in vert1) { if (vert2.IndexOf(s) == -1) //если vert2 не содержит очередную строку { vert2.Add(s); //если уникальный, то добавляем } } return(vert2); }
ClusteringAlgNew(List <Tuple <string, string, string, int> > arr, int n) { double average = PropertiesHelper.AverageWeight(arr); List <string> vert = PropertiesHelper.Vertexes(arr); //находим вершины List <List <string> > clusts = new List <List <string> >(); //лист кластеров //создаем n начальных кластеров for (int i = 0; i < n; i++) { clusts.Add(new List <string>()); } for (int i = 0; i < vert.Count; i++) { clusts[i % n].Add(vert[i]); } List <double> prevAverage = new List <double>(); List <int> prevAmount = new List <int>(); for (int i = 0; i < n; i++) { int prev; //вычисляем первоначальный средний вес ребер в кластерах prevAverage.Add(PropertiesHelper.AverageWeightVertexes(out prev, clusts[i], arr)); prevAmount.Add(prev); } //по всем вершинам проходимся for (int i = 0; i < vert.Count; i++) { int indexFirst = i % n; //индекс кластера, в котором вершина находится в начале string v = vert[i]; //пересоздаем новые средние кластеров List <double> newAverage = new List <double>(); List <int> newAmount = new List <int>(); for (int k = 0; k < n; k++) { if (k == indexFirst) { clusts[k].Remove(v); //удаляем вершину из того кластера, где она была //характеристики не поменялись newAmount.Add(prevAmount[k]); newAverage.Add(prevAverage[k]); } else { clusts[k].Add(v); //добавляем в конец //теперь вершина, от которой нужно посчитать //количество новых ребер с остальными и их суммарный вес, //находится в конце //считаем новый средний вес ребер int newAmountEdg; newAverage.Add(PropertiesHelper.AverWeightLastVertex(prevAmount[k], out newAmountEdg, prevAverage[k], clusts[k], arr)); //добавляем новое количество newAmount.Add(newAmountEdg); //удаляем последнюю clusts[k].RemoveAt(clusts[k].Count - 1); } } newAverage = newAverage.Select(x => x - average).ToList(); int indexSecond = newAverage.IndexOf(newAverage.Min()); clusts[indexSecond].Add(v); //добавляем в конец нужного кластера //меняем старый список на новый if (indexFirst != indexSecond) { //новый вес того кластера, в который добавили prevAverage[indexSecond] = newAverage[indexSecond]; //новый вес того кластера, из которого убрали int prevAmountFirst; prevAverage[indexFirst] = PropertiesHelper.AverageWeightVertexes (out prevAmountFirst, clusts[indexFirst], arr); prevAmount[indexSecond] = newAmount[indexSecond]; prevAmount[indexFirst] = prevAmountFirst; } //если добавили в ту же вершину, из которой убрали, то ничего не поменялось } return(clusts); }