조합 최적화로 볼록한 다각형의 최적 삼각형 분할
이게 뭐야
수학과 컴퓨터 어드벤트 캘린더의 11일째 기사 「볼록 다각형의 최적 삼각형 분할」를 조합 최적화에서 풀어 보았습니다.
사고방식
볼록 N각형에 교차하지 않도록 N-3개의 대각선을 그리면 삼각형 분할할 수 있으므로 합이 최소의 것을 선택하면 됩니다.
수리 최적화 절차는 스도쿠를 통해 조합 최적화를 배우자.을 참조하세요.
예제
적당히 다각형을 만듭니다.
python3import matplotlib.pyplot as plt
import numpy as np, pandas as pd, networkx as nx
from pulp import LpProblem, lpDot, lpSum, value
from ortoolpy import addbinvars
plt.rcParams['figure.figsize'] = (4,4)
plt.axes().set_aspect('equal', 'datalim')
pos = np.array([[1,2],[2,0],[4,0],[6,1],[5,4],[4,5],[2,4]])
dcpos = dict(enumerate(pos))
n = len(pos)
g = nx.Graph()
g.add_edges_from([(i,(i+1)%n) for i in range(n)])
nx.draw_networkx(g,pos=dcpos)
plt.show()
변수 테이블
변수 테이블을 만듭니다.
python3a = pd.DataFrame([(i,j,np.linalg.norm(pos[i]-pos[j]))
for i in range(n) for j in range(i+2,n-(i==0))], columns='I J Dist'.split())
a['Var'] = addbinvars(len(a))
a[:2]
I
J
Dist
Var
0
0
2
3.605551
v000001
1
0
3
5.099020
v000002
공식화하고 풀다
제약은 N-3개 필요라고 하면 교차시키지 않게 됩니다.
python3m = LpProblem()
m += lpDot(a.Dist, a.Var)
m += lpSum(a.Var) == n-3 # N-3本必要
for idx,(i1,j1,_,v1) in a.iterrows():
for _,(i2,j2,_,v2) in a[idx+1:].iterrows():
if i1 < i2 < j1 < j2:
m += v1+v2 <= 1 # 交差させない
m.solve()
a['Val'] = a.Var.apply(value)
print('対角線の和',value(m.objective))
g.add_edges_from(a[a.Val>0.5].values[:,:2])
nx.draw_networkx(g,pos=dcpos)
plt.show()
>>>
対角線の和 15.200792856081229
할 수 있었습니다.
이상
Reference
이 문제에 관하여(조합 최적화로 볼록한 다각형의 최적 삼각형 분할), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/SaitoTsutomu/items/a514b1e2c4198518e119
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
import matplotlib.pyplot as plt
import numpy as np, pandas as pd, networkx as nx
from pulp import LpProblem, lpDot, lpSum, value
from ortoolpy import addbinvars
plt.rcParams['figure.figsize'] = (4,4)
plt.axes().set_aspect('equal', 'datalim')
pos = np.array([[1,2],[2,0],[4,0],[6,1],[5,4],[4,5],[2,4]])
dcpos = dict(enumerate(pos))
n = len(pos)
g = nx.Graph()
g.add_edges_from([(i,(i+1)%n) for i in range(n)])
nx.draw_networkx(g,pos=dcpos)
plt.show()
a = pd.DataFrame([(i,j,np.linalg.norm(pos[i]-pos[j]))
for i in range(n) for j in range(i+2,n-(i==0))], columns='I J Dist'.split())
a['Var'] = addbinvars(len(a))
a[:2]
m = LpProblem()
m += lpDot(a.Dist, a.Var)
m += lpSum(a.Var) == n-3 # N-3本必要
for idx,(i1,j1,_,v1) in a.iterrows():
for _,(i2,j2,_,v2) in a[idx+1:].iterrows():
if i1 < i2 < j1 < j2:
m += v1+v2 <= 1 # 交差させない
m.solve()
a['Val'] = a.Var.apply(value)
print('対角線の和',value(m.objective))
g.add_edges_from(a[a.Val>0.5].values[:,:2])
nx.draw_networkx(g,pos=dcpos)
plt.show()
>>>
対角線の和 15.200792856081229
Reference
이 문제에 관하여(조합 최적화로 볼록한 다각형의 최적 삼각형 분할), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/SaitoTsutomu/items/a514b1e2c4198518e119텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)