public static List <Board> GetOptimalBoards(Board b, Options o, BoardScorer.Options bso) { object bestLock = new object(); Board best = new Board(b); double bestScore = 0; List <Board> particles = new List <Board>(); for (int i = 0; i < o.NumParticles; i++) { particles.Add(GetRandomBoard(b)); } Parallel.For(0, o.SAIterations, iteration => //for (int iteration = 0; iteration < o.SAIterations; iteration++) { var r = new Random(rng.Next()); var temp = o.StartTemp * (1.0 - (double)iteration / o.SAIterations); for (int n = 0; n < o.NumParticles; n++) { var neighbor = GetBoardAfterRandomSwap(particles[n], r); var oldBoardScore = particles[n].Score(bso); var newBoardScore = neighbor.Score(bso); if (oldBoardScore < newBoardScore) { particles[n] = neighbor; lock (bestLock) { if (newBoardScore > bestScore) { bestScore = newBoardScore; best = neighbor; } } continue; } if (Math.Exp(-(newBoardScore - oldBoardScore) / temp) < r.NextDouble()) { particles[n] = neighbor; continue; } } }); return(new List <Board> { best }); //return particles.Where(p => p.Score(bso) == particles.Max(s => s.Score(bso))).ToList(); }
public static Path GetBestPath(Board b, Options o, BoardScorer.Options bso) { Path bestPath = new Path(); object pathLock = new object(); Parallel.For(0, b.Height, i => { //for (int i = 0; i < b.Height; i++) Parallel.For(0, b.Width, j => { //for (int j = 0; j < b.Width; j++) var curPath = GetBestPathFrom(b, o, i, j, bso); lock (pathLock) { if (curPath.Score > bestPath.Score) { bestPath = curPath; } } }); }); return(bestPath); }
//public static Path GetBestPath(Board b, Options o, BoardScorer.Options bso) //{ // Board targetBoard = new Board(b.Height, b.Width); // Board goalBoard = GetOptimalBoards(b, o, bso).First(); // Path path = new Path(); // for (int j = 0; j < targetBoard.Width; j++) // for (int i = 0; i < targetBoard.Height; i++) // { // targetBoard.Orbs[i, j] = goalBoard.Orbs[i, j]; // path = GetBestPathFrom(b, targetBoard, bso, path); // b = b.GetBoardsAfterPath(path.Start.Item1, path.Start.Item2, path.Actions).Item1; // } // return path; //} //private static Path GetBestPathFrom(Board b, Board target, BoardScorer.Options bso, Path p) //{ // HashSet<Board> explored = new HashSet<Board>(); // explored.Add(b); // Queue<Tuple<Board, Path>> paths = new Queue<Tuple<Board, Path>>(); // paths.Enqueue(new Tuple<Board, Path>(b, p)); // while (paths.Any()) // { // var cur = paths.Dequeue(); // var curPath = cur.Item2; // var curBoard = cur.Item1; // if (curBoard.EqualsBoard(target, ignoreNone: true)) // return curPath; // foreach (var direction in Board.MoveDirections) // { // if (curPath.Length != 0 && // curPath.Actions.Last()[0] == -direction[0] && // curPath.Actions.Last()[1] == -direction[1]) // continue; // var newY = curPath.Current.Item1 + direction[0]; // var newX = curPath.Current.Item2 + direction[1]; // if (newY < 0 || newY >= b.Height || // newX < 0 || newX >= b.Width) // continue; // Board newBoard = new Board(curBoard); // Orb tempOrb = newBoard.Orbs[newY, newX]; // newBoard.Orbs[newY, newX] = newBoard.Orbs[curPath.Current.Item1, curPath.Current.Item2]; // newBoard.Orbs[curPath.Current.Item1, curPath.Current.Item2] = tempOrb; // var newPath = new List<int[]>(curPath.Actions); // newPath.Add(direction); // if (explored.Contains(newBoard)) // continue; // explored.Add(newBoard); // paths.Enqueue(new Tuple<Board, Path>(newBoard, new Path // { // Start = curPath.Start, // Current = new Tuple<int, int>(newY, newX), // Depth = curPath.Depth + 1, // Score = 0, // Actions = newPath // })); // } // } // return null; //} // a-star is silly if all edges are length 1...? public static Path GetBestPath(Board b, Options o, BoardScorer.Options bso) { Board goalBoard = GetOptimalBoards(b, o, bso).First(); Heuristic h = o.HeuristicGen(goalBoard); PriorityQueue <Tuple <Board, Path>, double> queue = new PriorityQueue <Tuple <Board, Path>, double>(); HashSet <Board> visited = new HashSet <Board>(); Dictionary <Board, double> toExplore = new Dictionary <Board, double>(); toExplore.Add(b, 0); queue.Enqueue(new Tuple <Board, Path>(b, new Path { Start = new Tuple <int, int>(2, 2) }), -h(b)); while (!queue.Empty) { var cur = queue.Dequeue(); var curBoard = cur.Item1; var curPath = cur.Item2; var curCost = curPath.Depth; if (curBoard.EqualsBoard(goalBoard)) { return(curPath); } visited.Add(curBoard); foreach (var direction in Board.MoveDirections) { if (curPath.Length != 0 && curPath.Actions.Last()[0] == -direction[0] && curPath.Actions.Last()[1] == -direction[1]) { continue; } var newY = curPath.Current.Item1 + direction[0]; var newX = curPath.Current.Item2 + direction[1]; if (newY < 0 || newY >= b.Height || newX < 0 || newX >= b.Width) { continue; } Board newBoard = new Board(curBoard); Orb tempOrb = newBoard.Orbs[newY, newX]; newBoard.Orbs[newY, newX] = newBoard.Orbs[curPath.Current.Item1, curPath.Current.Item2]; newBoard.Orbs[curPath.Current.Item1, curPath.Current.Item2] = tempOrb; if (visited.Contains(newBoard) || toExplore.ContainsKey(newBoard) && toExplore[newBoard] <= curCost + 1) { continue; } var newPath = new List <int[]>(curPath.Actions); newPath.Add(direction); queue.Enqueue(new Tuple <Board, Path>(newBoard, new Path { Start = curPath.Start, Current = new Tuple <int, int>(newY, newX), Depth = curCost + 1, Score = 0, //newBoard.Score(BoardScorer.Options.Horus) - curPath.Depth / 100, Actions = newPath }), -h(newBoard) - curCost - 1); toExplore[newBoard] = curCost + 1; } } return(new Path()); }
public static Path GetBestPathSA(Board b, Options o, BoardScorer.Options bso) { object bestLock = new object(); Path best = new Path(); double bestScore = 100000; Board goalBoard = GetOptimalBoards(b, o, bso).First(); Heuristic h = o.HeuristicGen(goalBoard); List <Board> particles = new List <Board>(); List <Path> particlePaths = new List <Path>(); for (int i = 0; i < o.NumParticles; i++) { var pos = new Tuple <int, int>(rng.Next(b.Height), rng.Next(b.Width)); particles.Add(new Board(b)); particlePaths.Add(new Path { Start = pos, Current = pos }); } //Parallel.For(0, o.SAIterations, iteration => for (int iteration = 0; iteration < o.TILE_SAIterations; iteration++) { var r = new Random(rng.Next()); var temp = o.TILE_StartTemp * (1.0 - (double)iteration / o.SAIterations); for (int n = 0; n < o.NumParticles; n++) { //if (goalBoard.EqualsBoard(particles[n])) // return particlePaths[n]; var neighbor = GetBoardAfterRandomSwap(particles[n], r, particlePaths[n]); var oldBoardScore = h(particles[n]); var newBoardScore = h(neighbor.Item1); if (newBoardScore < oldBoardScore) { particlePaths[n].Actions.Add(neighbor.Item2); var newY = particlePaths[n].Current.Item1 + neighbor.Item2[0]; var newX = particlePaths[n].Current.Item2 + neighbor.Item2[1]; particlePaths[n].Current = new Tuple <int, int>(newY, newX); particles[n] = neighbor.Item1; lock (bestLock) { if (newBoardScore < bestScore) { bestScore = newBoardScore; best = new Path { Start = particlePaths[n].Start, Actions = new List <int[]>(particlePaths[n].Actions), Current = new Tuple <int, int>(newY, newX) }; } } continue; } if (Math.Exp((newBoardScore - oldBoardScore) / temp) < r.NextDouble()) { particlePaths[n].Actions.Add(neighbor.Item2); var newY = particlePaths[n].Current.Item1 + neighbor.Item2[0]; var newX = particlePaths[n].Current.Item2 + neighbor.Item2[1]; particlePaths[n].Current = new Tuple <int, int>(newY, newX); particles[n] = neighbor.Item1; continue; } } } return(best); }
private static Path GetBestPathFrom(Board b, Options o, int y, int x, BoardScorer.Options bso) { Path bestPath = new Path(); PriorityQueue <Tuple <Board, Path>, double> paths = new PriorityQueue <Tuple <Board, Path>, double>(); paths.Enqueue(new Tuple <Board, Path>(b, new Path { Start = new Tuple <int, int>(y, x), Current = new Tuple <int, int>(y, x), Depth = 1, Score = b.Score(bso) })); int depth = 0; while (depth++ < o.MaxDepth) { // Console.WriteLine("currently at depth {0}...", depth); PriorityQueue <Tuple <Board, Path>, double> newPaths = new PriorityQueue <Tuple <Board, Path>, double>(); while (paths.Count != 0) { var cur = paths.Dequeue(); var curPath = cur.Item2; var curBoard = cur.Item1; if (curPath.Score > bestPath.Score) { bestPath = curPath; } //if (paths.Count() > o.WhenToPrune) //{ // var newPaths = new Stack<Tuple<Board, Path>>(); // foreach (var path in paths.OrderByDescending(p => p.Item2.Score).Take(o.NumToKeep).Reverse()) // newPaths.Push(path); // paths = newPaths; //} foreach (var direction in Board.MoveDirections) { if (curPath.Length != 0 && curPath.Actions.Last()[0] == -direction[0] && curPath.Actions.Last()[1] == -direction[1]) { continue; } var newY = curPath.Current.Item1 + direction[0]; var newX = curPath.Current.Item2 + direction[1]; if (newY < 0 || newY >= b.Height || newX < 0 || newX >= b.Width) { continue; } Board newBoard = new Board(curBoard); Orb tempOrb = newBoard.Orbs[newY, newX]; newBoard.Orbs[newY, newX] = newBoard.Orbs[curPath.Current.Item1, curPath.Current.Item2]; newBoard.Orbs[curPath.Current.Item1, curPath.Current.Item2] = tempOrb; var newPath = new List <int[]>(curPath.Actions); newPath.Add(direction); double score = newBoard.Score(bso) - curPath.Depth / 100; newPaths.Enqueue(new Tuple <Board, Path>(newBoard, new Path { Start = curPath.Start, Current = new Tuple <int, int>(newY, newX), Depth = curPath.Depth + 1, Score = score, Actions = newPath }), score); } } paths = newPaths.TrimToSize(o.BeamWidth); } return(bestPath); }
public static Path GetBestPath(Board b, BoardScorer.Options bso) { return(GetBestPath(b, Options.Default, bso)); }