import libPSC import copy ################################################################################# print "Chargement du module PSC" print "\t@version: 1.1 date: 24/04/2006 modified by the vincent.schickel-zuber@epfl.ch" print "\t@author: vincent.schickel-zuber@epfl.ch date: 24/04/2006" print "\t@copyright: EPFL-IC-IIF-LIA 2006" ################################################################################# ##contient tous les noeuds NOEUDS=[] ##contient tous les arcs ARCS=[] ##valeur retournee en cas d'echec ECHEC='echec' ##contient le nombre d'iteration de l'algorithme ITERATION = 0 ##contient les solutions de l'algorithme SOLUTION=[] ##applique l'algorithme de Variable Ordering def variableOrdering(): NOEUDS.sort() ##retourne toutes les contraintes unaires pour un noeud donnne ##@param noeud le noeud def retourneContraintesUnaires(noeud): contraintes=[] for a in ARCS: if a.refContrainte.depart==noeud.refVar and a.refContrainte.arrive==noeud.refVar: contraintes.append(a.refContrainte) return contraintes ##retourne toutes les contraintes binaires pour deux noeuds donnnes ##@param noeud1 le noeud de depart de la contrainte ##@param noeud2 le noeud d'arrive de la contrainte ##@ret toutes les contraintes bineaires ente n1 -> n2 def retourneContraintesBinaires(noeud1,noeud2): contraintes=[] for a in ARCS: if (a.refContrainte.depart==noeud1.refVar and a.refContrainte.arrive==noeud2.refVar): if a.refContrainte not in contraintes: contraintes.append(a.refContrainte) return contraintes ##verifie si deux noeud ayant chacun une valeur sont consitant avec les contraintes entre ces deux neouds ##@param n1 le noeud 1 ##@param n2 le noeud 2 ##@param contraintes contraintes entre n1 et n2 ##@ret true <=> consistant; else False def consistant(n1,n2,contraintes): if len(contraintes)==0: return True touteVraie = lambda x, y : x and y resultat=map(libPSC.ContrainteBinaire.estValide, contraintes) const = reduce(touteVraie,resultat) return const ##verifie la consistance des varibles PAS ENCORE instantiee ##@param n1 le noeud 1 instantiee ##@param n2 le noeud a verifier si consitent, ##@param containtes les contraintes entre n1 et n2 def consistanceFuture(n1,n2,contraintes): if len(contraintes)==0: return True touteVraie = lambda x, y : x and y n2.refVar.enleveDuLabel(n1.refVar.valeur) resultat=map(libPSC.ContrainteBinaire.estPossibleAvecLabel, contraintes) const = reduce(touteVraie,resultat) return const ##reinitialise le label de tous les variables def initLabelDesVariables(): for n in NOEUDS: n.refVar.initLabel() ##affiche la solution avec queques informations utile ##@param algo le nom de l'algo ##@param solution la solution trouvee def afficheSolution(algo,solution): print "\t",algo,": SOLUTION TROUVEE en ",ITERATION,"etapes et avec ",libPSC.NBCONTRAINTE," contraintes verifiees; SOLUTION=",solution ##affiche le nombre d'iteration avec queques informations utile ##@param algo le nom de l'algo ##@param k la pronfondeur actuelle def afficheNbIteration(algo,k): print algo,": Ieration:=",ITERATION," pronfondeur actuelle:=",k ,"et",libPSC.NBCONTRAINTE," contraintes verifiees" ##retourne le contenu des label de tous les noeuds dans un tableau def retournelabels(): labels=[] for n in NOEUDS: labels.append(copy.deepcopy(n.refVar.label)) return labels ##met a jour les labels de tous les noeuds ##@param labels les nouveau labels def metAJourlabels(labels): for i in range(0,len(NOEUDS)): NOEUDS[i].refVar.label=copy.deepcopy(labels[i]) ##gere tous les noeuds dans NOEUDS class Noeuds: ##initialise le tableau de noeuds def __init__(self): del NOEUDS[:] ##retourne le noeud referencant le variable ayant un nom=nom ##@param nom le nom de la variable ##@ret le noeud, -1 si pas trouvée def retourneNoeud(self, nom): for noeud in NOEUDS: if noeud.refVar.nomEstEgalle(nom): return noeud return -1 ##ajoute un noeud a la lite def ajouteNoeud(self,noeud): NOEUDS.append(noeud) ##applique la consistance des noeuds def consistanceDesNoeuds(self): for n in NOEUDS: n.consistanceDuNoeud(retourneContraintesUnaires(n)); ##retourne une liste d'instances initialisee a -1 ##utilise dans le backtrack et forward checking ##@ret [-1,...,-1] def instances(self): inst=[] for n in NOEUDS: inst.append(-1) return inst ##affiche tous les noeuds def __str__(self): counter=1 str = "Noeuds\n" for n in NOEUDS: str+="\t" +n.__str__()+"\n" counter+=1 return str ##gere tous les noeuds dans ARCS class Arcs: ##initialise le tableau des ARCS def __init__(self): del ARCS[:] ##ajoute un arc a la lite def ajouteArc(self,arc): ARCS.append(arc) ##retourne tous les arcs unaire pour un noeud donnne ##@param noeud le noeud def retourneArcs(noeud): arcs2 for a in ARCS: if a.refContrainte.depart==noeud.refVar and a.refContrainte.arrive==noeud.refVar: arcs2.append(a) return arcs2 ##applique la consistance des arcs def consistanceDesArcs(self): modified = True while modified: modified = False for a in ARCS: if a.refContrainte.dimension() == 2 and a.reviser(): modified = True ##affiche tous les noeuds def __str__(self): str = "Arcs\n" for n in ARCS: str+="\t1. "+ n.__str__()+"\n" return str ## Algorithme de Bactrack simple ## @param instances les n variables; rempli jusqu'a k ## @param k la pronfondeur de la recherce (commence a 0) ## @param toutesLesSolutions si True alors cherche TOUTES les solutions, sinon s'arrete a la premiere (valeur oar defaut) ## @param initialise initialise les variables gloabl ITEARTION et SOLUTION ## @ret instances contenant la solution OU echec si aucune solution trouvée def backtrack(instances, k, touteLesSolutions=None, initialise=None): algo="bt" global ITERATION global SOLUTION if touteLesSolutions==None: touteLesSolutions=False if initialise==None: ITERATION=0 SOLUTION=[] libPSC.NBCONTRAINTE=0 initialise=False ITERATION=ITERATION+1 afficheNbIteration(algo,k) if k >= len(NOEUDS): afficheSolution(algo,instances) SOLUTION.append(copy.deepcopy(instances)) if not touteLesSolutions: return instances else: n = NOEUDS[k] for x in n.refVar.domaine: n.refVar.metAJourValeur(x) consistant = True for i in range(k): if not reduce(lambda x,y: x and y.estValide(), retourneContraintesBinaires(n, NOEUDS[i]), True): consistant = False if consistant: instances[k] = x rest = backtrack(instances, k+1, touteLesSolutions, initialise) if rest != ECHEC: return rest return ECHEC ## Algorithme de Forward Chekcing simple ## @param instances les n variables; rempli jusqu'a k ## @param k la pronfondeur de la recherce (commence a 0) ## @param toutesLesSolutions si True alors cherche TOUTES les solutions, sinon s'arrete a la premiere (valeur oar defaut) ## @param initialise initialise les variables gloabl ITEARTION et SOLUTION, et le laebl des noeuds ## @ret instances contenant la solution OU echec si aucune solution trouvée def forwardChecking(instances, k, touteLesSolutions=None, initialise=None): algo="ft" global ITERATION global SOLUTION if touteLesSolutions==None: touteLesSolutions=False if initialise==None or initialise==True: ITERATION=0 SOLUTION=[] libPSC.NBCONTRAINTE=0 initLabelDesVariables() initialise=False ITERATION=ITERATION+1 afficheNbIteration(algo,k) if k>(len(NOEUDS)-1): afficheSolution(algo,instances) SOLUTION.append(copy.deepcopy(instances)) if not touteLesSolutions: return instances else: noeud = NOEUDS[k] labels = retournelabels() for d in noeud.refVar.label: ##domaine: noeud.refVar.metAJourValeur(d) consistantFuturOK=True for i in range(k+1,len(NOEUDS)): ##print "\t\tVerification de la consitance da la valeur", d, "avec la variable non instantie",NOEUDS[i] if not consistanceFuture(noeud,NOEUDS[i],retourneContraintesBinaires(noeud,NOEUDS[i])): consistantFuturOK=False if consistantFuturOK: instances[k]=d rest = forwardChecking(instances,k+1,touteLesSolutions,initialise) if rest!= ECHEC: return rest metAJourlabels(labels) return ECHEC #execfile("testConsistance.py") execfile("test.py")