예제 #1
0
        public static IList <int> GeneticAlgorithm(
            MatrixGraph graph,
            int populationSize,
            long timeToPerform,
            Func <IList <int>, IList <int>, IList <int> > crossover, // rodzic1, rodzic2, zwraca dziecko
            double crossoverCoefficient,
            Func <IList <int>, IList <int> > mutation,               //dziecko, zwraca zmutowane dziecko
            double mutationCoefficient
            )
        {
            numberOfCities                  = graph.Size;
            Algorithms.populationSize       = populationSize;
            Algorithms.crossover            = crossover;
            Algorithms.crossoverCoefficient = crossoverCoefficient;
            Algorithms.mutation             = mutation;
            Algorithms.mutationCoefficient  = mutationCoefficient;
            int bestSolutionValue = int.MaxValue;
            var stopwatch         = new Stopwatch();

            stopwatch.Start();

            #region stworzenie populacji startowej

            population = new List <IList <int> >(populationSize);
            populationSolutionValues = new int[populationSize];
            for (int i = 0; i < populationSize; i++)
            {
                population.Add(GenerateRandomPermutation());
                populationSolutionValues[i] = graph.CalculateRoute(population[i]);
            }

            #endregion

            bestSolution = population[0]; // defaultowe przypisanie

            while (stopwatch.ElapsedMilliseconds <= timeToPerform)
            {
                // selekcja rodziców (indeksy rodziców)
                List <int> parents = Selection();
                // tworzenie dzieci - krzyżowanie, mutacja
                List <IList <int> > newPopulation = CreateNewGeneration(parents);
                population = newPopulation; // nowa populacja
                for (int i = 0; i < populationSize; i++)
                {
                    populationSolutionValues[i] = graph.CalculateRoute(population[i]);
                    if (populationSolutionValues[i] < bestSolutionValue)
                    {
                        bestSolution      = population[i];
                        bestSolutionValue = populationSolutionValues[i];
                    }
                }
            }

            return(bestSolution);
        }
예제 #2
0
 static int BranchAndBoundValue(BnBVertex vertex)
 {
     if (vertex.Vertices.Count == graph.Size)
     {
         return(graph.CalculateRoute(vertex.Vertices));
     }
     else
     {
         return(int.MaxValue);
     }
 }
예제 #3
0
파일: Program.cs 프로젝트: FilipJQ77/PEA
 static void PerformAlgorithm(Func <MatrixGraph, Action <IList <int>, int, int>, long, bool, IList <int> > algorithm)
 {
     stopwatch.Restart();
     solution = algorithm(graph, neighbourhoodType, timePerform, diversification);
     stopwatch.Stop();
     Console.WriteLine($"Czas: {stopwatch.ElapsedMilliseconds / 1000.0}s");
     Console.Write("Trasa: ");
     WriteList(solution);
     Console.Write("Koszt: ");
     Console.WriteLine(graph.CalculateRoute(solution));
 }
예제 #4
0
 static void PerformAlgorithm(Func <MatrixGraph, IList <int> > algorithm)
 {
     stopwatch.Restart();
     bestPermutation = algorithm(graph);
     stopwatch.Stop();
     Console.WriteLine(string.Format("Czas: {0}s", stopwatch.ElapsedMilliseconds / 1000.0));
     Console.Write("Trasa: ");
     WriteList(bestPermutation);
     Console.Write("Koszt: ");
     Console.WriteLine(graph.CalculateRoute(bestPermutation));
 }
예제 #5
0
        /// <summary>
        /// Przegląd zupełny za pomocą NextPermutation
        /// </summary>
        public static IList <int> BruteForce(MatrixGraph graph)
        {
            int[] permutation     = new int[graph.Size - 1];
            int[] bestPermutation = new int[graph.Size];
            bestPermutation[0] = 0;
            for (int i = 1; i < graph.Size; i++)
            {
                permutation[i - 1] = i;
            }
            int bestSum = int.MaxValue, newSum;

            do
            {
                newSum = graph.Matrix[0, permutation[0]] + graph.CalculateRoute(permutation);
                if (newSum < bestSum)
                {
                    bestSum = newSum;
                    Array.Copy(permutation, 0, bestPermutation, 1, graph.Size - 1);
                }
            } while (NextPermutation(permutation));
            return(bestPermutation);
        }
예제 #6
0
파일: Program.cs 프로젝트: FilipJQ77/PEA
        static void ConsoleMenu()
        {
            while (true)
            {
                Console.WriteLine(graph == null ? "\nNIE WCZYTANO MIAST." : "\nWCZYTANO MIASTA.");

                Console.Write(
                    timeToPerform != long.MaxValue / 1000
                        ? $"Maksymalny czas: {timeToPerform / 1000}s, "
                        : "Brak limitu czasu, "
                    );

                switch (mutationType)
                {
                case 1:
                    Console.Write("Mutacja: Swap, ");
                    break;

                case 2:
                    Console.Write("Mutacja: Reverse, ");
                    break;
                }

                switch (crossoverType)
                {
                case 1:
                    Console.Write("Krzyżowanie: Partially Matched Crossover\n");
                    break;

                case 2:
                    Console.Write("Krzyżowanie: Order Crossover\n");
                    break;
                }

                Console.Write(
                    $"Wielkość populacji: {populationSize}, Współczynnik mutacji: {mutationCoefficient}, Współczynnik krzyżowania: {crossoverCoefficient}");

                Console.WriteLine();
                Console.WriteLine();

                Console.WriteLine(
                    @"1. Wczytanie danych z pliku
2. Wprowadzenie kryterium stopu
3. Ustawienie wielkości populacji początkowej
4. Ustawienie współczynnika mutacji
5. Ustawienie współczynnika krzyżowania
6. Wybór metody mutacji
7. Wybór metody krzyżowania
8. Uruchomienie algorytmu genetycznego
0. Wyjdź");

                var    strInput = Console.ReadLine();
                int    intInput;
                double doubleInput;
                try
                {
                    intInput = int.Parse(strInput);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    continue;
                }

                switch (intInput)
                {
                case 1:
                    Console.WriteLine("Podaj ścieżkę do pliku: ");
                    strInput = Console.ReadLine();
                    graph    = ReadGraphFromFile(strInput);
                    break;

                case 2:
                    Console.WriteLine("Podaj maksymalny czas w sekundach (0 - brak limitu)");
                    strInput = Console.ReadLine();
                    try
                    {
                        intInput = int.Parse(strInput);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                        break;
                    }

                    timeToPerform = intInput > 0 ? intInput * 1000 : long.MaxValue / 1000;

                    break;

                case 3:
                    Console.WriteLine("Podaj nową wielkość populacji, musi być parzysta");
                    strInput = Console.ReadLine();
                    try
                    {
                        intInput = int.Parse(strInput);
                        if (intInput <= 0)
                        {
                            throw new Exception("Wielkość populacji musi być większa od 0");
                        }
                        if (intInput % 2 == 1)
                        {
                            throw new Exception("Wielkość populacji w założeniu jest parzysta");
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                        break;
                    }

                    populationSize = intInput;
                    break;

                case 4:
                    Console.WriteLine("Podaj nowy współczynnik mutacji");
                    strInput = Console.ReadLine();
                    try
                    {
                        doubleInput = double.Parse(strInput);
                        if (doubleInput < 0.0 || doubleInput > 1.0)
                        {
                            throw new Exception("Współczynnik mutacji musi być w przedziale [0, 1]");
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                        break;
                    }

                    mutationCoefficient = doubleInput;
                    break;

                case 5:
                    Console.WriteLine("Podaj nowy współczynnik krzyżowania");
                    strInput = Console.ReadLine();
                    try
                    {
                        doubleInput = double.Parse(strInput);
                        if (doubleInput < 0.0 || doubleInput > 1.0)
                        {
                            throw new Exception("Współczynnik krzyżowania musi być w przedziale [0, 1]");
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                        break;
                    }

                    crossoverCoefficient = doubleInput;
                    break;

                case 6:
                    Console.WriteLine("Wybór mutacji: 1. Swap, 2. Reverse");
                    strInput = Console.ReadLine();
                    try
                    {
                        intInput = int.Parse(strInput);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                        break;
                    }

                    switch (intInput)
                    {
                    case 1:
                        mutationType = Mutation1;
                        mutation     = Algorithms.MutationSwap;
                        break;

                    case 2:
                        mutationType = Mutation2;
                        mutation     = Algorithms.MutationReverse;
                        break;
                    }

                    break;

                case 7:
                    Console.WriteLine("Wybór krzyżowania: 1. Partially Matched Crossover, 2. Order Crossover");
                    strInput = Console.ReadLine();
                    try
                    {
                        intInput = int.Parse(strInput);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                        break;
                    }

                    switch (intInput)
                    {
                    case 1:
                        crossoverType = Crossover1;
                        crossover     = Algorithms.PartiallyMatchedCrossover;
                        break;

                    case 2:
                        crossoverType = Crossover2;
                        crossover     = Algorithms.OrderCrossover;
                        break;
                    }

                    break;

                case 8:
                    if (graph != null)
                    {
                        // tworzenie wątku odpowiadającego za wyświetlanie pośrednich wyników
                        var timesThread = new Thread(() =>
                        {
                            const int n = 5;     // liczba próbek czasu
                            for (int i = 0; i < n; i++)
                            {
                                Thread.Sleep((int)(timeToPerform / n));
                                Console.WriteLine(
                                    $"{stopwatch.ElapsedMilliseconds / 1000.0}s - {graph.CalculateRoute(Algorithms.bestSolution)}");
                            }
                        });
                        Console.WriteLine("Czas - koszt uzyskanej trasy");
                        timesThread.Start();
                        stopwatch.Restart();
                        solution = Algorithms.GeneticAlgorithm(
                            graph,
                            populationSize,
                            timeToPerform,
                            crossover,
                            crossoverCoefficient,
                            mutation,
                            mutationCoefficient
                            );
                        timesThread.Join();
                        stopwatch.Stop();
                        Console.WriteLine($"Czas: {stopwatch.ElapsedMilliseconds / 1000.0}s");
                        Console.Write("Trasa: ");
                        WriteList(solution);
                        Console.Write("Koszt: ");
                        Console.WriteLine(graph.CalculateRoute(solution));
                    }

                    break;

                case 0:
                    Environment.Exit(0);
                    break;

                default:
                    Console.WriteLine("Niepoprawna opcja.");
                    break;
                }
            }
        }
예제 #7
0
        /// <summary>
        /// https://cs.pwr.edu.pl/zielinski/lectures/om/localsearch.pdf - strona 13
        /// http://www.pi.zarz.agh.edu.pl/intObl/notes/IntObl_w2.pdf - strona 21
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="neighbourhood">typ sąsiedztwa</param>
        /// <param name="time">czas W SEKUNDACH</param>
        /// <param name="notImportant">bool jako parametr tylko po to by parametry zgadzały się z tabu search</param>
        /// <returns></returns>
        public static IList <int> SimulatedAnnealing(MatrixGraph graph, Action <IList <int>, int, int> neighbourhood,
                                                     long time,
                                                     bool notImportant)
        {
            int numberOfCities = graph.Size;
            int bestSolutionValue;
            int currentSolutionValue;

            int[] bestSolution      = new int[numberOfCities];
            int[] currentSolution   = new int[numberOfCities];
            int[] neighbourSolution = new int[numberOfCities];

            #region generowanie pierwszego, losowego rozwiązania

            for (int i = 0; i < numberOfCities; i++)
            {
                currentSolution[i] = i;
            }

            Shuffle(currentSolution);
            bestSolutionValue = currentSolutionValue = graph.CalculateRoute(currentSolution);
            Array.Copy(currentSolution, bestSolution, numberOfCities);

            #endregion

            #region temperatura początkowa, współczynnik skalowania, końcowa temperatura

            double       temperature    = bestSolutionValue * numberOfCities;
            const double alpha          = 0.99;
            const double endTemperature = 0.000000001;

            #endregion

            var stopwatch = new Stopwatch();
            time *= 1000; //zamiana sekund na milisekundy
            stopwatch.Start();
            while (stopwatch.ElapsedMilliseconds <= time && temperature > endTemperature)
            {
                bool foundBetterSolution;
                do
                {
                    foundBetterSolution = false;

                    for (int i = 0; i < numberOfCities * 5; i++)
                    {
                        #region generowanie losowej permutacji z sąsiedztwa obecnego rozwiązania

                        Array.Copy(currentSolution, neighbourSolution, numberOfCities);
                        neighbourhood(neighbourSolution, random.Next(1, numberOfCities),
                                      random.Next(1, numberOfCities));
                        int neighbourSolutionValue = graph.CalculateRoute(neighbourSolution);

                        #endregion

                        int delta = neighbourSolutionValue - currentSolutionValue;

                        #region jeśli nowa permutacja jest najlepsza, ustaw ją jako obecną i najlepszą permutację

                        if (neighbourSolutionValue < bestSolutionValue)
                        {
                            foundBetterSolution = true;
                            Array.Copy(neighbourSolution, currentSolution, numberOfCities);
                            currentSolutionValue = neighbourSolutionValue;

                            Array.Copy(neighbourSolution, bestSolution, numberOfCities);
                            bestSolutionValue = neighbourSolutionValue;
                        }

                        #endregion

                        #region w przeciwnym razie, jeśli nowa permutacja jest lepsza niż obecna, ustaw ją jako obecną

                        else if (delta < 0)
                        {
                            Array.Copy(neighbourSolution, currentSolution, numberOfCities);
                            currentSolutionValue = neighbourSolutionValue;
                        }

                        #endregion

                        #region w przeciwnym razie, jeśli nowa permutacja jest gorsza od obecnej, ustaw ją jako obecną z prawdopodobieństwem exp(-delta/T)

                        else if (random.NextDouble() < Math.Exp(-delta / temperature))
                        {
                            Array.Copy(neighbourSolution, currentSolution, numberOfCities);
                            currentSolutionValue = neighbourSolutionValue;
                        }

                        #endregion
                    }
                } while (foundBetterSolution);

                temperature *= alpha;
            }

            return(bestSolution);
        }
예제 #8
0
        /// <summary>
        /// http://www.zio.iiar.pwr.wroc.pl/pea/w5_ts.pdf - strona 20
        /// http://www.pi.zarz.agh.edu.pl/intObl/notes/IntObl_w2.pdf - strona 38
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="neighbourhood">typ sąsiedztwa</param>
        /// <param name="time">czas W SEKUNDACH</param>
        /// <param name="diversification"></param>
        /// <returns></returns>
        public static IList <int> TabuSearch(MatrixGraph graph, Action <IList <int>, int, int> neighbourhood, long time,
                                             bool diversification)
        {
            int numberOfCities = graph.Size;
            int bestSolutionValue;
            int currentSolutionValue;

            int[] bestSolution      = new int[numberOfCities];
            int[] currentSolution   = new int[numberOfCities];
            int[] neighbourSolution = new int[numberOfCities];

            // int lifetime = numberOfCities;
            int lifetime       = 10;
            int criticalEvents = 0;

            // w C# tablice domyślnie wypełnione są zerami
            int[,] tabuList = new int[numberOfCities, numberOfCities];

            #region generowanie pierwszego, losowego rozwiązania

            for (int i = 0; i < numberOfCities; i++)
            {
                currentSolution[i] = i;
            }

            Shuffle(currentSolution);
            bestSolutionValue = currentSolutionValue = graph.CalculateRoute(currentSolution);
            Array.Copy(currentSolution, bestSolution, numberOfCities);

            #endregion

            var stopwatch = new Stopwatch();
            stopwatch.Start();
            time *= 1000; // zamiana sekund na milisekundy
            while (stopwatch.ElapsedMilliseconds <= time)
            {
                int previousCurrentSolutionValue = currentSolutionValue;

                #region znalezienie najlepszego rozwiązania w sąsiedztwie

                int bestI = 0, bestJ = 0;
                for (int i = 1; i < numberOfCities; i++)
                {
                    for (int j = i + 1; j < numberOfCities; j++)
                    {
                        Array.Copy(currentSolution, neighbourSolution, numberOfCities);

                        neighbourhood(neighbourSolution, i, j);
                        int neighbourSolutionValue = graph.CalculateRoute(neighbourSolution);
                        // jeżeli rozpatrywane rozwiązanie jest lepsze od najlepszego dotychczas znalezionego, to przyjmujemy je jako obecne nawet jeżeli jest zakazane
                        // w przeciwnym wypadku przyjmujemy tylko jeśli jest lepsze od obecnego rozwiązania i nie ma go na liście tabu
                        if (neighbourSolutionValue < bestSolutionValue ||
                            (neighbourSolutionValue < currentSolutionValue && tabuList[i, j] == 0))
                        {
                            currentSolutionValue = neighbourSolutionValue;
                            bestI = i;
                            bestJ = j;
                        }
                    }
                }

                neighbourhood(currentSolution, bestI, bestJ);
                tabuList[bestI, bestJ] = lifetime;

                #endregion

                TabuSearchDecrementTabuList(tabuList);

                if (currentSolutionValue < bestSolutionValue)
                {
                    Array.Copy(currentSolution, bestSolution, numberOfCities);
                    bestSolutionValue = currentSolutionValue;
                    criticalEvents    = 0;
                }
                else if (diversification && currentSolutionValue >= previousCurrentSolutionValue)
                {
                    criticalEvents++;
                    // zbyt dużo krytycznych momentów, dywersyfikacja (jeśli włączona)
                    if (criticalEvents >= 20 /*10*//*lifetime*/)
                    {
                        Shuffle(currentSolution);
                        currentSolutionValue = graph.CalculateRoute(currentSolution);
                        TabuSearchEmptyTabuList(tabuList);
                    }
                }
            }

            return(bestSolution);
        }