Generatore di Catene di Markov da Testo

di il
4 risposte

Generatore di Catene di Markov da Testo

Questo programma analizza un file di testo di input e genera una rappresentazione statistica delle sequenze di parole, simile a una catena di Markov del primo ordine. Il risultato è una tabella CSV dove ogni riga rappresenta una parola iniziale seguita dalle parole che la seguono con le rispettive frequenze.

  1. Legge il testo di input, tokenizzando in parole e simboli di punteggiatura.
  2. Costruisce una struttura dati matriciale dove:
    • La prima colonna contiene le parole iniziali (chiavi).
    • Le colonne successive contengono le parole che seguono con le loro frequenze.
  3. Utilizza un dizionario (trie) per l'efficiente ricerca e inserimento delle parole.
  4. Elabora i dati attraverso processi separati usando pipe per la comunicazione.
  5. Genera un file CSV di output con le statistiche calcolate.

Il programma funziona correttamente con input di piccole dimensioni, ma si blocca o entra in un loop indeterminato con input molto grandi (centinaia di migliaia o milioni di righe). Il debugging è difficoltoso poiché in questo stato il programma non produce output. Si sospetta che il problema sia legato alla gestione della memoria o alla logica di elaborazione per input di grandi dimensioni.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/wait.h> 
#include <unistd.h>
#include <wchar.h>
#include <wctype.h>
#include <locale.h>

// Definizione della struttura per un oggetto contenente una stringa, la sua frequenza, e le coordinate nella matrice
typedef struct {
  wchar_t Stringa[31];
  float frequenza;
  int occorrenza;
  int x;
  int y;
} oggetto;

// Definizione della struttura per una matrice contenente una lista di oggetti e le sue dimensioni
typedef struct {
    oggetto** lista;
    int* x;
    int y;
} matrice;

// Definizione della struttura per l'alfabeto contenente un sottoalfabeto e una parola
struct Alfabeto {
    struct Alfabeto* sottoalfabeto[46];
    oggetto *parola;
};

// Definizione del tipo Dizionario come un puntatore a struct Alfabeto
typedef struct Alfabeto Dizionario;

// Dichiarazione della funzione ricorsivaDeallocazione
Dizionario* deallocazione(Dizionario* diz);
int creaTabella(FILE* file, matrice* matrix, Dizionario* diz, int pipe1[], int pipe2[], wchar_t primaParola[]);
int indiceAscii(wchar_t carattere);
bool confrontaStringhe(wchar_t* stringa1, wchar_t* stringa2);
bool ricercaOperativa(wchar_t stringa[], int indice, Dizionario* diz, int i, int p, matrice* m);
void leggiParolaFileInput(FILE* file, int pipe1[],long int posizione);
void stampa(FILE* foglio, int pipe2[]);
long int primaParola(FILE* file, matrice* matrix);

int main(void) { //dichiaro la funzione main

    setlocale(LC_ALL, "it_IT.UTF-8");  // Imposta una locale che supporta Unicode

    FILE* file = fopen("prova.txt", "r");
    FILE* foglio = fopen("controprova.csv", "w");
    if (file == NULL || foglio == NULL) { //se uno dei file non si apre
        exit(EXIT_FAILURE); //esco con errore
    }

    Dizionario* dizionario = (Dizionario*)calloc(1, sizeof(Dizionario)); //alloco il dizionario
    dizionario->parola = (oggetto*)calloc(1,sizeof(oggetto)); //alloco una parola nel dizionario

    matrice matrix; //dichiaro una matrice

    matrix.lista = (oggetto**)calloc(1, sizeof(oggetto*));
    matrix.lista[0] = (oggetto*)calloc(2, sizeof(oggetto));
    matrix.x = (int*)calloc(1, sizeof(int));
    matrix.x[0] = 1;

    long int posizione = primaParola(file, &matrix);
    if(posizione == -1){
        exit(EXIT_FAILURE); //esco con errore
    }
    //wprintf(L"%ls ", matrix.lista[0][0].Stringa);

    int pipe1[2], pipe2[2]; //dichiaro due pipe

    if (pipe(pipe1) == -1 || pipe(pipe2) == -1) { //se la creazione delle pipe fallisce
        exit(EXIT_FAILURE); //esco con errore
    }
    int MAX; //massimo numero di bytes da allocare in una riga nella matrice
    pid_t pid_Processo1, pid_Processo2, pid_Processo3; //dichiaro i pid dei processi

    pid_Processo1 = fork(); //creo il primo processo
    if (pid_Processo1 == -1) { //se la fork fallisce
        perror("Fork errore"); //stampo un errore
        return 1; //ritorno 1
    } else if (pid_Processo1 == 0) { //se sono nel processo figlio
        close(pipe1[0]); //chiudo la lettura della pipe1
        leggiParolaFileInput(file, pipe1,posizione); //chiamo la funzione leggiParolaFileInput
        exit(0); //esce dal processo
    } else { //se sono nel processo padre
        close(pipe1[1]); //chiudo la scrittura della pipe1
        waitpid(pid_Processo1, NULL, 0); //attendo la terminazione del processo 1
    }

    pid_Processo2 = fork();
    if (pid_Processo2 == -1) {
        perror("Fork errore");
        return 1;
    } else if (pid_Processo2 == 0) {
        close(pipe2[0]); // Chiudi la lettura della pipe2
        wchar_t primaParolaArray[31];
        wcscpy(primaParolaArray, matrix.lista[0][0].Stringa);
        creaTabella(file, &matrix, dizionario, pipe1, pipe2, primaParolaArray);
        exit(0);
    }

    // Attendi che il processo 2 finisca prima di iniziare il processo 3
    waitpid(pid_Processo2, NULL, 0);

    pid_Processo3 = fork();
    if (pid_Processo3 == -1) {
        perror("Fork errore");
        return 1;
    } else if (pid_Processo3 == 0) {
        close(pipe2[1]); // Chiudi la scrittura della pipe2
        stampa(foglio, pipe2);
        exit(0);
    }

    // Chiudi tutte le estremità delle pipe nel processo principale
    close(pipe1[0]);
    close(pipe1[1]);
    close(pipe2[0]);
    close(pipe2[1]);

    waitpid(pid_Processo3, NULL, 0);
    wait(NULL); //attendo la terminazione di tutti i processi figli
    wait(NULL); //attendo la terminazione di tutti i processi figli
    wait(NULL); //attendo la terminazione di tutti i processi figli

    fclose(foglio); //chiudo il file di output
    fclose(file); //chiudo il file di input

    for (int i = 0; i < 46; i++) { //libero la memoria del dizionario
        dizionario->sottoalfabeto[i] = deallocazione(dizionario->sottoalfabeto[i]); //chiamo la funzione deallocazione
    }
    free(dizionario->parola); //libero la memoria della parola
    free(dizionario); //libero la memoria del dizionario

    return 0; //ritorno 0
}

Dizionario* deallocazione(Dizionario* diz) { //dichiaro la funzione deallocazione
    if (diz == NULL) { //se il dizionario è NULL
        return NULL; //ritorno NULL
    }

    for (int i = 0; i < 46; i++) { //scorro i 30 elementi del sottoalfabeto
        diz->sottoalfabeto[i] = deallocazione(diz->sottoalfabeto[i]); //chiamo la funzione deallocazione ricorsivamente
    }
    free(diz->parola); //libero la memoria della parola
    free(diz); //libero la memoria del dizionario
    return NULL; 
}
// Funzione per ottenere l'indice ASCII di un carattere
int indiceAscii(wchar_t carattere) {
    // Converti il carattere in minuscolo
    wchar_t c = towlower(carattere);

    if (iswalpha(c)) {
        //Gestione delle lettere non accentate
        return c - L'a';
    } else {
        //Gestione dei caratteri accentati
        switch (c) {
            case L'à': return 26;
            case L'è': return 27;
            case L'é': return 28;
            case L'ì': return 29;
            case L'ò': return 30;
            case L'ù': return 31;
            case L'!': return 32;
            case L'?': return 33;
            case L'.': return 34;
            case L'\'': return 35;
        }
    }

    //Gestione dei numeri
    if (c >= L'0' && c <= L'9') {
        return 36 + (c - L'0');
    }

    //Carattere non riconosciuto
    return -1;
}


//funzione per confrontare due stringhe
bool confrontaStringhe(wchar_t* Stringa1, wchar_t* Stringa2) { //dichiaro la funzione confrontaStringhe
    if (*Stringa1 == L'\0' && *Stringa2 == L'\0') { //se entrambe le stringhe sono terminate
        return true; //ritorno true
    }
    
    if (*Stringa1 == *Stringa2 || (towlower((wchar_t)*Stringa1) == towlower((wchar_t)*Stringa2))) { //controlla se i caratteri sono uguali o se sono uguali in minuscolo
        return confrontaStringhe(Stringa1 + 1, Stringa2 + 1); //richiamo la funzione sul prossimo carattere
    }

    return false; //se i caratteri non sono uguali, ritorno false
}
long int primaParola(FILE* file, matrice* matrix){
    wchar_t carattere;
    const wchar_t* caratteriAccentati = L"àèéìòóùÀÈÉÌÒÓÙ";
    int indice = 0; //inizializzo l'indice a 0
    long int pos = 0; // Inizializza pos a 0

    while((carattere = fgetwc(file)) != WEOF){
        wchar_t successivo = fgetwc(file);
        ungetwc(successivo,file);
        if (carattere==L'\n'|| carattere==L' '){ //se i primi caratteri sono \n o spazio saltali
            continue;
        }else if(iswalnum(carattere) || (wcschr(caratteriAccentati, carattere) != NULL)){  //se trovi o quando troverai dei caratteri alfanumerici allora aggiungi alla matrice in prima posizione
            matrix->lista[0][0].Stringa[indice]= carattere;
            indice++;
            if (successivo==L' '||(successivo == L'\n' || successivo == L'\r')|| successivo==L'!' || successivo ==L'?' || successivo == L'.'){ //se seguito da spazio o da a capo termina la Stringa 
                matrix->lista[0][0].Stringa[indice]= L'\0';
                indice = 0;
                return ftell(file);

            }else if (successivo == L'\''){ //se seguito da apostrofo appendi l'apostrofo e termina la Stringa e la primaparola
                matrix->lista[0][0].Stringa[indice]= L'\'';
                matrix->lista[0][0].Stringa[indice+1]= L'\0';
                indice = 0;
                return ftell(file);
            }
            continue;
        }else if (carattere == L'!' || carattere == L'?' || carattere == L'.'){ // se incontri dei caratteri speciali aggiungili alla matrice come dei caratteri a se
                    indice = 0;
                    matrix->lista[0][0].Stringa[indice++] = carattere;
                    if(successivo == '\''){
                        matrix->lista[0][0].Stringa[indice++] = '\'';
                        fgetwc(file);
                    }
                    matrix->lista[0][0].Stringa[indice] = L'\0';
                    indice = 0;
            return ftell(file);
        }
    }
    
    // Se arriviamo qui, significa che abbiamo raggiunto la fine del file senza trovare una parola valida
    return -1; // Ritorniamo -1 per indicare che non è stata trovata una parola valida
}
// Funzione per la ricerca operativa di una stringa nella matrice
bool ricercaOperativa(wchar_t stringa[], int indice, Dizionario* diz, int i, int p, matrice* m) { //dichiaro la funzione ricercaOperativa
    Dizionario* dizAttuale = diz; //inizializzo dizAttuale con diz
    int ASCII; //dichiaro la variabile ASCII

    if (stringa[indice] == '\0') { //se il carattere corrente è il terminatore di stringa

        if (confrontaStringhe(dizAttuale->parola->Stringa, m->lista[i][0].Stringa)) { //se la stringa della parola del dizionario è uguale alla stringa della matrice
            int n = 1; //inizializzo n a 1
            int y = dizAttuale->parola->y; //assegno la coordinata y della parola del dizionario a y
            int x = dizAttuale->parola->x; //assegno la coordinata x della parola del dizionario a x
            int trovato = 0; //inizializzo trovato a 0

            m->lista[y][0].occorrenza++; //incremento l'occorrenza della parola nella matrice
            while (n <= m->x[y] && m->lista[y][n].x == n) { //finché n è minore o uguale alla dimensione x della matrice e l'elemento della matrice è uguale a n
                if (confrontaStringhe(m->lista[y][n].Stringa, m->lista[i][p].Stringa)) { //se la stringa corrente è uguale alla stringa della matrice
                    m->lista[y][n].occorrenza++; //incremento l'occorrenza
                    m->lista[y][n].frequenza = (float)m->lista[y][n].occorrenza / (float)m->lista[y][0].occorrenza; //calcolo la frequenza
                    trovato = 1; //imposto trovato a 1
                }
                m->lista[y][n].frequenza = (float)m->lista[y][n].occorrenza / (float)m->lista[y][0].occorrenza; //calcolo la frequenza
                n++; //incremento n
            }

            if (!trovato) { //se non ho trovato la stringa
                if (n > m->x[y]) { //se n è maggiore della dimensione x della matrice
                    m->x[y] = n; //assegno n a x
                }
                m->lista[y] = realloc(m->lista[y], (n + 1) * sizeof(oggetto)); //rialloco la memoria per la riga della matrice
                wcscpy(m->lista[y][n].Stringa, m->lista[i][p].Stringa); //copio la stringa nella matrice
                m->lista[y][n].occorrenza = 1; //inizializzo l'occorrenza a 1
                m->lista[y][n].frequenza = (float)m->lista[y][n].occorrenza / (float)m->lista[y][0].occorrenza; //calcolo la frequenza
                m->lista[y][n].x = n; //assegno n alla coordinata x
            }

            return true; //ritorno true
        }

        wcscpy(dizAttuale->parola->Stringa, stringa); //copio la stringa nella parola del dizionario
        dizAttuale->parola->x = p; //assegno p alla coordinata x della parola
        dizAttuale->parola->y = i; //assegno i alla coordinata y della parola
        m->lista[i][1].x = 1; //assegno 1 alla coordinata x della matrice
        m->lista[i][0].x = 0; //assegno 0 alla coordinata x della matrice
        m->lista[i][1].occorrenza = 1; //inizializzo l'occorrenza a 1
        m->lista[i][0].occorrenza = 1; //inizializzo l'occorrenza a 1
        m->lista[i][1].frequenza = (float)m->lista[i][1].occorrenza / (float)m->lista[i][0].occorrenza; //calcolo la frequenza

        return false; //ritorno false
    }

    ASCII = indiceAscii(stringa[indice]); //calcolo l'indice ASCII del carattere corrente
    if (dizAttuale->sottoalfabeto[ASCII] == NULL) { //se il sottoalfabeto corrente è NULL
        dizAttuale->sottoalfabeto[ASCII] = (Dizionario*)calloc(1, sizeof(Dizionario)); //alloco memoria per il sottoalfabeto
        if (dizAttuale->sottoalfabeto[ASCII] == NULL) { //se la memoria non è stata allocata
            exit(1); //esco con errore
        }
        dizAttuale->sottoalfabeto[ASCII]->parola = (oggetto*)calloc(1,sizeof(oggetto)); //alloco memoria per la parola del sottoalfabeto
        if (dizAttuale->sottoalfabeto[ASCII]->parola == NULL) { //se la memoria non è stata allocata
            exit(1); //esco con errore
        }
    }
    dizAttuale = dizAttuale->sottoalfabeto[ASCII]; //assegno il sottoalfabeto corrente a dizAttuale
    return ricercaOperativa(stringa, indice + 1, dizAttuale, i, p, m); //richiamo la funzione ricorsivamente
}
// Funzione per gestire la fine di una stringa
int creaTabella(FILE* file, matrice* matrix, Dizionario* diz, int pipe1[], int pipe2[], wchar_t primaParola[]) { //dichiaro la funzione creaTabella
    wchar_t stringa1[31]; //dichiaro una stringa di 31 caratteri
    matrix->y = 1; //inizializzo la dimensione y a 1
    matrix->lista = NULL; //inizializzo la lista a NULL

    matrix->lista = (oggetto**)calloc(1,matrix->y * sizeof(oggetto*)); //alloco memoria per la matrice
    matrix->lista[matrix->y - 1] = (oggetto*)calloc(1,2 * sizeof(oggetto)); //alloco memoria per una riga della matrice

    wcscpy(matrix->lista[0][0].Stringa, primaParola); //copio la prima parola nella matrice

    // Legge tutte le parole dalla pipe1 prima di scrivere sulla pipe2
    while (read(pipe1[0], &stringa1, sizeof(stringa1)) > 0) { //legge tutte le parole dalla pipe1
        if (stringa1[0] == '\0') { //se la stringa è vuota
            break; //esce dal ciclo
        }

        // Aggiunge le parole come valore alla struttura dati Matrice
        wcscpy(matrix->lista[matrix->y - 1][1].Stringa, stringa1); //copio la stringa nella matrice
        matrix->lista[matrix->y - 1][1].x = 1; //assegno 1 alla coordinata x
        matrix->lista[matrix->y - 1][0].x = 0; //assegno 0 alla coordinata x

        int controllo = ricercaOperativa(matrix->lista[matrix->y - 1][0].Stringa, 0, diz, matrix->y - 1, 1, matrix); //chiamo la funzione ricercaOperativa
        if (controllo == 0) {
            matrix->y++;
            matrix->lista = realloc(matrix->lista, matrix->y * sizeof(oggetto*));
            matrix->lista[matrix->y - 1] = (oggetto*)calloc(2, sizeof(oggetto));
            matrix->x = realloc(matrix->x, matrix->y * sizeof(int));
            matrix->x[matrix->y - 1] = 1;
        }

        wcscpy(matrix->lista[matrix->y - 1][0].Stringa, stringa1); //copio la stringa nella matrice
        stringa1[0] = '\0'; //resetto la stringa
    }

    // Gestisci la fine
    wcscpy(matrix->lista[matrix->y - 1][1].Stringa, matrix->lista[0][0].Stringa); //copio la prima parola nell'ultima riga
    int controllo = ricercaOperativa(matrix->lista[matrix->y - 1][0].Stringa, 0, diz, matrix->y - 1, 1, matrix); //chiamo la funzione ricercaOperativa
    if (controllo == 0) { //se il controllo è 0
        matrix->y++; //incremento la dimensione y
    }
    close(pipe1[0]); //chiudo la pipe1

    // Scrivi il numero di righe della matrice
    write(pipe2[1], &(matrix->y), sizeof(int));

    for (int i = 0; i < matrix->y-1; i++) {
        // Calcola la lunghezza della riga
        size_t len = wcslen(matrix->lista[i][0].Stringa);
        for (int j = 1; j <= matrix->x[i]; j++) {
            len += wcslen(matrix->lista[i][j].Stringa) + 7; // +7 per ",%.4f,"
        }
        len++; // Per il carattere di nuova linea

        // Alloca memoria per la riga
        wchar_t* riga = calloc(len + 1, sizeof(wchar_t));
        
        // Costruisci la riga
        swprintf(riga, len + 1, L"%ls", matrix->lista[i][0].Stringa);
        for (int j = 1; j <= matrix->x[i]; j++) {
            wchar_t temp[50];
            swprintf(temp, 50, L",%ls,%.4f", matrix->lista[i][j].Stringa, matrix->lista[i][j].frequenza);
            len += 50;
            riga = realloc(riga,len*sizeof(wchar_t));
            wcscat(riga, temp);
        }
        wcscat(riga, L"\n");

        // Scrivi la lunghezza della riga e poi la riga stessa
        write(pipe2[1], &len, sizeof(size_t));
        write(pipe2[1], riga, len * sizeof(wchar_t));

        free(riga);
    }

    // Scrivi un segnale di fine (lunghezza 0)
    size_t end_signal = 0;
    write(pipe2[1], &end_signal, sizeof(size_t));

    close(pipe2[1]);
    return 0;
}
void stampa(FILE* foglio, int pipe2[]) {
    close(pipe2[1]); // Chiudi la scrittura della pipe2

    int num_righe;
    ssize_t bytes_read = read(pipe2[0], &num_righe, sizeof(int));
    if (bytes_read != sizeof(int)) {
        if (bytes_read == 0) {
            fprintf(stderr, "Pipe chiusa inaspettatamente durante la lettura del numero di righe\n");
        } else {
            perror("Errore nella lettura del numero di righe");
        }
        exit(EXIT_FAILURE);
    }
    fprintf(stderr, "Numero di righe lette: %d\n", num_righe);

    for (int i = 0; i < num_righe; i++) {
        size_t len;
        bytes_read = read(pipe2[0], &len, sizeof(size_t));
        if (bytes_read != sizeof(size_t)) {
            if (bytes_read == 0) {
                fprintf(stderr, "Pipe chiusa inaspettatamente durante la lettura della lunghezza della riga %d\n", i);
            } else {
                perror("Errore nella lettura della lunghezza della riga");
            }
            exit(EXIT_FAILURE);
        }
        fprintf(stderr, "Lunghezza della riga %d: %zu\n", i, len);

        if (len == 0) {
            fprintf(stderr, "Ricevuto segnale di fine dati\n");
            break;
        }

        wchar_t* riga = calloc(len + 1, sizeof(wchar_t));
        if (riga == NULL) {
            perror("Errore nell'allocazione della memoria per la riga");
            exit(EXIT_FAILURE);
        }

        bytes_read = read(pipe2[0], riga, len * sizeof(wchar_t));
        if (bytes_read != len * sizeof(wchar_t)) {
            if (bytes_read == 0) {
                fprintf(stderr, "Pipe chiusa inaspettatamente durante la lettura della riga %d\n", i);
            } else {
                perror("Errore nella lettura della riga");
            }
            free(riga);
            exit(EXIT_FAILURE);
        }

        riga[len] = L'\0';
        fprintf(stderr, "Riga %d letta: %ls\n", i, riga);
        fwprintf(foglio, L"%ls", riga);

        free(riga);
    }

    close(pipe2[0]);
    fprintf(stderr, "Stampa completata\n");
}
// Funzione per la lettura del file di input
void leggiParolaFileInput(FILE* file, int pipe1[], long int posizione) {

    
    wchar_t stringa1[31];
    int indice = 0;
    wchar_t carattere;
    const wchar_t* caratteriAccentati = L"àèéìòóùÀÈÉÌÒÓÙ";
    for(int i = 0; i==posizione; i++){
        fgetwc(file);
    }

    while ((carattere = fgetwc(file)) != WEOF) {
        wchar_t successivo = fgetwc(file);
        ungetwc(successivo,file);
        if ((carattere == L' ' || (carattere == L'\n' || carattere == L'\r')) && successivo == WEOF) {
            // Handle the case where the last character is a space or newline
            if (indice > 0) {
                stringa1[indice] = L'\0';
                write(pipe1[1], stringa1, sizeof(stringa1));
            }
            break;
        }

        if (carattere == L'!' || carattere == L'?' || carattere == L'.') {
            if (indice > 0) {
                stringa1[indice] = L'\0';
                write(pipe1[1], stringa1, sizeof(stringa1));
                indice = 0;
            }
            stringa1[indice] = carattere;
            if (successivo == L'\'') {
                indice++;
                stringa1[indice] = L'\'';
                fgetwc(file);
            }
            indice ++;
            if (successivo == WEOF) {
                stringa1[indice] = L'\0';
                write(pipe1[1], stringa1, sizeof(stringa1));
                break;
            }
        } else if (indice>0 && carattere=='\''){
                stringa1[indice] = L'\'';
                indice++;
                stringa1[indice] = L'\0';
                write(pipe1[1], stringa1, sizeof(stringa1));
                indice = 0;
                stringa1[indice] = L'\0';
            } else if (iswalnum(carattere) || (wcschr(caratteriAccentati, carattere) != NULL)) {
            if (indice > 0 && (stringa1[indice -1] == '!' || stringa1[indice -1] == '?' || stringa1[indice -1] == '.' || stringa1[indice -1] == '\'')) {
                stringa1[indice] = L'\0';
                write(pipe1[1], stringa1, sizeof(stringa1));
                indice = 0;
                stringa1[indice] = L'\0';
            }
            stringa1[indice++] = carattere;
            if(successivo == '\''){
                stringa1[indice++] = L'\'';
                stringa1[indice] = L'\0';
                write(pipe1[1], stringa1, sizeof(stringa1));
                fgetwc(file);
                indice = 0;
            }
            if (successivo == L' ' || (successivo == L'\n' || successivo == L'\r') || successivo == WEOF ||
                successivo == L'!' || successivo == L'?' || successivo == L'.' ) {
                    stringa1[indice] = L'\0';
                    write(pipe1[1], stringa1, sizeof(stringa1));
                    indice = 0;
            }
        }
        else if (carattere == L' ' || (carattere == L'\n' || carattere == L'\r')) {
            if (indice > 0) {
                stringa1[indice] = L'\0';
                write(pipe1[1], stringa1, sizeof(stringa1));
                indice = 0;
                stringa1[indice] = L'\0';

            }
        } else if (!(iswalnum(carattere) || (wcschr(caratteriAccentati, carattere) != NULL) ||
                     carattere == L'\'' || carattere == L'!' ||
                     carattere == L'?' || carattere == L'.') &&
                   (successivo == L' ' || (successivo == L'\n' || successivo == L'\r'))) {

            continue;
        }

        if (successivo == WEOF) {
            stringa1[indice] = L'\0';
            write(pipe1[1], stringa1, sizeof(stringa1));
            break;
        }
    }

    close(pipe1[1]);
}

Esempio di input/output atteso: Input: 

Cosa dicono le previsioni del tempo? Previsioni del tempo di oggi: tempo incerto! Previsioni di domani?

Output CSV: 

Cosa,dicono,1.0000 
dicono,le,1.0000 
le,previsioni,1.0000 
previsioni,del,0.6667,di,0.3333 
del,tempo,1.0000 
tempo,?,0.3333,di,0.3333,incerto,0.3333 
?,Previsioni,0.5000,Cosa,0.5000 
di,oggi,0.5000,domani,0.5000 
oggi,tempo,1.0000 
incerto,!,1.0000 
!,Previsioni,1.0000 
domani,?,1.0000

Questo esempio mostra come il programma dovrebbe elaborare le sequenze di parole e calcolare le frequenze delle parole successive. Il problema attuale impedisce di ottenere risultati simili per testi molto più lunghi. 
Ho cercato di creare una versione minimizzata del codice per facilitare il debug, ma dato il comportamento imprevedibile con input di grandi dimensioni, questo tentativo non ha prodotto risultati significativi. Il programma continua a entrare in uno stato di loop o di blocco senza fornire output utili per il debugging. 
Basandomi sull'analisi del codice e sul comportamento osservato, ho un forte sospetto che il problema si verifichi nella comunicazione tra le funzioni creaTabella() e stampa(), in particolare quando si scrivono dati sulla PIPE2. È possibile che ci sia un problema di sincronizzazione o di gestione della memoria in questa fase critica del programma.

4 Risposte

  • Re: Generatore di Catene di Markov da Testo

    La matrice dei conteggi delle coppie di parole, SE implementata come matrice NxN e non come ‘matrice sparsa’ (infinitamente piu' efficiente ma piu' complicato da fare) ha dei limiti.

    con 128gb di ram, usando interi a 32 bit, non puoi avere un dizionario piu' ampio di circa 185.000 parole. diciamo 150.000, tanto per essere sicuri di avee qualche bit a disposizione anche per il programma.

    Poi il codice e' tanto e bisogna copiarselo in locale, compilarlo e provare, SU macchina linux.Ci vorra' un po' di tempo

  • Re: Generatore di Catene di Markov da Testo

    Ma qual è il punto di questi post? La stragrande maggioranza dei codici prima o poi raggiungerà il limite di risorse hardware disponibili. Dobbiamo cercare noi il modo di spostare il tuo limite qualche milione di righe più in là?

  • Re: Generatore di Catene di Markov da Testo

    05/07/2024 - Weierstrass ha scritto:


    Ma qual è il punto di questi post? La stragrande maggioranza dei codici prima o poi raggiungerà il limite di risorse hardware disponibili. Dobbiamo cercare noi il modo di spostare il tuo limite qualche milione di righe più in là?

    Il problema che sto riscontrando non è legato ai limiti delle risorse hardware per testi estremamente lunghi. Il mio programma mostra difficoltà anche con testi relativamente brevi, come la Divina Commedia, che conta circa 20.000 righe.
    Questo è preoccupante perché un programma ben progettato dovrebbe gestire senza problemi testi di questa lunghezza, che sono comuni in molte applicazioni pratiche. Il fatto che il programma entri in un loop indeterminato o si blocchi con input di questa dimensione suggerisce che ci sia un problema fondamentale nell'algoritmo o nell'implementazione. Inoltre, tutti i testi che sto utilizzando sono codificati in UTF-8, quindi non dovrebbero esserci problemi di compatibilità con i caratteri.
    L'obiettivo non è quello di spingere il programma ai limiti estremi delle risorse hardware, ma di farlo funzionare correttamente per casi d'uso realistici e comuni. Risolvere questo problema non solo migliorerà le prestazioni del programma, ma potrebbe anche rivelare errori di progettazione o implementazione che potrebbero essere utili per migliorare la qualità complessiva del codice.

  • Re: Generatore di Catene di Markov da Testo

    05/07/2024 - migliorabile ha scritto:


    La matrice dei conteggi delle coppie di parole, SE implementata come matrice NxN e non come ‘matrice sparsa’ (infinitamente piu' efficiente ma piu' complicato da fare) ha dei limiti.

    con 128gb di ram, usando interi a 32 bit, non puoi avere un dizionario piu' ampio di circa 185.000 parole. diciamo 150.000, tanto per essere sicuri di avee qualche bit a disposizione anche per il programma.

    Poi il codice e' tanto e bisogna copiarselo in locale, compilarlo e provare, SU macchina linux.Ci vorra' un po' di tempo

    Vorrei chiarire che il problema che sto riscontrando non è legato alla versione a singolo processore del programma, né sembra essere una questione di limiti di memoria per il dizionario.
    Il problema si manifesta specificamente nella versione multi-processo del programma, in particolare quando si utilizza la comunicazione tra processi attraverso le pipe. Nello specifico, sembra che ci siano complicazioni quando si scrive sulla seconda pipe (pipe2) in creaTabella().
    Questa versione con concorrenza tra processi presenta comportamenti anomali che non si verificano nella versione con implementazione quasi identica a singolo processore. Il loop indeterminato o il blocco del programma si verifica anche con input di dimensioni relativamente modeste, ben al di sotto dei limiti di memoria che lei ha giustamente evidenziato. Quindi, mentre le sue considerazioni sulla gestione della memoria sono certamente valide e utili per ottimizzazioni future, il problema attuale sembra essere più legato alla gestione della concorrenza e alla comunicazione inter-processo che ai limiti di memoria del dizionario.

Devi accedere o registrarti per scrivere nel forum
4 risposte