示例#1
0
        /// <summary>
        /// Algorithme permettant de verifier avec un temps d'avance si des valeurs legales ne pourront jamais etre assigne a une variable
        /// </summary>
        /// <param name="cspBase">Les contraintes actuelles sur le sudoku</param>
        /// <param name="assignement">L'attribution actuelle des variables</param>
        /// <param name="lastAssignedVariable">La derniere variable attribue</param>
        /// <returns>Les contraintes possiblement avec des valeurs legales en moins</returns>
        public static SudokuCSP ACThree(SudokuCSP cspBase, SudokuSolver.SudokuAssignment assignement, SudokuSolver.SudokuVariable lastAssignedVariable)
        {
            // Le fait d'effectuer une copie permet de ne pas avoir a s'inquieter de reset les changements qui on ete effectue
            // dans l'algorithme si le chemin n'est pas retenue
            // Cela amene cependant une complexite suplementaire dans l'algorithme
            SudokuCSP newCsp = new SudokuCSP(cspBase);

            // On modifie a jour le domaine de la derniere variable assigne
            // Cela est fait dans cette fonction car cela permet de ne pas avoir a se souvenir du domaine modifie
            // si jamais l'assignement de cette variable ne permet pas de resoudre le sudoku
            newCsp.m_variablesDomain[lastAssignedVariable.X, lastAssignedVariable.Y].Clear();
            newCsp.m_variablesDomain[lastAssignedVariable.X, lastAssignedVariable.Y].Add(assignement.Grid[lastAssignedVariable.X, lastAssignedVariable.Y]);
            foreach (SudokuSolver.SudokuVariable neighbor in newCsp.m_variableRemainingNeighbor[lastAssignedVariable.X, lastAssignedVariable.Y])
            {
                newCsp.m_variableRemainingNeighbor[neighbor.X, neighbor.Y].Remove(lastAssignedVariable);
            }

            Queue <Tuple <SudokuSolver.SudokuVariable, SudokuSolver.SudokuVariable> > arcs = new Queue <Tuple <SudokuSolver.SudokuVariable, SudokuSolver.SudokuVariable> >();

            // On fait d'abord un tour sur les arcs entre toute les variables restantes et leur voisin
            foreach (SudokuSolver.SudokuVariable remainingVariable in assignement.RemainingVariable)
            {
                // Ici du fait que l'on sache dans quel variable on va modifier les domaines, on peut se permettre de ne pas rajouter ses voisins
                // a chaque fois qu'on lui enleve un domaine
                bool remove = false;
                foreach (SudokuSolver.SudokuVariable neighbor in newCsp.m_variablesNeighbors[remainingVariable.X, remainingVariable.Y])
                {
                    remove |= RemoveInconsistentValue(newCsp, remainingVariable, neighbor);
                }
                if (remove)
                {
                    foreach (SudokuSolver.SudokuVariable remainingNeighbor in newCsp.m_variableRemainingNeighbor[remainingVariable.X, remainingVariable.Y])
                    {
                        arcs.Enqueue(new Tuple <SudokuSolver.SudokuVariable, SudokuSolver.SudokuVariable>(remainingNeighbor, remainingVariable));
                    }
                }
            }

            // On effectue ensuite les operations necessaire sur la queue jusqu'a ce que celle-ci soit vide
            while (arcs.Count != 0)
            {
                Tuple <SudokuSolver.SudokuVariable, SudokuSolver.SudokuVariable> arc = arcs.Dequeue();
                if (RemoveInconsistentValue(newCsp, arc.Item1, arc.Item2))
                {
                    foreach (SudokuSolver.SudokuVariable remainingNeighbor in newCsp.m_variableRemainingNeighbor[arc.Item1.X, arc.Item1.Y])
                    {
                        arcs.Enqueue(new Tuple <SudokuSolver.SudokuVariable, SudokuSolver.SudokuVariable>(remainingNeighbor, arc.Item1));
                    }
                }
            }

            return(newCsp);
        }
示例#2
0
        /// <summary>
        /// Retourne une liste des variables auquel il reste le moins de variables legales
        /// </summary>
        /// <param name="assignment"></param>
        /// <returns>Les variables qui contiennent le moins de valeurs legales</returns>
        public List <SudokuSolver.SudokuVariable> MinimumRemainingValues(SudokuSolver.SudokuAssignment assignment)
        {
            int mrv = 10;
            List <SudokuSolver.SudokuVariable> values = new List <SudokuSolver.SudokuVariable>();

            foreach (SudokuSolver.SudokuVariable variable in assignment.RemainingVariable)
            {
                // Recupere le nombre de valeurs restante de la variable
                // On peut se permettre de faire ca car on utilise le forward checking
                // Dans le cas contraire il aurait fallu regarder tous les voisin pour chaque variables
                int domainSize = m_variablesDomain[variable.X, variable.Y].Count;
                if (domainSize < mrv)
                {
                    mrv = domainSize;
                    values.Clear();
                    values.Add(variable);
                }
                else if (domainSize == mrv)
                {
                    values.Add(variable);
                }
            }
            return(values);
        }
示例#3
0
        /// <summary>
        /// Constructeur
        /// </summary>
        /// <param name="assignment">Attribution initiale du sudoku</param>
        public SudokuCSP(SudokuSolver.SudokuAssignment assignment)
        {
            m_size                      = assignment.Size;
            int[,] grid                 = assignment.Grid;
            m_variablesDomain           = new List <int> [m_size, m_size];
            m_variablesNeighbors        = new List <SudokuSolver.SudokuVariable> [m_size, m_size];
            m_variableRemainingNeighbor = new List <SudokuSolver.SudokuVariable> [m_size, m_size];

            SudokuSolver.SudokuVariable[,] tempVariableGrid = new SudokuSolver.SudokuVariable[m_size, m_size];

            // Creer les variables
            for (int x = 0; x < m_size; x++)
            {
                for (int y = 0; y < m_size; y++)
                {
                    tempVariableGrid[x, y]            = new SudokuSolver.SudokuVariable(x, y);
                    m_variablesDomain[x, y]           = new List <int>(Enumerable.Range(1, m_size));
                    m_variablesNeighbors[x, y]        = new List <SudokuSolver.SudokuVariable>();
                    m_variableRemainingNeighbor[x, y] = new List <SudokuSolver.SudokuVariable>();
                }
            }

            int squareSize = (int)Math.Sqrt(m_size);

            // Creer les contraintes
            for (int x = 0; x < m_size; x++)
            {
                for (int y = 0; y < m_size; y++)
                {
                    // Si la variable a deja ete assigne on peut mettre a jour son domaine et ne pas chercher ses voisins
                    if (grid[x, y] != -1)
                    {
                        m_variablesDomain[x, y].Clear();
                        m_variablesDomain[x, y].Add(grid[x, y]);
                        continue;
                    }

                    // Sinon on l'ajoute a la liste des variable non assignes
                    assignment.AddRemainingVariable(tempVariableGrid[x, y]);

                    // On va aussi chercher tous ses voisins
                    // Si l'un d'entre eux a ete assigne on enleve sa valeur des valeurs legal de la variable courente, il n'est aussi pas
                    // necessaire de l'ajouter a la liste des voisins restant de cette variables
                    // Colonnes
                    for (int k = 0; k < m_size; k++)
                    {
                        if (k != y)
                        {
                            m_variablesNeighbors[x, y].Add(tempVariableGrid[x, k]);
                            if (grid[x, k] != -1)
                            {
                                m_variablesDomain[x, y].Remove(grid[x, k]);
                            }
                            else
                            {
                                m_variableRemainingNeighbor[x, y].Add(tempVariableGrid[x, k]);
                            }
                        }
                    }

                    // Lignes
                    for (int k = 0; k < m_size; k++)
                    {
                        if (k != x)
                        {
                            m_variablesNeighbors[x, y].Add(tempVariableGrid[k, y]);
                            if (grid[k, y] != -1)
                            {
                                m_variablesDomain[x, y].Remove(grid[k, y]);
                            }
                            else
                            {
                                m_variableRemainingNeighbor[x, y].Add(tempVariableGrid[k, y]);
                            }
                        }
                    }

                    // Carre
                    for (int k = (x / squareSize) * squareSize; k < (x / squareSize) * squareSize + squareSize; k++)
                    {
                        for (int l = (y / squareSize) * squareSize; l < (y / squareSize) * squareSize + squareSize; l++)
                        {
                            if (x != k && y != l)
                            {
                                m_variablesNeighbors[x, y].Add(tempVariableGrid[k, l]);
                                if (grid[k, l] != -1)
                                {
                                    m_variablesDomain[x, y].Remove(grid[k, l]);
                                }
                                else
                                {
                                    m_variableRemainingNeighbor[x, y].Add(tempVariableGrid[k, l]);
                                }
                            }
                        }
                    }
                }
            }
        }