Quantcast
Channel: Forum Pasja Informatyki - Najnowsze pytania bez odpowiedzi
Viewing all articles
Browse latest Browse all 21942

Algorytm genetyczny słabo działa

$
0
0

Hej!

Mam taki projekt, o którym słyszałem na sucho na uczelni na tzw. wstępie do informatyki i trochę mnie to zaciekawiło, ale niestety po napisaniu go mam dosyć marne rezultaty, także jak ktoś ma ochotę, to proszę o wsparcie ;)

Zadanie:

Znajdź trzy sinusy, które po zsumowaniu będą "jak najbliżej" listy punktów(x,y) podanych jako argument do programu.

 

Mój program:

Każdy sinus zapisałem w takiej postaci a*sin(b*x+c)+d, gdzie a,b,c,d to zmienne typu double, które będę próbował dobrać.

Jest jeszcze klasa Creature, która po prostu zawiera trzy sinusy i zmienną double rating która jest sumą odległości y punktów od funkcji w punkcie x. - Zmienna potrzebna do sortowania.

 

Pętla główna programu:

//sw - instancja stopwatch, do mierzenia czasu, aby nie spamować konsoli
//population - tablica Creature
//vec - tablica wektorów 2d określająca punkty do których chcę się zbliżyć

do
            {
                rateCreatures(population, vec);//wyznacza ratio dla każdego
                bestRatio = sortCreatures(population);//sortuje i zwraca wartość pierwszego po posortowaniu

                timeSinceLastLog = sw.Elapsed.Seconds;
                if (timeSinceLastLog > 1f)
                {
                    Console.WriteLine("Iteration: " + iter);
                    Console.WriteLine("current best creature ratio: " + bestRatio);
                    Console.WriteLine("current average creature ratio: " + getAvgRate(population)+"\n");
                    timeSinceLastLog = 0;
                    sw.Restart();
                }

                replaceHalfCreatures(population, random, range);//zostawia 0-50%, dla 50%-95% wybiera dwa losowe Creature z najlepszej połowy i kopiuje po koleji argumenty(rzuca monetą żeby sprawdzić z którego rodzica wziąć dany argument), dla 95%-100% nadpisuje nową, zupełnie losową instancją Creature
                iter++;
            } while (true);

Co do losowania argumentów przy tworzeniu nowych, losowych instancji Creature i zawierających Sinusów, to mam zmienną double range, którą ręcznie ustawiam, np na 10 - wtedy wszystkie typy wartościowe są losowane od -10 do 10. Zmienianie nie pomaga za bardzo - próbowałem

 

Na koniec załączam całość kodu:(projekt na 2h, więc nie jest piknie, ale komentarze co do jakości kodu, albo dobrych praktyk programowania też mile widziane! ;))

Klasa Sinus:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GeneticAlgorithm
{
    class Sinus
    {
        public double a, b, c;

        public Sinus(Random rand, double range)
        {
            //default: make a random Sinus object

            a = (rand.NextDouble() - 0.5f) * range*2f;
            b = (rand.NextDouble() - 0.5f) * range*2f;
            c = (rand.NextDouble() - 0.5f) * range*2f;
        }

        public Sinus(double _a, double _b, double _c)
        {
            //used for parenting in creature func.
            a = _a;
            b = _b;
            c = _c;
        }
    }
}

Klasa Creature:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace GeneticAlgorithm
{
    class Creature
    {
        public Sinus s1, s2, s3;
        public double d;
        public double rating;


        public Creature(Random rand, double range)
        {
            //default: for first generation only
            s1 = new Sinus(rand, range);
            s2 = new Sinus(rand, range);
            s3 = new Sinus(rand, range);
            d = (rand.NextDouble() - 0.5f) * 200f;
        }

        public void replace(Creature parent1, Creature parent2, Random rand, double range)
        {

            //data to fill and use to make new dude
            Sinus sin1 = new Sinus(rand, range);
            Sinus sin2 = new Sinus(rand, range);
            Sinus sin3 = new Sinus(rand, range);
            double d1=0;

            for (int i=0;i<10;i++)
            {
                int coinFlip = rand.Next(2);
                bool useFirst = true;
                if (coinFlip == 1)
                    useFirst = false;

                switch(i)
                {
                    case 0:
                        sin1.a = (useFirst) ? parent1.s1.a : parent2.s1.a;
                        break;
                    case 1:
                        sin1.b = (useFirst) ? parent1.s1.b : parent2.s1.b;
                        break;
                    case 2:
                        sin1.c = (useFirst) ? parent1.s1.c : parent2.s1.c;
                        break;

                    case 3:
                        sin2.a = (useFirst) ? parent1.s2.a : parent2.s2.a;
                        break;
                    case 4:
                        sin2.b = (useFirst) ? parent1.s2.b : parent2.s2.b;
                        break;
                    case 5:
                        sin2.c = (useFirst) ? parent1.s2.c : parent2.s2.c;
                        break;

                    case 6:
                        sin3.a = (useFirst) ? parent1.s3.a : parent2.s3.a;
                        break;
                    case 7:
                        sin3.b = (useFirst) ? parent1.s3.b : parent2.s3.b;
                        break;
                    case 8:
                        sin3.c = (useFirst) ? parent1.s3.c : parent2.s3.c;
                        break;

                    case 9:
                        d1 = (useFirst) ? parent1.d : parent2.d;
                        break;
                }
                s1 = sin1;
                s2 = sin2;
                s3 = sin3;
                d = d1;
            }
        }

        public void rate(Vector2[] points)
        {
            double toReturn = 0;
            for(int i=0; i < points.Length; i++)
            {
                double x = points[i].x;
                double y = points[i].y;
                double fY = this.valueIn(x);

                toReturn += Math.Sqrt((y - fY) * (y - fY));//TODO: consider getting rid of sqrt - may be more efficient
            }
            rating = toReturn;
        }

        public double valueIn(double x)
        {
            return Math.Sin(x * s1.a + s1.b) * s1.c + Math.Sin(x * s2.a + s2.b) * s2.c + Math.Sin(x * s3.a + s3.b) * s3.c + d;
        }
    }
}

Klasa Program:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;

namespace GeneticAlgorithm
{
    public struct Vector2
    {
        public double x, y;
    }


    class Program
    {
        static void Main(string[] args)
        {
            double range = 1f;
            Vector2[] vec = new Vector2[5];
            vec[0].x = 0f;
            vec[0].y = 5f;
            vec[1].x = 1f;
            vec[1].y = 3f;
            vec[2].x = 2f;
            vec[2].y = -5f;
            vec[3].x = 3f;
            vec[3].y = 3f;
            vec[4].x = 4f;
            vec[4].y = 0f;


            Random random = new Random();
            const int populationSize = 200;
            Creature[] population;
            List<Creature> creatures = new List<Creature>();

            for (int i = 0; i < populationSize; i++)
                creatures.Add(new Creature(random, range));
            population = creatures.ToArray();

            int iter = 0;
            double bestRatio = 0;
            float timeSinceLastLog = 1f;

            Stopwatch sw = Stopwatch.StartNew();

            rateCreatures(population, vec);
            Console.WriteLine("Iteration: " + 0);
            Console.WriteLine("current best creature ratio: " + sortCreatures(population));
            Console.WriteLine("current average creature ratio: " + getAvgRate(population) + "\n");

            do
            {
                rateCreatures(population, vec);
                bestRatio = sortCreatures(population);

                timeSinceLastLog = sw.Elapsed.Seconds;
                if (timeSinceLastLog > 1f)
                {
                    Console.WriteLine("Iteration: " + iter);
                    Console.WriteLine("current best creature ratio: " + bestRatio);
                    Console.WriteLine("current average creature ratio: " + getAvgRate(population)+"\n");
                    timeSinceLastLog = 0;
                    sw.Restart();
                }

                replaceHalfCreatures(population, random, range);
                iter++;
            } while (population[0].rating > 10f);

        }

        static void rateCreatures(Creature[] population, Vector2[] points)
        {
            foreach (Creature c in population)
                c.rate(points);
        }

        static double sortCreatures(Creature[] population)
        {
            population = population.OrderBy(n => n.rating).ToArray();
            /*Console.WriteLine("first: " + population[0].rating);
            Console.WriteLine("second: " + population[1].rating);
            Console.WriteLine("last: " + population[199].rating);*/

            return population[0].rating;
        }

        static void replaceHalfCreatures(Creature[] population, Random rand, double range)
        {
            int creaturesToKill = population.Length / 2;

            for(int i = creaturesToKill - 1; i<population.Length; i++)
            {
                if (i < population.Length - 10)
                {
                    //find two random creatures of the better part(TODO: the higher they are, the more likely should they be to be picked for gene selection)
                    int parent1Index = rand.Next(creaturesToKill);
                    int parent2Index = rand.Next(creaturesToKill);

                    population[i].replace(population[parent1Index], population[parent2Index], rand, range);
                }
                else
                {
                    population[i] = new Creature(rand, range);
                }
            }
        }

        static double getAvgRate(Creature[] population)
        {
            double toReturn = 0;
            foreach (Creature c in population)
                toReturn += c.rating;
            return toReturn / population.Length;
        }
    }
}

 

Na koniec to co widać na konsoli:

Iteration: 0
current best creature ratio: 19,8839451514098
current average creature ratio: 378,409788452106

Iteration: 4330
current best creature ratio: 19,8839451514098
current average creature ratio: 342,072062725768

Iteration: 8751
current best creature ratio: 19,7690783591971
current average creature ratio: 346,062072233154

Iteration: 13241
current best creature ratio: 19,6651993027145
current average creature ratio: 353,915512082182

Iteration: 17643
current best creature ratio: 19,8839451514098
current average creature ratio: 326,881308248833

Iteration: 22078
current best creature ratio: 18,7688923014568
current average creature ratio: 346,773040628046

Iteration: 26373
current best creature ratio: 19,3618102124538
current average creature ratio: 342,846981933711


Viewing all articles
Browse latest Browse all 21942

Trending Articles


[Filmy XviD / DivX] Czerwony pająk (2015) [WEBRip] [XviD-B89] [PL] Dodane...


Musierowicz Małgorzata - Noelka [audiobook PL]


Farming Simulator 17 Spolszczenie – Spolszczenie FS 17 PL


Praktyczny Elektronik – Rocznik 1993


1


Sok malinowy


Antena Rybakowa


Stuki na zimnym silniku ( film )


Auta / Cars (2006) PLDUB.BRRip.480p.XviD.AC3-LTN / DUBBING PL


Abradab - Czerwony Album (2004)


AutoMapa 6.27.0 ( 2301 ) Polska / Europe Finał ( PC_WinCE ) Cracked


H. H. Schild - MRI Zrozumieć Rezonans Magnetyczny [PDF] [DJVU] [PL]


Alawar Keygen POLECAM


Kombajn ziemniaczany GRIMME HLS 750


POTANIACZ


Kasowanie inspekcji Hyundai ix35


Wojciech Sawicki SP7GBF - SK


Sprawdź z którą postacią z anime dzielisz urodziny


Peugeot 508 problem z elektroniką


Windows XP Black Edition 8.2 PL