조합 최적화로 도로를 포장하십시오.
최단 시간에 도로를 포장하십시오.
당신은 마을 동사무소의 토목과 직원입니다.
사고방식
모든 변(도로)을 따라가는 폐로(일주해서 돌아오는 경로)를 구하는 문제를, 중국인 우편 배달 문제라고 합니다.
워셜 플로이드 방법을 이용하여 다항식 시간으로 계산할 수 있습니다만, 여기서는 조합 최적화 의 혼합 정수 최적화 문제라고 파악해 풀기로 합니다.
연결 그래프의 모든 점의 차수(점에 접속하고 있는 변의 수)가 짝수이면, 폐로가 존재하는 것이 알려져 있습니다. 차수가 홀수일 때는 같은 도로 위를 왕복하여 짝수가 되도록 하면 됩니다.
정책으로서는, 도로를 왕복할지 어떨지를 요구하기로 합니다.
(차수가 모두 짝수인 그래프의 폐로는 비교적 간단하게 구해지므로, 여기서는 생략합니다.)
공식화
최소화
$\sum_i{x_i}$
왕복하는 도로
변수
$x_i\in\{0, 1\} ~\forall i\in 도로$
왕복할지 여부
$y_j\ge 0,\in 정수 ~\forall j\in 점$
점 차수의 절반
제약
$\sum_{i\in 점 j에 연결된 변}{~~~~~~~~~~~~ x_i + 점 j의 차수} = 2 y_j\forall j\in 점$
차수가 짝수
(이 공식화는 그다지 좋지 않으므로 실제로는 다른 방법이 좋습니다.)
파이썬에서 실행
임의의 그래프를 만듭니다.
python3%matplotlib inline
import networkx as nx
from pulp import *
g = nx.random_graphs.fast_gnp_random_graph(8, 0.3, 11)
pos = nx.spring_layout(g)
nx.draw_networkx_nodes(g, pos=pos, node_size=600, node_color='w')
nx.draw_networkx_edges(g, pos=pos)
nx.draw_networkx_labels(g, pos=pos, font_size=20)
print([i for i, l in enumerate(g.adjacency_list()) if len(l)%2])
>>>
[0, 2, 3, 6]
점 0, 2, 3, 6의 차수가 홀수이므로, 이들 사이를 묶으면 좋은 것을 알 수 있습니다.
공식화하고 풀어 보겠습니다.
python3m = LpProblem()
xs, ys = [], []
for i, j in g.edges():
g.edge[i][j]['x'] = x = LpVariable('x%d_%d'%(i,j), cat=LpBinary)
xs.append(x)
m += lpSum(xs)
for i, ad in enumerate(g.adjacency_list()):
y = LpVariable(
'y%d'%i, cat=LpInteger)
m += lpSum(g.edge[i][j]['x'] for j in ad) + len(ad) == 2 * y
ys.append(y)
m.solve()
print([g.edges()[i] for i, x in enumerate(xs) if value(x)])
>>>
[(0, 2), (1, 3), (1, 6)]
가장 짧고 점 0, 2, 3, 6이 연결되어 있음을 알 수 있습니다.
이상
Reference
이 문제에 관하여(조합 최적화로 도로를 포장하십시오.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/SaitoTsutomu/items/480f057df56e93d964ba
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
최소화
$\sum_i{x_i}$
왕복하는 도로
변수
$x_i\in\{0, 1\} ~\forall i\in 도로$
왕복할지 여부
$y_j\ge 0,\in 정수 ~\forall j\in 점$
점 차수의 절반
제약
$\sum_{i\in 점 j에 연결된 변}{~~~~~~~~~~~~ x_i + 점 j의 차수} = 2 y_j\forall j\in 점$
차수가 짝수
(이 공식화는 그다지 좋지 않으므로 실제로는 다른 방법이 좋습니다.)
파이썬에서 실행
임의의 그래프를 만듭니다.
python3%matplotlib inline
import networkx as nx
from pulp import *
g = nx.random_graphs.fast_gnp_random_graph(8, 0.3, 11)
pos = nx.spring_layout(g)
nx.draw_networkx_nodes(g, pos=pos, node_size=600, node_color='w')
nx.draw_networkx_edges(g, pos=pos)
nx.draw_networkx_labels(g, pos=pos, font_size=20)
print([i for i, l in enumerate(g.adjacency_list()) if len(l)%2])
>>>
[0, 2, 3, 6]
점 0, 2, 3, 6의 차수가 홀수이므로, 이들 사이를 묶으면 좋은 것을 알 수 있습니다.
공식화하고 풀어 보겠습니다.
python3m = LpProblem()
xs, ys = [], []
for i, j in g.edges():
g.edge[i][j]['x'] = x = LpVariable('x%d_%d'%(i,j), cat=LpBinary)
xs.append(x)
m += lpSum(xs)
for i, ad in enumerate(g.adjacency_list()):
y = LpVariable(
'y%d'%i, cat=LpInteger)
m += lpSum(g.edge[i][j]['x'] for j in ad) + len(ad) == 2 * y
ys.append(y)
m.solve()
print([g.edges()[i] for i, x in enumerate(xs) if value(x)])
>>>
[(0, 2), (1, 3), (1, 6)]
가장 짧고 점 0, 2, 3, 6이 연결되어 있음을 알 수 있습니다.
이상
Reference
이 문제에 관하여(조합 최적화로 도로를 포장하십시오.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/SaitoTsutomu/items/480f057df56e93d964ba
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
%matplotlib inline
import networkx as nx
from pulp import *
g = nx.random_graphs.fast_gnp_random_graph(8, 0.3, 11)
pos = nx.spring_layout(g)
nx.draw_networkx_nodes(g, pos=pos, node_size=600, node_color='w')
nx.draw_networkx_edges(g, pos=pos)
nx.draw_networkx_labels(g, pos=pos, font_size=20)
print([i for i, l in enumerate(g.adjacency_list()) if len(l)%2])
>>>
[0, 2, 3, 6]
m = LpProblem()
xs, ys = [], []
for i, j in g.edges():
g.edge[i][j]['x'] = x = LpVariable('x%d_%d'%(i,j), cat=LpBinary)
xs.append(x)
m += lpSum(xs)
for i, ad in enumerate(g.adjacency_list()):
y = LpVariable(
'y%d'%i, cat=LpInteger)
m += lpSum(g.edge[i][j]['x'] for j in ad) + len(ad) == 2 * y
ys.append(y)
m.solve()
print([g.edges()[i] for i, x in enumerate(xs) if value(x)])
>>>
[(0, 2), (1, 3), (1, 6)]
Reference
이 문제에 관하여(조합 최적화로 도로를 포장하십시오.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/SaitoTsutomu/items/480f057df56e93d964ba텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)