Пример #1
0
        // 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);
        }
Пример #2
0
        // 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);
        }
Пример #3
0
        // 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
    }
Пример #4
0
 // 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);
 }
Пример #5
0
        // 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);
        }
Пример #6
0
        // 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);
        }
Пример #7
0
        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);
        }
Пример #8
0
 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;
 }
Пример #9
0
        // 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();
        }
Пример #10
0
        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();
        }