/// <summary> /// Метод осуществляет скрещивание заданных геномов /// </summary> /// <param name="FirstParent">Геном первого родителя</param> /// <param name="SecondParent">Геном второго родителя</param> /// <returns>Возвращает геном, полученный в результате скрещивания</returns> public static SalesmanGenom Crossingover(SalesmanGenom FirstParent, SalesmanGenom SecondParent) { if (FirstParent.genesCount != SecondParent.genesCount) { return(null); } int GenesCount = FirstParent.GenesCount; SalesmanGenom NewGenom = new SalesmanGenom(GenesCount); //Копируем половину (или меньше округленную в меньшую часть половину, если GenesCount - нечетное) генома первого родителя Array.ConstrainedCopy(FirstParent.townsIndicesSequence, 0, NewGenom.townsIndicesSequence, 0, GenesCount / 2); //..и затем вторую половину генома второго родителя Array.ConstrainedCopy(SecondParent.townsIndicesSequence, GenesCount / 2, NewGenom.townsIndicesSequence, GenesCount / 2, GenesCount / 2 + GenesCount % 2); return(NewGenom); }
/// <summary> /// Метод нахождения решения задачи коммивояжера для заданной матрицы смежности простым перебором /// </summary> /// <param name="ResultSequence"></param> /// <returns>Возвращает значение, позволющее судить о возникновении определенных исключительных ситуаций</returns> public static SalesmanGenom SolveViaExhaustiveAlgorithm() { //Засекаем начальное время DateTime StartTime = DateTime.Now; SalesmanGenom ResultSequence = null; int MatrixSize = adjacencyMatrix.GetLength(0); //Генерируем антилексикографически упорядоченную перестановку из индексов городов, кроме того, с которого начинаем идти byte[] TempSequence = new byte[MatrixSize - 1]; int InsertPosition = 0; for (byte i = 0; i < MatrixSize; ++i) { if (i != startTown) { TempSequence[InsertPosition] = i; ++InsertPosition; } } //Переменная, хранящая минимальное пройденное расстояние int MinDistance = int.MaxValue; int t = 0; do { int CurrentDistance = adjacencyMatrix[startTown, TempSequence[0]]; //Считаем расстояния между городами for (int i = 0; i < MatrixSize - 2; ++i) { CurrentDistance += adjacencyMatrix[TempSequence[i], TempSequence[i + 1]]; } //Учитывая, что коммивояжер должен вернуться в первый город, прибавляем расстояние от последнего города до первого CurrentDistance += adjacencyMatrix[startTown, TempSequence[TempSequence.Count() - 1]]; //Если путь валидный и его длина меньше минимальной if (CurrentDistance < MinDistance) { MinDistance = CurrentDistance; ResultSequence = new SalesmanGenom(TempSequence); } ++t; } //Генерируем следующую перестановку while (NextPermutation(ref TempSequence)); //Вычисляем разницу между временем начала работы алгоритма и его концом exhaustiveExecutionTime = new TimeSpan((DateTime.Now - StartTime).Milliseconds); return(ResultSequence); }
private void buttonStartGenetic_Click(object sender, EventArgs e) { byte StartTown = (byte)(numericUpDownStartTown.Value); SalesmanTaskSolver.StartTown = (int)numericUpDownStartTown.Value; SalesmanGenom Genom = SalesmanTaskSolver.SolveViaGeneticAlgorithm(); StringBuilder Builder = new StringBuilder(StartTown.ToString(), 11); for (int i = 0; i < Genom.GenesCount; ++i) { Builder.Append('-'); Builder.Append(Genom[i].ToString()); } Builder.Append("-" + StartTown.ToString()); labelGeneticResult.Text = Builder.ToString(); int Length = 0; for (int i = 0; i < Genom.GenesCount - 1; ++i) { Length += AdjacencyMatrix[i, i + 1]; } labelGeneticPathLength.Text = Length.ToString(); labelGeneticTotalTime.Text = SalesmanTaskSolver.GeneticExecutionTime.ToString(); }