def minimal_imap(self, order): """ Returns a Bayesian Model which is minimal IMap of the Joint Probability Distribution considering the order of the variables. Parameters ---------- order: array-like The order of the random variables. Examples -------- >>> from pgmpy.factors import JointProbabilityDistribution >>> prob = JointProbabilityDistribution(['x1', 'x2', 'x3'], [2, 3, 2], np.ones(12)/12) >>> bayesian_model = prob.minimal_imap(order=['x2', 'x1', 'x3']) >>> bayesian_model <pgmpy.models.models.models at 0x7fd7440a9320> """ from pgmpy import models as bm import itertools def combinations(u): for r in range(len(u) + 1): for i in itertools.combinations(u, r): yield i G = bm.BayesianModel() for variable_index in range(len(order)): u = order[:variable_index] for subset in combinations(u): if self.check_independence(order[variable_index], set(u) - set(subset), subset): G.add_edges_from([(variable, order[variable_index]) for variable in subset]) return G
def red_bayesiana(self): """ Creamos la red bayesiana con la librería pgmpy """ Buscaminas_bayesiano = pgmm.BayesianModel() """ Variables importantes: x_totales: casillas ocultas totales del tablero x_ocultas: casillas ocultas con vecinos destapados y_destapadas: casillas destapadas """ x_ocultas = [] x_totales = [] y_destapadas = [] casilla_oculta_sin_colindantes_destapados = False """ Añadimos los nodos a la red. Serán las casillas ocultas con vecinos destapados y las casillas destapadas. """ for fila in range(self.filas): for columna in range(self.columnas): # Si la casilla no está pulsada if (self.tableroOculto[fila][columna] == 'T'): x = 'Tapada{0}{1}'.format( fila, columna) # Lo pone en formato Tapada01,Tapada02... x_totales.append( x ) # Añadimos las casillas sin pulsar a la variable x_totales casilla_tiene_vecinos_destapados = False # Obtenemos la posicion de las casillas vecinas casillas_vecinas = me.posicion_casillas_vecinas( self.tableroOculto, fila, columna) # Recorro todas las casillas vecinas de la casilla en la que estamos actualmente for vecino in casillas_vecinas: # Comprobamos que los vecinos de la casilla estan destapados if (self.tableroOculto[int(vecino[0])][int(vecino[1])] != 'T'): casilla_tiene_vecinos_destapados = True break # Comprobamos que la casilla actual tiene vecino destapado if (casilla_tiene_vecinos_destapados or not casilla_oculta_sin_colindantes_destapados): # Si lo tiene, añadimos la casilla a la lista de casillas tapadas con vecinos destapados x_ocultas.append(x) Buscaminas_bayesiano.add_nodes_from([ x ]) # Se añade la casilla como nodo de nuestra red if (not casilla_tiene_vecinos_destapados): casilla_oculta_sin_colindantes_destapados = True # Si la casilla está pulsada else: y = 'Destapada{0}{1}'.format( fila, columna ) # lo pone en formato Destapada 01,Destapada 02... #Listado_de_minas = listado_de_minas(tableroBuscaminas) # Variable que contiene la posición de las minas del tablero casilla_tiene_vecinos_ocultos = False casillas_vecinas = me.posicion_casillas_vecinas( self.tableroOculto, fila, columna) for vecino in casillas_vecinas: casilla_vecina_oculta = 'Tapada{0}{1}'.format( vecino[0], vecino[1]) if (self.tableroOculto[int(vecino[0])][int( vecino[1])] == 'T' and not self.Minas_encontradas.__contains__( casilla_vecina_oculta)): casilla_tiene_vecinos_ocultos = True break if (casilla_tiene_vecinos_ocultos): y_destapadas.append(y) Buscaminas_bayesiano.add_nodes_from([y]) print("Lista de casillas vecinas ocultas:\n") print(x_ocultas) print("Lista de casillas destapadas:\n") print(y_destapadas) print("Lista de minas encontradas:\n") print(self.Minas_encontradas) """ Añadimos las aristas entre los nodos. Las casillas destapadas tendrán aristas con sus vecinas ocultas """ Aristas = dict() for fila in range(self.filas): for columna in range(self.columnas): y = 'Destapada{0}{1}'.format(fila, columna) # Si la casilla ha sido destapada y se ha añadido a la lista de casillas destapadas if (self.tableroOculto[fila][columna] != 'T' and y_destapadas.__contains__(y)): ListaColindantesOcultos = [] # Obtenemos la posicion de las casillas vecinas casillas_vecinas = me.posicion_casillas_vecinas( self.tableroOculto, fila, columna) # Recorremos sus vecinos for vecino in casillas_vecinas: x = 'Tapada{0}{1}'.format(vecino[0], vecino[1]) # Si el vecino es oculto añadimos la arista de la destapada a la tapada if (x_ocultas.__contains__(x)): Buscaminas_bayesiano.add_edges_from([(x, y)]) ListaColindantesOcultos.append(x) # Asociamos la casilla destapada con todos sus vecinos ocultos Aristas.update({y: ListaColindantesOcultos}) """ Generación de tablas de probabilidad (CPDs) Las tablas de probabilidad de las casillas tapadas no dependen de nada. Las tablas de probabilidad de las casillas destapadas dependen de sus casillas vecinas tapadas. Para cada variable creamos una instancia de la clase `TabularCPD`, proporcionando: Nombre de la variable (atributo `variable`), Cantidad de valores (cardinalidad) que puede tomar (atributo `variable_card`), Lista de listas, conteniendo cada una de estas las probabilidades para un valor concreto, según los valores de los padres (atributo `values`, el valor se transforma a un array), Lista con los nombres de los padres (atributo `evidence`, valor `None` si no se proporciona), Lista con la cantidad de valores (cardinalidad) que puede tomar cada uno de los padres (atributo `evidence_card`, valor `None` si no se proporciona). """ """ Tabla de probabilidad de las casillas tapadas """ ListadoDestapadas = dict() for fila in range(self.filas): for columna in range(self.columnas): x = 'Tapada{0}{1}'.format(fila, columna) y = 'Destapada{0}{1}'.format(fila, columna) if (self.tableroOculto[fila][columna] == 'T' and x_ocultas.__contains__(x)): # Si la casilla por detapar es una mina if (self.Minas_encontradas.__contains__(x)): probabilidad_mina = 1 # Si el numero de casillas por destapar es mayor que el numero de minas que tiene el tablero elif (len(x_ocultas) > 0): probabilidad_mina = (self.minas - len( self.Minas_encontradas)) / len(x_totales) else: probabilidad_mina = 0 # Añadimos la cpd al modelo cpd = pgmf.TabularCPD( x, 2, [[1 - probabilidad_mina, probabilidad_mina]]) Buscaminas_bayesiano.add_cpds(cpd) # CPD de Destapadas elif (self.tableroOculto[fila][columna] != 'T' and y_destapadas.__contains__(y)): ListadoDestapadas.update( {y: int(self.tableroOculto[fila][columna])}) #A continuación divido entre los valores que puede tener 'Destapada' en función de las minas que tenga alrededor nColumnasCPD = pow(2, len(Aristas[y])) numero_maximo_minas = 9 if (fila == 0 or fila == self.filas - 1): numero_maximo_minas = 6 if (columna == 0 or columna == self.columnas - 1): if (numero_maximo_minas == 6): numero_maximo_minas = 4 else: numero_maximo_minas = 6 if (len(Aristas[y]) + 1 < numero_maximo_minas): numero_maximo_minas = len(Aristas[y]) + 1 listaProb = [] for var in range(numero_maximo_minas): listaFila = [] contador = 0 for x in range(nColumnasCPD): if (var == bin(contador).count('1')): listaFila.append(1) else: listaFila.append(0) contador += 1 listaProb.append(listaFila) ListaCardinalidad = [] for _ in range(len(Aristas[y])): ListaCardinalidad.append(2) cpd = pgmf.TabularCPD(y, numero_maximo_minas, listaProb, Aristas[y], ListaCardinalidad) Buscaminas_bayesiano.add_cpds(cpd) Buscaminas_bayesiano_ev = pgmi.VariableElimination( Buscaminas_bayesiano) consultas = [] for var in x_ocultas: if (not var in self.Minas_encontradas): consulta = Buscaminas_bayesiano_ev.query([var], ListadoDestapadas) consultas.append(consulta) ocultasProbabilidadDeNoSerMina = dict() for var in consultas: x = '' probabilidadDeNoSerMina = 0 for var1 in var.keys(): x = str(var1) for var2 in var.values(): probabilidadDeNoSerMina = float(var2.values[0]) if (probabilidadDeNoSerMina == 0.0): self.Minas_encontradas.append(x) ocultasProbabilidadDeNoSerMina.update({x: probabilidadDeNoSerMina}) maximaProbabilidadDeNoSerMina = 0. ocultaMaximaProbabilidadDeNoSerMina = '' mejor_oculta = [] print("Oculta con mayor probabilidad de no ser mina") for x, probabilidadDeNoSerMina in ocultasProbabilidadDeNoSerMina.items( ): print("x: {0} -> Probabilidad de no ser mina: {1}".format( x, probabilidadDeNoSerMina)) if (maximaProbabilidadDeNoSerMina < probabilidadDeNoSerMina): ocultaMaximaProbabilidadDeNoSerMina = str(x) maximaProbabilidadDeNoSerMina = probabilidadDeNoSerMina mejor_oculta = [] mejor_oculta.append(ocultaMaximaProbabilidadDeNoSerMina) if (probabilidadDeNoSerMina == 1.0 and not x in mejor_oculta): mejor_oculta.append(x) self.mejor_oculta = mejor_oculta print( "Lista de mejores ocultas con alta probabilidad de no ser minas: {0}" .format(self.mejor_oculta))
def gameNetworkGenerator(game): #Definimos el tablero graph = [] width = game.board.board_width height = game.board.board_height #Averiguamos los vecinos de cada Y y creamos un conjunto con todos los nodos y las aristas relacionadas. for i in range(width): for j in range(height): vecinos = game.neightbours_of_position(i, j) for x in range(0, len(vecinos)): graph.append((vecinos[x], "Y" + str(i) + str(j))) #Añadimos a la modelo bayesiano la información obtenida anteriormente Modelo_msgame = pgmm.BayesianModel(graph) probabilidadBomba = game.board.num_mines / ((game.board.board_height) * (game.board_width)) probabilidadNoBomba = 1 - probabilidadBomba modelnodes = Modelo_msgame.nodes() modelnodesY = Modelo_msgame.nodes() res = [s for s in modelnodes if 'X' in s] #"A partir de aqui se obtienen las CPDS de las Xij" for e in range(0, len(res)): cpd_msgameX = "cpd_msgame" + (res[e]) cpd_msgameX = pgmf.TabularCPD( res[e], 2, [[probabilidadNoBomba, probabilidadBomba]]) Modelo_msgame.add_cpds(cpd_msgameX) resY = [s for s in modelnodesY if 'Y' in s] for l in range(0, len(resY)): i = resY[l][1:2] j = resY[l][2:3] vecinos = game.neightbours_of_position(int(i), int(j)) listOpt = [0, 1] #Se realizan las combinaciones resA = list(product(listOpt, repeat=len(vecinos))) #Se suman los unos de cada una de las combinaciones, es decir, se suman el número de bombas def counterPermutations(lsa): count = 0 for f in range(len(lsa)): if lsa[f] is 1: count = count + 1 return count #Generamos tantas listas como Y necesitamos + 1 (incluyendo la inexistencia de bomba) probabilidades_unidas = [] for v in range(len(vecinos) + 1): probabilidades_calculadas = [] for a in range(len(resA)): lsta = resA[a] counter = counterPermutations(lsta) if counter is v: probabilidades_calculadas.append(1) else: probabilidades_calculadas.append(0) probabilidades_unidas.append(probabilidades_calculadas) #Generamos la CPD cpd_letrasY = "cpd_letras" + (resY[l]) cpd_letrasY = pgmf.TabularCPD(resY[l], len(vecinos) + 1, probabilidades_unidas, vecinos, [2] * len(vecinos)) Modelo_msgame.add_cpds(cpd_letrasY) return Modelo_msgame
def generate_DAG(height, width): n = height m = width modelo_buscaminas = pgmm.BayesianModel() for i in range(1,n+1): for j in range(1,m+1): if i==1: if j==1: # El vértice Y11 siempre tiene los mismos # vecinos: X21, X22 y X12 modelo_buscaminas.add_edges_from([('X21', 'Y11'), ('X22', 'Y11'), ('X12', 'Y11')]) elif j==m: # El vértice Y1,m posee siempre los mismos # vecinos: X1,m-1 y X2,m y X2,m-1: modelo_buscaminas.add_edges_from([('X1'+str(m-1), 'Y1'+str(m)), ('X2'+str(m), 'Y1'+str(m)), ('X2'+str(m-1), 'Y1'+str(m))]) else: # Se añaden las aristas correspondientes a # los vértices Y1,j donde se cumple que 1<j<m modelo_buscaminas.add_edges_from([('X'+str(i)+str(j-1), 'Y1'+str(j)), ('X'+str(i)+str(j+1), 'Y1'+str(j)), ('X'+str(i+1)+str(j-1), 'Y1'+str(j)), ('X'+str(i+1)+str(j), 'Y1'+str(j)), ('X'+str(i+1)+str(j+1), 'Y1'+str(j))]) elif i==n: if j==1: # El vértice Yn,1 posee 3 vecinos que son: # Xn,2, Xn-1,1 y Xn-1,2: modelo_buscaminas.add_edges_from([('X'+str(n)+str(2), 'Y'+str(n)+str(1)), ('X'+str(n-1)+str(1), 'Y'+str(n)+str(1)), ('X'+str(n-1)+str(2), 'Y'+str(n)+str(1))]) elif j==m: # El vértice Yn,m posee como vecinos los # siguientes vértices: Xn,m-1, Xn-1,m y Xn-1,m-1 modelo_buscaminas.add_edges_from([('X'+str(n)+str(m-1), 'Y'+str(n)+str(m)), ('X'+str(n-1)+str(m), 'Y'+str(n)+str(m)), ('X'+str(n-1)+str(m-1), 'Y'+str(n)+str(m))]) else: # Los vecinos de los vértices Yn,j en los que # 1<j<m son: Xn,j-1, Xn,j+1, Xn-1,j-1, Xn-1,j y Xn-1,j+1 modelo_buscaminas.add_edges_from([('X'+str(n)+str(j-1), 'Y'+str(n)+str(j)), ('X'+str(n)+str(j+1), 'Y'+str(n)+str(j)), ('X'+str(n-1)+str(j-1), 'Y'+str(n)+str(j)), ('X'+str(n-1)+str(j), 'Y'+str(n)+str(j)), ('X'+str(n-1)+str(j+1), 'Y'+str(n)+str(j))]) else: # En esta rama, añadiremos las aristas de # aquellos vértices Yi,j siendo 1<i<m. if j==1: # Subrama 1: se añaden las aristas para los # vértices Yi,1 y sus correspondientes vecinos modelo_buscaminas.add_edges_from([('X'+str(i)+str(2), 'Y'+str(i)+str(1)), ('X'+str(i+1)+str(1), 'Y'+str(i)+str(1)), ('X'+str(i+1)+str(2), 'Y'+str(i)+str(1)), ('X'+str(i-1)+str(1), 'Y'+str(i)+str(1)), ('X'+str(i-1)+str(2), 'Y'+str(i)+str(1))]) elif j==m: # Subrama 2: se añaden las aristas para los # vértices Yi,m y sus correspondientes vecinos modelo_buscaminas.add_edges_from([('X'+str(i)+str(m-1), 'Y'+str(i)+str(m)), ('X'+str(i+1)+str(m), 'Y'+str(i)+str(m)), ('X'+str(i+1)+str(m-1), 'Y'+str(i)+str(m)), ('X'+str(i-1)+str(m), 'Y'+str(i)+str(m)), ('X'+str(i-1)+str(m-1), 'Y'+str(i)+str(m))]) else: # Subrama 3: se añaden las aristas para los # vértices Yi,j donde 1<j<m y sus correspondientes vecinos modelo_buscaminas.add_edges_from([('X'+str(i)+str(j+1), 'Y'+str(i)+str(j)), ('X'+str(i)+str(j-1), 'Y'+str(i)+str(j)), ('X'+str(i+1)+str(j-1), 'Y'+str(i)+str(j)), ('X'+str(i+1)+str(j), 'Y'+str(i)+str(j)), ('X'+str(i+1)+str(j+1), 'Y'+str(i)+str(j)), ('X'+str(i-1)+str(j-1), 'Y'+str(i)+str(j)), ('X'+str(i-1)+str(j), 'Y'+str(i)+str(j)), ('X'+str(i-1)+str(j+1), 'Y'+str(i)+str(j))]) return modelo_buscaminas
print("\n--------------------------------------------------------\n") print("Aristas:\n") ''' Guardamos las aristas ''' for edge in XML.get_edges(): edges.append(edge) print(edges) print("\n========================================================\n") print("Impresion del Modelo Bayesiano\n") ''' Creamos el modelo ''' Modelo = pgmn.BayesianModel() Modelo.add_nodes_from(variables) Modelo.add_edges_from(edges) print("Variables o nodos:") print(Modelo.nodes()) print("\n") print("Aristas:") print(Modelo.edges()) print("\n") ''' Metemos los tabular_cpds al modelo, que luego nos serviran para sacar las tablas de propiedades ''' for variable, valores in XML.variable_CPD.items(): cpd = pgmf.TabularCPD( variable,