Come possiamo supporre che le operazioni di base sui numeri richiedano un tempo costante?


74

Normalmente negli algoritmi non ci interessa il confronto, l'aggiunta o la sottrazione dei numeri - supponiamo che vengano eseguiti nel tempo . Ad esempio, assumiamo questo quando affermiamo che l'ordinamento basato sul confronto è , ma quando i numeri sono troppo grandi per essere inseriti nei registri, normalmente li rappresentiamo come array, quindi le operazioni di base richiedono calcoli aggiuntivi per elemento.O ( n registro n )O(1)O(nlogn)

Esiste una prova che dimostra che il confronto di due numeri (o altre funzioni aritmetiche primitive) può essere fatto in ? In caso contrario, perché stiamo dicendo che l'ordinamento basato sul confronto è ?O ( n registro n )O(1)O(nlogn)


Ho incontrato questo problema quando ho risposto un SO domanda e mi sono reso conto che il mio algoritmo non è perché prima o poi avrei dovuto affrontare grandi int, anche non è stato algoritmo di tempo pseudo polinomiale, era .PO(n)P


3
Se stai per contare la complessità del confronto dei numeri, dovresti anche scrivere i tuoi limiti di complessità in termini di dimensione dei bit dell'input. Quindi, dato -bit numeri, la dimensione bit dell'ingresso è e l'ordinamento può essere fatto in tempo. w n = N w O ( N w log N ) = O ( n log n )N wn=NwO(NwlogN)=O(nlogn)
Sasho Nikolov,

2
ci sono fondamentalmente due "regni" o "regimi" di studio della complessità. generalmente si operazioni operazioni a "larghezza fissa" che è un'approssimazione ragionevole per la maggior parte dei linguaggi che hanno rappresentazioni di numeri a larghezza fissa anche per virgola mobile, ad esempio 2-4 byte (vedere ad esempio gli standard IEEE). poi c'è "aritmetica di precisione arbitraria" in cui i numeri hanno dimensioni arbitrarie e c'è uno studio più attento / preciso della complessità delle operazioni. il primo è più nell'analisi applicata e il secondo è più nell'analisi teorica / astratta. O(1)
vzn

Risposte:


75

Per le persone come me che studiano algoritmi per vivere, il modello di calcolo standard del 21 ° secolo è la RAM intera . Il modello intende riflettere il comportamento dei computer reali in modo più accurato rispetto al modello della macchina di Turing. I computer del mondo reale elaborano numeri interi a più bit in tempo costante utilizzando hardware parallelo; non interi arbitrari , ma (poiché le dimensioni delle parole crescono costantemente nel tempo) non sono neppure numeri interi fissi .

Il modello dipende da un singolo parametro , chiamato dimensione della parola . Ogni indirizzo di memoria contiene un singolo numero intero -bit, o parola . In questo modello, la dimensione di input è il numero di parole nell'input e il tempo di esecuzione di un algoritmo è il numero di operazioni sulle parole . Le operazioni aritmetiche standard (addizione, sottrazione, moltiplicazione, divisione di numeri interi, resto, confronto) e operazioni booleane (bit a bit e, o, xor, shift, rotazione) sulle parole richiedono tempo per definizione .w n O ( 1 )wwnO(1)

Formalmente, la dimensione della parola NON è una costantew ai fini dell'analisi degli algoritmi in questo modello. Per rendere il modello coerente con l'intuizione, abbiamo bisogno di , poiché altrimenti non possiamo nemmeno memorizzare l'intero in una sola parola. Tuttavia, per la maggior parte degli algoritmi non numerici, il tempo di esecuzione è in realtà indipendente da , poiché quegli algoritmi non si preoccupano della rappresentazione binaria sottostante del loro input. Mergesort e heapsort vengono eseguiti entrambi nel tempo ; median-of-3-quicksort viene eseguito nel tempo nel peggiore dei casi. Un'eccezione notevole è l'ordinamento binario radix, che viene eseguito nel tempo .n w O ( n log n ) O ( n 2 ) O ( n w )wlog2nnwO(nlogn)O(n2)O(nw)

L'impostazione ci fornisce il tradizionale modello RAM a costo logaritmico. Ma alcuni algoritmi RAM interi sono progettati per dimensioni di parole più grandi, come l'algoritmo di ordinamento di numeri interi a tempo lineare di Andersson et al. , che richiede .w = Ω ( log 2 + ε n )w=Θ(logn)w=Ω(log2+εn)

Per molti algoritmi che sorgono in pratica, la dimensione della parola è semplicemente un problema e possiamo (e fare) ricadere sul modello RAM a costo uniforme molto più semplice. L'unica difficoltà seria viene dalla moltiplicazione nidificato, che può essere utilizzato per costruire molto grandi numeri interi molto rapidamente. Se potessimo eseguire l'aritmetica su interi arbitrari in tempo costante, potremmo risolvere qualsiasi problema in PSPACE in tempo polinomiale .w

Aggiornamento: dovrei anche menzionare che ci sono eccezioni al "modello standard", come l'algoritmo di moltiplicazione di numeri interi di Fürer , che utilizza macchine Turing multitape (o equivalentemente, il "bit RAM") e la maggior parte degli algoritmi geometrici, che sono analizzati in modo teorico modello "RAM reale" pulito ma idealizzato .

Sì, questa è una lattina di vermi.


3
So che dovrei votare, ma non riesco a impedirmi di dirlo: questa è la risposta migliore. Il trucco è che (1) le operazioni aritmetiche sono tempo costante per definizione e va bene perché in teoria puoi scegliere qualsiasi modello e (2) dovresti avere alcuni motivi per scegliere un certo modello, e questa risposta spiega quali sono.
rgrig,

Sono d'accordo con rgig, (anche io dovrei solo votare), ma un piccolo problema è che la dimensione di input non è correlata ai numeri di input, ad esempio se ho un input mio numero più grande è , e se scelgo il modello di calcolo come piace a me, questo fa sì che l'algoritmo del tempo pseudo polinomiale diventi , vero? nmP

1
Se il tuo input è costituito da numeri con più di bit, quindi per adattarsi al modello devi dividerli in blocchi -bit, proprio come nella vita reale. Ad esempio, se l'input è costituito da numeri interi compresi tra e , la dimensione effettiva dell'input è . Pertanto, i tempi di esecuzione pseudo-polinomiali come il tempo sono ancora esponenziali nella dimensione dell'input quando è grande. wwN0MNlogwM=(NlgM)/(lgw)O(NM)M
JeffE,

Esistono algoritmi analizzati nel modello Real RAM che non sono segretamente algoritmi "Order Type RAM"? Non ci ho mai pensato molto, ma non riesco a trovare rapidamente un esempio che non lo sia.
Louis,

1
@ Louis: Sì, molti: diagrammi di Voronoi, percorsi più brevi euclidei, talee ricorsive, alberi di partizione semplici, .... Ma il miglior esempio è l'eliminazione gaussiana, che gira in tempo sul modello RAM reale (o la RAM intera a costo unitario, ma necessita del tempo sulla RAM intera.O(n3)O(n4)
JeffE

24

Dipende solo dal contesto. Quando si ha a che fare con la complessità degli algoritmi a livello di bit , non diciamo che l'aggiunta di due numeri di bit sia , diciamo che è . Allo stesso modo per la moltiplicazione ecc.nO(1)O(n)


Dal tuo articolo di riferimento: "può essere misurato in due modi diversi: uno in termini di numeri interi testati o moltiplicati e uno in termini di numero di cifre binarie (bit) in tali numeri interi", ma non è vero, noi dovrebbe sempre misurare in base alla dimensione dell'input.

1
@SaeedAmiri: dipende solo dalla codifica utilizzata. Nell'articolo, ad esempio, se l'input è un numero intero specificato utilizzando la codifica unaria, la divisione di prova richiederà solo . Questo è polinomiale nella dimensione dell'input! Questo significa che il factoring per divisione di prova è in ? No, l'algoritmo è pseudo-polinomiale . Utilizzando la codifica binaria comune, si ottiene un algoritmo esponenziale, sempre nella dimensione dell'input. Come detto, ciò accade perché il numero di bit nell'ingresso è diventato esponenzialmente più piccolo cambiando la sua codifica. nθ(n1/2)Pn
Massimo Cafaro,

A proposito, gli algoritmi pseudo-polinomiali possono effettivamente essere utili, se l'ordine di grandezza dei loro parametri in casi reali è ragionevolmente basso. L'esempio più famoso è probabilmente l'algoritmo pseudo-polinomiale per risolvere il problema dello zaino.
Massimo Cafaro,

Per prima cosa dovrei menzionare che la tua pagina wiki di riferimento non è buona perché non ha buoni riferimenti, inoltre non so perché pensi che sto parlando di algoritmi di tempo pseudo-polinomiali, potrebbe essere perché la dimensione di input normalmente è collo di bottiglia in questi casi? ma non sto parlando di loro, sto parlando principalmente di problemi che sono in anche supponendo la dimensione dell'input, come l'ordinamento, comunque perché non possiamo barare e dire che il problema NPC è in Penso che non dovremmo diciamo che l'ordinamento è tranne che abbiamo una prova formale per ignorare il confronto. PPO(nlogn)

Sto discutendo algoritmi pseudo-polinomiali per focalizzare la vostra attenzione sulla dimensione dell'input, per mostrarvi che può essere fuorviante. Ecco un altro esempio. Ti viene dato un numero naturale come input, diciamo , e l'algoritmo esegue un ciclo in cui esegue operazioni temporali per iterazioni. La complessità di questo semplice algoritmo ad anello misurato in funzione della dimensione dell'ingresso, è . Poiché è la dimensione di input, l'algoritmo è esponenziale nella dimensione di input! Pensaci. Ora puoi capire cosa intendo con "Dipende solo dal contesto". O ( 1 ) n O ( n ) = O ( 2 l g n ) l g nnO(1)nO(n)=O(2lgn)lgn
Massimo Cafaro,

16

Per rispondere alla domanda come indicato: gli algoritmi lo fanno, abbastanza spesso, usando il modello RAM. Per l'ordinamento, in molti casi, le persone analizzano anche il modello di confronto più semplice , di cui discuto un po 'di più nella risposta collegata.

Per rispondere alla domanda implicita sul perché lo fanno: direi che questo modello ha un buon potere predittivo per alcuni tipi di algoritmi combinatori, in cui i numeri sono tutti "piccoli" e, su macchine reali, si inseriscono nei registri.

Per rispondere al follow-up implicito sugli algoritmi numerici: No, il semplice vecchio modello RAM non è lo standard qui. Anche l'eliminazione gaussiana può richiedere qualche cura. In genere, per i calcoli dei ranghi, entrerà il Schwartz Lemma (ad es., Sezione 5 qui ). Un altro esempio canonico è l'analisi dell'algoritmo ellissoide, che richiede una certa attenzione per l'analisi.

E infine: le persone hanno già pensato all'ordinamento delle stringhe , anche di recente.

Aggiornamento: il problema con questa domanda è che "noi" e "assumiamo" non sono così specificati. Direi che le persone che lavorano nel modello RAM non stanno facendo algoritmi numerici o teoria della complessità (dove determinare la complessità della divisione è stato un risultato celebre ).


Hmmmm, sembra una risposta interessante ....

C'è un motivo per cui non risponde completamente alla domanda?
Louis,

7

Non sono riuscito a trovare studi su questo, ma Kozen afferma nell'introduzione a "Il design e l'analisi degli algoritmi" che il modello "riflette l'osservazione sperimentale in modo più accurato [rispetto al modello log-cost] per dati di moderato dimensione (poiché la moltiplicazione richiede davvero un'unità di tempo). " Fornisce anche un riferimento a questo documento come esempio di come il modello possa essere abusato.O ( 1 )O(1)O(1)

Questo non è assolutamente una valutazione legittima (se non altro perché si tratta di Python), ma ecco alcuni numeri da corsa python -mtimeit "$a * $b"per $ain e . (Mi sono fermato a 66 perché è allora che la sintassi di Python smette di accettare valori letterali interi e dovrei cambiare leggermente il mio codice di valutazione, quindi non l'ho fatto.: P)10{1,2,...,66}$b = 2*$a

1050log10(sys.maxint)


O(n)O(nlognlogm)

7

O(1)

O(logM)O(NlogN)O(NlogNlogM)

M


O(logm)O(logn)m

O(logN)

nnnn

Hai ragione, ho corretto la mia risposta.
Erel Segal-Halevi,

4

Direi che in genere assumiamo operazioni aritmetiche O (1) perché di solito facciamo cose nel contesto di numeri interi a 32 bit o numeri interi a 64 bit o numeri in virgola mobile IEEE 754. O (1) è probabilmente una buona approssimazione per quel tipo di aritmetica.

Ma in generale, questo non è vero. In generale è necessario un algoritmo per eseguire addizioni, sottrazioni, moltiplicazioni e divisioni. La calcolabilità e la logica di Boolos, Burgess e Jefferies vengono in mente come un modo per comprenderne le prove, in termini di un paio di diversi sistemi formali, funzioni ricorsive e macchine Abacus, almeno nella mia copia della 4a edizione.

Puoi guardare i termini lambda-calcolo per sottrazione e divisione con i numeri di chiesa per una spiegazione chiara del perché queste due operazioni non sono O (1). È un po 'più difficile vedere per addizione, moltiplicazione ed esponenziazione, ma è lì se si considera la forma dei numeri della Chiesa stessi.

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.