Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| 전산물리학:열풀림_시늉 [2025/07/03 16:33] – created admin | 전산물리학:열풀림_시늉 [2026/01/09 15:18] (current) – admin | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ======최대 절단(max-cut) 문제====== | ||
| + | 모든 노드가 한쪽에 몰려 있는 상황에서 시작해보자. 즉 모든 노드 $k$에 대해 side[k]=+1이다. 이때 목적함수의 값은 obj=0에서 출발한다. 노드 사이의 실선은 +1의 가중치, 점선은 -1의 가중치를 의미한다. | ||
| + | |||
| + | {{: | ||
| + | |||
| + | 노드 하나를 무작위로 골라서 반대편으로 보낸다. $k=3$가 선택되었다고 하자. | ||
| + | |||
| + | {{: | ||
| + | |||
| + | side[k]=-1이 되고, 목적함수의 값은 obj=1로 변할 것이다. 그런데 이것은 원래 $k=3$이 가지고 있었던 링크들의 가중치를 모두 더한 것에 불과하다. | ||
| + | 따라서 애초에 chg[1]=1+1=2, | ||
| + | |||
| + | 위에서처럼 이미 $k=3$이 옮겨진 상황에서, | ||
| + | $k=1$이 선택된다면? | ||
| + | |||
| + | {{: | ||
| + | |||
| + | 그림처럼 다시금 obj=1이므로, | ||
| + | |||
| + | 이제 $k=1$을 옮겼으므로 방금 우리가 추측한 것처럼 $k=1$이 넘어간 그 순간에 chg의 값들을 갱신해보도록 하자. chg[1]이 -chg[1]으로 주어져 0임은 자명하다. $k=1$은 2와 3에 연결되어 있고 둘 모두 +1의 가중치로 연결되어 있다. 그러면 chg[2] += (-2)*1로서 chg[2]=-1이 된다. 이 값은 옳다. chg[3]도 chg[3] += (-2)*1로서 -3이 될까? 그렇지 않다. 옳은 값은 chg[3] += 2*1로서 chg[3]이 +1이 되는 것이다. 왜냐하면 노드 1과 3이 같은 편에 있게 되므로 1이 다시 왼쪽으로 넘어간다면 둘 사이의 가중치는 +의 역할을 하는 것이다. 따라서 옳은 규칙은 다음과 같다. | ||
| + | |||
| + | * 반대쪽으로 옮길 노드 $k$를 고른다. | ||
| + | * $k$에 연결된 노드 $v$들을 찾는다. | ||
| + | * $v$와 $k$가 원래 같은 쪽에 있다가 헤어지는 것이라면 둘 사이의 연결의 가중치 $w$를 찾아서 chg[v] += (-2)*w로 갱신한다. | ||
| + | * 그렇지 않고 다른 쪽에 있다가 만나는 것이라면 chg[v] += 2*w로 갱신한다. | ||
| + | |||
| + | {{: | ||
| + | |||
| + | 그림처럼 $k=3$을 골라서 다시 왼쪽으로 보냈다고 하고 (obj=2) 위의 규칙대로 chg의 값들을 갱신해보자. chg[3]은 부호만 뒤집으면 되므로 chg[3]=-1이다. chg[1]+=(-2)*1로서 chg[1]=-2가 된다. chg[2]+=2*(-1)로서 chg[2]=-3이 된다. 마지막으로, | ||
| + | |||
| + | 위 규칙을 코드로 구현하고 열풀림 시늉으로 풀어본 결과는 아래와 같다. | ||
| + | |||
| + | < | ||
| + | from numpy import zeros, array, ones | ||
| + | from numpy.random import randint, uniform | ||
| + | from math import exp | ||
| + | n = G.number_of_nodes() | ||
| + | m = G.number_of_edges() | ||
| + | chg = zeros(n, int) | ||
| + | |||
| + | for a, b, data in G.edges(data=True): | ||
| + | u = int(a)-1 | ||
| + | v = int(b)-1 | ||
| + | w = int(data.get(' | ||
| + | chg[u] += w | ||
| + | chg[v] += w | ||
| + | side = ones(n, int) | ||
| + | obj = 0 | ||
| + | best = 0 | ||
| + | beta = 0.0 | ||
| + | betamax = 10 | ||
| + | dbeta = 10**(-5) | ||
| + | blist = [] | ||
| + | while beta< | ||
| + | k = randint(n) | ||
| + | if chg[k]> | ||
| + | obj += chg[k] | ||
| + | side[k] *= -1 | ||
| + | chg[k] *= -1 | ||
| + | for origin, destination, | ||
| + | u = int(origin) - 1 | ||
| + | v = int(destination) - 1 | ||
| + | vw = int(data.get(' | ||
| + | chg[v] += vw * (2 - 4 *(side[k] != side[v])) | ||
| + | if obj > best: | ||
| + | for i in range(n): | ||
| + | best = obj | ||
| + | beta += dbeta | ||
| + | blist.append(best) | ||
| + | plt.plot(blist) | ||
| + | plt.show() | ||
| + | print(side) | ||
| + | print(best) | ||
| + | </ | ||
| + | |||
| ======참고문헌====== | ======참고문헌====== | ||
| - | * Spears, William M. //Simulated annealing for hard satisfiability problems//, Cliques, Coloring, and Satisfiability **26** (1993): 533-558. | + | * [[https:// |
| - | * Myklebust, Tor GJ. "Solving maximum cut problems by simulated annealing." arXiv preprint arXiv: | + | * [[https:// |
| * https:// | * https:// | ||
| * https:// | * https:// | ||
| + | * Aarts and Korst, Simulated Annealing and Boltzmann Machines (Wiley, Chichester, 1989). | ||