Tempo medio di uscita di una stringa

Parametro del calcolo probabilistico nell'analisi testuale

Definizione

modifica

Nella teoria delle probabilità il tempo medio di uscita di una stringa è il calcolo della previsione di uscita di una stringa prefissata di   caratteri estraendo casualmente le lettere da un insieme finito di caratteri, dato dalla formula  , dove:

  •   è il numero totale di caratteri dell'alfabeto di riferimento
  •   è un insieme di indici che contiene i valori
    • la posizione del primo carattere, pari a  
    • la posizione dell'ultimo carattere, pari alla lunghezza   della stringa
    • le posizioni di ogni sotto-stringa ripetuta all'interno della stringa
  •   è una variabile aleatoria che definisce il tempo di uscita della stringa

Per calcolare la previsione è necessario anche conoscere la probabilità di uscita di un carattere dall'insieme totale dei caratteri, dato da  , dove   è una variabile aleatoria che può assumere i valori di un carattere dell'alfabeto, mentre l'evento   definisce l'uscita del carattere   alla  -esima estrazione.

Esempio

modifica

Si calcola la previsione del tempo medio di uscita della parola ABRACADABRA utilizzando l'alfabeto inglese composto da ventisei lettere.

Utilizzando la definizione si ha che  

Si osserva che   contiene le posizioni del primo e dell'ultimo carattere, oltre alla posizione dell'ultimo carattere della sotto-stringa ABRA ripetuta.

Da ciò ne deriva che  , ossia il tempo medio di uscita della parola ABRACADABRA è dopo aver effettuato circa   miliardi di digitazioni casuali su una tastiera di   caratteri.

Passaggio al limite

modifica

Si può facilmente vedere che la previsione del tempo medio di uscita di una stringa è una funzione divergente all'aumentare del numero di caratteri da estrarre. Pertanto, il limite della previsione per un numero di caratteri che tende all'infinito è pari a infinito, ossia  .

Intuitivamente si può calcolare il limite, considerando l'ipotesi che non esistano sotto-stringhe ripetute. Se questo limite tende a infinito a maggior ragione il limite nel caso di ripetizioni tende ad infinito. Si può non tenere conto dell'indice iniziale, pari sempre a uno, in quanto nel calcolo del limite sarebbe una costante. In base a queste considerazioni si osserva che   e se il limite di   per   che tende a infinito è pari a infinito, allora anche il limite   sarà pari a infinito. Per ogni   la funzione   è divergente, quindi  .

Enunciato

modifica

Sia   un insieme di   caratteri, con  . Si può definire una stringa prefissata   di lunghezza   caratteri tale che  .

Sia   uno spazio di probabilità, tale che  ,   è una  -algebra di   e   una misura di probabilità sullo spazio  . Su questo spazio si può costruire una successione di variabili aleatorie   tali che  .

Sia   il tempo più piccolo entro il quale al tempo   la successione   realizza la stringa  . Si definisce   il tempo di uscita della stringa.

Si prova che  , con  .

Dimostrazione

modifica

Sia   una filtrazione tale che   e  , ossia la  -algebra generata dalla successione di variabili aleatorie al tempo  .

Osservazione 1

modifica

  e   sono dei tempi di arresto rispetto a  

Per il paradosso di Borel  , ossia la probabilità di ottenere la sequenza   digitando casualmente le lettere di una tastiera è quasi certa. Da ciò deriva che  . Anche   è un tempo di arresto rispetto a   in quanto, essendo   una costante, 

Osservazione 2

modifica

 

Si definisce una successione di variabili aleatorie indipendenti, per ogni   fissato,   tale che  . La successione è indipendente in quanto è funzione della successione  , anch'essa indipendente.

Per ogni   si osserva che la previsione di   è pari a uno. Infatti  

Si pone  

La successione   è una  -martingala.

Osservazione 2.1
modifica

 

Osservazione 2.2
modifica

 

Si pone  , che per la trasformazione secondo Burkholder è anch'essa una  -martingala.

Si trova il valore di  quando  .

 

Dato che stiamo considerando il caso che  , il valore più piccolo tra   e   è proprio  

 

Per definizione di  , ossia il più piccolo   tale che la stringa si realizzi, si ha   in quanto esiste almeno un carattere   compreso tra   e   dove  . Come conseguenza si ha che   e quindi  

Osservazione 2.3
modifica

 

Si trova il valore di   quando  .

 

 

 

Ne segue che

 

In base all'osservazione 2.3 si ha che  

Considerando che   per definizione si ha che  

Dato che la probabilità di una funzione indicatrice corrisponde all'evento stesso si ha che  

Conclusione

modifica

 

Per l'osservazione 2 si ha che  

Fissando   e facendo variare   si ottiene che 

La somma per ogni   della probabilità che il tempo di arresto   sia uguale a   equivale a calcolare la probabilità che   sia finito, pari a   per l'osservazione 1.

Pertanto si dimostra la tesi ottenendo che  

Verifiche sperimentali

modifica

Si può dimostrare sperimentalmente il tempo medio di uscita di una stringa implementando un algoritmo che simula l'estrazione casuale dei caratteri e campionando il numero di estrazioni necessarie a comporre una determinata parola. L'algoritmo può essere implementato attraverso un simulatore, oppure utilizzando un linguaggio di programmazione fornito di una libreria che implementi un generatore di numeri pseudo casuale. Di seguito si descrive un semplice algoritmo di esempio, scritto con il linguaggio ANSI C, che permette di campionare i tempi di uscita di una stringa. Successivamente si descrive come avviene il campionamento dei dati e si fa vedere che i dati tendono alla previsione matematica.

Algoritmo di campionamento

modifica

Per effettuare un campionamento del tempo di uscita di una stringa è necessario implementare un algoritmo che effettui la stessa estrazione un certo numero di volte, solitamente maggiore di trenta. L'alfabeto di riferimento è quello inglese composto da ventisei lettere.

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <time.h>

#define MIN_CAR 97
#define MAX_CAR 122
#define DELTA_CAR 26

#define MARKER_STR "-s"
#define MARKER_GIRI "-n"
#define MARKER_SID "-r"
#define MARKER_SAVE "-f"
#define MARKER_VERBOSE "-v"
#define VERBOSE_OFF "off"

int verbose;

unsigned long long estrai_stringa(int l, char * s){
	
	unsigned long long n;
	int k, maxk;
	char c;
	
	n = 0;
	k = 0;
	maxk = 0;
	
	while (k < l){
		
		if (n == ULLONG_MAX){
			
			if (verbose == 1){
				printf("raggiunto limite massimo di estrazioni: %llu\n", n);
				printf("numero massimo di caratteri estratti: %d su %d\n", maxk, l);
				fflush(stdout);
			}
			
			return 0;
		}
		
		c = (char) (MIN_CAR + (rand() % DELTA_CAR));
		
		if (c == s[k]){
			k++;
			
			if (maxk < k){
				maxk = k;
			}
			
		}else{
			k = 0;
		}
		
		n++;
		
	}
	
	if (verbose == 1){
		printf("stringa estratta dopo %llu step\n", n);
		fflush(stdout);
	}
	
	return n;
	
}

int main(int argc, char * argv[]){
	
	int i, l = -1, n = -1;
	time_t t;
	unsigned int sid = 0;
	unsigned long long ret;
	char * s;
	FILE * f = NULL;
	
	verbose = 1;
	
	for (i = 0; i < argc; i++){
		
		if (strcmp(argv[i], MARKER_STR) == 0){
			s = argv[i + 1];
			l = strlen(s);
		}else if (strcmp(argv[i], MARKER_GIRI) == 0){
			n = atoi(argv[i + 1]);
		}else if (strcmp(argv[i], MARKER_SID) == 0){
			sid = atoi(argv[i + 1]);
		}else if (strcmp(argv[i], MARKER_VERBOSE) == 0){
			if (strcmp(argv[i + 1], VERBOSE_OFF) == 0){
				verbose = 0;
			}
		}else if (strcmp(argv[i], MARKER_SAVE) == 0){
			
			f = fopen(argv[i + 1], "a");
			
			if (f == NULL){
				
				printf("errore nella creazione del file\n");
				fflush(stdout);
				
				return -1;
				
			}
			
		}
		
	}
	
	if (l == -1){
		if (verbose == 1){
			printf("specificare la stringa da estrarre: -s [stringa]\n");
			fflush(stdout);
		}
		return -1;
	}
	
	if (n == -1){
		if (verbose == 1){
			printf("specificare il numero di iterazioni: -n [numero iterazioni]\n");
			fflush(stdout);
		}
		return -1;
	}
	
	if (sid == 0){
		if (verbose == 1){
			printf("nessun sid specificato (opzione -r [sid]), uso sid generato automaticamente\n");
			fflush(stdout);
		}
		sid = (unsigned int) time(&t);
	}
	
	if (verbose == 1){
		printf("**** start estrazione ****\n");
		printf("sid = %du\n", sid);
		printf("stringa = %s\n", s);
		printf("lunghezza = %d\n", l);
		printf("iterazioni = %d\n\n", n);
		fflush(stdout);
	}
	
	srand(sid);
	
	for (i = 0; i < n; i++){
		
		ret = estrai_stringa(l, s);
		
		if (ret == 0){
			printf("errore nell'estrazione della stringa\n");
			fflush(stdout);
			return -1;
		}
		
		if (f != NULL){
			fprintf(f, "%llu\n", ret);
		}
		
	}
	
	if (f != NULL){
		fclose(f);
	}
	
	return 0;
	
}

Per compilare il codice è necessario salvarlo in un file (es. gen.c) e creare l'eseguibile attraverso un compilatore C. Di seguito si riporta il comando per compilare il sorgente con il compilatore gcc per il sistema operativo linux.

gcc gen.c -o gen

Verifica ipotesi mediante test di Student

modifica

Il test di verifica ipotesi di Student permette di stabilire se la media campionaria   si discosti in modo significativo alla media matematica  . Per effettuare il test si formulano le ipotesi   e  . Nel caso in cui viene verificata l'ipotesi   si stabilisce che le due previsioni sono attinenti con una certa probabilità di errore. Nel caso in cui viene verificata l'ipotesi   si stabilisce che le due previsioni non sono attinenti con una certa probabilità di errore. Per effettuare il test di verifica è necessario ottenere i seguenti dati:

  •   è la numerosità del campione, ossia il numero di volte in cui si è registrato il tempo di uscita della parola "ciao"
  •   è il campione da verificare, dove   rappresenta il numero di estrazioni occorse prima di comporre la parola "ciao"
  •   è la media campionaria
  •   è la varianza campionaria
  •   è la media matematica
  •   è la statistica che ha legge di Student con   gradi di libertà
  •   è l'errore tollerabile nella conferma dell'ipotesi
  •   è il quantile della legge di Student con   gradi di libertà associato alla tolleranza  

Il test si esegue comparando il valore della statistica con il relativo quantile. Nel caso in cui   si verifica l'ipotesi   con una probabilità pari a  . Nel caso in cui, invece,   si respinge l'ipotesi   e si conferma l'ipotesi   con una probabilità di errore pari ad  .

Esempio

modifica

Si procede ad un esempio concreto per verificare mediante il test di Student le ipotesi   e  .

Per prima cosa si procede al campionamento dei dati utilizzando l'algoritmo descritto nella sezione precedente con il comando

./gen -s ciao -n 100 -f campionamento -r 1492875030

dove:

  • ciao è la stringa da estrarre
  • 100 è la numerosità del campionamento
  • campionamento è il nome del file dove verranno salvati i risultati delle estrazioni
  • 1492875030 è il seme per inizializzare il generatore pseudo casuale

Non appena il programma termina l'esecuzione è possibile procedere con il test di Student per stabilire se il numero di estrazioni necessarie per ottenere la stringa "ciao" è attinente alla previsione matematica. Si calcolano i parametri necessari a fare il test:

  •   è la numerosità del campione
  •   è la media campionaria
  •   è la varianza campionaria
  •   è la media matematica
  •   è la statistica con legge di Student
  • si pone   come errore tollerabile nel caso di verifica di  
  • il quantile associato è  

Essendo   si conferma l'ipotesi   e pertanto la media campionaria conferma la media matematica. Analizzando il grafico sottostante con l'andamento delle previsioni parziali al variare della numerosità si vede chiaramente come  .

 

Bibliografia

modifica

Paolo Baldi, Calcolo delle Probabilità e Statistica - Seconda Edizione, Milano, McGraw-Hill, 1998, ISBN 88-386-0737-0.

Paolo Baldi, Calcolo delle Probabilità, Milano, McGraw-Hill, 2007, ISBN 978-88-386-6365-9.

Francesca Biagini, Massimo Campanino, Elementi di Probabilità e Statistica, Milano, Springer, 2006, ISBN 88-470-0330-X.