/// <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); }
/// <summary> /// Constructeur de copie /// </summary> /// <param name="otherCSP">Le CSP a copie</param> public SudokuCSP(SudokuCSP otherCSP) { m_size = otherCSP.m_size; m_variablesNeighbors = otherCSP.m_variablesNeighbors; m_variablesDomain = new List <int> [m_size, m_size]; m_variableRemainingNeighbor = new List <SudokuSolver.SudokuVariable> [m_size, m_size]; for (int x = 0; x < m_size; x++) { for (int y = 0; y < m_size; y++) { m_variablesDomain[x, y] = new List <int>(otherCSP.m_variablesDomain[x, y]); m_variableRemainingNeighbor[x, y] = new List <SudokuSolver.SudokuVariable>(otherCSP.m_variableRemainingNeighbor[x, y]); } } }
/// <summary> /// Enleve les valeurs inconsistante des valeurs legales d'une variable /// </summary> /// <param name="csp">Les contraintes actuelle sur le sudoku</param> /// <param name="variableToCheck">La variables dont on verifie les valeurs legales</param> /// <param name="variableNeighbor">Un voisin de la variable</param> /// <returns></returns> static bool RemoveInconsistentValue(SudokuCSP csp, SudokuSolver.SudokuVariable variableToCheck, SudokuSolver.SudokuVariable variableNeighbor) { bool removed = false; List <int> domainsNode1 = new List <int>(csp.m_variablesDomain[variableToCheck.X, variableToCheck.Y]); List <int> domaineNode2 = csp.m_variablesDomain[variableNeighbor.X, variableNeighbor.Y]; foreach (int x in domainsNode1) { // Si le domaine de la variable voisine ne contient qu'une seule valeur c'est qu'elle a soit ete assigne // soit c'est la seule variable que l'on peut lui assigne. // Dans tous les cas on ne pourra pas donner cette valeur a la variable courante if (domaineNode2.Contains(x) && domaineNode2.Count == 1) { csp.m_variablesDomain[variableToCheck.X, variableToCheck.Y].Remove(x); removed = true; break; } } return(removed); }