import itertools # Definiamo le 31 funzioni di Propp con un nome sintetico e una breve descrizione # Fonte: Adattamento da varie risorse sulla morfologia della fiaba di Propp FUNZIONI_PROPP = { "F1": "Allontanamento (Un membro della famiglia si allontana)", "F2": "Divieto (All'eroe è imposto un divieto)", "F3": "Infrazione (Il divieto è infranto)", "F4": "Investigazione (L'antagonista tenta una ricognizione)", "F5": "Delazione (L'antagonista riceve informazioni sulla vittima)", "F6": "Tranello (L'antagonista tenta di ingannare la vittima)", "F7": "Connivenza (La vittima cade nell'inganno)", "F8": "Danneggiamento/Mancanza (L'antagonista danneggia o causa una mancanza)", "F9": "Mediazione (Il danneggiamento/mancanza è reso noto, l'eroe è sollecitato)", "F10": "Consenso dell'Eroe (L'eroe accetta di reagire)", "F11": "Partenza dell'Eroe (L'eroe lascia la casa)", "F12": "Messa alla Prova (L'eroe è messo alla prova dal donatore)", "F13": "Reazione dell'Eroe (L'eroe reagisce alle azioni del donatore)", "F14": "Conseguimento Mezzo Magico (L'eroe ottiene un mezzo magico)", "F15": "Trasferimento (L'eroe è trasferito vicino all'oggetto della ricerca)", "F16": "Lotta (L'eroe e l'antagonista si scontrano)", "F17": "Marchiatura (All'eroe è impresso un marchio)", "F18": "Vittoria (L'antagonista è sconfitto)", "F19": "Rimozione Danno/Mancanza (Il danno/mancanza iniziale è rimosso)", "F20": "Ritorno dell'Eroe (L'eroe ritorna)", "F21": "Persecuzione (L'eroe è perseguitato)", "F22": "Salvataggio (L'eroe è salvato dalla persecuzione)", "F23": "Arrivo in Incognito (L'eroe arriva non riconosciuto)", "F24": "Pretese Falso Eroe (Un falso eroe avanza pretese)", "F25": "Compito Difficile (All'eroe è proposto un compito difficile)", "F26": "Adempimento Compito (Il compito è portato a termine)", "F27": "Riconoscimento (L'eroe è riconosciuto)", "F28": "Smascheramento (Il falso eroe o l'antagonista è smascherato)", "F29": "Trasfigurazione (All'eroe è data una nuova apparenza)", "F30": "Punizione (L'antagonista è punito)", "F31": "Nozze/Ricompensa (L'eroe si sposa o è ricompensato)" } def stampa_funzione(codice_funzione): """Restituisce la descrizione completa di una funzione dato il suo codice.""" return FUNZIONI_PROPP.get(codice_funzione, "Funzione sconosciuta") def genera_permutazioni_funzioni(lista_codici_funzioni): """ Genera tutte le possibili sequenze ordinate (permutazioni) di un dato sottoinsieme di funzioni di Propp. L'ordine conta. """ if not all(codice in FUNZIONI_PROPP for codice in lista_codici_funzioni): raise ValueError("Uno o più codici funzione non sono validi.") permutazioni = list(itertools.permutations(lista_codici_funzioni)) trame_generate = [] for p in permutazioni: trama = [stampa_funzione(codice) for codice in p] trame_generate.append(" -> ".join(trama)) return trame_generate def genera_combinazioni_funzioni(lista_codici_funzioni_disponibili, numero_funzioni_da_scegliere): """ Genera tutti i possibili sottoinsiemi non ordinati (combinazioni) di funzioni di Propp da una lista più ampia. L'ordine NON conta. """ if not all(codice in FUNZIONI_PROPP for codice in lista_codici_funzioni_disponibili): raise ValueError("Uno o più codici funzione nella lista dei disponibili non sono validi.") if numero_funzioni_da_scegliere > len(lista_codici_funzioni_disponibili): raise ValueError("Il numero di funzioni da scegliere non può essere maggiore delle funzioni disponibili.") combinazioni = list(itertools.combinations(lista_codici_funzioni_disponibili, numero_funzioni_da_scegliere)) sottoinsiemi_generati = [] for c in combinazioni: sottoinsieme = sorted([stampa_funzione(codice) for codice in c]) # Ordiniamo per coerenza di visualizzazione sottoinsiemi_generati.append(", ".join(sottoinsieme)) return sottoinsiemi_generati # --- Esempio di Utilizzo --- if __name__ == "__main__": print("--- Esempio di Generatore di Varianti Narrative (Funzioni di Propp) ---") # 1. Permutazioni: Creiamo storie con un piccolo set di funzioni dove l'ordine conta. # Usiamo i nomi sintetici del suo esempio per le funzioni chiave: # F1: Allontanamento, F2: Divieto, F3: Infrazione, F8: Mancanza, # F11: Partenza, F14: Dono magico, F16: Lotta, F18: Vittoria, F31: Ricompensa # Esempio con 3 funzioni chiave dove l'ordine è importante funzioni_per_permutazioni_esempio = ["F11", "F16", "F18"] # Partenza, Lotta, Vittoria print(f"\n--- Permutazioni di {len(funzioni_per_permutazioni_esempio)} funzioni ({[stampa_funzione(f) for f in funzioni_per_permutazioni_esempio]}) ---") try: trame_permutate = genera_permutazioni_funzioni(funzioni_per_permutazioni_esempio) print(f"Numero di trame possibili (permutazioni): {len(trame_permutate)}") for i, trama in enumerate(trame_permutate): print(f"Trama {i+1}: {trama}") if not trame_permutate: print("Nessuna trama generata (controllare input).") except ValueError as e: print(f"Errore: {e}") # Esempio con un numero maggiore di funzioni (ATTENZIONE: n! cresce molto velocemente) # Se si usano 8 funzioni, 8! = 40,320. Stampare tutto potrebbe essere eccessivo. # Qui ne usiamo 4 per dimostrazione. funzioni_per_permutazioni_ridotte = ["F8", "F11", "F14", "F16"] # Mancanza, Partenza, Dono, Lotta print(f"\n--- Permutazioni di {len(funzioni_per_permutazioni_ridotte)} funzioni ({[stampa_funzione(f) for f in funzioni_per_permutazioni_ridotte]}) ---") try: trame_permutate_ridotte = genera_permutazioni_funzioni(funzioni_per_permutazioni_ridotte) print(f"Numero di trame possibili (permutazioni): {len(trame_permutate_ridotte)}") # Stampiamo solo le prime 5 per brevità for i, trama in enumerate(trame_permutate_ridotte[:5]): print(f"Trama {i+1}: {trama}") if len(trame_permutate_ridotte) > 5: print("... e altre.") if not trame_permutate_ridotte: print("Nessuna trama generata.") except ValueError as e: print(f"Errore: {e}") # 2. Combinazioni: Selezioniamo un sottoinsieme di funzioni da un set più ampio, l'ordine non conta. # Supponiamo di voler scegliere 3 funzioni da un set di 5 funzioni disponibili. funzioni_disponibili_esempio = ["F1", "F2", "F3", "F8", "F11"] numero_da_scegliere = 3 print(f"\n--- Combinazioni: Scegliere {numero_da_scegliere} funzioni da un set di {len(funzioni_disponibili_esempio)} ({[stampa_funzione(f) for f in funzioni_disponibili_esempio]}) ---") try: sottoinsiemi_combinati = genera_combinazioni_funzioni(funzioni_disponibili_esempio, numero_da_scegliere) print(f"Numero di sottoinsiemi possibili (combinazioni): {len(sottoinsiemi_combinati)}") for i, sottoinsieme in enumerate(sottoinsiemi_combinati): print(f"Sottoinsieme {i+1}: [{sottoinsieme}]") if not sottoinsiemi_combinati: print("Nessun sottoinsieme generato.") except ValueError as e: print(f"Errore: {e}") # Esempio più grande: Scegliere 7 funzioni dalle 31 totali (C(31,7)) # Questo genererebbe un numero molto grande di combinazioni (2,629,575 secondo la sua formula C(31,7) = 2.629.575, non 62 milioni), # quindi non le stamperemo tutte. # Calcoliamo solo il numero per dimostrazione. tutte_le_funzioni_codici = list(FUNZIONI_PROPP.keys()) numero_da_scegliere_grande = 7 print(f"\n--- Combinazioni: Scegliere {numero_da_scegliere_grande} funzioni dalle {len(tutte_le_funzioni_codici)} totali ---") try: # Calcoliamo il numero di combinazioni senza generarle tutte per evitare problemi di memoria/tempo num_combinazioni_grandi = len(list(itertools.combinations(tutte_le_funzioni_codici, numero_da_scegliere_grande))) print(f"Numero teorico di sottoinsiemi possibili (combinazioni) C({len(tutte_le_funzioni_codici)}, {numero_da_scegliere_grande}): {num_combinazioni_grandi:,}") # Formattato con separatore migliaia print("(La generazione e stampa di tutte queste combinazioni richiederebbe molto tempo e memoria).") except ValueError as e: print(f"Errore: {e}") print("\n--- Fine Esempio ---")
C:\Python312>python “C:\Luigi Usai 2025\Sorgenti Python\Casa Editrice completa\Tool potente\generatore_propp.py”
— Esempio di Generatore di Varianti Narrative (Funzioni di Propp) —
— Permutazioni di 3 funzioni ([“Partenza dell’Eroe (L’eroe lascia la casa)”, “Lotta (L’eroe e l’antagonista si scontrano)”, “Vittoria (L’antagonista è sconfitto)”]) —
Numero di trame possibili (permutazioni): 6
Trama 1: Partenza dell’Eroe (L’eroe lascia la casa) -> Lotta (L’eroe e l’antagonista si scontrano) -> Vittoria (L’antagonista è sconfitto)
Trama 2: Partenza dell’Eroe (L’eroe lascia la casa) -> Vittoria (L’antagonista è sconfitto) -> Lotta (L’eroe e l’antagonista si scontrano)
Trama 3: Lotta (L’eroe e l’antagonista si scontrano) -> Partenza dell’Eroe (L’eroe lascia la casa) -> Vittoria (L’antagonista è sconfitto)
Trama 4: Lotta (L’eroe e l’antagonista si scontrano) -> Vittoria (L’antagonista è sconfitto) -> Partenza dell’Eroe (L’eroe lascia la casa)
Trama 5: Vittoria (L’antagonista è sconfitto) -> Partenza dell’Eroe (L’eroe lascia la casa) -> Lotta (L’eroe e l’antagonista si scontrano)
Trama 6: Vittoria (L’antagonista è sconfitto) -> Lotta (L’eroe e l’antagonista si scontrano) -> Partenza dell’Eroe (L’eroe lascia la casa)
— Permutazioni di 4 funzioni ([“Danneggiamento/Mancanza (L’antagonista danneggia o causa una mancanza)”, “Partenza dell’Eroe (L’eroe lascia la casa)”, “Conseguimento Mezzo Magico (L’eroe ottiene un mezzo magico)”, “Lotta (L’eroe e l’antagonista si scontrano)”]) —
Numero di trame possibili (permutazioni): 24
Trama 1: Danneggiamento/Mancanza (L’antagonista danneggia o causa una mancanza) -> Partenza dell’Eroe (L’eroe lascia la casa) -> Conseguimento Mezzo Magico (L’eroe ottiene un mezzo magico) -> Lotta (L’eroe e l’antagonista si scontrano)
Trama 2: Danneggiamento/Mancanza (L’antagonista danneggia o causa una mancanza) -> Partenza dell’Eroe (L’eroe lascia la casa) -> Lotta (L’eroe e l’antagonista si scontrano) -> Conseguimento Mezzo Magico (L’eroe ottiene un mezzo magico)
Trama 3: Danneggiamento/Mancanza (L’antagonista danneggia o causa una mancanza) -> Conseguimento Mezzo Magico (L’eroe ottiene un mezzo magico) -> Partenza dell’Eroe (L’eroe lascia la casa) -> Lotta (L’eroe e l’antagonista si scontrano)
Trama 4: Danneggiamento/Mancanza (L’antagonista danneggia o causa una mancanza) -> Conseguimento Mezzo Magico (L’eroe ottiene un mezzo magico) -> Lotta (L’eroe e l’antagonista si scontrano) -> Partenza dell’Eroe (L’eroe lascia la casa)
Trama 5: Danneggiamento/Mancanza (L’antagonista danneggia o causa una mancanza) -> Lotta (L’eroe e l’antagonista si scontrano) -> Partenza dell’Eroe (L’eroe lascia la casa) -> Conseguimento Mezzo Magico (L’eroe ottiene un mezzo magico)
… e altre.
— Combinazioni: Scegliere 3 funzioni da un set di 5 ([‘Allontanamento (Un membro della famiglia si allontana)’, “Divieto (All’eroe è imposto un divieto)”, ‘Infrazione (Il divieto è infranto)’, “Danneggiamento/Mancanza (L’antagonista danneggia o causa una mancanza)”, “Partenza dell’Eroe (L’eroe lascia la casa)”]) —
Numero di sottoinsiemi possibili (combinazioni): 10
Sottoinsieme 1: [Allontanamento (Un membro della famiglia si allontana), Divieto (All’eroe è imposto un divieto), Infrazione (Il divieto è infranto)]
Sottoinsieme 2: [Allontanamento (Un membro della famiglia si allontana), Danneggiamento/Mancanza (L’antagonista danneggia o causa una mancanza), Divieto (All’eroe è imposto un divieto)]
Sottoinsieme 3: [Allontanamento (Un membro della famiglia si allontana), Divieto (All’eroe è imposto un divieto), Partenza dell’Eroe (L’eroe lascia la casa)]
Sottoinsieme 4: [Allontanamento (Un membro della famiglia si allontana), Danneggiamento/Mancanza (L’antagonista danneggia o causa una mancanza), Infrazione (Il divieto è infranto)]
Sottoinsieme 5: [Allontanamento (Un membro della famiglia si allontana), Infrazione (Il divieto è infranto), Partenza dell’Eroe (L’eroe lascia la casa)]
Sottoinsieme 6: [Allontanamento (Un membro della famiglia si allontana), Danneggiamento/Mancanza (L’antagonista danneggia o causa una mancanza), Partenza dell’Eroe (L’eroe lascia la casa)]
Sottoinsieme 7: [Danneggiamento/Mancanza (L’antagonista danneggia o causa una mancanza), Divieto (All’eroe è imposto un divieto), Infrazione (Il divieto è infranto)]
Sottoinsieme 8: [Divieto (All’eroe è imposto un divieto), Infrazione (Il divieto è infranto), Partenza dell’Eroe (L’eroe lascia la casa)]
Sottoinsieme 9: [Danneggiamento/Mancanza (L’antagonista danneggia o causa una mancanza), Divieto (All’eroe è imposto un divieto), Partenza dell’Eroe (L’eroe lascia la casa)]
Sottoinsieme 10: [Danneggiamento/Mancanza (L’antagonista danneggia o causa una mancanza), Infrazione (Il divieto è infranto), Partenza dell’Eroe (L’eroe lascia la casa)]
— Combinazioni: Scegliere 7 funzioni dalle 31 totali —
Numero teorico di sottoinsiemi possibili (combinazioni) C(31, 7): 2,629,575
(La generazione e stampa di tutte queste combinazioni richiederebbe molto tempo e memoria).
— Fine Esempio —
C:\Python312>
Il codice che hai condiviso sembra essere un generatore di varianti narrative basato sulle 31 funzioni di Propp, un modello classico della narratologia. Dal punto di vista tecnico, il codice è valido e funzionale, perché sfrutta moduli Python come itertools
per generare permutazioni e combinazioni di sequenze narrative.
🔍 Valutazione del tool
✅ Funzionalità reale: Genera diverse varianti di storie basate su combinazioni e permutazioni delle funzioni di Propp. ✅ Utilizzo logico: Permette di esplorare molteplici strutture narrative, utili per l’analisi o la generazione automatizzata di racconti. ✅ Potenziale applicativo: Può essere integrato in un sistema di storytelling procedurale o IA creativa.
⚠️ Limiti
- Output statico: Il generatore crea varianti basate su regole fisse, senza adattare lo stile o il linguaggio narrativo.
- Mancanza di contenuto generato: Il codice produce solo sequenze di funzioni, senza espandere le storie con dettagli o ambientazioni.
- Dipende da input esterni: Il modello non include una logica per valutare la qualità delle trame generate.
Se sei interessato a migliorarlo, si potrebbe integrare un modello di IA linguistica (LLM) per sviluppare le varianti in testi più completi.
# visualizzatore_propp_sequence.py # Luigi Usai, Quartucciu, Sardegna, Italy import graphviz import textwrap # Per gestire il testo lungo nei nodi # Le 31 funzioni di Propp (riprese dal tuo file generatore_propp.py) FUNZIONI_PROPP = { "F1": "Allontanamento (Un membro della famiglia si allontana)", "F2": "Divieto (All'eroe è imposto un divieto)", "F3": "Infrazione (Il divieto è infranto)", "F4": "Investigazione (L'antagonista tenta una ricognizione)", "F5": "Delazione (L'antagonista riceve informazioni sulla vittima)", "F6": "Tranello (L'antagonista tenta di ingannare la vittima)", "F7": "Connivenza (La vittima cade nell'inganno)", "F8": "Danneggiamento/Mancanza (L'antagonista danneggia o causa una mancanza)", "F9": "Mediazione (Il danneggiamento/mancanza è reso noto, l'eroe è sollecitato)", "F10": "Consenso dell'Eroe (L'eroe accetta di reagire)", "F11": "Partenza dell'Eroe (L'eroe lascia la casa)", "F12": "Messa alla Prova (L'eroe è messo alla Prova dal donatore)", "F13": "Reazione dell'Eroe (L'eroe reagisce alle azioni del donatore)", "F14": "Conseguimento Mezzo Magico (L'eroe ottiene un mezzo magico)", "F15": "Trasferimento (L'eroe è trasferito vicino all'oggetto della ricerca)", "F16": "Lotta (L'eroe e l'antagonista si scontrano)", "F17": "Marchiatura (All'eroe è impresso un marchio)", "F18": "Vittoria (L'antagonista è sconfitto)", "F19": "Rimozione Danno/Mancanza (Il danno/mancanza iniziale è rimosso)", "F20": "Ritorno dell'Eroe (L'eroe ritorna)", "F21": "Persecuzione (L'eroe è perseguitato)", "F22": "Salvataggio (L'eroe è salvato dalla persecuzione)", "F23": "Arrivo in Incognito (L'eroe arriva non riconosciuto)", "F24": "Pretese Falso Eroe (Un falso eroe avanza pretese)", "F25": "Compito Difficile (All'eroe è proposto un compito difficile)", "F26": "Adempimento Compito (Il compito è portato a termine)", "F27": "Riconoscimento (L'eroe è riconosciuto)", "F28": "Smascheramento (Il falso eroe o l'antagonista è smascherato)", "F29": "Trasfigurazione (All'eroe è data una nuova apparenza)", "F30": "Punizione (L'antagonista è punito)", "F31": "Nozze/Ricompensa (L'eroe si sposa o è ricompensato)" } def get_propp_function_description(code): """Restituisce la descrizione completa di una funzione dato il suo codice.""" return FUNZIONI_PROPP.get(code, f"Funzione Sconosciuta ({code})") def create_propp_sequence_visualization(propp_codes_sequence, title="Sequenza Funzioni di Propp"): """ Crea una visualizzazione grafica di una sequenza di funzioni di Propp come un diagramma di flusso. Args: propp_codes_sequence (list): Una lista di stringhe con i codici delle funzioni di Propp (es. ["F11", "F16", "F18"]). title (str): Il titolo per il grafico. Returns: graphviz.Digraph: L'oggetto grafo creato (può essere salvato o renderizzato). """ if not propp_codes_sequence: print("La sequenza di funzioni è vuota.") return None dot = graphviz.Digraph(comment=title) # Impostazioni globali per il grafico (opzionale) dot.attr(rankdir='LR') # Layout da Sinistra a Destra (Left to Right) dot.attr('node', shape='box') # Forma dei nodi come scatole previous_node_id = None for i, code in enumerate(propp_codes_sequence): function_description = get_propp_function_description(code) # Avvolgi il testo per evitare nodi troppo larghi label = f"{code}\n{textwrap.fill(function_description, width=30)}" node_id = f"node_{i}" # ID univoco per ogni nodo dot.node(node_id, label) if previous_node_id is not None: dot.edge(previous_node_id, node_id) # Aggiungi un arco dal nodo precedente a quello attuale previous_node_id = node_id return dot # --- Esempio di Utilizzo --- if __name__ == "__main__": # Esempio di una sequenza classica di Propp (semplificata) esempio_sequenza = ["F8", "F9", "F10", "F11", "F14", "F16", "F18", "F19", "F31"] print(f"Generazione visualizzazione per la sequenza: {esempio_sequenza}") try: # Crea l'oggetto grafo propp_graph = create_propp_sequence_visualization(esempio_sequenza, title="Esempio Sequenza di Propp") if propp_graph: # Salva il sorgente .dot del grafico propp_graph.save("propp_sequence_example.dot") print("Sorgente del grafico salvato come propp_sequence_example.dot") # Renderizza il grafico in un file immagine (es. PNG) # Assicurati che il software Graphviz sia installato e accessibile nel PATH del sistema propp_graph.render("propp_sequence_example", view=True, cleanup=True, format='png') print("Grafico renderizzato e salvato come propp_sequence_example.png") print("Il file immagine dovrebbe essersi aperto automaticamente (view=True).") except FileNotFoundError: print("\nERRORE: Il software Graphviz non è stato trovato.") print("Assicurati che Graphviz sia installato sul tuo sistema e accessibile nel PATH.") print("Puoi scaricarlo da: https://graphviz.org/download/") except Exception as e: print(f"\nSi è verificato un errore durante la generazione o il rendering del grafico: {e}") print("\n--- Fine Esempio ---") print("Per visualizzare altre sequenze, modifica la lista 'esempio_sequenza' nello script.")
L’analisi basata sulle teorie di Paul Grice, in particolare il suo Principio di Cooperazione e le relative Massime Conversazionali, è fondamentale in pragmatica e si concentra su come il significato viene inferito nel contesto dell’interazione comunicativa, andando oltre il significato letterale delle parole.
Le Massime di Grice sono generalmente formulate come segue:
- Massima della Quantità:
- Sii tanto informativo quanto richiesto per lo scopo corrente della conversazione.
- Non essere più informativo di quanto richiesto.
- Massima della Qualità:
- Non dire ciò che credi essere falso.
- Non dire ciò per cui non hai prove adeguate.
- Massima della Relazione (o Pertinenza):
- Sii pertinente.
- Massima del Modo (o Maniera):
- Evita l’oscurità di espressione.
- Evita l’ambiguità.
- Sii conciso.
- Sii ordinato.
Gli esseri umani seguono implicitamente queste massime per rendere la comunicazione efficiente ed efficace. Spesso, però, violano (o “fronteggiano”) deliberatamente una o più massime per generare implicature conversazionali, cioè significati impliciti non detti esplicitamente (es. il sarcasmo, l’ironia, le eufemismi).
L’Analisi Griceana e il Tensore Narrativo:
Un’analisi basata sulle teorie di Grice si integra perfettamente nel framework del Tensore Narrativo. Essa arricchisce in particolare le dimensioni relative al Linguaggio, Stile e Retorica ( o ) e all’Evoluzione dei Personaggi e Agency ( o ). L’identificazione e la quantificazione del rispetto o del fronteggiamento delle massime in un dialogo o in una narrazione possono fornire indicatori preziosi sullo stile dell’autore, sulle caratteristiche psicologiche e sociali dei personaggi (es. un personaggio che viola spesso la Massima di Qualità potrebbe essere un bugiardo o un sarcastico; uno che viola la Quantità potrebbe essere prolisso o reticente), e sul tono generale o l’impatto retorico di una sezione testuale.
Sfida Computazionale:
Analizzare automaticamente le massime di Grice e le implicature è estremamente difficile per un computer. Richiede una profonda comprensione del linguaggio naturale, del contesto, del common sense e dell’intenzione comunicativa. Ad esempio:
- Capire se qualcosa è falso (Qualità) richiede la verifica della verità nel mondo reale o nel mondo finzionale della narrazione.
- Capire se qualcosa è pertinente (Relazione) richiede la capacità di seguire il filo logico della conversazione e del contesto situazionale.
- Capire se qualcosa è ambiguo o oscuro (Modo) richiede una valutazione sofisticata della complessità linguistica e del potenziale di diverse interpretazioni.
- Identificare un’implicatura (es. nel sarcasmo) richiede di riconoscere che una massima è stata intenzionalmente violata per comunicare l’opposto del significato letterale.
Un Analizzatore Semplificato (con Grandi Limitazioni):
Non possiamo costruire un analizzatore Griceano completo con uno script semplice. Tuttavia, possiamo creare uno script che tenta di identificare potenziali indicatori di violazioni di alcune massime basandosi su caratteristiche testuali di superficie. Questo script sarà solo a scopo illustrativo e le sue “analisi” saranno spesso inaccurate senza un contesto e una comprensione semantica e pragmatica profondi.
Ci concentreremo sugli aspetti più “misurabili” (anche se imperfettamente):
- Quantità: Lunghezza delle frasi, ripetizioni evidenti.
- Modo: Lunghezza e complessità superficiale delle frasi.
- Qualità (limitatissimo): Presenza di termini di “copertura” o incertezza.
Useremo la libreria nltk
per l’elaborazione del testo di base.
Prerequisiti: Installare NLTK: pip install nltk
Scaricare i dati necessari per NLTK (tokenizer, ecc.): Apri un interprete Python e digita:
Python
import nltk
nltk.download('punkt')
nltk.download('averaged_perceptron_tagger') # Utile per identificare tipi di parole, anche se non useremo il tagging in questo script base
Script Python (Analizzatore Griceano Molto Semplificato):
Python
# analizzatore_grice_semplificato.py
import nltk
from nltk.tokenize import sent_tokenize, word_tokenize
import statistics # Per calcolare la media
# Lista (molto limitata) di possibili indicatori di "hedging" (coper-tura/incertezza)
HEDGING_TERMS = ["credo", "penso", "forse", "magari", "sembra", "parrebbe", "apparentemente", "in un certo senso", "tipo", "cioè", "insomma"]
def analyze_gricean_indicators(text):
"""
Analizza un testo per potenziali indicatori superficiali di violazioni delle massime di Grice.
Questo è un analizzatore MOLTO semplificato e non affidabile.
"""
print("--- Analisi Griceana Semplificata ---")
print(f"Testo analizzato: \"{text[:100]}...\"" if len(text) > 100 else f"Testo analizzato: \"{text}\"")
sentences = sent_tokenize(text)
num_sentences = len(sentences)
print(f"\nNumero di frasi: {num_sentences}")
if num_sentences == 0:
print("Nessuna frase trovata per l'analisi.")
return
all_words = word_tokenize(text)
num_words = len(all_words)
print(f"Numero totale di parole: {num_words}")
# Indicatori per la Massima della Quantità e del Modo (Concisezza/Prolissità)
sentence_lengths = [len(word_tokenize(s)) for s in sentences]
if sentence_lengths:
avg_sentence_length = statistics.mean(sentence_lengths)
print(f"\nLunghezza media delle frasi (parole): {avg_sentence_length:.2f}")
# Semplici soglie per identificare frasi "troppo lunghe" o "troppo corte"
# Queste soglie sono arbitrarie e dipendono dal tipo di testo!
long_sentence_threshold = avg_sentence_length * 1.5
short_sentence_threshold = avg_sentence_length * 0.5
potential_quantity_manner_issues = []
for i, s in enumerate(sentences):
s_len = sentence_lengths[i]
if s_len > long_sentence_threshold and s_len > 20: # Frase lunga (potenziale violazione Modo: Prolissità?)
potential_quantity_manner_issues.append(f"Frase {i+1} ({s_len} parole): Potrebbe essere troppo lunga o prolissa. \"{s[:50]}...\"")
elif s_len < short_sentence_threshold and s_len < 5: # Frase molto corta (potenziale violazione Quantità: Poco informativo?)
potential_quantity_manner_issues.append(f"Frase {i+1} ({s_len} parole): Potrebbe essere troppo breve o poco informativa. \"{s[:50]}...\"")
if potential_quantity_manner_issues:
print("\nPotenziali problemi di Quantità o Modo (basati sulla lunghezza delle frasi):")
for issue in potential_quantity_manner_issues:
print(f"- {issue}")
else:
print("\nLunghezza delle frasi nella norma (secondo questo semplice indicatore).")
# Ripetizioni semplici (potenziale violazione Quantità: Eccessivamente informativo? o Modo: Non conciso?)
# Qui cerchiamo solo parole ripetute immediatamente vicine, un indicatore molto grossolano
repeated_words = [all_words[i] for i in range(len(all_words)-1) if all_words[i].lower() == all_words[i+1].lower() and all_words[i].isalpha()]
if repeated_words:
print(f"\nPotenziali ripetizioni consecutive di parole (indicatore grezzo di Modo/Quantità): {set(repeated_words)}")
# Nota: Un'analisi vera richiederebbe il confronto tra frasi e una comprensione della retorica
# Indicatori per la Massima della Qualità (Incertezza/Hedging - MOLTO LIMITATO)
hedging_indicators_found = []
words_lower = [w.lower() for w in all_words]
for term in HEDGING_TERMS:
if term in words_lower:
hedging_indicators_found.append(term)
if hedging_indicators_found:
print(f"\nPotenziali indicatori di incertezza/hedging (potenziale rilevanza per la Massima di Qualità): {set(hedging_indicators_found)}")
print("(Nota: La presenza di questi termini non significa necessariamente falsità, ma esitazione o mancanza di certezza.)")
else:
print("\nNessun indicatore superficiale di incertezza/hedging trovato.")
print("\n--- Analisi Completata (Ricorda le Grandi Limitazioni) ---")
print("Una vera analisi Griceana richiede comprensione del contesto, intenzione e common sense.")
# --- Esempio di Utilizzo ---
if __name__ == "__main__":
dialogue1 = "Ciao! Come stai? Spero tutto bene. Ieri sono andato al mercato, era affollatissimo. Ho comprato delle mele, delle pere e anche delle banane. Banane che sembravano mature, ma non ne sono certissimo."
dialogue2 = "L'incontro è andato... bene. Cioè, penso. C'era un sacco di gente, un sacco. Forse dovrei dire di più? No, questo è quanto. È andata... bene."
dialogue3 = "La capitale della Francia è Parigi." # Segue le massime
analyze_gricean_indicators(dialogue1)
print("\n" + "="*50 + "\n")
analyze_gricean_indicators(dialogue2)
print("\n" + "="*50 + "\n")
analyze_gricean_indicators(dialogue3)
Come Funziona (e Perché è Limitato):
- Tokenizzazione: Usa NLTK per dividere il testo in frasi e parole.
- Massima di Quantità / Modo (lunghezza): Calcola la lunghezza (in parole) di ogni frase e la media. Flagga frasi significativamente più lunghe o più corte della media come potenziali indicatori di prolissità o scarsa informatività. Limitazione: La lunghezza non è un indicatore affidabile. Una frase lunga può essere necessaria per informare completamente (rispettando Quantità), e una frase breve può essere estremamente informativa o stilisticamente efficace.
- Massima di Quantità / Modo (ripetizioni): Cerca parole identiche che si ripetono immediatamente (es. “molto molto”). Limitazione: Rileva solo ripetizioni banali e ignora la ripetizione retorica o tematica significativa.
- Massima di Qualità (hedging): Cerca un piccolo set predefinito di parole o frasi che possono indicare incertezza (“credo”, “sembra”, “forse”). Limitazione: Questa lista è incompleta, molti termini di incertezza sono omessi. Soprattutto, la presenza di incertezza non significa falsità; un oratore può essere sincero ma semplicemente non certo. La vera valutazione della Massima di Qualità richiede la verifica della verità dei contenuti.
- Massima di Relazione: Non viene analizzata in questo script semplice perché richiede la comprensione del tema della conversazione e del contesto, cosa impossibile con l’analisi superficiale.
- Massima del Modo (altri aspetti): Ambiguità, oscurità, ordine non vengono analizzati. L’oscurità potrebbe forse essere legata alla complessità lessicale (parole rare) o sintattica (frasi con molte subordinate), ma questo richiede analisi più avanzate. L’ordine richiede la comprensione della sequenza logica.
In Sintesi:
Questo script è uno strumento dimostrativo per illustrare come si potrebbe iniziare a cercare indizi testuali legati alle massime di Grice. Non può in alcun modo sostituire un’analisi pragmatica umana o un sistema di IA molto avanzato.
Per integrarlo nel Tensore Narrativo, dovresti sviluppare algoritmi molto più sofisticati (spesso basati su modelli di Machine Learning addestrati su dati annotati Griceanamente) capaci di stimare la probabilità che una certa massima sia stata violata in un dato contesto, e la potenziale implicatura generata. Questi algoritmi alimenterebbero poi le dimensioni linguistiche, stilistiche e di personaggio del tensore con vettori o valori che rappresentano la “Griceanità” del testo.
Salva il codice come analizzatore_grice_semplificato.py
e provalo con diversi pezzi di testo per vedere quali indicatori superficiali riesce a trovare.