이 명백한 -O (n lg n) 곱셈 알고리즘의 실수는 어디에 있습니까?


15

균등하게 간격을 둔 3 개의 것을 찾는 것에 관한 최근 퍼즐 블로그 게시물 은 O (n lg n) 시간에 그것을한다고 주장하는 최고의 대답과 함께 stackoverflow 질문 으로 이어집니다. 흥미로운 부분은 솔루션이 다항식을 제곱하고, 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 년 동안 Schönhage-Strassen 알고리즘 의 명백한 변형을 놓쳤 습니까? 이것은 아마도 가장 적은 것 같습니다.

효율적인 다항식 곱셈을 제외하고 실제로 이것을 구현하는 코드를 작성했습니다 (수 이론 정리는 아직 충분히 이해하지 못합니다). 무작위 테스트는 알고리즘이 올바른지 확인하는 것으로 보이므로 시간 복잡성 분석에 문제가있을 수 있습니다.


정사각형을 포함해서는 안 x^10 + 2x^8됩니까? x ^ 10 한 번만 (x ^ 5 * x ^ 5), x ^ 8을 두 번 (x ^ 6 * x ^ 2 + x ^ 2 * x ^ 6)
Sjoerd

나는 손으로 모범을 보였다. 나는 산술 실수를했다. 죄송합니다. 실제로 알고리즘을 구현하고 테스트하여 올바른 결과를 얻었습니다.
Craig Gidney

답변:



1

여기서 "실수"는 푸리에 변환을 변환 할 숫자를 더하거나 곱하는 O (n log n) 단계로 계산할 수 있지만, n이 실제로 커질수록 변환되는 숫자도 커진다는 것입니다. 다른 요인 로그 로그 n.

실제로 FFT에서 쿼드 정밀 부동 소수점 (두 개의 이중 값을 사용하는 128 비트 부동 소수점) 또는 128 비트 고정 소수점을 사용하면 작은 제품을 계산하기에 충분하다고 생각합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.