// Méthode permettant de copier un tableau pour briser les références public static EvaluableBoard CopyBoard(EvaluableBoard board) { EvaluableBoard result = new EvaluableBoard(board.Score); Cell[,] structure = new Cell[board.Size, board.Size]; foreach (Cell cell in board) { Cell newCell = new Cell(cell.Value); int posI, posJ; board.Board.FindCellByValue(out posI, out posJ, cell.Value); structure[posI, posJ] = newCell; } // Might me proper Cell emptyOne = new Cell("-"); Cell emptyTwo = new Cell("-"); int e1i, e1j, e2i, e2j; board.Board.FindEmptyOne(out e1i, out e1j); board.Board.FindEmptyTwo(out e2i, out e2j); structure[e1i, e1j] = emptyOne; structure[e2i, e2j] = emptyTwo; // Till there is not really needed result.Board = new Board(structure); result.Size = result.Board.Structure.GetLength(0); return(result); }
// Implémentation de l'Heuristique spécifique à cette méthode humaine private int Eval(EvaluableBoard board, int step) { int score = 0; int optI, optJ, currI, currJ; // Prise en compte de la case courante a placer Functions.pos2coord(out optI, out optJ, step, Size); board.Board.FindCellByValue(out currI, out currJ, Convert.ToString(step)); score += Params[0] * (Math.Abs(optI - currI) + Math.Abs(optJ - currJ)); int hole1I, hole1J, hole2I, hole2J; board.Board.FindEmptyOne(out hole1I, out hole1J); board.Board.FindEmptyTwo(out hole2I, out hole2J); // Prise en compte de la distance trou case à placer int distH1T = Math.Abs(hole1I - currI) + Math.Abs(hole1J - currJ); int distH2T = Math.Abs(hole2I - currI) + Math.Abs(hole2J - currJ); score += Params[1] * distH1T; score += Params[1] * distH2T; // Prise en compte de la distance trou destination int distH1 = Math.Abs(optI - hole1I) + Math.Abs(optJ - hole1J); int distH2 = Math.Abs(optI - hole2I) + Math.Abs(optJ - hole2J); score += Params[2] * Math.Min(distH1, distH2); return(score); }
// Création des enfants spécifique à la méthode humaine public static List <EvaluableBoard> CreateChild(EvaluableBoard board, int step) { List <EvaluableBoard> neighbours = new List <EvaluableBoard>(); int size = board.Board.Structure.GetLength(0); List <int> values; // Valeurs possibles dans les tableaux if (size == 3) { values = new List <int>() { 0, 1, 2, 3, 4, 7, 5, 6 } } ; else { values = new List <int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 20, 16, 21, 17, 22, 18, 19 } }; int maxIndex = values.IndexOf(step); // On parcours toutes les cellules du tableau foreach (Cell cell in board) { if (cell.Value != "-") { int index = values.IndexOf(Convert.ToInt32(cell.Value)); // On bloque le mouvement des cases déjà positionnées if (index >= maxIndex) { int i, j; board.Board.FindCellByValue(out i, out j, cell.Value); if (cell.IsMovable()) { foreach (Cell.Moves move in cell.AvailableMoves) { EvaluableBoard neighbour = CopyBoard(board); neighbour.Cost = board.Cost; neighbour.Board.Move(neighbour.Board.Structure[i, j], move); neighbour.Previous = board; neighbours.Add(neighbour); } } } } } return(neighbours); } #endregion }
// Fonction permettant de résoudre Stopwatch UnderStep(int rank, Stopwatch chrono) { _destination = new EvaluableBoard(CreateStep(Size, rank)); // Boucle de résolution while (_openSet.Count > 0) { _currentBoard = _openSet[0]; if (_currentBoard.Equals(_destination)) { // Si l'on est à la dernière étape on stop le chrono if (rank == Size * Size - 3) { chrono.Stop(); return(chrono); } // Sinon on nettoie le solver pour la prochaine étape else { _openSet = new List <EvaluableBoard>(); _closedSet = new List <EvaluableBoard>(); _currentBoard.Cost = 0; _currentBoard.Score = 0; _openSet.Add(_currentBoard); break; } } // Gestion de la descendance List <EvaluableBoard> holder = CreateChild(_currentBoard, rank); foreach (EvaluableBoard testBoard in holder) { if (FindPast(testBoard) || FindBest(testBoard)) { } else { testBoard.Cost += 1; // Evaluation d'une heuristique humaine spécifique int thisHumanHeuri = Eval(testBoard, rank); testBoard.Score = testBoard.Cost + thisHumanHeuri; _openSet.Add(testBoard); } } _closedSet.Add(_currentBoard); _openSet.Remove(_currentBoard); _openSet = _openSet.OrderBy(b => b.Score).ToList(); // Si le solver dépasse la minute on l'interrompt if (chrono.Elapsed.Minutes >= 1) { break; } } return(chrono); }
// Fonciton de recherche des antécédents public bool FindPast(EvaluableBoard board) { bool result = false; foreach (EvaluableBoard oldBoard in _closedSet) { if (oldBoard.Equals(board)) { result = true; } } return(result); }
// Méthode de résolution globlae public Stopwatch Solve(EvaluableBoard board) { // Etape d'initialisation _openSet = new List <EvaluableBoard>(); _closedSet = new List <EvaluableBoard>(); Size = board.Board.Structure.GetLength(0); // On prend le premier état _openSet.Add(board); // On init et on démarre un Chronomètre Stopwatch chrono = new Stopwatch(); chrono.Start(); // On parcours d'abord en ligne case par case for (int rank = 0; rank < (Size * Size) - Size * 2; rank++) { // On résoud chaque étape une par une en placant la case cible chrono = UnderStep(rank, chrono); if (chrono.Elapsed.Minutes >= 1) { return(chrono); } } int start = Size * Size - Size * 2; // On parcours ensuite les deux dernière lignes en colonnes for (int rank = start; rank < start + Size; rank++) { // On fait la ligne du haut chrono = UnderStep(rank, chrono); if (chrono.Elapsed.Minutes >= 1) { return(chrono); } // Puis la ligne du bas int step = rank + Size; if (step < Size * Size - 2) { chrono = UnderStep(step, chrono); if (chrono.Elapsed.Minutes >= 1) { return(chrono); } } } // On arrête le chrono si on a fini chrono.Stop(); return(chrono); }
public bool FindBest(EvaluableBoard board) { bool result = false; foreach (EvaluableBoard currentBoard in _openSet) { if (board.Equals(currentBoard) && currentBoard.Cost <= board.Cost) { result = true; } else if (board.Equals(currentBoard) && currentBoard.Cost > board.Cost) { currentBoard.Cost = board.Cost; } } return(result); }
public ResultForm(Solver solver, EvaluableBoard board) { InitializeComponent(); // Cacher les fonctionnalitée en attendant les résultats leftButton.Hide(); rightButton.Hide(); nbMovesLabel.Hide(); openLabel.Hide(); label2.Hide(); // Attribution des utilitaires Solver = solver; _board = board; _solverThread = new BackgroundWorker(); // Assignation des event du thread d'arrière plan _solverThread.DoWork += new DoWorkEventHandler(SolverThreadDoWork); _solverThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(SolverThreadWorkDone); // Launch du backGroundWorker _solverThread.RunWorkerAsync(); _solverThread.WorkerReportsProgress = true; _solverThread.WorkerSupportsCancellation = true; }
// Fonction qui lance la résolution du Taquin courant public void SolveButton_Click(object sender, EventArgs e) { // On crée un EvaluableBoard a partir de l'état courant du Taquin EvaluableBoard board = new EvaluableBoard(taquin.Board); // On envoie le board et le solver courant a un resultForm que l'on affiche if (_solver.GetType() == typeof(AstarUni)) { _solver = new AstarUni(_selectedHeuristic); } else if (_solver.GetType() == typeof(IDAstar)) { _solver = new IDAstar(_selectedHeuristic); } else { _solver = new Segments(_selectedHeuristic); } _resultForm = new ResultForm(_solver, board); _resultForm.Show(); }
static void Main(string[] args) { // Initialisations Setup(); int nbGen = 10; // Nombre de génération int nbIndiv = 100; // Nombre d'individus de la population int nbCible = 20; // Nombre d'exemple a résoudre Random r = new Random(); List <ParametrizeSolver> _population = new List <ParametrizeSolver>(); List <EvaluableBoard> _targets = new List <EvaluableBoard>(); //Initialisation Création de la population Console.Write("Initializing population : "); for (int _ = 0; _ < nbIndiv; _++) { int max = 10; //ParametrizeSolver current = new ParametrizeSolver(r.Next(0, max), r.Next(0, max), r.Next(0, max), r.Next(0, max), r.Next(0, max)); ParametrizeSolver current = new ParametrizeSolver(7, 4, 8);//,9,4); Mutate(current, r); _population.Add(current); } Console.Write(_population.Count + " solver created."); // Initialisation : Creation des cibles Console.Write(" - Initializing targets : "); for (int _ = 0; _ < nbCible; _++) { Board b = new Board(5); Fill(b); EvaluableBoard target = new EvaluableBoard(b); _targets.Add(target); } Console.Write(_targets.Count + " target created. \n \n"); // Life Loop Console.WriteLine("Starting Life Loop :\n"); for (int i = 0; i < nbGen; i++) { Console.ForegroundColor = ConsoleColor.DarkBlue; Console.Write("Starting generation {0}", i); // Mélanger les cibles Console.ForegroundColor = ConsoleColor.DarkCyan; // Updating targets _targets = new List <EvaluableBoard>(); for (int _ = 0; _ < nbCible; _++) { Board b = new Board(5); Fill(b); b = Shuffle(b, r, 100 * (i + 1)); // Difficulté du mélange EvaluableBoard target = new EvaluableBoard(b); _targets.Add(target); } Console.WriteLine(" - All targets shuffled - Starting :"); // Calculating performances Console.ForegroundColor = ConsoleColor.Black; int top = Console.CursorTop; foreach (ParametrizeSolver solver in _population) { List <TimeSpan> _performances = new List <TimeSpan>(); int progress = (_population.IndexOf(solver) + 1); string progressStr = new String('=', progress); foreach (EvaluableBoard board in _targets) { Stopwatch chrono = solver.Solve(board); TimeSpan perf = chrono.Elapsed; _performances.Add(perf); } // Informations d'avancement Console.SetCursorPosition(0, top); Console.Write("\rProgress [" + progressStr + new String(' ', (nbIndiv - progress)) + "] - "); Console.ForegroundColor = ConsoleColor.Red; Console.Write(progress + "% \n"); Console.ForegroundColor = ConsoleColor.Black; // Calcul du temps moyen var averageTimespan = new TimeSpan(Convert.ToInt64(_performances.Average(ts => ts.Ticks))); solver.performance = averageTimespan; } _population = _population.OrderBy(s => s.performance).ToList(); ParametrizeSolver _currentBest = _population[0]; Console.ForegroundColor = ConsoleColor.Green; //Console.Write("Result of generation {0} : Best solver mean time is {1}, with p1 = {2} - p2 = {3} - p3 = {4} - p4 = {5} - p5 = {6}\n",i, _currentBest.performance, _currentBest.Params[0], _currentBest.Params[1], _currentBest.Params[2], _currentBest.Params[3], _currentBest.Params[4]); Console.Write("Result of generation {0} : Best solver mean time is {1}, with p1 = {2} - p2 = {3} - p3 = {4}\n", i, _currentBest.performance, _currentBest.Params[0], _currentBest.Params[1], _currentBest.Params[2]); ParametrizeSolver _currentWorst = _population[nbIndiv - 1]; Console.ForegroundColor = ConsoleColor.DarkRed; //Console.Write("Result of generation {0} : Worst solver mean time is {1}, with p1 = {2} - p2 = {3} - p3 = {4} - p4 = {5} - p5 = {6}\n\n", i, _currentWorst.performance, _currentWorst.Params[0], _currentWorst.Params[1], _currentWorst.Params[2], _currentBest.Params[3], _currentBest.Params[4]); Console.Write("Result of generation {0} : Worst solver mean time is {1}, with p1 = {2} - p2 = {3} - p3 = {4}\n\n", i, _currentWorst.performance, _currentWorst.Params[0], _currentWorst.Params[1], _currentWorst.Params[2]); Console.ForegroundColor = ConsoleColor.Black; // Dealing with generation decendance... _population = _population.GetRange(0, nbIndiv / 2); // Evolution pour la génération suivante while (_population.Count < nbIndiv - nbIndiv / 4) { // Choix de parents ParametrizeSolver father = _population[r.Next(0, _population.Count)]; // /2 Pour favoriser les meilleurs pas forcément ParametrizeSolver mother = _population[r.Next(0, _population.Count)]; // La meilleure solution int param1, param2, param3; //, param4, param5; int gene1, gene2, gene3; //, gene4, gene5; gene1 = r.Next(0, 2); gene2 = r.Next(0, 2); gene3 = r.Next(0, 2); //gene4 = r.Next(0, 2); //gene5 = r.Next(0, 2); param1 = gene1 == 0 ? father.Params[0] : mother.Params[0]; param2 = gene2 == 0 ? father.Params[1] : mother.Params[1]; param3 = gene3 == 0 ? father.Params[2] : mother.Params[2]; //param4 = gene4 == 0 ? father.Params[3] : mother.Params[3]; //param5 = gene5 == 0 ? father.Params[4] : mother.Params[4]; // Création et mutation d'un enfant ParametrizeSolver child = new ParametrizeSolver(param1, param2, param3);//, param4, param5); Mutate(child, r); _population.Add(child); } // Ajout d'objets aléatoire pour agrandir la diversité while (_population.Count < nbIndiv) { int max = 10; ParametrizeSolver current = new ParametrizeSolver(r.Next(0, max), r.Next(0, max), r.Next(0, max));//, r.Next(0, max), r.Next(0, max)); Mutate(current, r); _population.Add(current); } } Console.Read(); }