Newer
Older
ai / lab6 / PSC.py
@Andreas Jaggi Andreas Jaggi on 8 May 2006 8 KB Did Lab 6a, with a sudoku :-)
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")