2013-04-09 2 views
6

큰 그래프의 각 점에 대해 시작 노드에서 거리 n에있는 방문하지 않은 노드의 수를 포함하는 목록을 만들려고합니다. 예시적인 출력은 3 새로운 (비경) 노드가 거리 0으로 시작 노드 자체가 거리 1에서 존재한다는 것을 의미한다 [1,3,6] 은이 상당히그래프의 모든 노드에 대해 거리 n의 방문한 노드를 계산합니다.

하나만 시작점있는 경우 등등 쉽다 : 폭 넓은 우선 순위 검색의 상단에 쉘 카운터를 추가하면된다. 그래프에서 모든 노드에 대해이 작업을 수행해야 할 때 문제가 발생합니다. 내 그래프가 크기 때문에 (> 100000 노드), 모든 점에 대해 위의 루틴을 수행하는 것이 다소 느립니다.

내가 처음으로 최적화하려는 시도는 노드 a의 목록이 a의 모든 이웃 목록으로 구성 될 수 있는지 확인하는 것이었지만 지금까지는 그래프의주기 때문에 운이 없었습니다. 여러분 중 일부는 멋진 아이디어를 가지고있을 수도 있고 캐시 할 수있는 몇 가지 추가 정보가 필요할 수도 있습니다.

내 질문 : 모든 노드에 대해 노드에 대해 수행해야한다는 것을 알고 있다면 그러한 검색을 최적화하는 방법이 있습니까?

+0

에서 [모든 최단 경로 문제 (http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm)는 거리 계산에 의해 그룹화 한 후 무엇을 추구 기본적으로, 당신은 아마 수 O (| V |^3)보다 훨씬 훌륭합니다. – Nuclearman

+0

내 우선 순위 검색은 O (| E |)이며, 이는 내 경우에 O (| V |)와 같습니다. 모든 노드에서이 작업을 수행해야하므로 현재의 복잡성은 O (| V | ²)입니다. 지금 병렬 처리를 사용하여 프로세스 속도를 높이고 있지만 다른 제안 사항을 환영합니다! –

+0

여전히 최악의 경우 O (| V |^3) 인 O (| V | * | E |) 여야합니다. 그러나, | V | | E |에 가까우면, 최단 경로를 나열해야하는 O (| V |^2) 개의 가능한 정점 조합이 있다는 것을 고려하면 할 수있는 것보다 많지는 않습니다. 비록 대부분의 정점이 차수가 2 이하일 경우, 가장 긴 경로 (또는 충분히 긴 경로)를 간단하게 나열하고 이들 중에서 가장 짧은 경로를 추출하는 것이 현실적 일 수 있습니다. – Nuclearman

답변

0

O(n*|V|^2) 미만의 솔루션이있을 것 같지 않으므로 여기서는 파이썬에서 너무 끔찍한 방법이 있습니다.

# some basic topologies 
def lineE(N): 
    return(set((i,i+1) for i in range(N-1))) 

def ringE(N): 
    return(lineE(N).union([(0,N-1)])) 

def fullE(N): 
    return(set([(i,j) for i in range(N) for j in range(i)])) 

# propagate visitors from x to y 
def propagate(V, curr, x, y, d): 
    nexty = set() 
    for cx in curr[x]: 
    if not cx in V[y]["seen"]: 
     V[y]["seen"].add(cx) 
     V[y]["foaf"][d] = V[y]["foaf"].get(d,0) + 1 
     nexty.add(cx) 
    return(nexty) 

# run for D iterations 
def mingle(N, E, D): 
    V = dict((i, {"seen":set([i]), "foaf":{0:1}}) for i in range(N)) 
    curr = dict((i, set([i])) for i in range(N)) 
    for d in range(1, min(D+1, N)): 
    next = dict((i, set()) for i in range(N)) 
    for (h, t) in E: 
     next[t] = next[t].union(propagate(V, curr, h, t, d)) 
     next[h] = next[h].union(propagate(V, curr, t, h, d)) 
    curr = next 
    return(V) 

것은, 10 개 노드와 거리 3 그것을 밖으로 시도

N=10 
D=3 
for (topology, E) in [("line", lineE(N)), ("ring", ringE(N)), ("full", fullE(N))]: 
    V = mingle(N, E, D) 
    print "\n", topology 
    for v in V: 
    print v, V[v]["foaf"] 

우리는 올바른 것

line 
0 {0: 1, 1: 1, 2: 1, 3: 1} 
1 {0: 1, 1: 2, 2: 1, 3: 1} 
2 {0: 1, 1: 2, 2: 2, 3: 1} 
3 {0: 1, 1: 2, 2: 2, 3: 2} 
4 {0: 1, 1: 2, 2: 2, 3: 2} 
5 {0: 1, 1: 2, 2: 2, 3: 2} 
6 {0: 1, 1: 2, 2: 2, 3: 2} 
7 {0: 1, 1: 2, 2: 2, 3: 1} 
8 {0: 1, 1: 2, 2: 1, 3: 1} 
9 {0: 1, 1: 1, 2: 1, 3: 1} 

ring 
0 {0: 1, 1: 2, 2: 2, 3: 2} 
1 {0: 1, 1: 2, 2: 2, 3: 2} 
2 {0: 1, 1: 2, 2: 2, 3: 2} 
3 {0: 1, 1: 2, 2: 2, 3: 2} 
4 {0: 1, 1: 2, 2: 2, 3: 2} 
5 {0: 1, 1: 2, 2: 2, 3: 2} 
6 {0: 1, 1: 2, 2: 2, 3: 2} 
7 {0: 1, 1: 2, 2: 2, 3: 2} 
8 {0: 1, 1: 2, 2: 2, 3: 2} 
9 {0: 1, 1: 2, 2: 2, 3: 2} 

full 
0 {0: 1, 1: 9} 
1 {0: 1, 1: 9} 
2 {0: 1, 1: 9} 
3 {0: 1, 1: 9} 
4 {0: 1, 1: 9} 
5 {0: 1, 1: 9} 
6 {0: 1, 1: 9} 
7 {0: 1, 1: 9} 
8 {0: 1, 1: 9} 
9 {0: 1, 1: 9} 

를 얻을. 또한 100000 노드의 거리 100에 대한 간단한 토폴로지 실행은 노트북에서 약 1 분 정도 소요됩니다. 물론 밀도가 높은 그래프 (예 : fullE)가 있으면이 그래프가 폭발합니다.

N=100000 
D=100 
for (topology, E) in [("line", lineE(N)), ("ring", ringE(N))]: 
    V = mingle(N, E, D) 
관련 문제