조합 최적화의 격차를 풀기
Advent Calendar 16일 기사 조합 최적화로 미술관 풀기
이게 뭐야
의 놀라움을 파이썬으로 조합 최적화 모델을 만들고 풀어줍니다.
푸는 재미는 모델링을 고안하는 것입니다.
자신도 시도하고 싶은 사람은 아래를 참조하십시오.
문제
아래는 문제와 대답입니다.
공식화
\begin{array}{cl}
変数 & v_{ij} \in \{0, 1\} ~ \forall i, j ~ ~ ~ (マスi,jが黒かどうか) (1) \\
& r_{k} \in \{0, 1\} ~ \forall k, 縦または横 ~ ~ ~ ~ ~ (縦または横ごとにk番目の候補を選ぶかどうか) (2) \\
\mbox{subject to} & \sum_k{r_k} = 1 ~ \forall 縦または横 ~ ~ ~ ~ (縦または横ごとに候補の中から1つ) (3) \\
& 候補を選んだらマスの色は候補の通り (4) \\
\end{array}
hinth
에 가로 힌트가 있고 hintv
에 세로 힌트가 있다고 가정합니다.파이썬
import numpy as np, matplotlib.pyplot as plt
from pulp import LpProblem, lpSum, value
from ortoolpy import addvars, addbinvars
hinth = [[int(s) for s in t.split(',')] for t in
'2 3,2 2,3 2,2 8 7 1,4 3,3 1,1 3'.split()]
hintv = [[int(s) for s in t.split(',')] for t in
'2 1,2 1,5 5,2 1,2,1 3 6 1,3,2,1 3,4 1,1'.split()]
수리 모델을 만들어 풀다
의 놀라움을 해결하기 위해 제약 조건을 추가하고 수리 모델을 만들고 풀어 봅시다.
do
에서 행 또는 열 힌트를 처리합니다. makelist
에서 힌트를 기반으로 패턴을 열거하고 0-1 변수로 하나의 패턴을 선택합니다. 파이썬
def baselist(i, j, k):
return [0] * i + [1] * j + [0] * k
def makelist(n, l):
p = l[-1]
if len(l) == 1:
if n < p: return None
return [baselist(i, p, n - p - i) for i in range(n - p + 1)]
ll = l[:-1]
s = sum(ll) + len(ll) - 1
return [j + baselist(1, p, n - p - s - i - 1) \
for i in range(n - p - s) for j in makelist(i + s, ll)]
def do(m, v, hint):
for i, hh in enumerate(hint):
l = makelist(v.shape[0], hh)
r = addbinvars(len(l)) # (2)
m += lpSum(r) == 1 # (3)
for j, c in enumerate(l):
for k, b in enumerate(c):
m += (1 - 2 * b) * v[k,i] <= 1 - b - r[j] # (4)
m = LpProblem()
v = np.array(addvars(len(hintv), len(hinth))) # (1)
do(m, v, hinth)
do(m, v.T, hintv)
m.solve()
결과 표시
파이썬
plt.imshow(1-np.vectorize(value)(v), cmap='gray', interpolation='none')
plt.show()
풀리고 있는지 확인할 수 있습니다.
이상
Reference
이 문제에 관하여(조합 최적화의 격차를 풀기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/SaitoTsutomu/items/7e01f4bc3acb540b4c81텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)