したがって、明らかに、P = NP [閉じた]


111

SATは、ブール式を真にできるかどうかを判断する問題です。たとえば、(A)はA = TRUEを設定することでtrueにできますが、(A &&!A)は決してtrueになりません。この問題はNP完全であることが知られています。ブール充足可能性を参照してください。

あなたのタスクは、多項式時間で実行するSAT用のプログラムを作成することですが、すべての場合を解決できるとは限りません。

いくつかの例では、それが実際に多項式ではない理由は、次の理由による可能性があります。

  1. 明らかではないが、ランタイムが悪いエッジケースがあります
  2. アルゴリズムは、いくつかの予期しないケースで実際に問題を解決できません
  3. 実際に使用しているプログラミング言語の一部の機能の実行時間は、予想されるよりも長いです
  4. あなたのコードは実際にそれがやっているように見えるものとは全く異なることをします

任意のプログラミング言語(または言語の組み合わせ)を使用できます。アルゴリズムの複雑さの正式な証明を提供する必要はありませんが、少なくとも説明を提供する必要があります。

判断の主な基準は、コードの説得力です。

これは人気のコンテストなので、1週間で最高の評価が得られた回答が勝ちます。


11
問題のある領域制限する方が良いでしょう。さもなければ、「よく知られている」ことの周りに不確実性のクラウドを呼び出します。NP困難な問題を1つだけ選んで、それに焦点を当ててみませんか?それには、他のそのような問題を同じ線に沿って将来の質問に対して開かれたままにするという利点があります。いくつかの狭い質問は、幅広い質問よりもはるかに多くの継続的な喜びとエンターテイメントをサイトに提供できます。
ジョナサンヴァンマトレ14年

9
@ gnasher729:SAT問題を解決するC#コンパイラーを入手しました。それはかなり興味深い成果だと思います。
エリックリッパー14年

9
ここで誰かが誤って多項式時間でSATを解くと楽しいでしょう。
チュリオン14年

5
@Turionの数十年の研究、数百万の報酬と賞、そしてすべての女性と名声-しかし、P = NPを解決するための本当の動機は、このPCGチャレンジになるでしょう。
何も不可能14年

3
このサイトでは、手に負えない課題はもはや歓迎されないので、この質問をトピック外として終了することに投票しています。meta.codegolf.stackexchange.com/a/8326/20469
cat

回答:


236

C#

あなたのタスクは、多項式時間で実行されるように見えるSAT用のプログラムを書くことです。

「表示」は不要です。SAT問題を解決するために多項式時間で実際に実行するプログラムを書くことができます。実際、これは非常に簡単です。

メガボーナス:実際に多項式時間で実行されるSATソルバーを作成すると、100万ドルを獲得できます。しかし、とにかくスポイラータグを使用してください。

驚くばかり。百万ドルを送ってください。真剣に、私は多項式ランタイムでSATを解決するプログラムをここに持っています。

まず、SAT問題のバリエーションを解決することを述べることから始めましょう。3-SAT問題の独自の解決策示すプログラムの作成方法を説明します。各ブール変数の評価は、ソルバーが機能するために一意でなければなりません。

まず、いくつかの単純なヘルパーメソッドと型を宣言します。

class MainClass
{
    class T { }
    class F { }
    delegate void DT(T t);
    delegate void DF(F f);
    static void M(string name, DT dt)
    {
        System.Console.WriteLine(name + ": true");
        dt(new T());
    }
    static void M(string name, DF df)
    {
        System.Console.WriteLine(name + ": false");
        df(new F());
    }
    static T Or(T a1, T a2, T a3) { return new T(); }
    static T Or(T a1, T a2, F a3) { return new T(); }
    static T Or(T a1, F a2, T a3) { return new T(); }
    static T Or(T a1, F a2, F a3) { return new T(); }
    static T Or(F a1, T a2, T a3) { return new T(); }
    static T Or(F a1, T a2, F a3) { return new T(); }
    static T Or(F a1, F a2, T a3) { return new T(); }
    static F Or(F a1, F a2, F a3) { return new F(); }
    static T And(T a1, T a2) { return new T(); }
    static F And(T a1, F a2) { return new F(); }
    static F And(F a1, T a2) { return new F(); }
    static F And(F a1, F a2) { return new F(); }
    static F Not(T a) { return new F(); }
    static T Not(F a) { return new T(); }
    static void MustBeT(T t) { }

それでは、3-SAT問題を選んで解決しましょう。まあ言ってみれば

(!x3) & 
(!x1) & 
(x1 | x2 | x1) & 
(x2 | x3 | x2)

それをもう少し括弧で括りましょう。

(!x3) & (
    (!x1) & (
        (x1 | x2 | x1) & 
        (x2 | x3 | x2)))

このようにエンコードします:

static void Main()
{
    M("x1", x1 => M("x2", x2 => M("x3", x3 => MustBeT(
      And(
        Not(x3),
        And(
          Not(x1),
          And(
            Or(x1, x2, x1),
            Or(x2, x3, x2))))))));
}

プログラムを実行すると、多項式時間で3-SATの解が得られます。実際、ランタイムは問題のサイズに比例します!

x1: false
x2: true
x3: false

あなたは多項式ランタイムを言った。多項式コンパイル時間については何も言わなかっ。このプログラムは、C#コンパイラにx1、x2、およびx3のすべての可能な型の組み合わせを試行させ、型エラーを示さない一意の組み合わせを選択します。コンパイラがすべての作業を行うため、ランタイムは必要ありません。2007年にブログでこの興味深い技術を初めて公開しました:http ://blogs.msdn.com/b/ericlippert/archive/2007/03/28/lambda-expressions-vs-anonymous-methods-part-five.aspx 注もちろんこの例は、C#のオーバーロード解決が少なくともNP-HARDであることを示しています。NP-HARDか実際には決定不能か 型の互換性が一般的な反変の存在下でどのように機能するかについての特定の微妙な詳細に依存しますが、それは別の日の主題です。


95
あなたはあなたの百万ドルのために粘土数学研究所に連絡する必要があります。しかし、彼らが満足するかどうかはわかりません。
ジョナサンプラノ14年

15
もちろん、SAT問題は同等の3-SAT問題に変換できるため、この制限は単に不便です。私の「解決策」のより厄介問題は、問題に独自の解決策が必要であることです。解決策がない場合、または複数の解決策がある場合、コンパイラはエラーを返します。
エリックリッパー14年

11
@EricLippertの一意性の要件は大丈夫です。多項式時間ランダム削減を使用して、SATを常にUnique-SATに減らすことができます(SAT、ただし入力に0または1の割り当てがあると仮定)。キーワード:分離補題、Valiant-Vazirani定理。
ディエゴデエストラダ14年

44
「真剣に、多項式ランタイムでSATを解決するプログラムがここにあります。」-私もですが、残念ながらこのコメントボックスには収まりません。
CompuChip 14年

11
@コビ:はい、それは冗談です。
エリックリッパー14年

166

多言語(1バイト)

多くの言語で有効で、ほとんどが機能的で難解な次のプログラムは、多数のSAT問題に対して正しい答えを与え、一定の複雑さを持ちます(!!!):

0

驚くべきことに、次のプログラムは残りのすべての問題に対して正しい答えを出し、同じ複雑さを持っています。したがって、適切なプログラムを選択するだけで、すべての場合に正しい答えが得られます。

1

6
これは素晴らしいです。私は大笑いしました。
カール

2
絶対に素晴らしい!
ブルードッグ14年

78
うーん。今では簡単です。私がする必要があるのは、適切なプログラムを選択するプログラムを書くことです!
ランチャー14年

正確に!:
マウ14年

6
xkcd.com/221を連想さます。
msh210 14年

34

JavaScript

反復非決定論を使用することにより、SATは多項式時間で解くことができます!

function isSatisfiable(bools, expr) {
    function verify() {
        var values = {};
        for(var i = 0; i < bools.length; i++) {
            values[bools[i]] = nonDeterministicValue();
        }
        with(values) {
            return eval(expr);
        }
    }
    function nonDeterministicValue() {
        return Math.random() < 0.5 ? !0 : !1;
    }

    for(var i = 0; i < 1000; i++) {
        if(verify(bools, expr)) return true;
    }
    return false;
}

使用例:

isSatisfiable(["a", "b"], "a && !a || b && !b") //returns 'false'

このアルゴリズムは、与えられたブール式をランダム入力で千回チェックするだけです。ほとんどの場合、小さな入力に対して機能しますが、より多くの変数が導入されると信頼性が低下します。

ちなみに、私は右隣同士にはJavaScriptの中で最も利用されていない機能のうちの2つを利用する機会があったことを誇りに思っている:evalwith


4
これは実際に確立されたテスト方法です。HaskellのQuickCheckライブラリがすべての楽しみを開始したと思います。それ以来、多くの言語で再実装されています。
ジョンタイリー14年

4
このプログラムは、sat式が大きいほど、正しい答えを返す可能性が低いことに注意する必要があると思います。1000forループでは、何らかの形で入力サイズ(一部の多項式非O(1)スケーリング)してスケーリングすべきです。
ランチャー

2
@Cruncherより正確には、変数の数が多いほど、正しい答えを返す可能性は低くなります。(たとえば、1つの変数を持つ非常に長い式は、ほとんど常に正しい答えを返します)
ピーターオルソン

2
@TimSeguineこの文脈での「非決定的」という言葉の使用は、SATを多項式時間で解くことができるという主張のように、せいぜい疑わしいと認めます。私はそれが正しくないことを知っています、それは詐欺のゲームの一部にすぎません。
ピーターオルソン14年

4
@PaulDraperを使用して、それらを十分に使用しないでください!いい笑いがありました!
ロブ14年

32

Mathematica +量子コンピューティング

Mathematicaには量子コンピューターが搭載されていることをご存じないかもしれません

Needs["Quantum`Computing`"];

量子断熱計算は、最小エネルギーの状態(「基底状態」)が解を表すように、ハミルトニアン(エネルギー演算子)で解決される問題をエンコードします。したがって、ハミルトニアンの基底状態への量子システムの断熱進化とその後の測定により、問題の解決策が得られます。

||式の一部に対応するサブハミルトニアンを定義し、変数とその否定に対するパウリ演算子の適切な組み合わせを使用します

ここに画像の説明を入力してください

このような表現の場所

expr = (! x3) && (! x1) && (x1 || x2 || x1) && (x2 || x3 || x2);

引数は次のようになります

{{{1, x3}}, {{1, x1}}, {{0, x1}, {0, x2}, {0, x1}}, {{0, x2}, {0, x3}, {0, x2}}}

bool式からこのような引数を構築するコードは次のとおりです。

arg = expr /. {And -> List, Or -> List, x_Symbol :> {0, x}, 
    Not[x_Symbol] :> {1, x}};
If[Depth[arg] == 3, arg = {arg}];
arg = If[Depth[#] == 2, {#}, #] & /@ arg

ここで、サブハミルトニアンを合計した完全なハミルトニアンを作成します(合計&&は式の一部に対応します)

H = h /@ arg /. List -> Plus;

そして、最低エネルギー状態を探します

QuantumEigensystemForm[H, -1]

ここに画像の説明を入力してください

固有値がゼロの場合、固有ベクトルは解です

expr /. {x1 -> False, x2 -> True, x3 -> False}
> True

残念ながら、「Quantum Computing」アドオンの公式サイトはアクティブではなく、ダウンロードする場所が見つかりません。コンピューターにインストールしたままです。アドオンには、コードを基にしたSAT問題の解決策が文書化されています。


19
この答えがどのように機能するかはわかりません。+1
ジョナサンプラノ14年

5
@XiaogeSu「自然に」。
スウィッシュ

3
@XiaogeSu進化はハミルトニアンによって決定され、当然、最低のエネルギーに進化します。そのため、スペクトルを知っていれば、システムが基底状態になると想定できます。
スウィッシュ

3
@XiaogeSuは、基底状態に行くために、より高い状態を興奮させる環境との相互作用も必要です、あなたは正しいです。ここでの考え方は、この相互作用は非常に小さく、「断熱的」であるということです。
チュリオン14年

3
fyi 断熱QMコンピューティングには、古典的なシミュレーテッドアニーリングと多くの類似点があります。現在Dwaveによって実装されています。その最小値で「発見/安定」する「冷却」温度/エネルギーシステムに似ています。
vzn 14年

27

ここでの3つのアプローチは、すべてSATを2D幾何学的共通語に還元することを含みます:非グラム論理パズル。ロジックパズルのセルは、SAT変数、節の制約に対応しています。

完全な説明(およびバグについてはコードを確認してください!)のために、ノノグラムソリューション空間内のパターンに関する洞察を既に投稿しました。https://codereview.stackexchange.com/questions/43770/nonogram-puzzle-solution-spaceを参照してください。40億を超えるパズルソリューションを列挙し、それらを真理値表に適合するようにエンコードすると、フラクタルパターン(自己相似性、特に自己親和性)が示されます。このアフィン冗長性は、問題を解決するために必要な計算リソースを削減するために利用可能な問題内の構造を示しています。また、成功したアルゴリズム内で混oticとしたフィードバックが必要であることも示しています。「簡単な」インスタンスは粗い構造に沿ったものであり、「ハード」なインスタンスは通常のヒューリスティックからはまったく見えない細かいディテールへのさらなる反復を必要とするフェーズ遷移動作には説明力があります。この無限の画像の隅にズームしたい場合(すべての<= 4x4パズルインスタンスがエンコードされている)、http://re-curse.github.io/visualizing-intractability/nonograms_zoom/nonograms.htmlを参照してください

方法1.カオスマップと機械学習を使用して、非グラム解空間の影を外挿します(マンデルブロ集合を生成する関数に似た近似関数を考えます)。

http://i.stack.imgur.com/X7SbP.png

これが誘導の視覚的証拠です。これらの4つの画像を左から右にスキャンして、欠落している5番目... 6番目...などの画像を生成することをお勧めしていると思われる場合は、非グラム解の決定問題のNPオラクルとしてプログラムしました存在。世界で最も強力なスーパーコンピューターとしてあなたの賞を獲得してください。私は時々あなたに電気の衝撃を与えますが、世界はあなたの計算の貢献に感謝しています。

方法2。入力のブール画像バージョンでフーリエ変換を使用します。FFTは、インスタンス内の周波数と位置に関するグローバル情報を提供します。大きさの部分は入力ペア間で類似しているはずですが、それらの位相情報は完全に異なります。特定の軸に沿った解の投影に関する方向付けられた情報を含みます。十分に賢い場合は、入力位相画像の特別な重ね合わせを使用して、ソリューションの位相画像を再構築できます。次に、位相と共通の大きさを逆変換して、解の時間領域に戻します。

この方法は何を説明できますか?連続した実行の間に柔軟なパディングを伴うブール画像の多くの順列があります。これにより、入力間のマッピングが可能になります。ソリューションは、時間領域<->(周波数、位相)間の双方向の一意のマッピングのFFTのプロパティを保持しながら、多重度を考慮します。また、「解決策なし」などというものがないことも意味します。それが言うことは、連続的なケースでは、従来の非グラムパズル解法のバイレベル画像を見るときに考慮していないグレースケールソリューションがあるということです。

なぜそうしないのですか?今日の浮動小数点の世界ではFFTは大きなインスタンスに対して非常に不正確であるため、実際に計算するのは恐ろしい方法です。精度は大きな問題であり、量子化された振幅と位相の画像から画像を再構築することは、人間の目のしきい値については視覚的ではないかもしれませんが、通常は非常に近似したソリューションを作成します。また、実際にそれを行う機能の種類は現在不明であるため、この重ね合わせビジネスを思い付くのは非常に困難です。それは単純な平均化スキームでしょうか?おそらくそうではなく、直感を除いてそれを見つけるための特定の検索方法はありません。

方法3.ノノグラムパズルの対称バージョンを解くセルラーオートマトンルール(フォンノイマン2状態ルールの場合、約40億のルールテーブルから)を見つけます。ここに示すように、セルに問題を直接埋め込む方法を使用します。 保守的な対称ノノグラム

これはおそらく、シンプルさと将来のコンピューティングへの効果という点で、最もエレガントな方法です。このルールの存在は証明されていませんが、存在する予感があります。その理由は次のとおりです。

ノノグラムを正確に解くには、アルゴリズム内の多くのカオスフィードバックが必要です。これは、Code Reviewにリンクされたブルートフォースコードによって確立されます。CAは、混oticとしたフィードバックをプログラムするための最も有能な言語です。

視覚的に正しく見えます。ルールは、埋め込みを介して進化し、情報を水平および垂直に伝播し、干渉し、セットセルの数を保存するソリューションに安定します。この伝播ルートは、物理オブジェクトの影を元の構成に投影するときに通常考えるパス(後方)をたどります。ノノグラムは、離散トモグラフィーの特殊なケースから派生しているため、2つの子猫用CTスキャナーに同時に座っていると想像してください。これが、X線が伝播して医療画像を生成する方法です。もちろん、境界の問題があります-トロイダルユニバースを許可しない限り、CAユニバースの端は限界を超えて情報を伝播し続けることができません。また、これはパズルを周期的な境界値の問題として投げかけます。

複数の解決策を、入力としての出力の交換とその逆の継続的な振動効果における過渡状態として説明します。設定されたセルの数を節約しない元の構成として、ソリューションを持たないインスタンスを説明します。そのようなルールを見つけることの実際の結果に応じて、セルの状態保存されている密接なソリューションで解決不可能なインスタンスを近似することさえあります。


2
「なぜ私はそれ考えなかったのか?」:P
ナビン14年

あなたはスティーブン・ウルフラムであり、私は私の5ポンドを請求します!
Quuxplusone 14年

4
この答えは説得力のあるプログラムを作成するための最良の試みであるため、本当に多くの信用に値します。良いショー。
ジョナサンプラノ14

10

C ++

多項式時間での実行が保証されているソリューションは次のとおりです。ここで実行さO(n^k)れるのnは、ブール値の数でkあり、選択した定数です。

それは、この場合には、私はCS-話すが、「それは運のビットと、正解ほとんどの時間を与える」ためであると考えている、発見的に正しい(と、の適切大きな値k- 編集は、それが実際にいることに私に起こりました修正済みのn場合は、そのkように設定できますn^k > 2^n-その不正行為ですか?)。

#include <iostream>  
#include <cstdlib>   
#include <time.h>    
#include <cmath>     
#include <vector>    

using std::cout;     
using std::endl;     
typedef std::vector<bool> zork;

// INPUT HERE:

const int n = 3; // Number of bits
const int k = 4; // Runtime order O(n^k)

bool input_expression(const zork& x)
{
  return 
  (!x[2]) && (
    (!x[0]) && (
      (x[0] || x[1] || x[0]) &&
      (x[1] || x[2] || x[1])));
}

// MAGIC HAPPENS BELOW:    

 void whatever_you_do(const zork& minefield)
;void always_bring_a_towel(int value, zork* minefield);

int main()
{
  const int forty_two = (int)pow(2, n) + 1;
  int edition = (int)pow(n, k);
  srand(time(6["times7"]));

  zork dont_panic(n);
  while(--edition)
  {
    int sperm_whale = rand() % forty_two;
    always_bring_a_towel(sperm_whale, &dont_panic);

    if(input_expression(dont_panic))
    {
      cout << "Satisfiable: " << endl;
      whatever_you_do(dont_panic);
      return 0;
    }
  }

  cout << "Not satisfiable?" << endl;
  return 0;
}
void always_bring_a_towel(int value, zork* minefield)
{
  for(int j = 0; j < n; ++j, value >>= 1)
  {
    (*minefield)[j] = (value & 1);
  }
}

void whatever_you_do(const zork& minefield)
{
  for(int j = 0; j < n; ++j) 
  {
    cout << (char)('A' + j) << " = " << minefield[j] << endl;
  }
}

いい答えだ。私は説明をネタバレのタグに入れて、人々がそれをじっと見て頭を少し掻くことができるようにします。
ジョナサンプラーノ14年

@JonathanPullanoの提案に感謝します。スポイラータグを追加し、コードを少し難読化しました。
CompuChip 14年

ちなみに、私はたった今知ったばかりでbitfield、多分それを好むでしょうstd::vector
CompuChip 14年

3
クリエイティブな難読化とヒッチハイカーの参照のために+1
ブレイクミラー14年

2
はい、それは不正行為です。kがnに依存する場合、それはあまり定数ではありません:-)
RemcoGerlich 14年

3

ruby / gnuplot 3dサーフェス

(ああ、厳しい競争!)...とにかく...千の言葉に値する写真ですか?これらは、SAT遷移点のgnuplotで作成された3つの個別の表面プロットです。(x、y)軸は節と変数の数で、zの高さはソルバーの再帰呼び出しの合計数です。ルビーで書かれたコード。各100サンプルで10x10ポイントをサンプリングします。統計の基本原理を実証/使用し、モンテカルロシミュレーションです。

基本的には、DIMACS形式で生成されたランダムインスタンスで実行されるdavis putnamアルゴリズムです。これは、理想的には世界中のCSクラスで行われるタイプのエクササイズであり、学生は基礎を学ぶことができますが、特に具体的にはまったく教えられません...多分偽のP?統計物理学で非常に有名なトピックであり、CSでも重要である遷移点現象について説明するウィキペディアの記事さえありません。[a] [b] 遷移点に関する多くの論文がCSにありますただし、表面プロットを表示するものはほとんどありません!(代わりに、通常2Dスライスを表示します。)

実行時間の指数関数的な増加は、最初のプロットで明確に示されています。1 番目のプロットの中央を通るサドルが遷移ポイントです。2 番目と3 番目のプロットは、%充足可能な遷移を示しています。

[A] CS PPTにおける相転移挙動トビーウォルシュ
[B] のk-SATの充足可能性の経験的確率 tcs.se
[C] 経験的/実験数学/(T)CS / SATに大きなモーメント、TMachineブログ

ここに画像の説明を入力してください ここに画像の説明を入力してください ここに画像の説明を入力してください

P =?NP QED!

#!/usr/bin/ruby1.8

def makeformula(clauses)
    (1..clauses).map \
    {
            vars2 = $vars.dup
            (1..3).map { vars2.delete_at(rand(vars2.size)) * [-1, 1][rand(2)] }.sort_by { |x| x.abs }
    }

end

def solve(vars, formula, assign)

    $counter += 1
    vars2 = []
    formula.each { |x| vars2 |= x.map { |y| y.abs } }
    vars &= vars2

    return [false] if (vars.empty?)
    v = vars.shift
    [v, -v].each \
    {
            |v2|
            f2 = formula.map { |x| x.dup }
            f2.delete_if \
            {
                    |x|
                    x.delete(-v2)
                    return [false] if (x.empty?)
                    x.member?(v2)
            }
            return [true, assign + [v2]] if (f2.empty?)
            soln = solve(vars.dup, f2, assign + [v2])
            return soln if (soln[0])
    }
    return [false]
end

def solve2(formula)
    $counter = 0
    soln = solve($vars.dup, formula, [])
    return [$counter, {false => 0, true => 1}[soln[0]]]
end


c1 = 10
c2 = 100
nlo, nhi = [3, 10]
mlo, mhi = [1, 50]
c1.times \
{
    |n|
    c1.times \
    {
            |m|
            p1 = nlo + n.to_f / c1 * (nhi - nlo)
            p2 = mlo + m.to_f / c1 * (mhi - mlo)
            $vars = (1..p1.to_i).to_a
            z1 = 0
            z2 = 0
            c2.times \
            {
                    f = makeformula(p2.to_i)
                    x = solve2(f.dup)
                    z1 += x[0]
                    z2 += x[1]
            }
#           p([p1, p2, z1.to_f / c2, z2.to_f / c2]) # raw
#           p(z1.to_f / c2)                         # fig1
#           p(0.5 - (z2.to_f / c2 - 0.5).abs)       # fig2
            p(z2.to_f / c2)                         # fig3
    }
    puts
}

2
この回答にご協力いただきありがとうございます。PとNP(どちらの方法でも)の成功した証明では、予測力の多くの要件の1つです。その重要性を指摘していただきありがとうございます。:)

詳細黙想NP対P、多くのトップ/収集、引用文献など
vzn
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.