/// <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);
        }
Example #4
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);
        }