Пример #1
0
        static void Main(string[] args)
        {
            int dataLen;

            int[,] data;

            int[,] population;
            int[] fitnessValues;

#if BERLIN_DEBUG
            Debugger.Launch();
#endif

            Console.CancelKeyPress += (sender, e) =>
            {
                _running = false;
            };

            ProgramSettings settings = new ProgramSettings();
            string          error    = null;
            if (!ParseCommandLine(args, settings, ref error))
            {
                Console.WriteLine(error);
                throw new NullReferenceException();
            }

            using (FileStream stream = new FileStream(settings.DataFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                using (StreamReader reader = new StreamReader(stream))
                {
                    string header = reader.ReadLine();
                    dataLen = int.Parse(header);
                    data    = new int[dataLen, dataLen];

                    for (int i = 0;
                         i < dataLen;
                         ++i)
                    {
                        string[] line = reader.ReadLine()
                                        .Trim()
                                        .Split(' ');

                        for (int j = 0;
                             j <= i;
                             ++j)
                        {
                            int val = int.Parse(line[j]);
                            data[i, j] = val;
                            data[j, i] = val;
                        }
                    }
                }

#if BERLIN_DEBUG
            /*
             *  NOTE(SpectatorQL): This doesn't catch situations where some wild
             *  combination of nodes gives us the exact same sum, but at least
             *  it provides _some_ means of asserting that a specimen is valid.
             */
            int validationSum = 0;
            for (int i = 0;
                 i < dataLen;
                 ++i)
            {
                validationSum += i;
            }
#endif

            var bestSpecimen = new BestSpecimen
            {
                Nodes = new int[dataLen],
                Value = int.MaxValue
            };

            int          m = settings.PopulationSize;
            double       mutationChance = settings.MutationChance;
            op_selection Selection      = settings.Selection;
            op_crossover Crossover      = settings.Crossover;

            population    = new int[m, dataLen];
            fitnessValues = new int[m];
            for (int i = 0;
                 i < m;
                 ++i)
            {
                for (int j = 0;
                     j < dataLen;
                     ++j)
                {
                    population[i, j] = j;
                }

                for (int j = 0;
                     j < dataLen;
                     ++j)
                {
                    int swapIdx = _rand.Next(dataLen);
                    int a       = population[i, j];
                    population[i, j]       = population[i, swapIdx];
                    population[i, swapIdx] = a;
                }
            }
            EvaluateFitness(data, population, m, dataLen, fitnessValues);


            int[] selected = new int[m];
            while (Continue())
            {
                Debug_StartTimer();

                int[,] newPopulation = new int[m, dataLen];
                Selection(selected, fitnessValues, m);

                for (int i = 0;
                     i < m;
                     i += 2)
                {
                    int[] parent1 = new int[dataLen];
                    int[] parent2 = new int[dataLen];
                    int   p1      = selected[i];
                    int   p2      = selected[i + 1];

                    for (int j = 0;
                         j < dataLen;
                         ++j)
                    {
                        parent1[j] = population[p1, j];
                        parent2[j] = population[p2, j];
                    }


                    int midPoint = dataLen / 2;
                    int offset   = 0;
                    int leftCut  = _rand.Next(offset, midPoint);
                    int rightCut = _rand.Next(midPoint, dataLen - offset);


                    int[] child1 = new int[dataLen];
                    int[] child2 = new int[dataLen];
                    Crossover(child1, parent1, parent2, leftCut, rightCut, dataLen);
                    Crossover(child2, parent2, parent1, leftCut, rightCut, dataLen);


                    int    range = 100;
                    double d     = _rand.Next(range) / (double)range;
                    if (d <= mutationChance)
                    {
                        InversionMutation(child1, dataLen);
                    }

                    d = _rand.Next(range) / (double)range;
                    if (d <= mutationChance)
                    {
                        InversionMutation(child1, dataLen);
                    }

#if BERLIN_DEBUG
                    Debug.Assert(IsValidSpecimen(child1, validationSum));
                    Debug.Assert(IsValidSpecimen(child2, validationSum));
#endif

                    for (int j = 0;
                         j < dataLen;
                         ++j)
                    {
                        newPopulation[i, j]     = child1[j];
                        newPopulation[i + 1, j] = child2[j];
                    }
                }

                population = newPopulation;
                EvaluateFitness(data, population, m, dataLen, fitnessValues);


                int bestVal    = fitnessValues[0];
                int bestValIdx = 0;
                for (int i = 1;
                     i < m;
                     ++i)
                {
                    int val = fitnessValues[i];
                    if (val < bestVal)
                    {
                        bestVal    = val;
                        bestValIdx = i;
                    }
                }

                if (bestVal < bestSpecimen.Value)
                {
                    for (int i = 0;
                         i < dataLen;
                         ++i)
                    {
                        bestSpecimen.Nodes[i] = population[bestValIdx, i];
                    }
                    bestSpecimen.Value = bestVal;

                    PrintOutput(bestSpecimen, dataLen);
                }


                Debug_StopTimer();
            }

            Console.WriteLine("Press any key to exit.");
        }
Пример #2
0
        static bool ParseCommandLine(string[] args, ProgramSettings settings, ref string error)
        {
            bool result = false;

            if ((args != null) || (args.Length != 0))
            {
                string file = args[0];
                if (File.Exists(file))
                {
                    settings.DataFile = args[0];

                    bool popSizeParseSuccess = int.TryParse(args[1], out settings.PopulationSize);
                    if (popSizeParseSuccess)
                    {
                        /*
                         *  NOTE(SpectatorQL): Enables the use of a dot in run.bat,
                         *  instead of the culture-specific decimal point character.
                         */
                        bool mutationChanceParseSuccess = double.TryParse(args[2],
                                                                          System.Globalization.NumberStyles.Float,
                                                                          System.Globalization.CultureInfo.InvariantCulture,
                                                                          out settings.MutationChance);
                        if (mutationChanceParseSuccess)
                        {
                            for (int i = 3;
                                 i < args.Length;
                                 ++i)
                            {
                                string arg = args[i];
                                switch (arg)
                                {
                                case "-tournament":
                                {
                                    settings.Selection = TournamentSelect;
                                    break;
                                }

                                case "-roulette":
                                {
                                    settings.Selection = RouletteSelect;
                                    break;
                                }

                                case "-PMX":
                                {
                                    settings.Crossover = PMXCrossover;
                                    break;
                                }

                                case "-OX":
                                {
                                    settings.Crossover = OXCrossover;
                                    break;
                                }

                                default:
                                {
                                    Console.WriteLine("Unrecognized parameter: \"{0}\"", arg);
                                    break;
                                }
                                }
                            }

                            if (settings.Selection != null)
                            {
                                if (settings.Crossover != null)
                                {
                                    result = true;
                                }
                                else
                                {
                                    error = "Error. Invalid crossover parameter.";
                                }
                            }
                            else
                            {
                                error = "Error. Invalid selection parameter.";
                            }
                        }
                        else
                        {
                            error = "Error. Incorrect mutation chance (expected double)";
                        }
                    }
                    else
                    {
                        error = "Error. Incorrect population size (expected int).";
                    }
                }
                else
                {
                    error = "Error. File " + file + " not found.";
                }
            }
            else
            {
                error = "Error. The program was launched without any parameters.";
            }

            return(result);
        }