1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

パズルAdvent Calendar 2017

Day 5

組合せ最適化でステンドグラスを解く

Last updated at Posted at 2017-12-04

Advent Calendar 4日目の記事 組合せ最適化でエデンの園配置を証明する
Advent Calendar 6日目の記事 組合せ最適化でタイルペイントを解く

これなに

ステンドグラスを、Pythonで組合せ最適化モデルを作って解きます。
解く楽しみは、モデル化を工夫することになります。

自分でも試してみたい人は、下記を参考にしてください。

問題

  • 線で区切られた部分(ピース)のいくつかを黒くぬります
  • 小さな丸は、その丸が接している周囲のピースのうち、黒ピースと白ピースのどちらの数が多いかを表します
  • 黒丸なら黒ピースの方が多く、白丸なら白ピースの方が多く、灰色の丸は、同数となります

下記は、左が問題で、右が答えです。

Pythonでは、npi(ピースの数)、hint(色と周りのピース)を使うことにします。

python
from pulp import LpProblem, lpSum, value
from ortoolpy import addbinvars
npi = 11 # ピース数
hint = [s.split(',') for s in """\
W,0,1,2
W,0,3
B,0,1,3,4,5
B,1,5
B,1,2,5,6
W,3,4,7
G,5,6,9,10
G,5,7,8,10""".splitlines()]

数理モデルを作り解く

変数は、各ピースが黒(1)か白(0)にしましょう。

  • ヒントが'W':黒のピース数が半分未満
  • ヒントが'B':黒のピース数が半分超
  • ヒントが'G':黒のピース数がちょうど半分
python
m = LpProblem() # 数理モデル
v = addbinvars(npi) # 変数(黒かどうか)
for c,*lst in hint:
    vlst = [v[int(i)] for i in lst] # 周囲のピースの変数
    if c == 'W':
        m += lpSum(vlst) <= (len(vlst) - 1) // 2
    elif c == 'B':
        m += lpSum(vlst) >= (len(vlst) + 2) // 2
    else:
        m += lpSum(vlst) == len(vlst) // 2
m.solve()

結果の表示

python
print('black:', [i for i in range(npi) if value(v[i])>0.5])
>>>
black: [1, 4, 5, 6, 8]

解けていることが確認できます。簡単ですね。

以上

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?