kbigwheelのプログラミング・ソフトウェア技術系ブログ

プログラミング・ソフトウェア技術系のことを書きます

NP困難の問題のアルゴリズムを考える その2

kbigwheel.hateblo.jp

の末尾に書いた通り、ortoolsを使おうとしている。 そのためには定式化が必要で、今見ている問題がどのタイプの問題かを判断する必要がある。

ここら辺で重大なことに気づいた。巡回サラリーマン問題などは点と点の間に距離があり、それが問題だった。しかし、今回の塗装の問題は塗る色の間に距離などない。白と黄色の距離と、白とくろの距離は同じである(なぜならエアブラシのカップの中に入れる色が何であれ、手間は変わらないからである)。

この問題、もしかしてNP困難ではないのでは?

問題を整理する

 C_1~  C_NのN個の色を塗るとする。 また、 C_a → C_b のような塗装順の制約がP個ある。 このとき、最小となるような塗装順を見つけたい。

これは、書き換えると次のような問題になる。

 C_1~  C_NのN個の記号がある。  C_1~  C_Nをそれぞれ1つ以上含んだ最短の記号列を求めよ。 ただし、 C_aより後に必ず C_bを含む必要がある、といった制約LがP個ある。

こう考えるとNP困難ではない気がする。

多角的にこの問題を考えよう。 まず、[text: L_1] ~ [text: L_P]のどれにも含まれていない記号 C_xは考慮からすべて外せる。というのは、制約に含まれる記号を制約を満たすように順序付けしたあとは、制約に含まれていない記号はその列の任意の間に好きな順序でおけるからである。先頭にあまり全てをおいても良いし、末尾でも良い。ランダムでも数字順にソートでもいが、そのどれでも塗装回数に影響しない。

となると問題は以下のように書き換えられる。

 C_1~  C_NのN個の記号がある。  C_1~  C_Nをそれぞれ1つ以上含んだ最短の記号列を求めよ。 ただし、 C_aより後に必ず C_bを含む必要がある、といった制約LがP個ある。また、 C_1~  C_Nは制約 L_1~  L_Pの中に必ず1度以上出てくる。

これを図として表現すると、NxNの行列(対角線はn/a)になる。 例えば -  C_1のあとで C_2 -  C_1のあとで C_3 -  C_2のあとで C_1

というルールは次の行列で表現できる。

先に通る点 \ 後に通る点  C_1  C_2  C_3
 C_1 n/a true true
 C_2 true n/a false
 C_3 false false n/a

この行列を持って最適化する。それが、この問題の解き方(の気がする・・・)。

もしかして、DPで行ける?

2022/08/11追記

重みがないから更に効率的なアルゴリズムがありそうと2,3日調査しながら頭をひねった結果、制約を一つずつ見ながらtreeを作っていくロジックを考えついた。