CATENE DI MARKOV: UN'APPLICAZIONE ALLA COMPOSIZIONE MUSICALE PROGETTO DI METODI MATEMATICI E STATISTICI DI MARIO ALVISE DI BERNARDO ANNO ACCADEMICO 2012/2013 • • • • • • • • 1.Introduzione 2.Cenni sulla composizione algoritmica ◦ 2.1.Il “gioco di dadi musicale” di Mozart 3.Cenni sulle catene di Markov ◦ 3.1.Alcune applicazioni 4.Analisi della catena utilizzata ◦ 4.1.Probabilità di transizione ad un passo: matrice di transizione ◦ 4.2.Grafo associato ◦ 4.3.Calcolo di leggi congiunte ◦ 4.4.Classificazione degli stati ◦ 4.5.Probabilità invarianti ◦ 4.6.Stato stazionario 5.Implementazione ◦ 5.1.Descrizione dell'algoritmo utilizzato 6.Analisi dei risultati ◦ 6.1.Analisi della forma d'onda 7.Allegati 8.Webgrafia 1.INTRODUZIONE Nella seguente trattazione, vedremo in che modo la statistica può trovare applicazione in ambito di composizione musicale. In particolare, verranno prima introdotti separatamente i concetti di composizione algoritmica musicale e catena di Markov, osservando successivamente, con un esempio pratico, in che modo sia possibile implementare un algoritmo che permetta di comporre musica tramite processo markoviano. Nel trattare la composizione algoritmica, verrà approfondito maggiormente il carattere aleatorio del comporre tramite casualità (vedremo un esempio storico di musica composta con l'uso di dadi) a discapito del legame tra la composizione musicale e l'uso del computer. Saranno poi allegati due file audio ottenuti da due esecuzioni successive dello stesso algoritmo e ne saranno evidenziate le differenze date dal carattere aleatorio dell'implementazione stessa. 2.CENNI SULLA COMPOSIZIONE ALGORITMICA Si definisce come algoritmico un processo musicale che si svolge, prevalentemente mediante elaboratore digitale, in base ad un ben determinato schema utilizzato per la generazione delle strutture musicali. L'oggetto del comporre, in questo caso, non sono gli eventi sonori quali altezze, durate e timbro, ma il processo stesso di composizione. Gli algoritmi (intesi come insiemi di regole formali) sono stati utilizzati per secoli per comporre musica: le procedure utilizzate per intrecciare le voci nel contrappunto occidentale, ad esempio, possono spesso essere ridotte a determinatezza algoritmica. Il termine, tuttavia, solitamente indica l'uso di procedure formali per fare musica senza l'intervento umano, sia attraverso l'introduzione di procedure casuali sia attraverso l'uso del computer. Alcuni algoritmi che non hanno alcuna rilevanza musicale immediata vengono utilizzati dai compositori come ispirazione creativa per la loro musica. Algoritmi come frattali, sistemi Lindenmayer, modelli statistici e anche dati arbitrari (ad esempio dati del censimento, coordinate GIS, o le misurazioni del campo magnetico) sono stati utilizzati come materiali di partenza. 2.1.Il “gioco di dadi musicale” di Mozart I primi esempi di composizione algoritmica si possono ravvisare nel XVIII secolo, quando compositori come Bach, Haydn e Haendel iniziarono, per divertimento, a comporre musica utilizzando i dadi. Nel 1793 questa tecnica inizia ad avere larga diffusione grazie alla pubblicazione a Berlino e ad Amsterdam di un "Musikalisches Würfelspiel" ("Gioco di dadi musicale") utilizzabile per comporre minuetti "senza la minima conoscenza della musica, tirando due dadi". Il gioco, il cui autore era Wolfgang Amadeus Mozart, ebbe subito un grandissimo successo: in pochi anni moltissime case editrici europee lo ristamparono, e vennero pubblicate versioni economiche e di lusso. Il "Musikalisches Würfelspiel" permetteva di comporre, in modo automatico, un minuetto strutturato secondo la forma tripartita usata in quell'epoca: • una prima parte (il minuetto vero e proprio); • una parte centrale, detta "trio" perché originariamente era assegnata a tre strumenti solisti; • una terza parte, che riproponeva il minuetto iniziale. I minuetti e i trii dell'epoca erano costituiti tipicamente da 16 battute, e la loro struttura poteva basarsi su schemi abbastanza standard. Fu proprio questa semplicità strutturale a dar modo a Mozart di poter concepire l'idea di una composizione automatica. Per comporre il minuetto, il gioco prevedeva l'utilizzo di una tabella con 11 righe e 16 colonne. In ognuna delle caselle risultanti era presente un numero da 1 a 176, che rimandava ad un libretto nel quale erano trascritte 176 battute composte da Mozart. Le 16 colonne della tabella corrispondevano alle 16 battute del minuetto. Lanciando, per ciascuna delle 16 battute, due dadi e sottraendo 1 dal punteggio totale si otteneva un numero da 1 a 11. Consultando il libretto con il numero presente all'intersezione tra la colonna del numero di battuta e la riga determinata dal lancio dei dadi, si trovava la battuta mozartiana da utilizzare. Seguendo questo procedimento il "giocatore" si ritrovava con un minuetto di 16 battute. Per quanto riguarda il trio da usare come parte centrale, il procedimento era del tutto analogo, ma in questo caso la tabella da utilizzare aveva soltanto 6 righe, per cui era sufficiente un solo dado. È importante sottolineare che nel lancio di due dadi le 11 combinazioni possibili non hanno tutte la stessa probabilità: ad esempio il punteggio 7 è il più probabile, poiché si può ottenere con 6 diverse combinazioni, mentre il 2 o il 12 si ottengono con una sola combinazione. Alcuni minuetti, quindi, sono più probabili di altri ma non sappiamo se Mozart abbia tenuto conto di questo, ad esempio facendo corrispondere le battute migliori ai lanci di dadi più probabili. Ciò che è certo, è che la bravura di Mozart fu quella di scrivere battute che potessero adattarsi bene l'una con l'altra, cosa tutt'altro che banale, specie analizzando i possibili risultati ottenibili. Infatti, per ognuna delle 16 battute del tema principale ci sono 11 battute possibili: quindi le combinazioni sono 1116. Analogamente, il gioco consente la composizione di 616 trii. Poiché il minuetto, come forma musicale tripartita, è dato dalla combinazione di un minuetto e di un trio, abbiamo in tutto 1116 x 616 = 129.629.238.163.050.258.624.287.932.416 diverse composizioni possibili, cioè circa 129 miliardi di miliardi di miliardi! È possibile giocare al "Musikalisches http://sunsite.univie.ac.at/Mozart/dice. Würfelspiel" andando all'indirizzo 3.CENNI SULLE CATENE DI MARKOV Un processo di Markov è un processo stocastico nel quale la probabilità di transizione che determina il passaggio ad uno stato di sistema dipende unicamente dallo stato di sistema immediatamente precedente (proprietà di Markov) e non dal come si è giunti a tale stato (in quest'ultima ipotesi si parla di processo non markoviano). Tale processo prende il nome dal matematico russo Andrej Andreevi č Markov che per primo ne sviluppò la teoria. In riferimento a un processo stocastico con spazio degli stati e tempo discreti, possiamo dare la seguente definizione formale: P( Xn+1 = j | X0, X1, …, Xn ) = P( Xn+1 = j | Xn ) ovvero: se il istema si trova nello stato n, il suo stato al tempo n+1 non dipende dagli stati ai tempi 0, 1, …, n-1, ma solo dallo stato al tempo n. 3.1.Alcune applicazioni Il motore di ricerca Google assegna un valore all'importanza di un sito web tramite l'algoritmo PageRank: quest'ultimo si basa sull'assegnare una probabilità di transizione da un sito web A a un sito B basata sulla quantità di link che da A conducono a B. Conoscendo la probabilità di transizione è possibile ottenere la distribuzione stazionaria di probabilità della catena di Markov formata da tutti i siti web. La distribuzione stazionaria assegna un valore nell'intervallo [0,1] ad ogni sito (corrispondente alla quantità media di tempo spesa sul sito da un gran numero di utenti dopo un tempo tendente a infinito): tale valore, opportunamente riscalato, costituisce il Page Rank del sito. Gran parte della modellistica di serie temporali in finanza si basa su processi stocastici generati da catene di Markov. Modelli di tipo markoviano vengono anche utilizzati nel progetto di reti di telecomunicazioni; la teoria delle code che ne consegue trova applicazione in molti ambiti: dalla fila alle poste ai pacchetti in coda in un router. Le catene di Markov trovano applicazione anche nella composizione algoritmica musicale, in particolare in linguaggi e ambienti di sviluppo come CSound, Max o SuperCollider. Tale argomento, verrà approfondito nei prossimi paragrafi. 4.ANALISI DELLA CATENA UTILIZZATA Data una catena di primo ordine, gli stati del sistema diventano note, e per ciascuno viene costruito un vettore di probabilità, componendo una matrice di probabilità di transizione. L'algoritmo produce e manda in output i valori delle note basandosi sui pesi della matrice di transizione. Tali valori saranno, nell'esempio trattato, frequenza (in Hertz) e valore della nota. Note LA DO MI LA DO MI 0.4 0.3 0.3 0.6 0.25 0.15 0.1 0 0.9 Un esempio con una matrice di prim'ordine. Pur se non argomento di questa trattazione, è interessante considerare l'utilizzo di catene di Markov di ordine superiore al primo, che tengono conto sia dello stato attuale che di quelli precedenti, permettendo così di raggruppare assieme sequenze particolari di note che saranno occasionalmente interrotte da altri pattern. Catene di ordine superiore al primo permettono così di generare risultati con una certa struttura nei fraseggi, a differenza del “vagare senza meta” prodotto da un sistema di primo ordine. Note LA RE LA LA 0.5 0.5 LA RE 0.3 0.5 LA SOL 1 0 RE RE 0.5 0.25 RE LA 0.75 0 RE SOL 0.9 0.1 SOL SOL 0.4 0.4 SOL LA 0 1 SOL RE 0.15 0.75 SOL 0 0.2 0 0.25 0.25 0 0.2 0 0.1 Un esempio con una matrice di secondo ordine. 4.1.Probabilità di transizione ad un passo: matrice di transizione La seguente matrice Q descriverà l'evoluzione del sistema: ogni elemento qi,j ci dirà infatti con quale probabilità il sistema passerà dallo stato i al tempo n, allo stato j al tempo n+1. 0 0 0 0 0 Q= 0 0 0 0 1/3 1 0 0 0 0 0 0 0 0 0 0 1 0 0 ¼ 0 0 0 0 0 0 0 ½ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 ¾ 1/3 0 ½ 0 1/3 0 0 0 0 0 2/3 ½ 0 0 0 0 0 ½ 0 0 0 ½ 0 0 0 0 0 0 0 0 0 0 ½ 0 0 0 0 0 0 0 0 0 0 1 1/3 Ogni riga rappresenta il comportamento dell'i-esimo stato, per questo la somma degli elementi di una riga è sempre 1. 4.2.Grafo associato Una rappresentazione alternativa per le catene di Markov prevede l'utilizzo di un grafo orientato pesato, i cui vertici rappresentano gli stati e i pesi degli archi le probabilità di transizione. Per ogni stato è indicata la nota, il valore della frequenza in hertz e la durata relativa, che andrà poi divisa per i bps (beats per second) per ottenere la durata effettiva. 4.3.Calcolo di leggi congiunte Sia E = {X0, X1, X2, X3, X4, X5, X6, X7, X8, X9} l'insieme degli stati della catena di Markov. Esso ha cardinalità n = 10. Vogliamo individuare la legge w per X n. Data v legge di X0, calcoliamo: w = vQn Eseguendo il calcolo con Matlab, otteniamo: w = [ 0.0432 0.0415 0.0398 0.0046 0.0139 0.2271 0.2695 0.1392 0.0794 0.1418 ] 4.4.Classificazione degli stati Sia E = {X0, X1, X2, X3, X4, X5, X6, X7, X8, X9} l'insieme degli stati della catena di Markov precedentemente definita e sia C un sottonsieme di stati tale che C ⊂ E. Non sono presenti sottoinsiemi di stati che siano chiusi, pertanto E è l'unica classe irriducibile, ovvero per ogni i, j ∈ E, con i ≠ j, esisterà sempre n > 0 tale che qi,j(n) > 0. Questo significa che, presi due stati qualunque, esisterà un percorso che andrà dallo stato i allo stato j in n passi. Essendo E la sola classe irriducibile, e avendo essa cardinalità maggiore di 1, non sono presenti stati assorbenti, ossia stati che costituiscono da soli una classe irriducibile. Uno stato i si dice ricorrente se il sistema, essendo stato una volta in i, tornerà in i con probabilità 1, ovvero pi, i = 1. In caso contrario lo stato si dirà transitorio e pi, i < 1. Gli stati 0, 1, 2, 7, 8 e 9 sono ricorrenti, mentre gli stati 3, 4, 5 e 6 sono transitori. La catena è aperiodica. Infatti, dato k ≥ 1, non esiste nessuna m > 1 per cui un qualche stato j soddisfi la seguente relazione: P(Xn+s = j | Xn = j) = 0, con s ≠ mk. Dalla matrice Q risulta evidente che: • lo stato 0 comunica con lo stato 1; • lo stato 1 comunica con lo stato 2; • lo stato 2 comunica con gli stati 3 e 7; • lo stato 3 comunica con lo stato 4; • lo stato 4 comunica con gli stati 2 e 5; • lo stato 5 comunica con gli stati 5 e 6; • lo stato 6 comunica con gli stati 6 e 7; • lo stato 7 comunica con gli stati 5 e 8; • lo stato 8 comunica con lo stato 9; • lo stato 9 comunica con gli stati 0, 5 e 9. 4.5.Probabilità invarianti Nessuna delle probabilità su E è invariante o stazionaria. Infatti è facile verificare che non esiste nessuna v probabilità su E tale che: v = vQ Poichè la matrice di transizione Q è regolare, ovvero esiste m intero positivo tale che: qi, j(m) > 0, per ogni i, j ∈ E la catena di Markov si dirà regolare. Ne segue che tutti gli stati comunicano tra loro e quindi la catena è irriducibile e gli stati ricorrenti. Ma non vale il viceversa. 4.6.Stato stazionario Studiamo ora la catena di Markov per tempi molto grandi. Quando l'istante di osservazione è molto lontano dal punto iniziale, la probabilità p j che la catena si trovi nello stato j non dipende dallo stato iniziale, ovvero, per j = 0, 1, ...: lim P( Xn=j | X0=i ) = lim qi, j(n) = pj n→∞ n →∞ Le probabilità limite pj, se esistono, sono dette distribuzione di equilibrio o distribuzioni dello stato stazionario di una catena di Markov, e la loro somma è 1. Vediamo se esiste una distrubuzione di equilibrio per la nostra catena. Per il teorema di Markov, data una catena di Markov avente stati finiti e pari a N e matrice di transizione Q regolare, allora esiste un'unica probabilità invariante p = (p 1, p2, …, pN) di Q tale che: lim qi, j(n) = pj n→∞ Poiché la nostra catena soddisfa le ipotesi, abbiamo la certezza dell'esistenza di p. Troviamo p = (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9). Calcoliamo le equazioni di bilancio. Per j = 0 si ha: p0 = p9 / 3 Per j = 1 si ha: p1 = p0 Per j = 2 si ha: p2 = p1 + p4 / 4 Per j = 3 si ha: p3 = p2 / 2 Per j = 4 si ha: p4 = p3 Per j = 5 si ha: p5 (2 / 3) = p4 (3 / 4) + p7 / 2 + p9 / 3 Per j = 6 si ha: p6 / 2 = p5 (2 / 3) Per j = 7 si ha: p7 = p2 / 2 + p6 / 2 Per j = 8 si ha: p8 = p7 / 2 Per j = 9 si ha: p9 (2 / 3) = p8 L'equazione di normalizzazione è: p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 = 1 Mettendo a sistema equazioni di bilancio e equazione di normalizzazione si ha: p0 = p1 = 2 / 43 p2 = p3 = p4 = 0 p5 = 9 / 43 p6 = 12 / 43 p7 = 8 / 43 p8 = 4 / 43 p9 = 6 / 43 Pertanto, la proprietà invariante per la nostra catena è: p = ( 2 / 43, 2 / 43, 0, 0, 0, 9 / 43, 12 / 43, 8 / 43, 4 / 43, 6 / 43 ) Tali risultati possono essere osservati empiricamente con dei semplici test sul codice allegato. Basterà infatti inserire un comando che stampi a video lo stato corrente a ogni passo (chiameremo percorso questo insieme di valori) e calcolare la distribuzione di frequenza con la funzione FREQUENZA di Excel, usando il percorso come dati e gli stati possibili (ovvero gli elementi dell'insieme E) come classi. Per n = 100 otteniamo: Stato 0 1 2 3 4 5 6 7 8 9 Frequenza 5 5 5 2 2 23 22 18 8 10 Mentre per n = 1000 otteniamo: Stato 0 1 2 3 4 5 6 7 8 9 Frequenza 36 37 41 17 17 209 297 167 74 105 Per valori molto grandi di n, dunque, la distribuzione di frequenza degli stati della catena tenderà a stabilizzarsi seguendo la proprietà invariante p. 5.IMPLEMENTAZIONE Per l'implementazione dell'algoritmo, è stato usato SuperCollider, un linguaggio di programmazione per la sintesi audio in tempo reale con integrato un ambiente di sviluppo diviso in due componenti: un server (scsynth) e un client (sclang). Questi componenti comunicano tramite OSC (Open Sound Control). 5.1.Descrizione dell'algoritmo utilizzato Iniziamo definendo il sintetizzatore, ossia lo strumento che suonerà il nostro spartito. Apriamo un Task (questo ci permetterà di gestire il tempo tra l'avvio di una nota e la successiva tramite la durata effettiva e il comando wait) e usiamo un array per definire la nostra catena secondo lo schema: [freq, dur_rel, <lista_adiacenza>]. Nella lista di adiacenza indicheremo ogni stato direttamente collegato a quello corrente con la relativa probabilità: [[stato_1, probabilità_1], [stato_2, probabilità_2], …] Stabilito un bpm, calcoliamo quindi i bps per poi ottenere la durata effettiva delle note in secondi. Questo ci permetterà di cambiare la velocità a nostro piacimento modificando solo il valore bpm. Inizializziamo il nodo corrente a 0. In questo modo lo stato 0, rappresentato dalla prima riga della matrice, sarà lo stato iniziale. Apriamo un ciclo do impostando il contatore a 99, così da avere un totale di n = 100 passi. A ogni passo, useremo il sintetizzatore per eseguire la nota (o la pausa) dello stato corrente. Lo stato successivo viene scelto secondo la seguente procedura: • viene calcolata la somma dei pesi presenti nella lista di adiacenza dello stato corrente; • viene estratto un numero casuale compreso tra 0 e il peso totale; • se il numero estratto è minore o uguale al primo peso, viene scelto il primo nodo della lista. Altrimenti, si confronta il numero estratto con il secondo peso più il primo: se è minore o uguale si sceglie il secondo nodo della lista. In caso contrario si passa al confronto tra il numero casuale e la somma dei primi tre pesi, e così via. Lo spartito sarà quindi il percorso definito dal cambiamento degli stati della catena di Markov. 6.ANALISI DEI RISULTATI Analizzeremo ora due tracce audio ottenute da due esecuzioni del codice mostrando come, se pur generate dallo stesso algoritmo, le due tracce presentino notevoli differenze. Sebbene tali differenze siano già evidenti all'ascolto, saranno mostrati dei grafici ottenuti col software Audacity. 6.1.Analisi della forma d'onda La forma d'onda è il profilo generato su un piano cartesiano dalla misurazione di un segnale rispetto a due grandezze, che nel nostro caso sono il tempo t e il potenziale elettrico V del segnale, normalizzato tra -1 e 1. Seguono le forme d'onda osservate nei due canali (stereo) di ciascuna traccia. Traccia 1. Traccia 2. Osservando le creste e gli avvallamenti, è possibile notare come le due tracce siano composte dagli stessi eventi sonori, ma disposti in maniera diversa. Ad esempio, le forme d'onda dei suoni eseguiti tra l'istante 0 e l'istante 1 sono le stesse per entrambe le tracce. In effetti, come si evince dal grafico e dalla matrice di transizione, la nostra catena forza i passaggi tra gli stati 0 e 1, e tra 1 e 2. Agli istanti successivi le tracce iniziano a diversificarsi. Nel file “sc_markov canali separati.mp3” le due tracce vengono eseguite contemporaneamente su diversi canali stereo, ossia ascoltando il file audio su un sistema stereo, la prima traccia sarà udibile sulla cassa destra, mentre la seconda sulla cassa sinistra. Come precedentemente osservato nei grafici, le tracce saranno identiche nel primo istante di riproduzione, dopodichè inizieranno a differenziarsi. 7.ALLEGATI • • • • sc_markov 1.mp3: prima traccia audio generata. sc_markov 2.mp3: seconda traccia audio generata. sc_markov canali separati.mp3: mix delle due tracce. È stato attribuito un canale diverso a ogni traccia così da evidenziarne le differenze. Catena di Markov.scd: file SuperCollider. 8.WEBGRAFIA • • http://en.wikipedia.org/wiki/Algorithmic_composition http://web.tiscalinet.it/gruppo_a/fog_txt.html