サブセット和問題とNP完全問題の可解性
-
23-09-2019 - |
質問
私はサブセット和問題について読んでいた。
(defun subset-contains-sum (set sum)
(let ((subsets) (new-subset) (new-sum))
(dolist (element set)
(dolist (subset-sum subsets)
(setf new-subset (cons element (car subset-sum)))
(setf new-sum (+ element (cdr subset-sum)))
(if (= new-sum sum)
(return-from subset-contains-sum new-subset))
(setf subsets (cons (cons new-subset new-sum) subsets)))
(setf subsets (cons (cons element element) subsets)))))
「セット」は、重複や「和」を含まないリストは、合計がためにサブセットを検索することです。 「サブセット」「車が」サブセットリストと「CDR」であるサブセットの和であるコンスセルのリストです。新サブセットはちょうど手前に要素をcons'ingことにより、O(1)時間に古いものから作成されます。
私はそれの実行時の複雑さが何であるかわからないが、表示されている各要素と「合計」には、少なくとも二次ことに私には見えるので、「サブセット」ダブルスのサイズ、プラスワンで成長します。
私の印象は前NP完全問題は難治する傾向があるということでしたので、私はこれを掲示していますし、通常のために望むことができる最高のものは、ヒューリスティックであることが、これが表示されますが、あなたが持っていると仮定すると、汎用的なソリューションという意志であることをCPUサイクルは、常にあなたに正しい答えを与えます。どのように他の多くのNP完全問題はこの1つのように解くことができますか?
解決
NP完全問題のすべてが解決策を持っています。限り、あなたは答えを計算するための時間を費やすことをいとわないとして、それはです。 の効率的なのアルゴリズムが存在しないという理由だけで、1が存在しないという意味ではありません。たとえば、あなただけのすべての潜在的な解決策を反復処理ができ、あなたは最終的には1を取得します。これらの問題はすべて、実世界のコンピューティングの場所で使用されています。あなたはちょうどあなたが指数時間が必要になるだろう場合、あなた自身のために設定され、大きなA問題(またはより悪いが!)それを解決する方法について注意する必要があります。
他のヒント
NP完全問題は、(我々が知る限り)だけでは多項式時間で、解決できます。つまり、NP完全問題は、それを解決することができO(n*2^n)
アルゴリズムを有することができるが、それは、例えば、それを解決するためにO(n^3)
アルゴリズムを持っていません。
興味深いことに、その後、NP内のすべての問題は多項式時間で解くことができました。これは、P = NPがあるものについてである。
私が正しくあなたのアルゴリズムを理解する(そしてこれは、より多くのあなたのコメントのコードよりも基づいています)場合は、は、それはO(n*2^n)
アルゴリズム<のhref = "http://en.wikipedia.org/wiki/Subset_sum_problemに相当します#Polynomial_time_approximate_algorithm」のrel = "nofollowをnoreferrer">ここを。そこ2^n
サブセットであり、そしてあなたも、各サブセットを合計する必要があるため、アルゴリズムがO(n*2^n)
です。
複雑さについてのもう一つ - O(whatever)
だけどれだけ特定のアルゴリズムスケールを示しています。あなたは、2つのアルゴリズムを比較すると、1が速く、他のよりもこれに基づいていると言うことはできません。ビッグO記法は、実装の詳細および最適化を気にしない - 1がはるかに高速以外であることと同じアルゴリズムの2つの実装を記述することが可能である、彼らは両方のO(n^2)
かもしれないにもかかわらず。赤ちゃんを作る一人の女性は、O(n)
操作ですが、チャンスは、これはもはやあなたが行う最もO(n*log(n))
ソートよりも多くを取るしようとしていることです。あなたはこれに基づいて言えることは、ソートをn個の非常に大きな値のために遅くなるということです。
私は何ランタイムわかりません その複雑さはあるが、それを表示されます 各要素「合計は」によって成長して 「サブセット」ダブルスのサイズ、プラス1、 それは、少なくともすることが私には表示されます 二次ます。
Nの各増加のための実行時ダブルスは、あなたがO(2 ^ N)アルゴリズムで探しているなら。それは正確に2 ^ Nのメンバー(あなたはRHE空のセットが含まれている場合)だとしてそれは、私がセットのすべての部分集合(または集合の冪のすべてのメンバーを)訪問から期待するものもあります。
追加または全て従来-見セットに要素を追加することではないが速いという事実は、全体の処理が高速であることを意味するものではない。
はここで何が起こっているかはるかに簡単に再帰を使って表現することができます:
(defun subset-sum (set sum &optional subset) (when set (destructuring-bind (head . tail) set (or (and (= head sum) (cons head subset)) (subset-sum tail sum subset) (subset-sum tail (- sum head) (cons head subset))))))
末端に2つの再帰呼び出しは明らかに我々は深さのバイナリツリーをトラバースnは、与えられた集合の大きさを示しています。予想通り、バイナリツリー内のノードの数は、O(N ^ 2)である。
これは、多項式時間にkarpreducibleです。決定問題のO(nM)をヒープまたはバイナリ探索上限を使用するカープ低減と低減が対数である(M * 2 ^ M)=関数logm +ログ(2 ^ M)=関数logm + Mlog2エルゴ時間:O(nM)を