Newer
Older
ai / lab6 / sudoku.py
@Andreas Jaggi Andreas Jaggi on 8 May 2006 10 KB Did Lab 6a, with a sudoku :-)
#################################################################################
print "Chargement du module variable et noeud pour PSC"
print "\t@version: 1.0  date: 1/05/2006 modified by the vincent.schickel-zuber@epfl.ch"
print "\t@author: vincent.schickel-zuber@epfl.ch date: 1/05/2006"
print "\t@copyright: EPFL-IC-IIF-LIA 2006"
#################################################################################

import copy
import libPSC
import PSC

##le symbol vide dans la grille = 0
X = 0

##le domaine des variables
DOMAINE=range(1,10)

##contient l'ennonce de depart
PROBLEME=[]
##defini la grille du sudoku
GRILLE=[[]]
##nombre de collone de la grille
NBCOL=9
##nombre de ligne de la grille
NBLGN=9

NOEUDS = PSC.Noeuds()
ARCS =  PSC.Arcs()

##taille des sous grille
TAILLESOUSGRILLE=3

 ##retourne la position de la ss_grille correspondant a la position absolue
##@pos la position absolue
def retournePosSSGille(pos):
    return pos/TAILLESOUSGRILLE

##retourne la position DANS dans la ss_grille correspondant a la position absolue
##@pos la position absolue
def retournePosINSSGille(pos):
    return pos%TAILLESOUSGRILLE 


## verifie si un symbole passe en parametre = symbole vide
def estVide(symb):
    return symb==X

##definit une sous grille (qui fera partie de la grille)
class SSGrille:

   
    ##constructeur
    ##@param posL la position sur la ligne[0..2]
    ##@param posC la position dans la colonne[0..2]
    def __init__(self, posL,posC):
        global X
        global DOMAINE
        self.posL=posL
        self.posC=posC
        self.ssgrille=[]
        self.notPossible=[]
        ##self.domaine=copy.deepcopy(DOMAINE)
        for i in range(0,TAILLESOUSGRILLE):
            self.ssgrille.append([])
            
        for i in range(0,TAILLESOUSGRILLE):
            for j in range(0,TAILLESOUSGRILLE):
                id="v["+str(self.posL)+","+str(self.posC)+"]["+str(i)+","+str(j)+"]"
                noeud = libPSC.Noeud(libPSC.Variable(id,DOMAINE))
                self.ssgrille[i].append(noeud)
                NOEUDS.ajouteNoeud(noeud)

    ##met a jour la valeur du noeud dans la sous grille a un endroit specifique
    ##@param valeur la valeur de la variable
    ##@param domaine le domaine de la variable
    ##@param posX la position en X
    ##@param posY la position en Y
    def ajouteNoeud(self, valeur, domaine , posX,posY):   
        global X
        self.ssgrille[posX][posY].refVar.metAJourValeur(valeur)
        if valeur in DOMAINE:
            ##self.domaine.remove(valeur)
            self.ssgrille[posX][posY].refVar.domaine=[valeur]
            self.notPossible.append(valeur)
        else:
            self.ssgrille[posX][posY].refVar.domaine=copy.deepcopy(DOMAINE)         

    ##retourne la coordonne absolue d'un element dans la grille
    ##@param x la position en axe x dans la sous-grille
    ##@param y la position en axe y dans la sous-grille
    ##@ret (x_abolue,y_abolue)
    def positionAbolue(self,x,y):
        global TAILLESOUSGRILLE
        posx=self.posL*TAILLESOUSGRILLE+x
        posy=self.posC*TAILLESOUSGRILLE+y
        return (posx,posy)

    ##retourne la valeur a une position donnee
    def valeur(self,posX,posY):
        return self.ssgrille[posX][posY].refVar.valeur

    ## genre toutes les contraintes de groupes
    def genereContraintesSSGrille(self):
        global NBLGN
        for i in range(0,TAILLESOUSGRILLE):
            for j in range(0,TAILLESOUSGRILLE):                
                for k in range(0,TAILLESOUSGRILLE):
                    for l in range(0,TAILLESOUSGRILLE):
                        if i<>k and j<>l:
                            n1=self.ssgrille[i][j]
                            n2=self.ssgrille[k][l]
                            c=libPSC.ContrainteBinaire(n1.refVar,"<>",n2.refVar)
                            c2=libPSC.ContrainteBinaire(n2.refVar,"<>",n1.refVar)
                            ARCS.ajouteArc(libPSC.Arc(c2))
                            ARCS.ajouteArc(libPSC.Arc(c))     

##definit la grille, qui est faite de 9 sous grille        
class Grille:    

    ##constructeur
    ##initilaise la variable globale GRILLE
    def __init__(self):
        self.init()

    ##initialise la grille avec le contenu du probleme
    def init(self):
        global GRILLE
        global PROBLEME
        global TAILLESOUSGRILLE
        global GRILLE
        global NBLGN
        global NBCOL
        del GRILLE[:]
        for i in range(0,TAILLESOUSGRILLE):
            GRILLE.append([])

        ##remplit la grille de sous-grille
        ssgrillecol=0
        ssgrillelgn=0            
        for i in range(0,TAILLESOUSGRILLE):
            for j in range(0,TAILLESOUSGRILLE):
                GRILLE[i].append(SSGrille(i,j))
        

        ##remplit les sous-grille                  
        ssgrillecol=0
        ssgrillelgn=0
        for i in range(0,NBLGN):
            ssgrillecol=0
            if i>0 and i%TAILLESOUSGRILLE==0:
                ssgrillelgn+=1
            for j in range(0,NBCOL):
                if j>0 and j%TAILLESOUSGRILLE==0:
                    ssgrillecol+=1
                if not (PROBLEME[i][j]==X):
                    GRILLE[retournePosSSGille(i)][retournePosSSGille(j)].ajouteNoeud(PROBLEME[i][j],[PROBLEME[i][j]],retournePosINSSGille(i),retournePosINSSGille(j))
                else:
                    GRILLE[retournePosSSGille(i)][retournePosSSGille(j)].ajouteNoeud(PROBLEME[i][j],DOMAINE,retournePosINSSGille(i),retournePosINSSGille(j))
                ##GRILLE[retournePosSSGille(i)][retournePosSSGille(j)].ssgrille[retournePosINSSGille(i)][retournePosINSSGille(j)].refVar.metAJourValeur(PROBLEME[i][j])
                self.retourneNoeud(i,j).refVar.metAJourValeur(PROBLEME[i][j])
      

    ##retourne la grille en string
    def __str__(self):
        global NBLGN
        global NBCOL
        global GRILLE
        ssgrillecol=0
        ssgrillelgn=0
        ligne=""
        for i in range(0,NBLGN):
            ssgrillecol=0
            if i>0 and i%TAILLESOUSGRILLE==0:
                ssgrillelgn+=1
            ligne+="\t"
            for j in range(0,NBCOL):
                if j>0 and j%TAILLESOUSGRILLE==0:
                    ssgrillecol+=1
                ligne+=str(GRILLE[retournePosSSGille(i)][retournePosSSGille(j)].valeur(retournePosINSSGille(i),retournePosINSSGille(j)))+" "    
            ligne+="\n"
        return ligne

    ##retourne un noeud se trouvant une position en valeur absolue
    ##@param posX la position absolue X
    ##@param posY la position absolue Y
    def retourneNoeud(self,posX,posY):
        n=GRILLE[retournePosSSGille(posX)][retournePosSSGille(posY)].ssgrille[retournePosINSSGille(posX)][retournePosINSSGille(posY)]
        return n

    ## genere toutes les contraintes de lignes
    def genereContraintesLignes(self):
        global NBLGN
        for i in range(0,NBCOL):
            for j in range(0,NBLGN):
                for k in range(j+1,NBLGN):
                    n1=self.retourneNoeud(j,i)
                    n2=self.retourneNoeud(k,i)
                    c=libPSC.ContrainteBinaire(n1.refVar,"<>",n2.refVar)
                    c2=libPSC.ContrainteBinaire(n2.refVar,"<>",n1.refVar)
                    ARCS.ajouteArc(libPSC.Arc(c2))
                    ARCS.ajouteArc(libPSC.Arc(c))
                    
    ## genere toutes les contraintes de colonne
    def genereContraintesColonnes(self):
        global NBLGN
        for i in range(0,NBLGN):
            for j in range(0,NBCOL):
                for k in range(j+1,NBCOL):
                    n1=self.retourneNoeud(i,j)
                    n2=self.retourneNoeud(i,k)
                    c=libPSC.ContrainteBinaire(n1.refVar,"<>",n2.refVar)
                    c2=libPSC.ContrainteBinaire(n2.refVar,"<>",n1.refVar)
                    ARCS.ajouteArc(libPSC.Arc(c2))
                    ARCS.ajouteArc(libPSC.Arc(c))                    

    ##genere toutes les contraintes de sous-grille
    def genereContraintesSSGrilles(self):
        for i in range(0,TAILLESOUSGRILLE):
            for j in range(0,TAILLESOUSGRILLE):
                GRILLE[i][j].genereContraintesSSGrille()
## initialise le jeu (la grille) et trouve la solution
def run(algo,grille):
    print "|+| Chargement du probleme"
    global PROBLEME
    if grille=="A":
        PROBLEME=[[9,X,X,X,X,X,X,X,2], 
               [3,X,7,1,X,X,4,X,8],
               [X,1,X,X,5,4,X,6,X],
               [X,X,1,X,X,X,X,7,X],
               [X,X,4,X,X,X,9,X,X],
               [X,2,X,X,X,X,8,X,X],
               [X,8,X,3,2,X,X,4,X],
               [7,X,3,X,X,6,2,X,1],
               [4,X,X,X,X,X,X,X,5]]
    elif grille=="B":
        PROBLEME=[[1,X,4,X,X,8,X,5,2], 
               [8,X,X,4,X,X,9,X,X],
               [X,5,X,X,9,1,X,X,8],
               [3,X,2,7,X,5,X,1,X],
               [X,X,6,X,X,X,5,X,X],
               [X,7,X,1,X,2,8,X,4],
               [7,X,X,3,8,X,X,9,X],
               [X,X,5,X,X,4,X,X,6],
               [9,6,X,5,X,X,1,X,3]]
    else:
        print "|-| Grille" ,grille,"pas definit"
    
    global NOEUDS
    global ARCS
    NOEUDS = PSC.Noeuds()
    ARCS = PSC.Arcs()
    
    print "|+| Initialisation de la grille"
    grille = Grille()
    print grille

    print "|+| Ajoute les contraintes"
    grille.genereContraintesLignes()
    grille.genereContraintesColonnes()
    grille.genereContraintesSSGrilles()
    
    print "|+| Fait la consitance des noeuds"    
    NOEUDS.consistanceDesNoeuds()
    ##print NOEUDS

    print "|+| Fait la consitance des arcs"
    ARCS.consistanceDesArcs()
    ##print ARCS
    print grille

    PSC.variableOrdering()
        
    if algo=="FC":
        sol=PSC.forwardChecking(NOEUDS.instances(),0,False,True)
    else:
       sol=PSC.backtrack(NOEUDS.instances(),0,False,True)
    print grille

## genre toutes les contraintes de lignes
## @param grille l'objet


    
#################################################################################################################    
##run
run("FC","A")