minAresta = None k = k - 1 if caminho == []: break return caminhos if __name__ == '__main__': g = Grafo() g.addVertice('a') g.addVertice('b') g.addVertice('c') g.addVertice('d') g.addVertice('e') g.addVertice('f') g.addAresta('a', 'b', 1) g.addAresta('a', 'c', 1) g.addAresta('a', 'f', 1) g.addAresta('b', 'c', 1) g.addAresta('b', 'd', 1) g.addAresta('c', 'd', 1) g.addAresta('c', 'f', 1) g.addAresta('d', 'e', 1) g.addAresta('e', 'f', 1) for path in kpaths(g, 'a', 'f', 7): print path
class DesenhaGrafo(): """ Representa a interação entre a camada de interface (GUI) e a estrutura Grafo. """ def __init__(self, canvas, callback): self.grafo = Grafo() self.canvas = canvas self.vertices = [] #coordenadas dos vértices self.arestas = [] #coordenadas das arestas self.selecionados = set() self.selecionadas = [] #TODO: mudar esse nome. Usada para arestas. self.attCallback(callback) self.desenhaGrafo() def attCallback(self, func): """Recebe a funcao opcoes(peso, label) para chamada nessa classe""" self.callback = func def getVerticePos(self, vertice): """Retorna as coordenadas do vertice do grafo""" return self.vertices[vertice] def setVerticePos(self, vertice, coordenadas): """Seta as coordenadas do vertice do grafo""" self.vertices[vertice] = coordenadas self.canvas.move('vertice', *coordenadas) self.canvas.update() def colideVerticeAresta(self, coord, raio, checaVertice = True): """Checa colisao entre o vertice(passado como parametro por meio das coordenadas e raio), os demais vertices e as arestas""" xca, yca, xcb, ycb = coord[0]-raio, coord[1]-raio, coord[0]+raio, coord[1]+raio if checaVertice: for x,y in self.vertices: xa, ya, xb, yb = x-raio, y-raio, x+raio, y+raio if xa <= xca <= xb and ya <= yca <= yb: return (True,True) elif xa <= xcb <= xb and ya <= ycb <= yb: return (True,True) elif xa <= xcb <= xb and ya <= yca <= yb: return (True,True) elif xa <= xca <= xb and ya <= ycb <= yb: return (True,True) #as quatros retas represetam o quadrado que envolve o vertice retaA = Reta((xca,yca,xcb,yca)) retaB = Reta((xca,yca,xca,ycb)) retaC = Reta((xcb,yca,xcb,ycb)) retaD = Reta((xca,ycb,xcb,ycb)) ################################################################# for xra,yra,xrb,yrb,va,vb in self.arestas: #faz a checagem se houve algum cruzamento das retas retaX = Reta((xra,yra,xrb,yrb)) if retaX.checaInter(retaA) or retaX.checaInter(retaB) or retaX.checaInter(retaC) or retaX.checaInter(retaD): return (True,va,vb) return (False,False) def colidePontoVertice(self, coord, raio): """Checa se um ponto colide com algum vertice do grafo, ele retorna o vertice que colodiu""" for n in range(len(self.vertices)): x, y = self.vertices[n][0], self.vertices[n][1] xa, ya, xb, yb = x-raio, y-raio, x+raio, y+raio if xa < coord[0] < xb and ya < coord[1] < yb: return n return -1 def colidePontoAresta(self, coord, raio): """Checa se um ponto colide com alguma aresta do grafo""" for x,y in self.vertices: xca, yca, xcb, ycb = x-raio, y-raio, x+raio, y+raio retaA = Reta((xca,yca,xcb,yca)) retaB = Reta((xca,yca,xca,ycb)) retaC = Reta((xcb,yca,xcb,ycb)) retaD = Reta((xca,ycb,xcb,ycb)) retaX = Reta(coord) if retaX.checaInter(retaA) or retaX.checaInter(retaB) or retaX.checaInter(retaC) or retaX.checaInter(retaD): return True return False def desenhaVertice(self, coordenadas, label=None): """Cria um novo vertice e o printa na tela, caso nao colida com nenhum outro vertice ou uma aresta""" b = self.colideVerticeAresta(coordenadas, cfg.TAM_VERTICE) if not b[0]: self.grafo.addVertice(label) self.vertices.append(coordenadas) self.desenhaGrafo() else: print 'colidiu mah!!!' def apagaVertice(self, coordenadas): """Apaga o vertice que tem (x,y) = coordenadas, caso exista tal vertice""" nvertice = self.colidePontoVertice(coordenadas, cfg.TAM_VERTICE) if nvertice > -1: self.grafo.remVertice(nvertice) del self.vertices[nvertice] self.desenhaGrafo() else: print 'nao colidiu mah!!!' def apagaAresta(self,coordenadas): """Apaga a aresta caso ela contenha (x,y) = coordenadas""" x,y = coordenadas b = self.colideVerticeAresta(coordenadas, cfg.TAM_VERTICE-20, False) if b[0]: self.grafo.remAresta((b[1],b[2])) self.desenhaGrafo() def selecionaVertice(self, coordenadas,peso = -1, dir = 0, add = True): """Seleciona um vertice. Se ja houver um outro vertice selecionado e o modo aresta estiver ativo uma nova aresta é feita entre os vertices selecionados""" nvertice = self.colidePontoVertice(coordenadas, cfg.TAM_VERTICE) if nvertice > -1: if nvertice not in self.selecionados: if len(self.selecionados) > 0: if add == True: aux = self.selecionados.pop() self.grafo.addAresta((aux, nvertice),peso) if dir == 0: self.grafo.addAresta((nvertice, aux),peso) nvertice = -1 else: self.selecionados.add(nvertice) else: self.selecionados.remove(nvertice) nvertice = -1 self.desenhaGrafo() else: self.selecionados.clear() self.desenhaGrafo() print 'num selecionou ninguem!!!' return nvertice def moverTodos(self, posicao): """Move todo o grafo""" print posicao dx, dy = posicao for i, vertice in enumerate(self.vertices): self.vertices[i] = (vertice[0] + dx, vertice[1] + dy) print self.vertices self.desenhaGrafo() def buscaProfundidade(self, verticePos): """Chama o método de busca de pronfudidade do grafo e pisca os vertices passado por ele""" inicial = self.colidePontoVertice(verticePos, cfg.TAM_VERTICE) ordem = self.grafo.buscaProfundidade(inicial) self.animaGrafo(ordem,1.0) print ordem def buscaLargura(self, verticePos): """Chama o método de busca por largura do grafo e pisca os vertices passado por ele""" inicial = self.colidePontoVertice(verticePos, cfg.TAM_VERTICE) ordem = self.grafo.buscaLargura(inicial) self.animaGrafo(ordem,1.0) print ordem def agmPrim(self): """Chama a o metodo de prim do grafo e muda o cor das arestas da arvore geradora minima""" ordem = self.grafo.agmPrim() self.selecionadas.extend(ordem) self.desenhaGrafo() def agmKruskal(self): """Chama a o metodo de Kruskal do grafo e muda o cor das arestas da arvore geradora minima""" ordem = self.grafo.agmKruskal() print ordem self.selecionadas.extend(ordem) self.desenhaGrafo() def colorir(self): """Chama o metodo de coloracao do grafo e os colore na tela""" cores = self.grafo.colorir() self.coloreGrafo(cores) def _gerarCores(self, n): """Gera as coloracoe dos vertices""" print 'gerar', n, 'cores' lista = [] i = 0 repetir = False while i < n: repetir = False novacor = random.randint(0,255), random.randint(0,255), random.randint(0,255) print novacor for cor in lista: dif = abs(cor[0] - novacor[0]) + abs(cor[1] - novacor[1]) + abs(cor[2] - novacor[2]) print dif, if dif < 20: repetir = True break if not repetir: lista.append(novacor) i += 1 return lista def coloreGrafo(self, cores): """Faz a coloracao dos vertices""" ncores = max(cores) listaCores = self._gerarCores(ncores) for indice in range(len(self.vertices)): x, y = self.vertices[indice] self.circuloFull((x,y), cfg.TAM_VERTICE, str(indice), "#%02x%02x%02x" % listaCores[cores[indice]-1]) def circuloFull(self, centro, raio, tag, ccor = None): """Cria um novo circulo de outra cor por cima dos vertices""" x, y = centro cor = cfg.COR_VERTICE gamb = int(tag) #TODO: warning: gambiarra... if gamb in self.selecionados: cor = cfg.COR_SELECIONADA elif ccor is not None: cor = ccor self.canvas.create_oval(x-raio, y-raio, x+raio,y+raio, tag=tag, fill=cor,outline=cor, width=2) def minDijkstra(self,sour,dest): """Chama a o metodo de Dijkstra para menor caminho do grafo e muda o cor das arestas mostrando qual e esse caminho""" ordem = self.grafo.min_dijkstra(sour,dest) print ordem self.selecionadas.extend(ordem) self.desenhaGrafo() def minBellman(self,sour,dest): """Chama a o metodo de Bellman para menor caminho do grafo e muda o cor das arestas mostrando qual e esse caminho""" ordem = self.grafo.minBellman(sour,dest) print ordem self.selecionadas.extend(ordem) self.desenhaGrafo() #TODO: refatorar essa funcao. Muitos parametros. def circulo(self, centro, raio, tag, ccor = None): """Desenha um circulo na tela""" x, y = centro cor = cfg.COR_VERTICE gamb = int(tag) #TODO: warning: gambiarra... if gamb in self.selecionados: cor = cfg.COR_SELECIONADA elif ccor is not None: cor = ccor self.canvas.create_oval(x-raio, y-raio, x+raio,y+raio, tag=tag, outline=cor, width=2) def animaGrafo(self, lista, passo=cfg.ANM_PASSO): """Metódo que faz animacao nos metodos de busca""" self.selecionados.clear() self.desenhaGrafo() self.canvas.update() time.sleep(passo) back = -1 for indice in lista: if back >= 0: self.circulo(self.vertices[back], cfg.TAM_VERTICE, str(indice),ccor=cfg.COR_ANIMACAO2) self.canvas.create_text(self.vertices[back],text=str(back),fill=cfg.COR_TEXTO1) self.circulo(self.vertices[indice], cfg.TAM_VERTICE, str(indice),ccor=cfg.COR_ANIMACAO1) self.canvas.create_text(self.vertices[indice],text=str(indice),fill=cfg.COR_TEXTO1) back = indice self.canvas.update() time.sleep(passo) time.sleep(passo) self.desenhaGrafo() def tremerGrafo(self): """Faz a tela tremer de um modo nao muito bonito""" y=10 for x in range(1,20): self.canvas.move('all',x,y) self.canvas.update() time.sleep(0.1) self.canvas.move('all',-x,-y) self.canvas.update() y-=1 time.sleep(0.1) for x in range(20,1,-1): self.canvas.move('all',x,y) self.canvas.update() time.sleep(0.1) self.canvas.move('all',-x,-y) self.canvas.update() time.sleep(0.1) y+=1 def desenhaGrafo(self): """Faz todo o tratamento para reprintar todo o grafo na tela""" w,h = self.canvas["width"],self.canvas["height"] self.canvas.delete('all') self.canvas.create_rectangle(0, 0, w, h, fill=cfg.COR_TELA) self.arestas = [] #TODO: pensar se seria melhor fazer self.arestas[:] = [] raio = cfg.TAM_VERTICE peso, direcao, label = self.callback() for indice in range(len(self.vertices)): x, y = self.vertices[indice] self.circulo((x,y), cfg.TAM_VERTICE, str(indice)) if label == 0: self.canvas.create_text(self.vertices[indice],text=str(indice), tag = str(indice), activefill="#405252", fill=cfg.COR_TEXTO2) else: self.canvas.create_text(self.vertices[indice],text=self.grafo.labels[indice], tag = str(indice), activefill="#405252", fill=cfg.COR_TEXTO2) for va in range(len(self.grafo.matriz)): arestas = self.grafo.matriz[va] for vb, pesob in arestas: xa, ya = self.vertices[va] xb, yb = self.vertices[vb] #print pesob ang = math.atan2(xb-xa, yb-ya) ang2 = math.atan2(xa-xb, ya-yb) #print int(15*math.cos(ang)), int(15*math.sin(ang)) if peso == 1: self.canvas.create_text(((xb+xa)/2 + int(15*math.sin(ang+1.57)), (ya+yb)/2 + int(15*math.cos(ang+1.57))), text=str(pesob), tag = str(va)+'-'+str(vb), fill=cfg.COR_SELECIONADA) x, y = xa + raio * math.sin(ang), ya + raio * math.cos(ang) x2, y2 = xb + raio * math.sin(ang2), yb + raio * math.cos(ang2) cor = 'white' if (va, vb) in self.selecionadas or (vb, va) in self.selecionadas: cor = cfg.COR_ARESTA2 self.canvas.create_line(x,y,x2,y2, tag=str(va)+'-'+str(vb), fill=cor,width=2, arrow="last") self.arestas.append((x,y,x2,y2,va,vb)) self.selecionadas = [] def info(self): """Fornece informacoes sobre a estrutura.""" info = [] info.append(len(self.vertices)) for a,b in self.vertices: info.append(a) info.append(b) info.extend(self.grafo.info()) return info def carregar(self, info): """Carrega o grafo e desenha na tela""" indice, nvertices = 1, int(info[0]) while (indice < 2 * nvertices + 1): self.vertices.append((int(info[indice]), int(info[indice+1]))) indice += 2 self.grafo.carregar(info[2 * nvertices + 1:]) self.desenhaGrafo()
vertex = input() vertex = grafo.getVertice(vertex) print("\nVertice 2: ", end="") vertex2 = input() vertex2 = grafo.getVertice(vertex2) if (vertex != None and vertex2 != None): print("\nPeso da aresta: ", end="") try: peso = float(input()) vertex.peso = peso vertex2.peso = peso #Por nao ser um grafo direcionado, a aresta deve estar nos dois vertices na lista if (grafo.addAresta(vertex, vertex2.copy()) and grafo.addAresta(vertex2, vertex.copy())): print("Aresta adicionada!") except ValueError: print("Peso invalido!\n") else: print("Um dos vertices nao pertencem ao grafo!") input() elif (key == '3'): #Representacao matematica grafo.RepresentacaoMatematica() input() elif (key == '4'): #Visualizacao dos adjacentes de determinado vertice
g.addVertice("CA2") g.addVertice("UT") g.addVertice("CO") g.addVertice("NE") g.addVertice("IL") g.addVertice("TX") g.addVertice("GA") g.addVertice("PA") g.addVertice("MI") g.addVertice("NY") g.addVertice("DC") g.addVertice("NJ") if pesos: print "Usando grafo com pesos" g.addAresta("WA", "CA1", 9) g.addAresta("WA", "CA2", 5) g.addAresta("WA", "IL", 15) g.addAresta("CA1", "UT", 4) g.addAresta("CA1", "CA2", 2) g.addAresta("CA2", "TX", 7) g.addAresta("UT", "MI", 5) g.addAresta("UT", "CO", 6) g.addAresta("CO", "TX", 4) g.addAresta("CO", "NE", 4) g.addAresta("NE", "IL", 5) g.addAresta("IL", "PA", 7) g.addAresta("PA", "NY", 2) g.addAresta("PA", "GA", 8) g.addAresta("PA", "NJ", 2) g.addAresta("NY", "MI", 4)
else: grafo = '../grafos/grafo' + str(opc)+'.txt' with open(grafo, mode='r', encoding='utf-8') as arquivo: tipo = arquivo.readline()[:-1] numero_de_vertices = int(arquivo.readline()) g = Grafo(numero_de_vertices, tipo) for linha in arquivo: dados = linha.split() u = g.addVertice(str(dados[0])) v = g.addVertice(str(dados[1])) # bloco try se o grafo for ponderado try: peso = dados[2] except IndexError as error: peso = 1 g.addAresta(u, v, int(peso)) g.sort() while True: print('Como deseja representar o Grafo?') print('''[ 1 ] Lista de Adjacencias\n[ 2 ] Matriz de Adjacencias\n[ 3 ] Ir para os Algoritmos''') opc = int(input('Escolha uma Opção: ')) if opc == 1: g.lista_de_adjacencias() elif opc == 2: g.matriz_de_adjacencia() elif opc == 3: break else: print('ERRO, OPÇÃO INVALIDA') break