I PRNG possono essere usati per comprimere magicamente roba?


38

Questa idea mi è venuta in mente da bambino che impara a programmare e al primo incontro con PRNG. Non so ancora quanto sia realistico, ma ora c'è lo scambio di stack.

Ecco uno schema di 14 anni per un incredibile algoritmo di compressione:

Prendi un PRNG e seminalo con seed sper ottenere una lunga sequenza di byte pseudo-casuali. Per trasmettere quella sequenza a un'altra parte, devi solo comunicare una descrizione del PRNG, il seme appropriato e la lunghezza del messaggio. Per una sequenza abbastanza lunga, tale descrizione sarebbe molto più breve della sequenza stessa.

Supponiamo ora di poter invertire il processo. Dato abbastanza tempo e risorse computazionali, potrei fare una ricerca della forza bruta e trovare un seme (e PRNG, o in altre parole: un programma) che produca la sequenza desiderata (diciamo una foto divertente di gatti maliziosi).

I PRNG si ripetono dopo che è stato generato un numero sufficiente di bit, ma rispetto ai cicli "tipici" il mio messaggio è piuttosto breve, quindi questo dosaggio non sembra un gran problema.

Voila, un modo efficace (se rube-goldbergiano) per comprimere i dati.

Quindi, supponendo:

  • La sequenza che desidero comprimere è limitata e nota in anticipo.
  • Non sono a corto di contanti o di tempo (solo se è richiesto un importo limitato di entrambi)

Mi piacerebbe sapere

  • C'è un difetto fondamentale nel ragionamento alla base del regime?
  • Qual è il modo standard per analizzare questo tipo di esperimenti mentali?

Sommario

Spesso le buone risposte chiariscono non solo la risposta, ma quello che stavo chiedendo davvero. Grazie per la pazienza di tutti e risposte dettagliate.

Ecco il mio ennesimo tentativo di riepilogo delle risposte:

  • L'angolo PRNG / seed non contribuisce a nulla, non è altro che un programma che produce la sequenza desiderata come output.
  • Il principio del buco del piccione: ci sono molti più messaggi di lunghezza> k di quanti siano i programmi (generazione di messaggi) di lunghezza <= k. Quindi alcune sequenze semplicemente non possono essere l'output di un programma più breve del messaggio.
  • Vale la pena ricordare che l'interprete del programma (messaggio) è necessariamente fissato in anticipo. E il suo design determina il (piccolo) sottoinsieme di messaggi che può essere generato quando viene ricevuto un messaggio di lunghezza k.

A questo punto l'idea del PRNG originale è già morta, ma c'è almeno un'ultima domanda da risolvere:

  • D: Potrei essere fortunato e scoprire che il mio messaggio lungo (ma finito) è solo l'output di un programma di lunghezza <k bit?

A rigor di termini, non è una questione di probabilità poiché il significato di ogni possibile messaggio (programma) deve essere conosciuto in anticipo. O è il significato di qualche messaggio di <k bit o non lo è .

Se scelgo un messaggio casuale di> = k bit in modo casuale (perché dovrei?), Avrei comunque una probabilità evanescente di poterlo inviare usando meno di k bit, e quasi la certezza di non essere in grado di inviare usando assolutamente meno di k bit.

OTOH, se scelgo un messaggio specifico di> = k bit da quelli che sono l'output di un programma inferiore a k bit (supponendo che ci sia un tale messaggio), allora in effetti sto sfruttando i bit già trasmessi al destinatario (il design dell'interprete), che conta come parte del messaggio trasferito.

Finalmente:

Alla fine, entrambi ci dicono la stessa cosa del principio (più semplice) del buco del piccione ci dice su quanto possiamo comprimere: forse per niente, forse alcuni, ma certamente non tanto quanto immaginiamo (a meno che non imbrogliamo).


6
Modifica leggermente la tua domanda e non puoi ancora comprimere ogni stringa (come descritto nelle risposte seguenti), ma ottieni la teoria delle informazioni algoritmiche ( en.wikipedia.org/wiki/Kolmogorov_complexity ). Sostituisci "PRNG" con "Universal Turing machine" e "seed" con "input tape contenente un programma che genera l'output che desidero". La maggior parte dei nastri di input sono più lunghi degli output che generano, ma per ogni output esiste almeno un input che genera tale output.
Wandering Logic,

No, ma la dimensione compressa è l'entropia della fonte ^ _ ^
Navin

5
Se lo implementi davvero, troverai una cosa interessante: per ricostruire input arbitrari, avrai bisogno di un seed + rng che sia, in media, grande quanto i dati originali. Ops.
Marco

Un altro modo per capire perché questo non funziona: anche se un PRNG può generare output arbitrariamente lunghi , non può generare output arbitrari . (L'output di un PRNG sarà sempre un ciclo o modello fisso, limitato dalla dimensione del suo stato.)
Pi Delport,

@PietDelport, Per ogni n esiste un PRNG il cui ciclo è molto più ampio, e la domanda posta non è nota in anticipo. Quindi non sono convinto che il fatto che i PRNG siano ciclici di per sé risolve direttamente la questione.

Risposte:


43

Hai un nuovo brillante schema di compressione, eh? Bene, allora ...

♫ Giochiamo tutti, il gioco dell'entropia ♫

Per essere semplice, suppongo che tu voglia comprimere i messaggi esattamente di bit, per alcuni n fissi . Tuttavia, vuoi essere in grado di usarlo per messaggi più lunghi, quindi hai bisogno di un modo per differenziare il tuo primo messaggio dal secondo (non può essere ambiguo ciò che hai compresso).nn

Quindi, il tuo schema è determinare una famiglia di PRNG / seed in modo tale che se vuoi comprimere, diciamo, , allora scrivi solo un numero k , che identifica un combo seed / PRNG precompilato (e condiviso) che genera quei bit dopo n query. Tutto apposto. Quante stringhe di bit diverse di lunghezza n ci sono? 2 n (puoi scegliere tra due voci; 0 e 1 ). Ciò significa che dovrai calcolare 2 n di queste combo. Nessun problema. Tuttavia, è necessario scrivere k in binario affinché io possa leggerlo. Quanto può arrivare k ? Bene, può essere grande quanto 201000111001knn2n012nkk . Di quanti bit ho bisogno per scrivere 2 n ? log 2 n = n .2n2nlog2n=n

Oops! Il tuo schema di compressione necessita di messaggi purché ciò che stai comprimendo!

"Haha!", Dici, "ma è nel peggiore dei casi! Uno dei miei messaggi sarà mappato su , che ha bisogno di solo 1 bit per rappresentare! Vittoria!"01

Sì, ma i tuoi messaggi devono essere inequivocabili! Come posso distinguere seguito da 0 da 10 ? Poiché alcune delle tue chiavi sono lunghe n , devono essere tutte, altrimenti non posso dire da dove hai iniziato e fermato.1010n

"Haha!", Dici, "ma posso solo mettere la lunghezza della stringa in binario prima! Questo deve solo contare fino a , che può essere rappresentato da log n bit! Quindi il mio 0 ora ha il prefisso con solo log n bit, vinco ancora! "nlogn0logn

Sì, ma ora quei numeri veramente grandi sono preceduti da bit. Il tuo schema di compressione ha reso alcuni dei tuoi messaggi ancora più lunghi! E metà di tutti i tuoi numeri inizia con 1 , quindi metà dei tuoi messaggi è molto più lunga!logn1

Procedi quindi a lanciare più idee come un carattere finale, comprimendo il numero e comprimendo la lunghezza stessa, ma tutti quelli si imbattono in casi in cui il messaggio risultante è solo più lungo. In effetti, per ogni bit salvato su qualche messaggio, un altro messaggio si allungherà in risposta. In generale, ti sposterai sul "costo" dei tuoi messaggi. Accorciare un po 'renderà altri più lunghi. Non puoi davvero inserire messaggi diversi in meno spazio rispetto alla scrittura di 2 n stringhe binarie di lunghezza n .2n2nn

"Haha!", Dici, "ma posso scegliere alcuni messaggi come" stupidi "e renderli illegali! Quindi non ho bisogno di contare fino a , perché non supporto così tanti messaggi!"2n

Hai ragione, ma non hai davvero vinto. Hai appena ridotto la serie di messaggi supportati. Se supportato solo e b = 111.111.110.101.000 come i messaggi inviati, allora si può sicuramente basta avere il codice di un 0 , b 1 , che corrisponde esattamente quello che ho detto. Qui, n = 1 . La lunghezza effettiva dei messaggi non è importante, è quanti ce ne sono.a=0000000011010b=111111110101000a0b1n=1

"Haha!", Dici, "ma posso semplicemente determinare che quegli stupidi messaggi sono rari! Renderò quelli rari grandi e quelli comuni piccoli! Poi vincerò in media!"

Sì! Congratulazioni, hai appena scoperto l' entropia ! Se si dispone di messaggi, dove la i esima messaggio ha probabilità p i di essere inviato, allora si può ottenere la lunghezza messaggio previsto verso l'entropia H = Σ n i = 1 p i log ( 1 / p I ) di questo insieme di messaggi. È una specie di strana espressione, ma tutto quello che devi sapere è che è più grande quando tutti i messaggi sono ugualmente probabili e più piccoli quando alcuni sono più comuni di altri. All'estremo, se sai praticamente ogni messaggio sarà unnipiH=i=1npilog(1/pi) . Quindi puoi usare questo codice super efficiente: a 0 , x 1 x altrimenti. Allora la vostra lunghezza del messaggio previsto è fondamentalmente 1 , che è impressionante, e che sta per essere davvero vicino alla entropia H . Tuttavia, H ha un limite inferiore e non puoi davvero batterlo, non importa quanto ci provi.a=000111010101a0x1x1HH

Qualunque cosa che pretenda di battere l'entropia probabilmente non sta fornendo abbastanza informazioni per recuperare in modo inequivocabile il messaggio compresso, o è semplicemente sbagliata. L'entropia è un concetto così potente che possiamo limitare il limite (e talvolta anche il limite superiore ) del tempo di esecuzione di alcuni algoritmi con esso, perché se corrono molto velocemente (o molto lentamente), allora devono fare qualcosa che viola l'entropia .


13
Ragazzo, sembro sciocco quando fai finta di essere me. Grazie a Dio posso essere orgoglioso di aver scoperto l'entropia. Scherzi a parte, questa è una buona risposta - Se solo il tono non fosse così macchiato di beffa.

6
Non avevo intenzione di deridere, stavo solo giocando con l'idea di "uno schema di 14 anni per un incredibile algoritmo di compressione". :)
Alexis Beingessner il

3
Neanche a me è sembrato deridere :) Questo è uno schema abbastanza comune per spiegare i problemi nella scienza popolare (e in alcuni altri campi), anche se è vero che "chi chiede" di solito è Alice o Bob piuttosto che un "vero" persona: D Vedi con quanta facilità riesci improvvisamente a capire quanto sia complesso il problema! (per non parlare del fatto che quando sto pensando a un problema complesso nella mia testa, uso lo stesso processo: un dialogo interiore è incredibilmente bravo a simulare "più teste ne sanno di più")
Luaan

2
@SteveJessop, questa è una falsa dicotomia e non andiamo lì. È una buona risposta e forse sono troppo sensibile, ecco.

3
@chipmonkey, penso che sia ancora coperto dalla risposta di Alexis sul "gioco dell'entropia". Probabilmente, il numero di algoritmi richiesti per farlo sarebbe così grande, che il numero di bit necessari per specificare quale era usato avrebbe annullato il vantaggio.

21

Ci sono stringhe binarie di lunghezza inferiore a N , e 2 N stringhe binarie di lunghezza esattamente N . Ciò significa che qualunque sia il tuo algoritmo di compressione , ci deve essere una stringa che non può affatto comprimere, solo perché il mapping dalla stringa originale alla stringa compressa deve essere iniettivo (uno a uno). Questa è la forza trainante di molte applicazioni della complessità di Kolmogorov.2N1N2NN

Nella vita reale, spesso sappiamo qualcosa sulla sequenza che stiamo comprimendo, diciamo che è la voce o un'immagine. Nel caso della compressione senza perdita, il teorema di codifica della sorgente di Shannon mostra che il tasso di compressione ottimale è uguale all'entropia della sorgente. Per la codifica con perdita di dati ci sono altri teoremi nella teoria dell'informazione (teoria della distorsione della frequenza). Quindi, anche in questo caso, esiste un limite a quanto è possibile comprimere i dati.


Non l'ho mai visto in questo modo, ma questo mi è venuto in mente: fondamentalmente, Shannon dice che anche il caso migliore non può essere compresso arbitrariamente e il Principio di Pigeonhole garantisce che ci deve essere un caso peggiore che non può essere compresso affatto. È una caratterizzazione sensata?
Jörg W Mittag,

1
Il caso migliore può sempre essere compresso, poiché puoi includere alcune stringhe come caso speciale del tuo algoritmo di compressione. Questo argomento funziona non solo per il caso peggiore ma anche per il caso medio, dimostrando che la compressione media è al massimo di 2 bit.
Yuval Filmus,

Ah certo. if input.empty? then output_very_long_stringdarebbe un rapporto di compressione infinito come il caso migliore. In realtà, esiste persino un algoritmo di compressione che lo utilizza. (Ho dimenticato il nome, purtroppo.) Esso è destinato per brevi stringhe, e ha codifiche speciali per sottostringhe hard-coded come http://, www., .come così via.
Jörg W Mittag,

Posso battere questo argomento se ho un modo di progettare una famiglia di PRNG in modo tale che le sequenze che non possono esprimere siano quelle che escludo in anticipo? (mi viene in mente la modellatura del rumore).

3
H=ipilog1/pipiH

7

sk2kn2nns

(Come notato un'altra risposta, questo accadrà per qualsiasi funzione di compressione scelta.)


Di per sé ciò non dimostra che non riesco a costruire un PRNG che generi semplicemente la sequenza prescelta come uno dei suoi possibili output, mentre per farlo richiede molti meno bit. Come capisco dalle altre risposte, l'entropia applica in modo dimostrabile un limite inferiore al numero di bit richiesti. Cioè, semplicemente non posso fare arbitrariamente bene per la sequenza prescelta.

Tutto ciò che dice è che se fate la vostra PRNG preferito, allora io posso venire a voi con una sequenza non produce, che rompe già la vostra idea. Un'affermazione più forte è che ci sono sequenze che non sono emesse da nessun programma molto più breve. (In altre parole, perdi ancora anche se ti lascio cambiare la tua funzione dopo aver visto la mia sequenza. Questo è ciò a cui Yuval allude con la "complessità di Kolmogorov".)
Louis

4

Accanto ad altri punti già risolti, voglio solo aggiungere questo link: https://www.schneier.com:443/blog/archives/2009/09/the_doghouse_cr.html

Ora, la produzione di energia annuale del nostro sole è di circa 1,21 × 10 ^ 41 erg. Questo è sufficiente per alimentare circa 2,7 × 10 ^ 56 modifiche a bit singolo sul nostro computer ideale; abbastanza cambiamenti di stato per mettere un contatore a 187 bit attraverso tutti i suoi valori. Se costruissimo una sfera Dyson attorno al sole e catturassimo tutta la sua energia per 32 anni, senza alcuna perdita, potremmo alimentare un computer per contare fino a 2 ^ 192. Ovviamente, non sarebbe rimasta l'energia per eseguire calcoli utili con questo contatore.

Quindi solo iterare (senza confrontare ...) per trovare una costellazione valida a 187 bit dei dati desiderati richiederebbe in condizioni ideali (non raggiungibili) più energia di quella che il sole emette in un anno.


1

Una prova molto rapida che non può esistere un compressore universale. Supponiamo che tu ne faccia uno e comprimi un input. Ora comprimi iterativamente l'output del tuo programma. Se riesci sempre a ridurne le dimensioni, diventerà sempre più piccolo ad ogni passo, fino a quando non scendi a 1 bit.

Potresti sostenere che, forse, l'output del tuo algoritmo ha una struttura tale da non poter essere più compresso, ma poi potresti semplicemente applicare uno shuffle deterministico * prima di ricomprimerlo.

Nota a piè di pagina: alcuni shuffling deterministici aiutano effettivamente in alcuni schemi di compressione: http://pytables.github.io/usersguide/optimization.html?highlight=shuffling#shufflingoptim


Penso che ti manchi che ogni messaggio compresso abbia un seme sassociato ad esso. Il messaggio 01001011 con un ´s´ di 2348 differirà dallo stesso messaggio con un ´s´ di 3924. A meno che non abbia frainteso l'algoritmo di foo1899 in alcun modo.
Azeirah,

1

L'uso di un PRNG per la "compressione" è sostanzialmente utile in una situazione: quando è necessario utilizzare un gruppo di dati "casuale" e registrare in modo compatto quali dati sono stati utilizzati. La maggior parte dei generatori pseudo-casuali può generare solo una minima parte delle possibili sequenze, ma se si necessita solo di un numero da piccolo a moderato di sequenze "casuali", la frazione di possibili sequenze che un PRNG può generare sarà spesso più che adeguata.

Se la sequenza di dati che si desidera archiviare accade coincidente per coincidenza con ciò che un determinato PRNG genererebbe dato il seme giusto, la memorizzazione del seme può essere un'alternativa compatta alla memorizzazione dei dati. A meno che la fonte di dati non sia tale che è probabile che si verifichino tali corrispondenze, tuttavia, sarebbero così rare che la ricerca di tali dati non sarebbe utile.


I PRNG vengono utilizzati in questo modo per rappresentare in modo compatto (pseudo) dati casuali, ad esempio per motivi di ripetibilità degli esperimenti.
Yuval Filmus,

1
@YuvalFilmus: esattamente. Possono anche essere utilizzati in alcune situazioni come la generazione di livelli di videogiochi in cui una piccola parte dei livelli generati sarebbe considerata accettabile, ma in cui un progettista di videogiochi può generare casualmente livelli fino a quando non trova alcuni di suo gradimento e registrare i semi che generato quelli. Un concetto molto utile storicamente, quando si codifica per una macchina per videogiochi con 128 byte di RAM, cercando di adattare il programma a una cartuccia con 4096 byte di ROM.
supercat

Questo è un ottimo esempio, corrisponde allo schema che ho descritto per cercare un seme "buono", ma sfrutta il fatto che in quello scenario molti messaggi possibili sono buoni.

@ foo1899: Per inciso, il gioco "Pitfall" en.wikipedia.org/wiki/Pitfall ! utilizzato la tecnica di cui sopra per utilizzare generare una mappa di 256 schermi su una cartuccia di gioco 4K su una macchina con 128 byte di RAM.
supercat

1

Qualcosa da considerare per aggiungere alla cacofonia di risposte che affermano perché ci sono alcune stringhe che non possono essere compresse a causa, per definizione, della natura iniettiva della decompressione e dell'universo limitato di stringhe compresse da cui selezionare per rappresentare i messaggi è questo: la maggior parte delle stringhe non può essere compressa perché ci sono molte più alte entropie, stringhe disordinate rispetto a quelle più basse e strutturate, dando quindi origine alla condizione che vediamo in pratica che: la compressione è il più delle volte utile, poiché i messaggi il più delle volte desiderano comprimere sono quelli più spesso possessivi di qualche aliquota di ordine e struttura, e per questo motivo, fanno parte dell'universo molto più piccolo di oggetti di entropia inferiore. Ciò significa che è possibile che, scegliendo una lunghezza di uscita adeguata, possiamo comprimere tutto nell'universo più piccolo e strutturato. Il termine strutturato, entropia e ordinato qui sono deliberatamente imprecisi, per riflettere le definizioni soggettive della semantica e dell'utilità dei messaggi che potremmo voler comprimere.

E in risposta diretta alla richiesta dell'interrogatore: * sì, ovviamente potresti semplicemente essere fortunato e scoprire che l'output del tuo PRNG è il messaggio esatto che desideri comprimere, è solo che così spesso non troverai questo è il caso perché la stessa proprietà che caratterizza un PRNG, vale a dire la sua capacità di produrre una varietà (quasi) infinita di stringhe diverse, rende concomitantemente improbabile produrre il tuo.

Ovviamente potresti mitigare questa improbabilità usando un PRNG per camminare su un "grafico di dominio" delle transizioni da parola a parola, e aumenti notevolmente la probabilità di apparizione del tuo messaggio, e scopri anche che ora devi aggiungere il grafico di dominio al messaggio compresso lunghezza.

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.