遗传算法 - 屏幕上的聚类点

时间:2015-02-09 19:39:43

标签: c# algorithm

下面是我使用遗传算法编写的聚类代码。点数来自图片框,在调用此类之前随机生成(X,Y)。然而,这个算法的结果比k-means或lbg我要差很多。有人可以查看算法中的任何错误,也许我省略了一些东西。感谢。

我是使用数组做的,另外两个我使用了列表,但我认为这不会对结果产生任何影响。

public class geneticAlgorithm
{
    static int pom = 0;
    static PictureBox pb1;
    public geneticAlgorithm(PictureBox pb)
    {            
        pb1 = pb;
    }

    public static void doGA(PointCollection points, int clusterCounter) 
//points is a list of points, 
//those point have (X,Y) coordinates generated randomly from pictureBox 
//coordinates. clusterCounter is how many clusters I want to divide the points into
    {
//this part converts list of points into array testtab, 
//where each array field hold X,Y of a point
        Point[] test = new Point[points.Count];
        test = points.ToArray();
        double[][] testtab = new double[test.Length][];
        for (int i = 0; i < testtab.GetLength(0); i++)
        {
            testtab[i] = new double[2];
            testtab[i][0] = test[i].X;
            testtab[i][1] = test[i].Y;
        }
//end of converting
        int n = testtab.GetLength(0);
        int k = clusterCounter;
        int chromosomeCount = 500;
        int dimensions = 2;

        double[][] testClusters = new double[k][];
        for (int i = 0; i < k; i++)
        {
            testClusters[i] = new double[dimensions];
        }
        double[][] testChromosomes = new double[chromosomeCount][];
        for (int i = 0; i < chromosomeCount; i++)
        {
            testChromosomes[i] = new double[2 * k];
        }
        int[][] testChromosomesInt = new int[chromosomeCount][];
        for (int i = 0; i < chromosomeCount; i++)
        {
            testChromosomesInt[i] = new int[2 * k];
        }
        double[] partner = new double[chromosomeCount];
        double[][] roulette = new double[chromosomeCount][];
        for (int i = 0; i < chromosomeCount; i++)
        {
            roulette[i] = new double[1];
        }
        double[][] errors = new double[chromosomeCount][];
        for (int i = 0; i < chromosomeCount; i++)
        {
            errors[i] = new double[1];
        }
        double crossingPossibility = 0.01;
        double mutationPossibility = 0.0001;

        int maxIterations = 10000;

//here I create chromosomes and initial clusters
        for (int j = 0; j < chromosomeCount; j++)
        {
            for (int i = 0; i < k; i++)
            {
                Random rnd = new Random();
                int r = rnd.Next(n);
                for (int q = 0; q < dimensions; q++)
                {
                    testClusters[i][q] = testtab[r][q];
                }
            }


            int help = 0;
            for (int i = 0; i < k; i++)
                for (int l = 0; l < dimensions; l++) // here is creation of chromosome
                {
                    testChromosomes[j][help] = testClusters[i][l];
                    help++;
                }

//end
//here I call accomodation function to see which of them are good
            errors[j][0] = accomodationFunction(testClusters, testtab, n, k);
//end
//cleaning of the cluster table
            testClusters = new double[k][];
            for (int i = 0; i < k; i++)
            {
                testClusters[i] = new double[dimensions];
            }
        }

//end
        for (int counter = 0; counter < maxIterations; counter++)
        {
//start of the roulette
            double s = 0.0;
            for (int i = 0; i < chromosomeCount; i++)
                s += errors[i][0];

            for (int i = 0; i < chromosomeCount; i++)
                errors[i][0] = chromosomeCount * errors[i][0] / s;

            int idx = 0;

            for (int i = 0; i < chromosomeCount; i++)
                for (int j = 0; i < errors[i][0] && idx < chromosomeCount; j++)
                {
                    roulette[idx++][0] = i;
                }


            double[][] newTab = new double[chromosomeCount][];
            for (int i = 0; i < chromosomeCount; i++)
            {
                newTab[i] = new double[2 * k];
            }


            Random rnd = new Random();

            for (int i = 0; i < chromosomeCount; i++)
            {
                int q = rnd.Next(chromosomeCount);
                newTab[i] = testChromosomes[(int)roulette[q][0]];
            }

            testChromosomes = newTab;

//end of roulette
//start of crossing chromosomes
            for (int i = 0; i < chromosomeCount; i++)
                partner[i] = (rnd.NextDouble() < crossingPossibility + 1) ? rnd.Next(chromosomeCount) : -1;
            for (int i = 0; i < chromosomeCount; i++)
                if (partner[i] != -1)
                    testChromosomes[i] = crossing(testChromosomes[i], testChromosomes[(int)partner[i]], rnd.Next(2 * k), k);
 //end of crossing
//converting double to int
            for (int i = 0; i < chromosomeCount; i++)
                for (int j = 0; j < 2 * k; j++)
                    testChromosomes[i][j] = (int)Math.Round(testChromosomes[i][j]);
//end of conversion
//start of mutation
            for (int i = 0; i < chromosomeCount; i++)
                if (rnd.NextDouble() < mutationPossibility + 1)
                    testChromosomesInt[i] = mutation(testChromosomesInt[i], rnd.Next(k * 2), rnd.Next(10));
 //end of mutation
        }

 //painting of the found centre on the picture box
        int centrum = max(errors, chromosomeCount);
        Graphics g = pb1.CreateGraphics();
        SolidBrush brush = new SolidBrush(Color.Red);
        for (int i = 0; i < 2 * k - 1; i += 2)
        {
            g.FillRectangle(brush, testChromosomesInt[centrum][i], testChromosomesInt[centrum][i + 1], 20, 20);
        }
        return;

    }
//end of painting
    public static int max(double[][] tab, int chromosomeCount)
    {
        double max = 0;
        int k = 0;
        for (int i = 0; i < chromosomeCount; i++)
        {
            if (max < tab[i][0])
            {
                max = tab[i][0];
                k = i;
            }
        }

        return k;

    }

    public static int[] mutation(int[] tab, int elem, int bit)
    {
        int mask = 1;
        mask <<= bit;
        tab[elem] = tab[elem] ^ mask;
        return tab;
    }

    public static double[] crossing(double[] tab, double[] tab2, int p, int k)
    {
        double[] hold = new double[2 * k];
        for (int i = 0; i < p; i++)
            hold[i] = tab[i];
        for (int i = p; i < 2 * k; i++)
            hold[i] = tab2[i];

        return hold;
    }
//accomodation function, checks to which centre which point belongs based on distance
    private static double accomodationFunction(double[][] klastry, double[][] testtab, int n, int k)
    {
        double Error = 0;
        for (int i = 0; i < n; i++)
        {
            double min = 0;
            int ktory = 0;

            for (int j = 0; j < k; j++)
            {
                double dist = distance(klastry[j], testtab[i]);
                if (j == 0)
                {
                    min = dist;
                }
                if (min > dist)
                {
                    min = dist;
                    ktory = j;
                }
            }
            Error += min;
        }
        pom++;
        return 1 / Error;
    }

    public static double distance(double[] tab, double[] tab2)
    {
        double dist = 0.0;
        for (int i = 0; i < tab.GetLength(0); i++)
            dist += Math.Pow(tab[i] - tab2[i], 2);

        return dist;
    }


}

算法应该这样工作:(对不起,如果不是最好的英语)  1.获取随机点数(让我们说100)  2.检查我们想要分割多少个簇(例如,我将使用k-means做同样的事情  3.获得染色体的起始种群  4.切割轮盘,交叉和突变选择最佳x中心,其中x是我们想要的簇数量  5.画它们。

以下是一些结果,以及为什么我认为这是错误的:(它使用了100分,5个集群)

k均值:

enter image description here

LBG:

enter image description here

遗传(现在没有颜色):

enter image description here

我希望这有点澄清。

0 个答案:

没有答案