public Tuple <MoveList, MoveList> DoCrossover(MoveList firstMovelist, MoveList secondMovelist) { var child1 = new MoveList(); var child2 = new MoveList(); if (firstMovelist.Count >= 3) { var firstCrossoverPoint = _randomizer.Next(1, firstMovelist.Count - 1); var secondCrossoverPoint = _randomizer.Next(1, firstMovelist.Count - 1); while (secondCrossoverPoint == firstCrossoverPoint) { secondCrossoverPoint = _randomizer.Next(1, firstMovelist.Count - 1); } var lowestCrossoverPoint = (firstCrossoverPoint < secondCrossoverPoint ? firstCrossoverPoint : secondCrossoverPoint); var highestCrossoverPoint = (firstCrossoverPoint > secondCrossoverPoint ? firstCrossoverPoint : secondCrossoverPoint); var difference = highestCrossoverPoint - lowestCrossoverPoint; child1.AddRange( firstMovelist.Take(lowestCrossoverPoint) .Concat(secondMovelist.Skip(lowestCrossoverPoint).Take(difference)) .Concat(firstMovelist.Skip(highestCrossoverPoint)) ); child2.AddRange( secondMovelist.Take(lowestCrossoverPoint) .Concat(firstMovelist.Skip(lowestCrossoverPoint).Take(difference)) .Concat(secondMovelist.Skip(highestCrossoverPoint)) ); var children = new Tuple <MoveList, MoveList>(child1, child2); return(children); } else { var performOnePointCrossover = _randomizer.NextBoolean(); //Not using the crossover factory to make sure a TwoPointCrossover won't be created. if (performOnePointCrossover) { var opc = new OnePointCrossover(_randomizer); var children = opc.DoCrossover(firstMovelist, secondMovelist); return(children); } else { var oc = new OrderedCrossover(_randomizer); var children = oc.DoCrossover(firstMovelist, secondMovelist); return(children); } } }
public Tuple <MoveList, MoveList> DoCrossover(MoveList firstMovelist, MoveList secondMovelist) { var child1 = new MoveList(); var child2 = new MoveList(); if (firstMovelist.Count > 2) { //If crossover = 0, you simply swap the entire sequence. This doesn't yield a new child //Same if the crossoverPoint = length - 1. var elementsToSkip = _randomizer.Next(1, firstMovelist.Count - 2); child1.AddRange(firstMovelist.Take(elementsToSkip).Concat(secondMovelist.Skip(elementsToSkip))); child2.AddRange(secondMovelist.Take(elementsToSkip).Concat(firstMovelist.Skip(elementsToSkip))); } else if (firstMovelist.Count == 1) { child1.Add(firstMovelist[0]); child2.Add(secondMovelist[0]); } else { var swapFirstMove = _randomizer.NextBoolean(); if (swapFirstMove) { child1.Add(secondMovelist[0]); child1.Add(firstMovelist[1]); child2.Add(firstMovelist[0]); child2.Add(secondMovelist[1]); } else { child1.Add(firstMovelist[0]); child1.Add(secondMovelist[1]); child2.Add(secondMovelist[0]); child2.Add(firstMovelist[1]); } } var children = new Tuple <MoveList, MoveList>(child1, child2); return(children); }
protected void CollectSolution(Node leaf) { foundSolution = true; // Don't bother if we're not collection solutions. if (!collectSolutions) { return; } // Prepare to construct the solution. MoveList solution = new MoveList(); Level tempLevel = new Level(originalLevel); tempLevel.Validate = validate; PathFinder tempFinder = PathFinder.CreateInstance(tempLevel, true); // Iterate over the nodes from the root to the leaf. int previousPushes = 0; #if false List<Node> nodeList = FindParents(root, leaf); #else List<Node> nodeList = new List<Node>(); for (int i = 0; i < current.ParentIndex; i++) { nodeList.Add(current.Parents[i]); } nodeList.Add(leaf); #endif foreach (Node node in nodeList) { // Check whether we need to move the sokoban. if (node.Coordinate != tempLevel.SokobanCoordinate) { // Move the sokoban to the box. solution.AddRange(tempFinder.FindAndGetPath(node.Coordinate)); tempLevel.MoveSokoban(node.Coordinate); } // Check whether we need to push a box. int consecutivePushes = node.Pushes - previousPushes; if (consecutivePushes != 0) { // Push the box one or more times. OperationDirectionPair push = new OperationDirectionPair(Levels.Operation.Push, node.Direction); for (int j = 0; j < consecutivePushes; j++) { solution.Add(push); tempLevel.Move(push); } previousPushes = node.Pushes; } } // Validate the solution. if (!tempLevel.IsComplete) { throw Abort("constructed move list does not solve level"); } if (optimizeMoves && solution.Count != leaf.Moves) { throw Abort("constructed move list does not match leaf tree in moves"); } if (LevelUtils.SolutionPushes(solution) != leaf.Pushes) { throw Abort("constructed move list does not match leaf tree in pushes"); } // Add the solution. solutions.Add(solution); int moves = solution.Count; int pushes = LevelUtils.SolutionPushes(solution); moveLimit = Math.Min(moveLimit, moves); pushLimit = Math.Min(pushLimit, pushes); #if DEBUG if (verbose) { Log.DebugPrint(" found solution: {0}/{1}", moves, pushes); } #endif }