/// <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);
        }
예제 #2
0
        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);
        }