Quali classi di strutture dati possono essere rese persistenti?


19

Le strutture di dati persistenti sono strutture di dati immutabili. Le operazioni su di essi restituiscono una nuova "copia" della struttura dei dati, ma modificata dall'operazione; la vecchia struttura di dati rimane tuttavia invariata. L'efficienza si ottiene generalmente condividendo alcuni dei dati sottostanti ed evitando la copia completa della struttura dei dati.

Domande:

  • Esistono risultati su classi di strutture di dati che possono essere resi persistenti (pur mantenendo le stesse o molto simili complessità)?

  • È possibile rendere persistenti tutte le strutture di dati (mantenendo le stesse complessità o molto simili)?

  • È noto che alcune strutture di dati non possono essere rese persistenti (pur mantenendo le stesse complessità o molto simili)?


1
Non è possibile rendere persistente un vettore con complessità O (1) preservata per l'accesso a un elemento casuale.
smossen


2
@smossen puoi dimostrarlo?
Realz Slaw,

1
La tua prima domanda è molto ampia. Ci sono molti risultati sull'argomento delle strutture di dati che possono essere resi persistenti. Si potrebbe scrivere un intero libro sull'argomento, e alcune persone hanno: per esempio, il libro di Okasaki è un classico sull'argomento. Hai fatto qualche ricerca su questo argomento? Puoi restringere la domanda? Allo stato attuale, sospetto che potrebbe essere troppo ampio per essere adatto a questo sito. Forse dividere la terza domanda in una domanda separata?
DW

@Realz Slaw: non posso provarlo formalmente, ma penso che sia buon senso. O (1) l'accesso agli elementi nei vettori (comprese le tabelle hash) dipende dal tempo fisso per la decodifica degli indirizzi su un determinato hardware. La persistenza aggiunge una o due dimensioni oltre all'indice vettoriale. Ma gli indirizzi hardware sono ancora monodimensionali.
smossen

Risposte:


22

Risultato positivo: la persistenza non costa troppo. Si può dimostrare che ogni struttura di dati può essere resa completamente persistente con al massimo un rallentamento .O(lgn)

Prova: puoi prendere un array e renderlo persistente usando strutture di dati standard (es. Un albero binario bilanciato; vedi la fine di questa risposta per un po 'più di dettaglio). Ciò comporta un rallentamento : ogni accesso all'array impiega il tempo con la struttura dei dati persistenti, anziché il tempo per l'array non persistente. Ora prendi qualsiasi algoritmo imperativo il cui tempo di esecuzione nel modello RAM è , dove indica la quantità di memoria utilizzata. Rappresenta tutta la memoria come un grande array (con elementi) e rendila persistente usando una mappa persistente. Ogni fase dell'algoritmo imperativo comporta al massimo un rallentamento , quindi il tempo di esecuzione totale èO(lgn)O(lgn)O(1)O(f(n))nnO(lgn)O(f(n)lgn) .

Apparentemente è possibile fare un po 'meglio: apparentemente si può ridurre il fattore di rallentamento a (tempo previsto, ammortizzato), usando le tecniche nel documento Demaine citato di seguito - ma non ho familiarità con i dettagli di quel lavoro, quindi non posso garantirlo io stesso. Grazie a jbapple per questa osservazione.O(lglgn)


Risultato negativo: non è possibile evitare qualche rallentamento, per alcune strutture di dati. Per rispondere alla tua terza domanda, esistono strutture di dati in cui è noto che renderle persistenti introduce un certo rallentamento.

In particolare, considera una matrice di elementi. Senza persistenza, ogni accesso all'array richiede tempo (nel modello RAM). Con persistenza, è stato apparentemente dimostrato che non c'è modo di costruire un array persistente con la complessità peggiore di per accedere a un elemento casuale. In particolare, a quanto pare esiste un limite inferiore che mostra che le matrici completamente persistenti devono avere un tempo di accesso di . Questo limite inferiore è affermato a p.3 del seguente documento:nO(1)O(1)Ω(lglgn)

Il limite inferiore è attribuito a Mihai Patrascu, ma non vi è alcuna citazione da una fonte che fornisca i dettagli della prova di questo limite inferiore affermato.


Una ricca area di ricerca. Se prendiamo una struttura di dati o un algoritmo arbitrari, è un po 'una domanda delicata se puoi renderlo persistente al massimo con rallentamento o meno. Non conosco alcun teorema di classificazione generale. Tuttavia, ci sono molte ricerche su come rendere persistenti strutture dati specifiche, in modo efficiente.O(1)

Esiste anche una forte connessione con linguaggi di programmazione funzionali. In particolare, ogni struttura di dati che può essere implementata in modo puramente funzionale (senza mutazioni) è già una struttura di dati persistente. (Il contrario non è necessariamente il caso, ahimè.) Se vuoi strizzare gli occhi, potresti prenderlo come una sorta di teorema di classificazione parziale debole: se è implementabile in un linguaggio di programmazione puramente funzionale con gli stessi limiti di tempo come in un linguaggio imperativo, quindi esiste una struttura dati persistente con gli stessi limiti temporali di quella non persistente. Mi rendo conto che questo probabilmente non è quello che stavi cercando - è soprattutto solo una banale riformulazione della situazione.


Come creare un array persistente. Non tenterò di descrivere la costruzione di come costruire un array completamente persistente con il tempo di accesso nel caso peggiore . Tuttavia, le idee di base non sono troppo complicate, quindi riassumerò l'essenza delle idee.O(lgn)

L'idea di base è che possiamo prendere qualsiasi struttura di dati ad albero binario e renderla persistente usando una tecnica chiamata copia del percorso . Diciamo che abbiamo un albero binario e vogliamo modificare il valore in qualche foglia . Tuttavia, per persistenza, non osiamo modificare il valore in quella foglia in atto. Invece, facciamo una copia di quella foglia e modifichiamo il valore nella copia. Quindi, creiamo una copia del suo genitore e cambiamo il puntatore figlio appropriato nella copia per puntare alla nuova foglia. Continua in questo modo, clonando ciascun nodo sul percorso dalla radice alla foglia. Se vogliamo modificare una foglia in profondità , questo richiede la copia nodi.d ddd

Se abbiamo un albero binario bilanciato ha nodi, allora tutte le foglie hanno profondità , quindi questa operazione sull'albero binario richiede tempo . Ci sono alcuni dettagli che sto saltando: per ottenere caso peggiore, potremmo aver bisogno di riequilibrare l'albero per assicurarci che rimanga equilibrato, ma questo ci dà l'idea.O ( lg n ) O ( lg n ) O ( lg n )nO(lgn)O(lgn)O(lgn)

Puoi trovare ulteriori spiegazioni, con belle immagini, alle seguenti risorse:

Questo ti darà l'idea principale. Ci sono ulteriori dettagli di cui occuparsi, ma i dettagli non rientrano nell'ambito di questa domanda. Fortunatamente, questo è tutto roba standard e ci sono molte informazioni disponibili in letteratura su come costruire tali strutture di dati. Sentiti libero di fare una domanda separata se le risorse di cui sopra non sono sufficienti e vuoi maggiori informazioni sui dettagli della costruzione di una struttura di dati di array persistente.


Non capisco davvero il primo paragrafo, come potrei fare per rendere persistente un array usando un albero rosso-nero?
G. Bach,

@ G. Bach, c'è una spiegazione abbastanza buona nelle sezioni intitolate "Alberi di ricerca binaria" e "Strutture ad accesso casuale" (in particolare, il metodo dell'albero) su toves.org/books/persist/index.html . Per un'altra bella descrizione, vedere netcode.ru/dotnet/?artID=6592#BinaryTrees e alcune delle sezioni successive. Questo ti darà l'idea principale. I dettagli non rientrano nell'ambito di questa domanda, ma si tratta di elementi standard; Ti incoraggio a porre una domanda separata se desideri ulteriori informazioni su come costruire una tale struttura di dati.
DW

4
Buona risposta, DW Puoi ridurre il tempo a (atteso ammortizzato) . Vedi "Confluently Persistent Tries forO(lglgn)
Demoine
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.