0

저는 인기있는 케빈 베이컨 게임에 대한 그래프 표현을 만들려고했습니다. 그래프와 버텍스 클래스를 만들었지 만 그래프를 가로 지르는 첫 번째 검색 방법을 만들고 케빈 베이컨에서 배우까지의 최단 경로를 찾아 문제의 가장자리를 인쇄하는 데 어려움을 겪고 있습니다. 사용자는 배우를 입력해야하며, 프로그램은 케빈 베이컨에서 해당 배우까지의 최단 경로를 찾아야합니다. 사용자는 계속해서 액터에 들어가고 그 액터에 대한 최단 경로를 취하게되고 케빈 베이컨 번호가 출력됩니다. 그렇지 않으면 아무 것도 출력하지 않습니다.케빈 베이컨 게임에 대한 최단 경로 그래프 탐색

버텍스 및 그래프 클래스가 있습니다. 정점 클래스는 연결된 다른 정점과 모서리를 포함하는 사전입니다.

이 같은 외모와 협력하고 데이터 :

정점 :

[ "케빈 베이컨", "actor1", "actor2", "actor3", "actor4", "actor5" "actor6"]

가장자리 :

("케빈 베이컨", "actor1", "극장 1")

("케빈 베이컨", "actor2", "극장 1")

("actor1", "actor2", "극장 1")

("actor1", "actor3", "movie2")

("actor3", "actor2", "movie3")

("actor3", "actor4", "movie4")

("actor5", "actor6", "movie5") 영화가 가장자리 이름 또는 무게가

하고, 튜플의 다른 부분은 정점입니다. BFS 알고리즘을 사용하여 모든 가장자리와 케빈 베이컨 수를 인쇄하거나 액터에 도달 할 수없는 경우 인쇄 할 수 없도록 인쇄합니다.

여기까지 코드가 있습니다. 모든 조언과 도움을 주시면 감사하겠습니다.

class Vertex: 
    ''' 
    keep track of the vertices to which it is connected, and the weight of each edge 
    ''' 
    def __init__(self, key): 
     ''' 

     ''' 
     self.ID = key 
     self.connected_to = {} 

    def add_neighbor(self, neighbor, weight=0): 
     ''' 
     add a connection from this vertex to anothe 
     ''' 
     self.connected_to[neighbor] = weight 

    def __str__(self): 
     ''' 
     returns all of the vertices in the adjacency list, as represented by the connectedTo instance variable 
     ''' 
     return str(self.ID) + ' connected to: ' + str([x.ID for x in self.connected_to]) 

    def get_connections(self): 
     ''' 
     returns all of the connections for each of the keys 
     ''' 
     return self.connected_to.keys() 

    def get_ID(self): 
     ''' 
     returns the current key id 
     ''' 
     return self.ID 

    def get_weight(self, neighbor): 
     ''' 
     returns the weight of the edge from this vertex to the vertex passed as a parameter 
     ''' 
     return self.connected_to[neighbor] 


class Graph: 
    ''' 
    contains a dictionary that maps vertex names to vertex objects. 
    ''' 
    def __init__(self): 
     ''' 

     ''' 
     self.vert_list = {} 
     self.num_vertices = 0 

    def __str__(self): 
     ''' 

     ''' 
     edges = "" 
     for vert in self.vert_list.values(): 
      for vert2 in vert.get_connections(): 
       edges += "(%s, %s)\n" %(vert.get_ID(), vert2.get_ID()) 
     return edges 

    def add_vertex(self, key): 
     ''' 
     adding vertices to a graph 
     ''' 
     self.num_vertices = self.num_vertices + 1 
     new_vertex = Vertex(key) 
     self.vert_list[key] = new_vertex 
     return new_vertex 

    def get_vertex(self, n): 
     ''' 

     ''' 
     if n in self.vert_list: 
      return self.vert_list[n] 
     else: 
      return None 

    def __contains__(self, n): 
     ''' 
     in operator 
     ''' 
     return n in self.vert_list 

    def add_edge(self, f, t, cost=0): 
     ''' 
     connecting one vertex to another 
     ''' 
     if f not in self.vert_list: 
      nv = self.add_vertex(f) 
     if t not in self.vert_list: 
      nv = self.add_vertex(t) 
     self.vert_list[f].add_neighbor(self.vert_list[t], cost) 

    def get_vertices(self): 
     ''' 
     returns the names of all of the vertices in the graph 
     ''' 
     return self.vert_list.keys() 

    def __iter__(self): 
     ''' 
     for functionality 
     ''' 
     return iter(self.vert_list.values()) 

    def bfs(self): 
     ''' 
     Needs to be implemented 
     ''' 
     pass 

답변

1
  1. 는 배우 케빈 베이컨
  2. 경우 배우 케빈 베이컨의 경우, 배우에게
  3. 확인을 받기는
  4. 했다 경로를 따라 돌아갈 시간 내 주셔서 감사
  5. 배우가 Kevin Bacon이 아닌 경우 아직 확인하지 않은이 배우와 연결된 모든 배우를 찾습니다.
  6. 이 액터가 연결되어있는 모든 액터를 목록에 추가하여 확인하십시오.

가장 어려운 문제는 이미 방문한 정점을 기록하는 것입니다. 따라서 귀하의 알고리즘이 꼭지점 목록을 확인해야한다고 생각합니다. 일부 가정 :

  • 각 정점은 한 번만 표시됩니다.
  • 정점은 단방향입니다. 즉, 액터 1에서 액터 2로, 액터 2에서 액터 1로 이동하려면 각 액터마다 하나씩 두 개의 정점이 필요합니다.
  • 당신은 체중이 있지만 어떻게 관련이 있는지 알 수 없습니다. 나는 그들을 구현하려고합니다. 또한 기본 가중치는 0이 아니어야하거나 모든 경로가 똑같이 짧을 것입니다 (0 * n = 0).

확인 허용.

def bfs(self, actor): 
    from heapq import heappush, heappop 
    if actor == "Kevin Bacon": 
     return print("This actor is Kevin Bacon!") 
    visited = set() 
    checked = [] 
    n = 0 
    heappush(checked, (0, n, [self.get_vertex(actor)])) 
    # if the list is empty we haven't been able to find any path 
    while checked: 
     # note that we pop our current list out of the list of checked lists, 
     # if all of the children of this list have been visited it won't be 
     # added again 
     current_list = heappop(checked)[2] 
     current_vertex = current_list[-1] 
     if current_vertex.ID == "Kevin Bacon": 
      return print(current_list) 
     for child in current_vertex.get_connections(): 
      if child in visited: 
       # we've already found a shorter path to this actor 
       # don't add this path into the list 
       continue 
      n += 1 
      # make a hash function for the vertexes, probably just 
      # the hash of the ID is enough, ptherwise the memory address 
      # is used and identical vertices can be visited multiple times 
      visited.add(child) 
      w = sum(current_list[i].get_weight(current_list[i+1]) 
        for i in range(len(current_list)-1)) 
      heappush(checked, (w, n, current_list + [child])) 
    print("no path found!") 

또한 정점 클래스에 __repr __() 메서드를 구현해야합니다. 내가 사용하는 하나의 출력은 다음과 같습니다

g = Graph() 
for t in [("Kevin Bacon", "actor1", "movie1") 
,("Kevin Bacon", "actor2", "movie1") 
,("actor1", "actor2", "movie1") 
,("actor1", "actor3", "movie2") 
,("actor3", "actor2", "movie3") 
,("actor3", "actor4", "movie4") 
,("actor5", "actor6", "movie5")]: 
    g.add_edge(t[0],t[1],cost=1) 
    g.add_edge(t[1],t[0],cost=1) 

g.bfs("actor4") 
# prints [Vertex(actor4), Vertex(actor3), Vertex(actor2), Vertex(Kevin Bacon)] 

내가 원래 이렇게 heapq를 사용하려고했지만 결국 나뿐만 아니라 수도 결정되지 않았습니다. 본질적으로 가장 짧은 경로를 먼저 얻으려면 검사 목록을 정렬해야합니다. 가장 간단한 방법은 상단에서 가장 작은 값을 팝업 할 때마다 목록을 정렬하는 것입니다. 그러나 목록이 커지면 매우 느려질 수 있습니다. Heapq은리스트를보다 효율적인 방법으로 정렬 할 수 있지만, 우리가 추가하는리스트의 가장 작은 값을 얻기위한 핵심적인 방법이 없기 때문에 튜플을 사용하여 위조 할 필요가있다. 튜플의 첫 번째 값은 경로의 실제 비용입니다. 두 번째 값은 단순히 "타이 브레이커"이므로 Vertexes를 비교하려고하지는 않습니다 (순서가 지정되지 않았으므로 그렇게하려고하면 예외가 발생합니다).).

관련 문제