https://pastein.ru/t/5D

  скопируйте уникальную ссылку для отправки


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Laba2Ml
{
    public partial class Form1 : Form
    {
        const int maxiter = 11;
        static string path = $@"D:/ML/Laba2/data1.txt";        
        const int makol = 10000;
        static int realkol;
        const int amofAt = 2;      
        static double[,] dataset = new double [makol, amofAt];
        static int[] classi_0 = new int[makol];
        static int[] classi_1 = new int[makol];
        static int kk = 5;    
        static int[] used;
        static double[,] centra;
        static int iterforkmean = 0;
        static bool f = false;//разрешение на выполнение FindNearest()
        static bool pc = false;//разрешение на выполнение пересчет
        static bool vsekonech = false;

        const int kolloktya = 11;
        static double[] rezloktya = new double[kolloktya+1];



        static void perechetcentrov()
        {
            if (!pc)
                return;
            double[] dyncentra = new double[kk];
           
            for (int k = 0; k < kk; k++)
            {
                double koorx;
                double koory;
                double sumx = 0;
                double sumy = 0;
                int koltoch = 0;
                for (int i = 0; i < realkol; i++)
                {
                    if (classi_0[i] == k)
                    {
                        sumx += dataset[i, 0];
                        sumy += dataset[i, 1];
                        koltoch++;
                    }
                }
                koorx = sumx / koltoch;
                koory = sumy / koltoch;
                centra[k, 0] = koorx;
                centra[k, 1] = koory;
            }

            pc = false;
            f = true;




        }
















        static void FindNearest()
        {
            if (vsekonech)
            {
                return;
            }

            for (int i = 0; i < realkol; i++)//перебор всех точек
            {
                double[] vremrast = new double[kk];//расстояния до всех центров, потом выбирается наименьшее и добавляется в rast[i]
                for (int j = 0; j < kk; j++)
                {
                    double slag1 = Math.Pow((centra[j, 0] - dataset[i, 0]), 2);
                    double slag2 = Math.Pow((centra[j, 1] - dataset[i, 1]), 2);
                    vremrast[j] = Math.Sqrt(slag1 + slag2);//расстояние до j центра
                }
                double minrast = vremrast[0];
                int nomercentra = 0;
                for (int j = 1; j < kk; j++)
                {
                    if (minrast > vremrast[j])
                    {
                        minrast = vremrast[j];
                        nomercentra = j;
                    }
                }
                classi_1[i] = nomercentra;
            }
            bool aa1 = false;
            for (int i = 0; i < realkol; i++)
            {
                if (classi_1[i] != classi_0[i])
                {
                    aa1 = true;
                }
            }
            if (aa1)
            {
                Array.Copy(classi_1, classi_0, realkol);
            }
            else
            {
                vsekonech = true;
            }
            f = false;
            pc = true;

        }





        static void loktya()
        {
            FindCent(kk);
            f = true;
            pc = false;
            while (!vsekonech)
            {
                FindNearest();
                perechetcentrov();
            }
            double sumkvarvnrast = 0;
            for (int k = 0; k < kk; k++)
            {
                
                double sumxy = 0;            
              
                for (int i = 0; i < realkol; i++)
                {
                    if (classi_0[i] == k)
                    {
                        sumxy += Math.Pow((dataset[i, 0]-centra[k,0]),2)+ Math.Pow((dataset[i, 1] - centra[k, 1]), 2);                      
                        
                    }
                }
                sumkvarvnrast += sumxy;

            }
            rezloktya[kk] = sumkvarvnrast;
            vsekonech = false;
            f = false;
            pc = false;
        }



















        static void FindCent(int kk1 )
        {
            double sumrast = 0;
            int kolvocentrov = 0;//сколько уже выбранно центров
            double[] rast = new double[realkol];//расстояния точки I доближайшего центра = rasr[i]
            used = new int[kk1];//записываются какие точки уже используются как центра
            centra = new double[kk1, amofAt];//матрица цетров
            Random rnd = new Random();
            int ind1 = rnd.Next(0, realkol);//выбор случайной точки, как первый центр          
          
            centra[0, 0] = dataset[ind1, 0];//добавление в матрицу
            centra[0, 1] = dataset[ind1, 1];           
            used[0] = ind1;
            kolvocentrov++;
            for (int k = 1; k < kk1; k++)
            {

                sumrast = 0;
                for (int i = 0; i < realkol; i++)//перебор всех точек
                {

                    double[] vremrast = new double[kolvocentrov];//расстояния до всех центров, потом выбирается наименьшее и добавляется в rast[i]
                    for (int j = 0; j < kolvocentrov; j++)
                    {
                        double slag1 = Math.Pow((centra[j, 0] - dataset[i, 0]), 2);
                        double slag2 = Math.Pow((centra[j, 1] - dataset[i, 1]), 2);
                        vremrast[j] = Math.Sqrt(slag1 + slag2);//расстояние до j центра
                    }
                    rast[i] = FindMin(vremrast);               

                    sumrast = sumrast + rast[i];
                 
                }

                double sumrast1 = 0;
                double p = rnd.NextDouble() * sumrast;
                for (int i = 0; i < realkol; i++)
                {
                    sumrast1 += rast[i];
                    if (sumrast1 > p)
                    {
                        ind1 = i;
                        break;
                    }
                }
              
                centra[k, 0] = dataset[ind1, 0];//добавление в матрицу
                centra[k, 1] = dataset[ind1, 1];
               
                used[k] = ind1;
                kolvocentrov++;
                
            }
            f = true;
           
        }



        static double FindMin(double[] rast)
        {

            double min = rast[0];
            for (int i = 1; i < rast.Length; i++)
            {
                if (min > rast[i])
                {
                    min = rast[i];
                }
            }
            return min;
        }



        public Form1()
        {
            InitializeComponent();
        }

        private void chart1_Click(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            int count = 0;
            string line;
            string[] s;
            System.IO.StreamReader file = new System.IO.StreamReader(path);
            while ((line = file.ReadLine()) != null)
            {
                s = line.Split();
                if (s.Length == 0)
                    continue;

                try
                {
                    dataset[count, 0] = Convert.ToDouble(s[1], CultureInfo.InvariantCulture);
                    dataset[count, 1] = Convert.ToDouble(s[3], CultureInfo.InvariantCulture);
                }
                catch (Exception eeerr)
                {
                    richTextBox1.Text = eeerr.ToString();
                    count--;
                    continue;
                }
               
                count++;
            }
            realkol = count;
            file.Close();        
            for (int i = 0; i < realkol - 1; i++)
            {

                chart1.Series[0].Points.AddXY(dataset[i, 0], dataset[i, 1]);

            }
        }

        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {

        }



        private void button2_Click(object sender, EventArgs e)
        {
            
            for (int k = 0; k < kk; k++)
            {
                chart1.Series[k + 1].Points.Clear();
                chart2.Series[k + 1].Points.Clear();
            }


           FindCent(kk);
            for (int k = 0; k < kk; k++)
            {
                chart1.Series[k + 1].Points.AddXY(centra[k, 0], centra[k, 1]);
                chart2.Series[k + 1].Points.AddXY(centra[k, 0], centra[k, 1]);
                richTextBox1.Text += $@"
            ";
                richTextBox1.Text += $"{k+1} центр -" + used[k].ToString();
                richTextBox1.Text += $@"
            { centra[k, 0].ToString()}    {centra[k, 1].ToString()}    ";
            }

        }





        private void chart2_Click(object sender, EventArgs e)
        {

        }

        private void button3_Click(object sender, EventArgs e)
        {
         
            for (int i = 0; i < realkol; i++)
            {
                chart2.Series[(classi_1[i] + 1)].Points.AddXY(dataset[i,0], dataset[i, 1] );
            }
        }

        private void button3_Click_1(object sender, EventArgs e)
        {
            if (vsekonech)
            {
                richTextBox1.Text = $"Дальше некуда, конец";
                return;
            }
            if (!f)
            {
                richTextBox1.Text = $"ошибка нахождения кластера";
                return;
            }
            FindNearest();
            for (int k = 0; k < kk+1; k++)
            {
                chart1.Series[k].Points.Clear();                
            }
            for (int i = 0; i < realkol; i++)
            {
                chart1.Series[classi_0[i] + 1].Points.AddXY(dataset[i, 0], dataset[i, 1]);
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            if (vsekonech)
            {
                richTextBox1.Text = $"Дальше некуда, конец";
                return;
            }
            if (!pc)
            {
                richTextBox1.Text = $"ошибка пересчета центров";
                return;
            }
           
            perechetcentrov();
            for (int k = 0; k < 11; k++)
            {
                chart2.Series[k].Points.Clear();
            }
            for (int k = 0; k < kk; k++)
            {
                
                chart2.Series[k + 1].Points.AddXY(centra[k, 0], centra[k, 1]);
            }

        }

        private void button5_Click(object sender, EventArgs e)
        {
            for (int k = 1; k <= kolloktya; k++)
            {
                kk = k;
                loktya();
                chart3.Series["loktya"].Points.AddXY(kk, rezloktya[kk]);
                chart3.Series["Tochki"].Points.AddXY(kk, rezloktya[kk]);
            }
            double opredvel = rezloktya[1] / 16;
            for (int k = 2; k <= kolloktya; k++)
            {
                double znachforprov = Math.Abs(rezloktya[k] - rezloktya[k - 1]);
                if (znachforprov < opredvel)
                {
                    kk = k;
                    richTextBox1.Text = $"Оптимальное кол-во кластеров = " + k.ToString();
                    break;
                }
            }

        }

        private void chart3_Click(object sender, EventArgs e)
        {

        }
    }
}