Dov'è l'errore in questo algoritmo di moltiplicazione apparentemente-O (nlg n)?


15

Un recente post sul blog di puzzle sulla ricerca di tre equidistanti mi porta a una domanda stackoverflow con una risposta superiore che afferma di farlo in tempo O (n lg n). La parte interessante è che la soluzione prevede la quadratura di un polinomio, facendo riferimento a un documento che descrive come farlo in tempo O (n lg n) .

Ora, moltiplicare i polinomi è praticamente uguale a moltiplicare i numeri. L'unica vera differenza è la mancanza di riporti. Ma ... i carry possono anche essere eseguiti in tempo O (n lg n). Per esempio:

    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

Quindi la mia domanda è questa: dov'è l'errore, qui? Moltiplicare i numeri in O (n lg n) è un gigantesco problema aperto nell'informatica, e dubito davvero che la risposta sarebbe così semplice.

  • Il trasporto è sbagliato o no O (n lg n)? Ho scoperto che lg n + 1 bit per valore è sufficiente per tracciare i carry e che l'algoritmo è così semplice che sarei sorpreso se fosse sbagliato. Si noti che, sebbene un singolo incremento possa richiedere tempo O (lg n), il costo aggregato per gli incrementi di x è O (x).
  • L'algoritmo di moltiplicazione polinomiale del documento è errato o sono presenti condizioni che sto violando? L'articolo utilizza una rapida trasformata di Fourier invece di una trasformazione teorica numerica, che potrebbe essere un problema.
  • Molte persone intelligenti hanno perso un'ovvia variante dell'algoritmo di Schönhage – Strassen da 40 anni? Questo sembra di gran lunga il meno probabile.

In realtà ho scritto codice per implementarlo, ad eccezione dell'efficiente moltiplicazione polinomiale (non capisco ancora abbastanza bene la trasformazione teorica dei numeri). Test casuali sembrano confermare che l'algoritmo è corretto, quindi il problema è probabilmente nell'analisi della complessità temporale.


Il quadrato non dovrebbe includere x^10 + 2x^8? x ^ 10 solo una volta (x ^ 5 * x ^ 5) e x ^ 8 due volte (x ^ 6 * x ^ 2 + x ^ 2 * x ^ 6)
Sjoerd

Ho fatto l'esempio a mano. Ho fatto un errore aritmetico. Scusa. In realtà ho implementato l'algoritmo, testandolo e ottenendo risultati corretti, però.
Craig Gidney,

Risposte:


13

Il tuo algoritmo è molto simile a Schönhage – Strassen. Nel passaggio FFT, ci sono molti numeri coinvolti - come dici tu, le loro dimensioni possono essere fino aO(logn). L'aritmetica su di loro non viene gratis. Devi applicare la costruzione in modo ricorsivo e perderai qualcosa.


1

L '"errore" qui è che una trasformazione di Fourier può essere calcolata in O (n log n) fasi di aggiunta o moltiplicazione dei numeri da trasformare, ma siccome n cresce davvero grande, anche i numeri che vengono trasformati diventano più grandi, il che aggiunge registro altro fattore n.

In pratica, penso che l'uso del punto di virgola mobile di precisione quadruplo (punto di virgola mobile a 128 bit utilizzando due valori doppi) o punto fisso a 128 bit nella FFT sarebbe sufficiente per qualsiasi prodotto che sia abbastanza piccolo da essere calcolato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.