1. 최단경로와 행렬곱 ( Shortest Paths and Matrix Multiplication )

이번에는ASP의 첫 번째 알고리즘 최단경로와 행렬곱 알고리즘에 대해 알아보겠습니다.

최단경로와 행렬곱 알고리즘은 ASP를 행렬곱을 이용해서 구하는 것입니다.

실제로 행렬곱을 이용하지는 않고 행렬 곱셈의 연산방식을 따를 뿐입니다.

( 수식이 많아도 어렵지 않으니 천천히 읽어봐주세요 ! )

ASP를 구현할 때 인접행렬을 이용한다고 했죠?

위의 그림과 같이 두 개의 인접행렬이 있을 때 빨간 네모 부분(2행과 4열)을 곱하면 의 원소가 될 것입니다.


원래대로 행렬의 곱셈을 하면 아래의 식과 같습니다.


그런데 최단경로와 행렬곱 알고리즘은 행렬 곱셉 방식을 따를 뿐 실제로 행렬 곱셈연산을 하지는 않습니다.

최단경로와 행렬곱 알고리즘 방식으로 다시 식을 작성해보겠습니다.

따라서 의 값은 0이므로 v2 -> v4의 최단 경로의 비용은 0입니다.





2. 최단경로와 행렬곱의 동적 계획법 - 재귀적 해법

동적계획법의 재귀적 해법으로 표현해보겠습니다.

( 최단경로와 행렬곱 알고리즘은 동적 계획법을 사용합니다. )


: 정점 i에서 j까지의 최대 m개의 간선을 갖는 모든 경로의 최소 가중치 라고 정의하겠습니다.


예를 들어( i=3, j=2, m=2) 의 의미는 v3에서 v2까지 최대 2개의 간선을 갖는 모든 경로 중 가중치가 가장 작은 것을 의미합니다.

최대 2개라고 했으므로 1개의 간선 또는 2개의 간선을 거쳐갈 경우를 생각해 볼 수 있네요.


1) 1개의 간선을 거쳐갈 경우 (직접 연결될 경우)

v3 -> v2로 직접 연결된 간선이 있고, 이 때의 가중치는 4입니다.


2) 2개의 간선을 거쳐갈 경우

v3 -> ? -> v2 에 해당하는 간선이 존재하지 않습니다.

따라서 의 값은 4입니다.



이제 이를 좀 더 수학적으로 표현해보겠습니다.

식이 어려워 보일 수 있는데 처음에 봤던 행렬 곱셈 방식을 식으로 정리한 것 뿐입니다.


는 인접행렬 의 이전 단계를 의미합니다.

는 k가 1부터 n( 정점의 개수 )까지에 대해서 인접행렬 (가중치 인접행렬) 의 행렬곱 방식을 수행한 것입니다.

위의 두 식을 계산한 후 최소 값이 이 됩니다.


방금 위의 예제에서 ( i=3, j=2, m=2)을 구할 때를 생각해볼게요.

맨 처음 행렬 곱 방식을 했던 것과 완전히 같습니다.


최단경로와 행렬곱 알고리즘은 이러한 원리로 구현됩니다.

지금까지 봤던 알고리즘에 비해서 꽤 복잡해보입니다.

그 이유는 식을 주저리 주저리 써놓아서 그런 것 뿐이지, 과정을 보시면 그리 어렵지는 않을 것입니다.





3. 최단경로와 행렬곱 알고리즘

그래프가 주어졌을 때 이를 인접행렬로 표현하면 위와 같습니다.





그리고 인접행렬 는 위의 관계를 따릅니다.

즉 이며, 정점의 개수가 5개이므로 를 구하는 것이 목표입니다.

( m은 최대 간선의 개수를 의미하므로 정점의 개수를 넘지 못합니다.)

이제 앞에서 살펴봤던 재귀적 해법을 이용하여 까지 구해보겠습니다.





를 구하면 다음과 같습니다.

i , j 를 정해놓고 k를 움직이면서 위의 식에 대입하면 결과를 얻을 수 있습니다.






행렬의 곱셈 연산의 방식을 이용하고 재귀적 해법의 식에 적절히 i , j , m , k 값을 대입하면 어렵지 않게 구할 수 있습니다.





4. 수도코드


1) SLOW-ALL-PAIRS-SHORTEST-PATHS 함수

line 3 ~ 5

m은 2부터 최대 n-1까지 Bottom-up(상향식) 방식으로 인접행렬 을 구합니다.

예를들어 정점의 개수가 5라면 까지 구하고 종료될 것입니다.



2) EXTEND-SHORTEST-PATHS 함수

line 3 ~ 7

변수 i , j는 각각 행과 열을 의미합니다.

그리고 변수 k는 1부터 n까지 움직이는 값으로써 재귀적 해법의 식을 수행합니다.




3) 시간복잡도

SLOW-ALL-PAIRS-SHORTEST-PATHS 함수에서 EXTEND-SHORTEST-PATHS 함수를 호출했습니다.

따라서 총 4번의 중첩 for문이 발생했으므로 시간 복잡도는 이 됩니다.



그런데 ASP를 소개할 때 Bellman-Ford 알고리즘과 Dijkstra's 알고리즘의 성능이 좋지 않아서 ASP를 구현한다고 했는데, 최단경로와 행렬곱 알고리즘은 성능이 그닥 좋지 못합니다.

그래서 이를 좀 더 개선한 방법이 있습니다.


이 글에서는 왼쪽의 방식으로 최단경로와 행렬곱 알고리즘을 소개했습니다.

그런데 이 구현을 오른쪽과 같이 수정하면 시간 복잡도를 만큼 줄일 수 있습니다.

왜냐하면, 의 크기로 증가하기 때문입니다.

이에 대한 수도코드는 아래와 같습니다.





이상으로 최단경로와 행렬곱 알고리즘에 대해 알아보았습니다.

수식이 많아서 글이 많이 어지럽네요.

사실 동작 과정과 구현은 그리 어렵지 않은데 말이죠...