この明らかにO(n lg n)乗算アルゴリズムの間違いはどこにありますか?


15

等間隔の3つを見つけることに関する最近のパズルブログの投稿で、私はO(n lg n)時間内にそれを行うと主張するトップアンサーを持つstackoverflowの質問に導かれました。興味深い部分は、解が多項式の2乗を伴い、O(n lg n)時間でそれを行う方法を説明する論文を参照することです。

現在、多項式の乗算は、数値の乗算と実質的に同じです。唯一の本当の違いは、キャリーがないことです。しかし...キャリーはO(n lg n)時間で行うこともできます。例えば:

    var value = 100; // = 0b1100100

    var inputBitCount = value.BitCount(); // 7 (because 2^7 > 100 >= 2^6)
    var n = inputBitCount * 2; // 14
    var lgn = n.BitCount(); // 4 (because 2^4 > 14 => 2^3)
    var c = lgn + 1; //5; enough space for 2n carries without overflowing

    // do apparently O(n log n) polynomial multiplication
    var p = ToPolynomialWhereBitsAreCoefficients(value); // x^6 + x^5 + x^2
    var p2 = SquarePolynomialInNLogNUsingFFT(p); // x^12 + 2x^11 + 2x^10 + x^8 + 2x^7 + x^4
    var s = CoefficientsOfPolynomial(p2); // [0,0,0,0,1,0,0,2,1,0,2,2,1]
    // note: s takes O(n lg n) space to store (each value requires at most c-1 bits)

    // propagate carries in O(n c) = O(n lg n) time
    for (var i = 0; i < n; i++)
        for (var j = 1; j < c; j++)
            if (s[i].Bit(j))
                s[i + j].IncrementInPlace();

    // extract bits of result (in little endian order)
    var r = new bool[n];
    for (var i = 0; i < n; i++)
        r[i] = s[i].Bit(0);

    // r encodes 0b10011100010000 = 10000

だから私の質問はこれです:ここで間違いはどこですか?O(n lg n)での数値の乗算は、コンピューターサイエンスの巨大な未解決の問題であり、この単純な答えは本当に疑わしいです。

  • 持ち運びは間違っていますか、それともO(n lg n)ではありませんか?キャリーを追跡するには、値ごとにlg n + 1ビットで十分であり、アルゴリズムが非常に単純であるため、間違っていた場合は驚くでしょう。個々の増分にはO(lg n)時間かかることがありますが、x増分の総コストはO(x)であることに注意してください。
  • 論文の多項式乗算アルゴリズムは間違っていますか、または違反している条件がありますか?この論文では、数論的変換ではなく高速フーリエ変換を使用していますが、これは問題になる可能性があります。
  • 賢い人の多くは、シェーンハーゲ–ストラッセンアルゴリズムの明らかなバリエーションを40年間見逃していませんか?これははるかに少ないようです。

効率的な多項式乗算を除いて、実際にこれを実装するコードを作成しました(数論変換はまだ十分に理解されていません)。ランダムテストはアルゴリズムが正しいことを確認しているように見えるため、問題は時間の複雑さの分析にある可能性があります。


正方形に含めるべきではありませんx^10 + 2x^8か?x ^ 10は1回のみ(x ^ 5 * x ^ 5)、x ^ 8は2回(x ^ 6 * x ^ 2 + x ^ 2 * x ^ 6)
シェード

この例を手作業で行いました。算術ミスをしました。ごめんなさい。ただし、実際にアルゴリズムを実装してテストし、正しい結果を得ました。
クレイグギドニー

回答:



1

ここでの「間違い」は、フーリエ変換が、変換される数値を加算または乗算するO(n log n)ステップで計算できることですが、nが大きくなると、変換される数値も大きくなります。別の要因ログlog n。

実際には、FFTで4倍精度浮動小数点(2つのdouble値を使用する128ビット浮動小数点)または128ビット固定小数点を使用すれば、計算が十分に小さい製品であれば十分だと思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.