equazioni lineari e matrici: la matematica in rete - Cineca
Transcript
equazioni lineari e matrici: la matematica in rete - Cineca
Piano Nazionale Lauree Scientifiche - a.a. 2010/11 Laboratorio PLS EQUAZIONI LINEARI E MATRICI: LA MATEMATICA IN RETE con I.T.C. “ZANON” (Udine) L.S. “LE FILANDIERE” (San Vito al Tagliamento) Dimitri Breda1 , Alessandra Maniglio2 , Paola Pignoni3 , Stefania Pividori3 1 Dipartimento di Matematica e Informatica Università degli Studi di Udine [email protected] http://users.dimi.uniud.it/˜dimitri.breda/ 2 Liceo Scientifico “Le Filandiere” San Vito al Tagliamento [email protected] 2 Istituto Tecnico Commerciale “Zanon” Udine [email protected] [email protected] 1 Indice 1 Introduzione 2 Vettori, matrici e sistemi lineari 2.1 Piano cartesiano e vettori . . . . . 2.2 Trasformazioni lineari e matrici . 2.3 Sistemi lineari . . . . . . . . . . . 2.4 Un po’ di trigonometria non nuoce 2.5 Ma quanto costa? . . . . . . . . . 3 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 5 9 17 23 27 Google 3.1 Matrici di connettività e navigatori casuali . . . . . . . . 3.2 La fortuna di Google: il metodo delle potenze e tanti zeri 3.3 Pagine penzolanti e ricerche personalizzate . . . . . . . 3.4 Pagerank finalmente?! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 30 36 40 50 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A Appendice: cifre significative, accuratezza e precisione 56 B Codici Pagerank realizzati 57 2 1 Introduzione Queste pagine vogliono rappresentare una breve guida alle attività svolte all’interno del Piano Nazionale Lauree Scientifiche (PLS) per il Laboratorio “Equazioni lineari e matrici: la matematica in rete”. Esse sono rivolte a selezioni di alunni di classi quarte provenienti dall’Istituto Tecnico Commerciale “Zanon” di Udine e dal Liceo Scientifico “Le Filandiere” di San Vito al Tagliamento, nonchè progettate congiuntamente tra i docenti universitari e gli insegnanti di cui nel frontespizio. Si premette che, seguendo le direttive del PLS, gli argomenti sviluppati non vengono presentati in modo meramente nozionistico, piuttosto con l’intento di stimolare la curiosità e l’interesse dei partecipanti verso tematiche a forte contenuto matematico - anche avanzato rispetto agli standard dei programmi ministeriali previsti per l’istruzione secondaria - ma che, tutto sommato, si possono spesso incontrare nella vita quotidiana, soprattutto in una realtà permeata dall’intensivo utilizzo della teconologia e dell’informatica come quella attuale. È bene avvisare il lettore più preparato che le esigenze di semplificazione emerse nella scrittura di queste note hanno spesso invaso lo spazio normalmente destinato al rigore e alla completezza caratteristici di una trattazione matematica. A tale scopo, e vista la disponibilità dei laboratori della Facoltà di Scienze MFN dell’Università di Udine, dove si svolge parte dell’attività, ci si avvale del software MATLAB© come veicolo di apprendimento. Rimandiamo una volta per tutte a [1, 2] gli eventuali lettori dall’interesse “insaziabile”, sottolineando che parte del materiale presentato è preso da tali riferimenti, frutto del creatore stesso di Matlab, Cleve Moler. I protagonisti di queste note sono in primo luogo i vettori, le matrici ed i sistemi lineari. Tralasciandone le più profonde connotazioni algebriche e geometriche per le ragioni premesse, vettori e matrici sono introdotti in Sezione 2 nel caso bidimensionale, ovvero il più semplice possibile. Aldilà delle esigenze di semplificazione, questo caso si presta ottimamante all’interpretazione geometrica della matrice come trasformazione lineare nel piano cartesiano. Dopo aver introdotto - e “digerito” - operazioni quali il prodotto scalare di vettori e il prodotto righe-colonne di matrici, rivisiteremo sotto un’altra prospettiva i sistemi di equazioni lineari che già ben conosciamo. La parte finale di tale sezione sarà dedicata all’analisi dei costi computazionali che comportano le operazioni base dell’algebra matriciale. L’intera Sezione è poi accompagnata da esempi ed esercizi con lo scopo di avvicinare gradualmente gli alunni all’utlizzo di Matlab. Apprese e consolidate le nuove nozioni di cui sopra, le sfrutteremo in Sezione 3 per addentrarci nel mondo della rete e del World Wide Web (WWW) in particolare. L’obiettivo che ci poniamo consiste nel comprendere gli aspetti fondamentali che ci permettono di ordinare le informazioni che ci interessano in un mondo tanto vasto come il WWW, di capirne la modellizzazione matematica che è ivi nascosta, per arrivare infine a realizzare delle implementazioni Matlab dell’algoritmo PAGERANK© utilizzato da GOOGLE© . Riguardo alla struttura delle attività, è bene osservare che il laboratorio inizia con la conferenza “Dal mattone a Google: equazioni ovunque” tenuta dal docente universitario presso gli Istituti aderenti, allo scopo di introdurre gli alunni alle tematiche trattate. Esso continua poi con una fase di “azzeramento” dei requisiti (coprente a grandi linee i contenuti della Sezione 2), condotta dagli insegnanti coinvolti presso i relativi Istituti. Si giunge quindi allo “stage” degli alunni presso i laboratori della Facoltà, dove vengono impartite le nozioni base di Matlab e si procede all’implementazione dei codici. Seguono poi opportune fasi di approfondimento e verifica. Con un po’ di pazienza, e guidati dal motore principe della ricerca e delle innovazioni scientifiche e, in genere, culturali - la curiosità - alla fine di quest’esperienza guarderemo alle matrici e ai sistemi con un riguardo maggiore di quello che potremmo abitualmente concedere ad una semplice tabella di numeri 3 o a delle noiose equazioni da risolvere. Certo non pretenderemo di coglierne a pieno tutte le notevoli potenzialità che celano al loro interno, ma per questo...c’è sempre l’opportunità di iscriversi ai Corsi di Laurea della Facoltà di Scienze! 4 2 2.1 Vettori, matrici e sistemi lineari Piano cartesiano e vettori Tutti noi conosciamo bene il piano cartesiano (da René Descartes [1596-1650], filosofo e matematico francese) e sappiamo che ogni suo punto può essere univocamente associato ad una coppia di numeri, le sue coordinate. Indichiamo tali numeri in un modo forse un po’ diverso da quello abituale, ovvero con un vettore colonna: x1 x= . x2 Ad esempio, il punto associato al vettore x di Figura 1 ha coordinate 2 x= . 4 Sono definite in modo naturale operazioni quali la somma algebrica di vettori x1 y1 x1 + y 1 x+y = + = x2 y2 x2 + y 2 e la moltiplicazione per uno scalare sx = s x1 x2 = sx1 sx2 Il loro significato geometrico è fornito, nel primo caso, dalla cosiddetta regola del parallelogramma e, nel secondo, dall’allungamento se |s| > 1 o accorciamento se |s| < 1, eventualmente accompagnati dal cambio di verso se s < 0. La loro “combinazione” prende il nome, appunto, di combinazione lineare di vettori: ax1 + by1 by1 ax1 y1 x1 . = + = +b ax + by = a ax2 + by2 by2 ax2 y2 x2 Esempio 1 In Figura 1 è rappresentato il vettore x= 2 4 relativo al punto di coordinate x1 = 2 ed x2 = 4. Inoltre abbiamo il vettore −1 y= , 2 la loro somma x+y = 2−1 4+2 = 1 6 ed, infine, il prodotto di x con lo scalare s = −0.5: −0.5 · 2 −1 s · x = −0.5 · x = = . −0.5 · 4 −2 Da notare che, come anticipato, uno scalare negativo ha l’effetto di cambiare il verso del vettore che moltiplica. 5 Esercizio 1 Secondo la regola del parallelogramma, il vettore somma di due vettori corrisponde geometricamente alla diagonale principale del parallelogramma che ha per lati i due vettori addendi, vedi Esempio 1. A cosa corrisponde invece il vettore differenza? (Sugg.: non servono regole nuove, basta usare sapientemente la somma e la moltiplicazione per uno scalare) Matlab 1 In Matlab potremmo eseguire il contenuto dell’Esempio 1 con le seguenti istruzioni (premete invio alla fine di ogni istruzione): >> x=[2;4] x = 2 4 >> y=[-1;2] y = -1 2 >> x+y ans = 1 6 >> s=-0.5 s = -0.5000 >> s*x ans = -1 -2 Cogliamo l’occasione per dire che il simbolo “+” indica la somma algebrica, mentre “*” la moltiplicazione in genere. Osserviamo poi che i vettori colonna si inseriscono separando gli elementi con “;” all’interno di parentesi quadre. Meno naturale può risultare l’operazione di prodotto scalare di due vettori, definito come x1 y1 x·y = · = x1 y1 + x2 y2 , x2 y2 ovvero la somma dei prodotti delle componenti corrispondenti. Esempio 2 Per 2 3 3 1 x= e y= risulta x · y = 2 · 3 + 3 · 1 = 9, 6 7 m 6 5 x 4 3 2 y 1 0 −1 −2 −3 −2 −0.5! x −1 0 1 2 3 Figura 1: somma algebrica e moltiplicazione per uno scalare. mentre con z= −3 2 risulta x · z = 2 · (−3) + 3 · 2 = 0. I vettori sono rappresentati in Figura 2. Matlab 2 In Matlab: >> x=[2;3] x = 2 3 >> y=[3;1] y = 3 1 >> x’*y ans = 9 >> z=[-3;2] z = -3 7 2 >> x’*z ans = 0 Per eseguire il prodotto scalare usiamo “’ *”. Ma per ora non occupiamoci del significato del simbolo “’”, lo apprenderemo strada facendo. 4 x 3 z 2 y 1 0 −1 −4 −3 −2 −1 0 1 2 3 4 Figura 2: prodotto scalare e vettori perpendicolari. Dal precedente esempio potremmo indurre che due vettori sono perpendicolari (od ortogonali) se il loro prodotto scalare risulta nullo. Questo fatto costituisce in realtà un fondamentale Teorema dell’algebra lineare e della geometria piana: x ⊥ y ⇔ x · y = 0 ⇔ x1 y1 + x2 y2 = 0. (1) Di seguito proponiamo un esempio interessante di uso del prodotto scalare. Ad ogni modo, il significato geometrico di tale operazione verrà approfondito più avanti. Esempio 3 Per apprezzare alcune implicazioni “reali” del prodotto scalare, prendiamo in prestito dalla Fisica il concetto di lavoro. Il lavoro L (scalare) che una forza F (vettore) compie a seguito dello spostamento s (vettore) del suo punto di applicazione è il prodotto scalare L = F · s. 8 2.2 Trasformazioni lineari e matrici Ora ci chiediamo, dato un punto del piano individuato dal vettore x, quale sia il modo più generale possibile per ottenere un nuovo punto individuato da un vettore y attraverso combinazione lineare delle coordinate di x. Più in dettaglio, vogliamo che ciascuna coordinata del nuovo punto y sia combinazione lineare delle coordinate di x. Traducendo in linguaggio matematico: y1 ax1 + bx2 y= = (2) y2 cx1 + dx2 con a, b, c e d scalari assegnati. Esempio 4 In Figura 3 possiamo vedere il caso concreto relativo a 2 x= 4 ed a = 4, b = −3, c = −2 e d = 1. Si ottiene dunque y1 ax1 + bx2 4·2−3·4 −4 y= = = = . y2 cx1 + dx2 −2 · 2 + 1 · 4 0 x 4 3 2 1 0 −1 −5 y=Ax −4 −3 −2 −1 0 1 2 3 Figura 3: prodotto matrice-vettore. Possiamo scrivere in modo più “compatto” il passaggio da x ad y? Il trucco è nel raccogliere in modo opportuno tutti i dati che ci servono, ovvero le coordinate di x (e questo lo sappiamo già fare con la 9 notazione di vettore colonna) e i quattro scalari a, b, c e d. Un modo semplice è quello di utilizzare una sorta di tabella con due righe e due colonne: a b , c d che ricalca fedelmente la posizione degli scalari nella (2). Ma come faccio a sapere che posizione occupa lo scalare c nella mia tabella se ne conosco solamente il “nome”? Per superare questa lieve difficoltà cambiamo notazione e diamo un nome (ragionevole) alla tabella: a11 a12 A= . a21 a22 Allora aij indicherà l’elemento della tabella A che occupa l’i-esima riga e la j-esima colonna. Ad esempio a21 indicherà l’elemento di A in seconda riga e prima colonna. Da questo momento in poi possiamo usare a pieno diritto il termine matrice per indicare l’oggetto matematico A. Tornando alla nostra trasformazione x → y, scriveremo dunque in modo compatto: x1 a11 a12 a11 x1 + a12 x2 y1 = Ax, = = y= x2 a21 a22 a21 x1 + a22 x2 y2 definendo cosı̀ il prodotto matrice-vettore. Riassumendo: tutte le trasformazioni che, preso un vettore ne producono un altro attraverso combinazioni lineari delle coordinate del primo sono esprimibili in modo compatto con l’applicazione di una matrice al vettore stesso. Si parla allora di trasformazioni lineari nel piano e le matrici vengono anche dette applicazioni lineari. Ora, come facciamo a memorizzare le regole usate per esprimere il prodotto matrice-vettore appena introdotto? Denotiamo con a1,: il vettore riga costituito dagli elementi della prima riga di A (la ragione di tale notazione sarà chiara in Matlab 3): a1,: = a11 a12 . Finora abbiamo utilizzato però vettori colonna. Allora introduciamo quella che si chiama trasposizione (da cui il simbolo T come apice): a11 T a1,: = . a12 In seguito approfondiremo la vera natura di tale operazione. Adesso che abbiamo la prima riga di A come colonna, possiamo usare l’abituale prodotto scalare con il vettore x per accorgerci che, se y = Ax, allora y1 = a11 x1 + a12 x2 = a1,: T · x. Analagomente: y2 = a21 x1 + a22 x2 = a2,: T · x per a2,: = ovvero T a21 a22 a2,: = a21 a22 . Deduciamo che ogni coordinata risultante da un prodotto matrice-vettore Ax è data dal prodotto scalare della relativa “riga” con il vettore x stesso. 10 Esempio 5 L’esempio 4 può essere rivisto nel seguente modo compatto: 4 −3 2 4·2−3·4 −4 y = Ax = = = . −2 1 4 −2 · 2 + 1 · 4 0 Esercizio 2 Non dovrebbe sorprendere che per qualunque vettore risulta sempre (vT )T = v. Matlab 3 Per usare Matlab dobbiamo prima imparare ad inserire una matrice, la qualcosa è abbastanza semplice ed intuitiva. Infatti, la matrice a11 a12 A= a21 a22 viene creata con il comando: A=[a11,a12;a21,a22] ovvero: • inserendo gli elementi tra parentesi quadre • separando le righe con “;” • separando gli elementi all’interno di una stessa riga con “,” (o spazi “ ”). Allora il nostro prodotto matrice-vettore si esegue nel seguente modo: >> A=[4,-3;-2,1] A = 4 -3 -2 1 >> x=[2;4] x = 2 4 >> y=A*x y = -4 0 L’esito si è già visto in Figura 3. Osserviamo anche l’uso del simbolo “:” per indicare righe e colonne di A: 11 >> A(1,:) ans = 4 -3 >> A(2,:) ans = -2 1 >> A(:,1) ans = 4 -2 >> A(:,2) ans = -3 1 Verifichiamo quindi che le componenti di y sono i prodotti scalari delle corrispondenti righe di A per il vettore x. Innanzitutto dobbiamo “trasporre” le righe di A per farle diventare vettori colonna. Per questo usiamo l’apice “’”: >> b1=A(1,:)’ b1 = 4 -3 >> b2=A(2,:)’ b2 = -2 1 ed effettuiamo il prodotto scalare come abbiamo imparato: >> b1’*x ans = -4 >> b2’*x ans = 0 Ora, avrete notato che abbiamo usato l’apice di traposizione due volte, il che non cambia le cose (Esercizio 2): >> b1 b1 = 4 -3 >> b1’’ ans = 4 -3 12 Ma su questo apparente corto circuito torneremo in seguito. Esercizio 3 Date due matrici A e B, la loro somma è definita estendendo in maniera naturale la somma componente per componente vista per i vettori, quindi: a11 a12 b11 b12 a11 + b11 a12 + b12 A+B = + = . a21 a22 b21 b22 a21 + b21 a22 + b22 Dimostrate ora che per il prodotto matrice-vettore vale la proprietà distributiva sia rispetto alla matrice, ovvero: (A + B)x = Ax + Bx, sia rispetto al vettore, ovvero: A(x + y) = Ax + Ay. Bene, adesso che abbiamo imparato il prodotto matrice-vettore, non sarà assolutamente difficile imparare il prodotto righe-colonne di due matrici. Consideriamo infatti le matrici a11 a12 A= a21 a22 e B= b11 b12 b21 b22 . Che cosa significa il prodotto C = AB = a11 a12 a21 a22 b11 b12 ? b21 b22 Se non l’avete già intuito, basta considerare la matrice B come una “collezione” di colonne, che indicheremo come (ricordando la notazione “:”) B = [b:,1 , b:,2 ] dove indichiamo con b11 b21 b12 b22 b:,1 = e b:,2 = i vettori corrispondenti, rispettivamente, alla prima e alla seconda colonna della matrice B, usando una notazione analoga a quanto già visto per le righe. Allora il prodotto C = AB può essere visto come la matrice C = [c:,1 , c:,2 ] dove ciascuna colonna è il prodotto della matrice A per la relativa colonna di B: a11 b11 + a12 b21 c:,1 = Ab:,1 = a21 b11 + a22 b21 13 e a11 b12 + a12 b22 a21 b12 + a22 b22 c:,2 = Ab:,2 = . Quindi il prodotto viene distribuito ad ogni colonna: AB = A[b:,1 , b:,2 ] = [Ab:,1 , Ab:,2 ] = [c:,1 , c:,2 ] = C ovvero a11 a12 a21 a22 b11 b12 b21 b22 = (3) a11 b11 + a12 b21 a11 b12 + a12 b22 a21 b11 + a22 b21 a21 b12 + a22 b22 . Esempio 6 Per A= e 4 −3 −2 1 B= 1 0 5 2 si ottiene AB = 4 −3 −2 1 1 0 5 2 = 4·1−3·5 4·0−3·2 −2 · 1 + 1 · 5 −2 · 0 + 1 · 2 = −11 −6 3 2 . Matlab 4 In Matlab (ricordando che A esiste già!): >> B=[1,0;5,2] B = 1 0 5 2 >> A*B ans = -11 -6 3 2 Esercizio 4 Provate a costruire una matrice I che, moltiplicando qualunque vettore x, lo lascia invariato, ovvero: Ix = x. Esercizio 5 Date tre matrici qualunque A, B e C di 2 righe e 2 colonne, dimostrate ora che per il prodotto righe-colonne valgono sia la proprietà distributiva A(B + C) = AB + AC sia la proprietà associativa A(BC) = (AB)C. 14 Senza ulteriori spiegazioni, non dovrebbe essere difficile accertarsi della validità delle seguente generalizzazione derivante dalla (3): A[b:,1 , b:,2 , . . . , b:,n ] = [c:,1 , c:,2 , . . . , c:,n ]. Come si suol dire, “fatto 30 facciamo 31”. Visto che abbiamo appena usato una matrice che ha più colonne (ovvero n) che righe (ovvero 2), allora diciamo che se una matrice M ha r righe e c colonne ed i suoi elementi sono numeri reali, cioè m11 m12 · · · m1c m21 m22 · · · m2c M = .. .. .. , . . . mr1 mr2 · · · mrc con mij ∈ R per ogni i = 1, 2, . . . , r e per ogni j = 1, 2, . . . , c, indicheremo questo fatto con M ∈ Rr×c . Commento 1 (importante!) Il prodotto matriciale appena introdotto ha l’unico vincolo di richiedere che il numero di colonne della prima matrice corrisponda al numero di righe della seconda matrice. Ne convenite? Se la risposta è affermativa, allora cosa rispondereste alla domanda sulla proprietà commutativa: AB = BA? Provate con un esempio, poi proveremo con Matlab... Bene, se non avete accusato il colpo allora non avrete problemi a considerare un vettore colonna di n elementi v1 v2 v = .. . vn come una particolare matrice: v ∈ Rn×1 (= Rn ). Esistono poi, come visto, anche i vettori riga: w = [w1 , w2 , . . . , wm ]. In tal caso w ∈ R1×m (indicabile anch’esso come Rm ). Ad ogni modo, la convenzione considera i vettori sempre come colonna, se non diversamente specificato. Bene, visto che i vettori sono particolari matrici, nulla ci vieta di applicare loro il prodotto “vettore-vettore” inteso come caso particolare del prodotto matriciale righe-colonne appena appreso. Siccome la regola dice che il numero di colonne del primo fattore deve coincidere col numero di righe del secondo, se entrambi i fattori sono vettori con lo stesso numero di elementi (diciamo n) ci rimangono solo due possibilità. Una consiste nel moltiplicare il vettore riga per il vettore colonna, ottenendo cosı̀ un numero scalare: R1×n · Rn×1 = R1×1 (= R). Ma questo è proprio il prodotto scalare di vettori, ecco spiegato finalmente l’uso della trasposizione se sono entrambi colonna: il primo deve diventare riga! Per la seconda avete un po’ più di tempo per pensarci: la incontreremo in Sezione 3.3. 15 Matlab 5 Proviamo ad eseguire diversi prodotti matriciali in Matlab, verificandone le proprietà riguardanti la dimensione dei fattori. Iniziamo con A ∈ R3×2 e B ∈ R3×4 , il cui prodotto AB non è possibile dato che il numero di colonne di A (2, primo fattore) differisce dal numero di righe di B (3, secondo fattore): >> A=[1,2;3,4;5,6] A = 1 2 3 4 5 6 >> B=[12,11,10,9;8,7,6,5;4,3,2,1] B = 12 11 10 9 8 7 6 5 4 3 2 1 >> A*B ??? Error using ==> mtimes Inner matrix dimensions must agree. Modifichiamo allora con B ∈ R2×4 , ottenendo AB ∈ R3×4 : >> B=[8,7,6,5;4,3,2,1] B = 8 7 6 5 4 3 2 1 >> A*B ans = 16 13 10 7 40 33 26 19 64 53 42 31 Verifichiamo che il prodotto di matrici non è, in generale, commutativo, cioè AB 6= BA. Questo succede sempre se le dimensioni non sono compatibili con la regola del prodotto, ad esempio con le matrici A e B inserite, AB è lecito ma BA non lo è: >> B*A ??? Error using ==> mtimes Inner matrix dimensions must agree. Ad ogni modo, in generale, il prodotto non è commutativo nemmeno quando i fattori sono “quadrati”: >> A=[1,2;3,4] A = 1 2 3 4 >> B=[4,3;2,1] B = 4 3 16 2 >> A*B ans = 8 20 >> B*A ans = 13 5 1 5 13 20 8 Vediamo ora cosa succede con i prodotti di vettori: >> v=[1;2;3] v = 1 2 3 >> w=[3;2;1] w = 3 2 1 >> v*w ??? Error using ==> mtimes Inner matrix dimensions must agree. >> v’*w ans = 10 >> v*w’ ans = 3 2 1 6 4 2 9 6 3 2.3 Sistemi lineari In questa sezione osserveremo i sistemi di equazioni lineari (in breve sistemi lineari) da un’altra prospettiva. Cominciamo dalle cose veramente essenziali. Come rappresentante delle più semplici equazioni lineari possiamo considerare a pieno titolo la seguente: 3x = 21, la cui soluzione (ricordando i principi di equivalenza) è banalmente x= 21 = 7. 3 17 Questo vale ovviamente per tutte le equazioni del tipo ax = b (4) con soluzione b a avendo preventivamente assunto a 6= 0. Se invece fosse a = 0, allora non avremmo soluzione per b 6= 0 (dato che non esiste alcun numero che moltiplicato per 0 fornisca un numero diverso da 0) mentre ne avremmo infinite per b = 0 (dato che qualunque numero moltiplicato per 0 fornisce 0). Complichiamoci ora un po’ la vita, ma non troppo, e consideriamo il classico problema della spesa che viene proposto in mille versioni a partire dalle scuole elementari (osservando tra l’altro come l’apprendimento di certe proprietà matematiche notevoli non richieda per forza di cose la trattazione di problemi complessi e lontani dalla realtà quotidiana più spicciola). x= Problema 1 Anna compra dal fruttivendolo 2 kg di mele e 1 kg di pere, spendendo 7 euro. Marco compra dallo stesso fruttivendolo 4 kg di mele e 3 kg di pere, spendendo 17 euro. Quanto costano, rispettivamente, 1 kg di mele e 1 kg di pere? La risoluzione di questo semplice quesito consiste nel tradurlo nelle equazioni di primo grado (ovvero lineari) 2x1 + x2 = 7 4x1 + 3x2 = 17 avendo assunto la convenzione che x1 ed x2 rappresentino, rispettivamente, il numero incognito di kg di mele e pere. È facile verificare che la soluzione è x1 = 2 e x2 = 3. Oppure si può procedere mediante il metodo di eliminazione di Gauss (Carl Friedrich [1777-1855], matematico tedesco) e la sostituzione all’indietro, come visto alla conferenza iniziale. Guardiamo con attenzione i due membri sinistri: ci ricordano qualcosa? Ciascuno di essi rappresenta una combinazione lineare delle incognite x1 ed x2 , attraverso rispettivamente gli scalari 2 ed 1 per la prima equazione e 4 e 3 per la seconda. Avendo imparato come esprimere le combinazioni lineari con le matrici, allora potremmo scrivere il nostro sistema lineare in forma vettoriale: 2 1 x1 7 = , x2 17 4 3 infatti 2 1 4 3 x1 x2 = Se ora indichiamo con 2x1 + 1x2 4x1 + 3x2 A= 2 1 4 3 la cosiddetta matrice dei coefficienti, con x1 x2 7 17 x= il vettore delle incognite e, infine, con b= 18 = 7 17 . il vettore dei termini noti, allora il nostro sistema diventa Ax = b che ricalca fedelemente la scrittura dell’equazione (4). Ora, ricordando il caso (scalare) della singola equazione (4), saremmo tentati di risolvere per x andando a dividere entrambi i membri per la matrice A. Ma questa, ahimè, non è certamente una strada matematicamente percorribile. La versione matematicamente corretta passa effettivamente per b b ax = ⇔x= , a a a ma, non essendo permessa la divisione per A, corrisponde piuttosto a: ax = b ⇔ ax = b ⇔ a−1 (ax) = a−1 b ⇔ (a−1 a)x = a−1 b ⇔ x = a−1 b che, nel caso della (4), è basata sull’identità 1 a−1 = , a sempre sotto l’ipotesi a 6= 0. Quindi la soluzione del nostro sistema lineare è rappresentata da Ax = b ⇔ A−1 (Ax) = A−1 b ⇔ (A−1 A)x = A−1 b ⇔ x = A−1 b dove A−1 è la cosiddetta matrice inversa di A. Ovviamente abbiamo “scommesso” che (A−1 A)x = x. Ma vale questa proprietà? E chi è A−1 ? Per rispondere, dobbiamo capire bene chi è a−1 . Tutti sappiamo che tale numero soddisfa a a−1 a = 1 = aa−1 (sempre per a 6= 0, chiaramente). Allora, per analogia, definiamo A−1 come quella matrice che soddisfa a AA−1 = I = A−1 A (5) con I la matrice identità, vedi Esercizio 4. Infatti I è il corrispondente di 1 nel caso scalare. Che proprietà ha il numero 1 nella moltiplicazione? Esso lascia invariato qualunque numero moltiplichi: 1 · a = a = a · 1. Ma questo vale anche per I se per moltiplicazione intendiamo il prodotto righe-colonne, infatti: IA = A = AI. Tale proprietà può essere verificata nel caso bidimensionale, dove 1 0 I= , 0 1 ma vale ovviamente per qualunque dimensione con 1 0 0 1 I= . .. 0 ··· 19 ··· ... 0 0 .. . . 0 1 Esempio 7 Possiamo verificare formalmente la proprietà della matrice identità: 1 0 a11 a12 1 · a11 + 0 · a21 1 · a12 + 0 · a22 a11 a12 = = . 0 1 a21 a22 0 · a11 + 1 · a21 0 · a12 + 1 · a22 a21 a22 Analogamente: a11 a12 1 0 a11 · 1 + a12 · 0 a11 · 0 + a12 · 1 a11 a12 = = . a21 a22 0 1 a21 · 1 + a22 · 0 a21 · 0 + a22 · 1 a21 a22 Matlab 6 La matrice inversa si ottiene con il comando Matlab inv(A) che per il nostro esempio fornisce >>A=[2,1;4,3]; >> iA=inv(A) iA = 1.5000 -0.5000 -2.0000 1.0000 cioè A −1 = 3/2 −1/2 −2 1 (se volete, provate a verificare che quest’ultima soddisfa la definizione appena data). Commento 2 (il determinante) Si può sempre definire A−1 ? Fidandoci ancora dell’analogia con il caso scalare, sappiamo che si può parlare del numero a−1 se e sole se a 6= 0. Ma cosa vorrebe dire nel caso delle matrici? Bisogna ricorrere alla nozione di determinante. Si definisce determinante di una matrice a11 a12 A= a21 a22 la quantità det (A) = a11 a22 − a12 a21 . Allora si può parlare di A−1 se e sole se det (A) 6= 0: questo, in realtà, è un vero e proprio Teorema dell’algebra lineare. Una matrice A tale per cui det (A) = 0 si dice anche singolare. Matlab 7 In Matlab il determinante si ottiene facilmente con il comando det(A) Ad esempio: 20 >> A=[2,1;4,3]; >> det(A) ans = 2 infatti det (A) = 2 · 3 − 1 · 4 = 6 − 4 = 2. Succede ad esempio che >> A=[2,1;4,2]; >> det(A) ans = 0 >> iA=inv(A) Warning: Matrix is singular to working precision. iA = Inf Inf Inf Inf Matlab 8 In Matlab il comando per la risoluzione dei sistemi lineari ricorda proprio la divisione. Infatti, dopo aver inserito i nostri dati (basta il vettore dei termini noti ora): >>b=[7;17]; si ottiene agevolmente la soluzione con il comando “\” (“backslash”): >>x=A\b x= 2 3 Con A−1 a disposizione, risolvere un sistema di 2 equazioni o di 20 equazioni non fa molta differenza. Inoltre, è interessante osservare come tale notazione vettoriale permetta di gestire contemporaneamente più sistemi lineari che abbiano la stessa matrice dei coefficienti A ma diversi vettori dei termini noti, diciamo b1 , b2 , . . . , bn : Ax1 = b1 Ax2 = b2 .. . Axn = bn . Infatti, se consideriamo la matrice B = [b1 , b2 , . . . , bn ] ottenuta collezionando le colonne corrispondenti ai diversi termini noti e la matrice incognita X = [x1 , x2 , . . . , xn ] 21 ottenuta collezionando le colonne corrispondenti ai diversi vettori incogniti, allora possiamo riassumere il tutto nel “sistemone” AX = B. Matematicamente l’operazione corrisponde a X = A−1 B. Dal punto di vista computazionale però (cioè dal punto di vista di come risolviamo i problemi con l’utilizzo del calcolatore), l’operazione di inversione di una matrice, seppur rappresenti un concetto matematico raffinato ed ineccepibile, non è una buona pratica! Quindi, invece di invertire una matrice è preferibile risolvere il sistema lineare corrispondente (cioè con matrice dei coefficienti A e termini noti dati dalla matrice identità I, perchè?), meglio se con metodi efficienti come quello di eliminazione di Gauss. Infine, proviamo a cambiare leggermente il nostro problema iniziale ipotizzando che Marco acquisti 2 kg di pere, anzichè 1, spendendo cosı̀ 14 euro. Quindi: 2x1 + x2 = 7 4x1 + 2x2 = 14 la cui matrice A= 2 1 4 2 è singolare, infatti: det(A) = 2 · 2 − 1 · 4 = 4 − 4 = 0. Geometricamente, ciò significa che le righe (e, analogamente, le colonne) di A rappresentano vettori paralleli e questo si traduce nel fatto algebrico che il membro sinistro di ciascuna delle due equazioni considerate è in realtà lo stesso (fatto deducibile dividendo per 2 la seconda), ovvero l’informazione fornita da una qualunque delle due equazioni è già contenuta nell’altra e perciò risulta superflua ai fini della risoluzione del problema. Inoltre (ancor peggio), se i termini noti non sono nella medesima proporzione, allora non esiste alcuna soluzione, il che è in perfetta analogia con il caso scalare (o se preferite pensate ai sistemi lineari di dimensione 2 come intersezioni di rette nel piano). In generale quindi, se det (A) = 0 non ha senso scrivere x = A−1 b, sarebbe come dividere per 0! Matlab 9 Sistemi lineari con termini noti multipli sono risolvibili in Matlab con lo stesso comando “\”: X=A\B e quindi il risultato può essere ottenuto con l’istruzione X=inv(A)*B, che è equivalente dal punto di vista teorico, ma non da quello computazionale. Infatti dietro “\” in Matlab c’è in realtà il metodo di eliminazione di Gauss. Passando invece al problema modificato della spesa: >>A=[2,1;4,2]; >>x=A\b x Inf -Inf 22 Cos’è accaduto? Proviamo a rispondere utilizzando la matrice inversa, sempre in Matlab: >>iA=inv(A) Warning: Matrix is singular to working precision. ans= Inf Inf Inf Inf infatti >>det(A) ans= 0 2.4 Un po’ di trigonometria non nuoce Dimentichiamoci ora delle matrici e torniamo ai vettori e al prodotto scalare. Prima però apriamo una breve parentesi parlando di trigonometria. Consideriamo il triangolo rettangolo AOB rappresentato in Figura 4. Esso ha l’ipotenusa di lunghezza 1. Per facilitare le cose quest’ultima è vista come il raggio di un cerchio (detto cerchio trigonometrico). Chiamiamo θ l’angolo al centro, cioè quello formato dal raggio (l’ipotenusa) e l’orizzontale. Allora definiamo il coseno dell’angolo θ come cos (θ) = OA = OA OB e il seno dell’angolo θ come AB = AB. OB Dunque cos (θ) è il rapporto tra la lunghezza del cateto adiacente l’angolo θ e l’ipotenusa, mentre sin (θ) è il rapporto tra la lunghezza del cateto opposto all’angolo θ e l’ipotenusa. Non dovrebbe sorprendere che sin (θ) = cos (0◦ ) = 1, sin (0◦ ) = 0, mentre cos (90◦ ) = 0, sin (90◦ ) = 1. Esercizio 6 Sapreste dire che valori si ottengono per θ = 45◦ ? Pensate alla diagonale del quadrato e al Teorema di Pitagora ([∼575-495 a.C.], filosofo e matematico greco)! Torniamo finalmente al prodotto scalare di due vettori introdotto in Sezione 1 come: x · y = x 1 y 1 + x2 y 2 per i vettori del piano x= x1 x2 23 (6) Figura 4: seni e coseni. ed y= y1 y2 . Una definizione alternativa, più legata alla geometria, è x · y = |x||y| cos (θ) (7) dove θ è l’angolo compreso tra i due vettori, mentre |x| ed |y| rappresentano la loro lunghezza, ovvero q |x| = x21 + x22 e q |y| = y12 + y22 come ci insegna il Teorema di Pitagora, Figura 5. Ma siamo sicuri che (6) e (7) coincidono? La risposta è affermativa e la dimostrazione (riportata di seguito per gli amanti...) si basa sul cosiddetto Teorema del Coseno o Teorema di Carnot (da Lazare Carnot [1753-1823], anche se in realtà il risultato si deve a François Viète [1540-1603], entrambi matematici francesi - errate attribuzioni non sono poi cosı̀ rare in matematica!). Teorema 1 Per ogni coppia di vettori piani x ed y che formano tra loro un angolo θ vale x · y = x1 y1 + x2 y2 = |x||y| cos (θ). Dimostrazione. Consideriamo il triangolo ABC di lati AB = x e AC = y, Figura 6. Sia θ l’angolo tra essi compreso. Allora, per il Teorema del Coseno (il quadrato costruito su un lato è pari alla somma dei 24 5 | x|2=x21+x22 x 4 3 | x| 2 x2 1 0 x1 −1 −1 0 1 2 3 Figura 5: Teorema di Pitagora. quadrati costruiti sugli altri due lati meno il doppio del prodotto delle lunghezze di quest’ultimi volte il coseno dell’angolo tra essi compreso) vale: 2 2 2 BC = AB + AC − 2AB · AC · cos (θ) ovvero, ricordando la differenza di vettori per cui BC = |x − y|, |x − y|2 = |x|2 + |y|2 − 2|x||y| cos (θ), da cui segue: 1 |x|2 + |y|2 − |x − y|2 2 1 2 x1 + x22 + y12 + y22 − [(x1 − y1 )2 + (x2 − y2 )2 ] = 2 1 = (2x1 y1 + 2x2 y2 ) 2 = x1 y 1 + x2 y 2 |x||y| cos (θ) = come volevasi dimostrare. Esercizio 7 Il Teorema di Pitagora è un caso particolare del Teorema del Coseno, quale? Esercizio 8 Il Teorema di Pitagora vale in qualunque dimensione, ovvero la lunghezza di un vettore x di n componenti è q |x| = x21 + x22 + · · · + x2n . Provate a dimostrarlo per n = 3 pensando alla diagonale di un parallelepipedo e usando lo stesso Teorema ma solo nel caso n = 2. 25 5 C 4 3 |x−y| |x| 2 ! 1 B |y| 0 −1 −1 A 2 2 2 BC =AB +AC −2AB" BCcos! 0 1 2 3 4 5 Figura 6: Teorema del Coseno. Ora che siamo certi dell’equivalenza delle due formule, possiamo tranquillamente misurare (il coseno del) l’angolo tra due vettori come cos (θ) = x1 y1 + x2 y2 x·y = . |x||y| |x||y| Inoltre, come visto risulta cos (90◦ ) = 0, ne consegue quindi che il prodotto scalare di due vettori tra loro perpendicolari è nullo (confronta con (1) e con l’esempio 2 in Sezione 1). In generale, il prodotto scalare di due vettori ci fornisce una qualche misura del coseno dell’angolo tra essi compreso: più quest’ultimo è vicino (in valore assoluto) ad 1, più i vettori sono tra loro paralleli, più esso è vicino a 0, più i vettori sono tra loro perpendicolari. Esercizio 9 Provate a fare i conti con i vettori di Figura 7. Matlab 10 Utilizzando Matlab e con un occhio a Figura 7 confermiamo quanto appena visto: >> x=[1;4] x= 1 4 >> y=[2;6] y= 2 6 26 7 y 6 5 x 4 3 2 1 z 0 −1 −3 −2 −1 0 1 2 3 Figura 7: prodotto scalare e angolo tra vettori. >> x’*y/(norm(x)*norm(y)) ans= 0.9971 >> z=[-3;1] z= -3 1 >> x’*z/(norm(x)*norm(z)) ans= 0.0767 Allora abbiamo incontrato anche la divisione con “/”. Devo invece dirvi a cosa serve l’istruzione norm o vi è chiaro? 2.5 Ma quanto costa? Ora che sappiamo il significato del prodotto scalare di vettori e di quello matrice-vettore, cerchiamo di capire quante operazioni comportano. Consideriamo il prodotto scalare di due vettori x, y ∈ Rn : x · y = x1 y 1 + x2 y 2 + · · · + xn y n . Chiaramente per ottenere il risultato dobbiamo eseguire n moltiplicazioni ed n − 1 addizioni, fatto che indicheremo come C(x · y) = nM + (n − 1)A. 27 Consideriamo ora il prodotto matrice-vettore di una matrice A ∈ Rm×n e di un vettore x ∈ Rn . Abbiamo imparato che ogni componente del risultato y = Ax è in realtà il prodotto scalare tra il vettore riga corrispondente di A e il vettore x: yi = ai,: T · x, i = 1, . . . , m. Poichè ognuno di questi costa quanto visto sopra e ne dobbiamo calcolare m, segue C(Ax) = m[nM + (n − 1)A] = mnM + (mn − m)A. Riscrivendo come C(Ax) = mn(M + A) − mA, si nota che il termine che “pesa” maggiormente è il primo, mn, possiamo quindi trascurare il secondo, m, soprattutto quando m ed n sono ragguardevoli. Diremo perciò che il costo dell’intera operazione è all’incirca mn flop e scriveremo O(mn) flop (si dice “dell’ordine di mn flop”). Commento 3 Il termine flop è l’abbreviazione di “floating point operation”: 1 flop è l’operazione base che può fare il calcolatore, diciamo che corrisponde ad una moltiplicazione ed un’addizione. Supponiamo ora (anche se capiremo il perchè di tutto ciò solo più avanti...) che la matrice A contenga molti elementi nulli, diciamo più precisamente che la riga i-esima di A contiene solo nnzi elementi diversi da 0 (nnz sta infatti generalmente per “Number of Non-Zero elements”), per i = 1, . . . , m. Se cosı̀ è, allora non è difficile intuire che il costo per il calcolo della componente i-esima yi risulta C(yi ) = nnzi M + (nnzi − 1)A = O(nnzi ), basta infatti non contare le moltiplicazioni per (e le addizioni con) 0! Allora il costo del prodotto finale y = Ax si ottiene sommando i costi di ciascuna componente, quindi: ! m m X X C(Ax) = O(nnzi ) = O nnzi = O(nnz) i=1 i=1 dove nnz = m X nnzi i=1 è il numero totale di elementi non nulli contenuti nella matrice A. Quello che servirà ricordare di tutto questo è che, in generale, un prodotto matrice-vettore di dimensione n (quindi A ∈ Rn×n ed x ∈ Rn ) costa O(n2 ), ma se la matrice A ha solo nnz elementi diversi da 0, allora il costo scende a O(nnz). Ovviamente vale sempre nnz ≤ n2 , ma a noi interesserà in particolar modo il caso nnz n2 (leggi “molto minore”), ovvero in cui la matrice A contiene per la maggior parte elementi nulli: si parla di matrici sparse, e rivestono un ruolo particolare nelle computazioni data la loro peculiarità. 28 3 Google Internet e il WWW rappresentano fonti di problemi matematici tanto interessanti quanto difficili, almeno a livello computazionale. Tra questi potremmo annoverare: • la gestione dei flussi di informazioni; • la ricerca delle informazioni; • l’ordinamento delle informazioni. Abbiamo accennato alle prime due tipologie durante la conferenza. In riferimento alla seconda, in particolare, è bene sottolineare che il problema nel contesto del World Wide Web (di seguito WWW) differisce abbastanza da quello relativo, ad esempio, ad una biblioteca. I motivi sono diversi: • la dimensione del WWW (numero di pagine web) è di gran lunga maggiore di quella di normali cataloghi di documenti: miliardi contro milioni (o migliaia); • il WWW si evolve molto più rapidamente di quanto lo possa fare, ad esempio, il patrimonio di una biblioteca; • la struttura a collegamenti ipertestuali (i link) è una caratteristica peculiare del WWW che non si trova da altre parti. Viste tali caratteristiche, l’ordinamento delle informazioni presenti nel WWW viene a rivestire un ruolo particolarmente cruciale. Non sorprende dunque che quest’ultimo rappresenti un argomento di ricerca attuale e tra i più gettonati. Tra l’altro è una tematica molto recente, si pensi che i primi lavori scientifici apparsi in letteratura risalgono appena alla fine degli anni 90. D’altronde la prima volta che si sono connessi due computer tra loro risale al 1969, il protocollo TCP/IP (Transmission Control Protocol / Internet Protocol) è stato introdotto negli anni 70, l’ipertesto HTTP (Hyper Text Transfer Protocol) negli anni 80 e il WWW ha fatto il suo ingresso ufficiale nella storia il 6 agosto 1991 (esattamente 46 anni dopo Hiroshima). La tecnologia messa in piedi da Google non è certamente l’unica a soddisfare l’esigenza di miliardi di utenti di trovare le informazioni desiderate in rete. Abbiamo deciso di occuparci limitatamente di questa (e in maniera semplificata) dato il suo notevole successo attuale. Altri metodi (vecchi e nuovi) condividono comunque con Google alcuni aspetti fondamentali: • sfruttano la caratteristica struttura a link del WWW (teoria dei grafi); • descrivono il problema con matrici e vettori (algebra lineare); • lo interpretano in senso probabilistico (teoria della probabilità); • lo risolvono con metodi efficienti (analisi numerica). Nel loro famoso lavoro (una copia è disponibile in rete, [3]), Larry Page and Sergey Brin (fondatori di Google) spiegano i concetti fondamentali con cui hanno gettato le regole per ordinare il contenuto del WWW. Al tempo erano due studenti, entrambi venticinquenni, della Stanford University. Presentiamo brevemente di seguito gli aspetti principali della loro teoria, riprendendo il percorso seguito durante la conferenza. 29 Innanzitutto l’obiettivo da raggiungere è quello di classificare (to rank in inglese) le pagine (pages in inglese) del WWW secondo la loro importanza relativa (e non assoluta: ci interessa sapere se una pagina è più importante di un’altra, ma non quanto è importante in assoluto). Da qui il nome dell’algoritmo noto come PageRank (http://www.google.it/intl/it/why_use.html). Ma che cos’è l’importanza (di seguito anche pagerank) di una pagina web? Potremmo ipotizzare che tale caratteristica • dipenda dal contenuto della pagina; • sia legata al numero di link che puntano alla pagina (entranti o inlink); • sia legata al numero di link che partono dalla pagina (uscenti o outlink); • etc.. Come si vede, vi sono diverse possibilità. I criteri proposti da Page e Brin sono i seguenti: (G1) il pagerank di una pagina è indipendente dal suo contenuto; (G2) il pagerank di una pagina è trasferito in parti uguali alle pagine collegate in uscita da questa (mediante gli outlink); (G3) il pagerank di una pagina è la somma delle frazioni di pagerank delle pagine collegate a questa in entrata (mediante gli inlink). I collegamenti di cui sopra si riferiscono, ovviamente, ai link ipertestuali tra le varie pagine. Il seguente esempio sarà di aiuto. Esempio 8 Consideriamo una piccolossima porzione del WWW, schematizzata come in Figura 8. Come si vede, la pagina 1 ha un pagerank 100 e, avendo 2 outlink, ne trasferirà 50 alla pagina 3 e 50 alla pagina 4 (criterio (G2)). La pagina 3 ha due inlink, riceve cosı̀ un pagerank di 50 (metà) dalla pagina 1 e un pagerank di 10 (un terzo) dalla pagina 2, totalizzando quindi un pagerank di 60 (criterio (G3)). Infine, osserviamo come tali calcoli siano stati fatti senza conoscere il contenuto delle pagine (criterio (G1)). Partendo da queste tre semplici regole svilupperemo il modello matematico su cui si basa il motore di ricerca Google. Inizieremo con un modello piuttosto primitivo e per questo richiedente alcune ipotesi semplificative rispetto alla situazione reale (Sezione 3.1). Impareremo poi a risolvere in maniera efficiente il problema matematico associato (Sezione 3.2). Infine rimuoveremo le ipotesi inziali per avvicinarci il più possibile alla realtà (Sezione 3.3). Nel frattempo, lungo il percorso, forniremo un’interpretazione alternativa a quella algebrica. 3.1 Matrici di connettività e navigatori casuali Come prima cosa, numeriamo le pagine web da 1 ad n e indichiamo con xi il pagerank della pagina i, i = 1, 2, . . . , n. Naturalmente n è molto grande, si stima essere attualmente intorno ai 18 miliardi (http:// www.worldwidewebsize.com/). Per il momento, visto che dobbiamo introdurre i concetti generali, ci avvaleremo di esempi con n molto basso, dell’ordine dell’unità (un WWW piccolissimo!). Supponiamo inoltre che ogni pagina abbia almeno un link entrante ed uno uscente, ipotesi che, come vedremo in seguito, ha un ruolo fondamentale. 30 Figura 8: pagine web e pagerank. Costruiamo la cosiddetta matrice di connettività C ∈ Rn×n come segue: l’elemento cij di C, quello che occupa la riga i-esima e la colonna j-esima, vale 1 se c’è un link dalla pagina j alla pagina i cij = 0 altrimenti. Esempio 9 Conisderiamo il WWW di n = 4 pagine rappresentato con i suoi link tramite il grafo (semplicemente un insieme di nodi e archi orientati) di Figura 9. In base alla regola precedente, la matrice di connettività associata risulta: 0 1 0 0 0 0 1 1 C= 1 1 0 0 . 0 1 1 0 Per costruirla possiamo seguire due strade: • per righe: ciascuna riga è relativa ad una pagina e dobbiamo guardare gli inlink di quest’ultima (entranti in); • per colonne: ciascuna colonna è relativa ad una pagina e dobbiamo guardare gli outlink di quest’ultima (uscenti da). Cosı̀, ad esempio, se osserviamo la pagina 3, questa riceve i link in ingresso dalle pagine 1 e 2, per cui la riga 3 della matrice C sarà c3,: = [1, 1, 0, 0]. Invece, se osserviamo i link in uscita da questa, andando essi alle pagine 2 e 4 daranno luogo alla colonna 3 di C, ovvero c:,3 = [0, 1, 0, 1]T . 31 Figura 9: il grafo di un WWW con n = 4 pagine. Adesso che abbiamo costruito la matrice di connettività C, effettuiamo quella che si chiama normalizzazione. Prendiamo dunque ciascuna colonna c:,j di C e la dividiamo per il numero di outlink outj della pagina relativa (possiamo farlo perchè abbiamo supposto che ve ne sia almeno uno, quindi outj 6= 0). Formiamo cosı̀ la nuova matrice H di colonne: h:,j = c:,j , j = 1, 2, . . . , n. outj Questa operazione realizza il corrispondente matematico del criterio (G2). Da notare che risulta essere 0 ≤ hij ≤ 1, i, j = 1, 2, . . . , n, e n X hij = 1, j = 1, 2, . . . , n. i=1 Inoltre (visto che ci siamo...), il numero di outlink della pagina j non è altro che la somma degli elementi di c:,j , quindi: n X cij = outj , j = 1, 2, . . . , n, i=1 mentre il numero di inlink della pagina i non è altro che la somma degli elementi di ci,: , quindi: n X cij = ini , i = 1, 2, . . . , n. j=1 32 Esempio 10 Tornando all’esempio di Figura 9, osserviamo che 4 P out = ci1 = 1 1 i=1 4 P ci2 = 3 out2 = i=1 4 P out3 = ci3 = 2 i=1 4 P out4 = ci4 = 1. i=1 Quindi la matrice H risulta 0 13 0 0 0 0 1 1 2 H= 1 1 0 0 . 3 0 13 12 0 Come stabilito dal criterio (G2) la pagina 3, ad esempio, trasferirà due metà del suo pagerank, in particolare alle pagine 2 e 4. Analogamente, la pagina 2 trasferirà tre terzi del suo pagerank, rispettivemente alle pagine 1, 3 e 4. Infine le pagine 1 e 4 trasferiranno tutto il loro pagerank, rispettivamente alle pagine 3 e 2. Per completezza contiamo anche gli inlink: 4 P in = c1j = 1 1 j=1 4 P in = c2j = 2 2 j=1 4 P in = c3j = 2 3 j=1 4 P c4j = 2. in4 = j=1 Come osservato, avendo assunto che ogni pagina ha almeno un outlink, la somma degli elementi di ciascuna colonna di H vale sempre 1. Si parla in questo caso di matrice stocastica (a colonne). Per spiegare questa terminologia ricorriamo ad un modello interpretativo di tipo probabilistico. Immaginiamo dunque di osservare un navigatore che sta visitando il WWW di Figura 9 e che sia obbligato a cambiare pagina ad ogni istante utilizzando a caso gli outlink a disposizione. Supponiamo ad esempio che ad un certo istante di tempo tale navigatore stia visitando la pagina 3 (che ha 2 outlink). Allora all’istante successivo dovrà per forza di cose trovarsi a visitare la pagina 2 o la pagina 4. Siccome si muove a caso, la probabilità di scegliere una o l’altra pagina è suddivisa in modo uguale, quindi 1/2 e 1/2 (o 50% e 50% se preferite). Per lo stesso principio, se scegliesse la pagina 4 (che ha 1 outlink), all’istante successivo si troverebbe obbligatoriamente sulla pagina 2, giungendovi con probabilità 1 (o 100%). Se invece avesse scelto la pagina 2 (che ha 3 outlink), allora all’istante successivo si ritroverebbe a visitare rispettivamente le pagine 1, 3 o 4 con uguale probabilità, ovvero 1/3, 1/3 e 1/3 (o tutte 33.333 . . . %). La metafora probabilistica di cui sopra va sotto il nome di navigatore virtuale. Sotto questo punto di vista, la matrice H è una matrice di transizione di probabilità: il suo generico elemento hij rappresenta la probabilità che ad un certo istante il navigatore virtuale passi dalla pagina j alla pagina i, seguendo 33 ovviamente l’outlink j → i. Per usare una terminologia più tecnica (e di richiamo), il navigatore virtuale è un modello di random walk lungo il grafo associato al WWW esaminato e rappresenta una catena di Markov. Veniamo adesso al criterio (G3). Esso esprime una legge di tipo ricorsivo: il pagerank di una pagina è definito sulla base del pagerank di altre pagine (quelle che hanno outlink verso di essa in particolare). Seguendo tale ricetta, possiamo ricostruire il pagerank di ciascuna pagina. Ogni pagina, come detto, riceve solo una frazione del pagerank di ogni altra pagina che abbia un outlink diretto alla prima. Tale frazione corrisponde al relativo elemento della matrice H, ed esprime appunto la probabilità di percorrere effettivamente quel link (e quindi di trasferire tramite esso parte del pagerank della pagina di partenza). Ad esempio, per la prima: x1 = h11 x1 + h12 x2 + h13 x3 + · · · + h1n xn , per la seconda: x2 = h21 x1 + h22 x2 + h23 x3 + · · · + h2n xn , per la terza: x3 = h31 x1 + h32 x2 + h33 x3 + · · · + h3n xn e via dicendo fino all’ultima: xn = hn1 x1 + hn2 x2 + hn3 x3 + · · · + hnn xn . Raccogliamo tutte queste informazioni come segue: x1 = h11 x1 + h12 x2 + h13 x3 + · · · + h1n xn x 2 = h21 x1 + h22 x2 + h23 x3 + · · · + h2n xn x3 = h31 x1 + h32 x2 + h33 x3 + · · · + h3n xn .. . x = h x + h x + h x + ··· + h x , n n1 1 n2 2 n3 3 nn n e, vista l’esperienza acquisita con l’algebra lineare, riscriviamo il tutto come x = Hx dove x= x1 x2 x3 .. . xn è il cosiddetto vettore pagerank. Attenzione: x è proprio l’incognita del nostro problema! Esempio 11 Sempre con riferimento al WWW di Figura 9, otteniamo le equazioni 1 x1 = 0 · x1 + · x2 + 0 · x3 + 0 · x4 3 x2 = 0 · x1 + 0 · x2 + 1 · x3 + 1 · x4 2 1 x3 = 1 · x1 + · x2 + 0 · x3 + 0 · x4 3 x4 = 0 · x1 + 1 · x2 + 1 · x3 + 0 · x4 , 3 2 34 ovvero, togliendo gli zeri superflui, 1 x1 = x2 3 x2 = 1 x3 + x4 2 1 x3 = x1 + x2 3 x4 = 1 x2 + 1 x3 . 3 2 Nella notazione vettoriale scriviamo invece x1 0 31 0 0 x2 0 0 1 1 2 x3 = 1 1 0 0 3 0 13 12 0 x4 x1 x2 . x3 x4 E a che cosa corrisponde tale problema? L’espressione x = Hx non rappresenta un vero e proprio sistema lineare: il vettore incognito compare anche al posto di quello noto. D’altro canto, non è nemmeno un prodotto matrice-vettore. Se però ci ricordiamo della matrice identica I di dimensione n, allora essendo x = Ix, sostituendo al primo membro otteniamo Ix = Hx, ovvero (ricordate Esercizio 3) (I − H)x = 0. Quest’ultimo è un vero e proprio sistema lineare, con matrice dei coefficienti I − A, vettore incognito x e vettore noto 0 (un caso veramente particolare). Esempio 12 Sempre con riferimento al WWW di Figura 9, le equazioni 1 x1 = x2 3 1 x2 = x3 + x4 2 1 x2 x = x + 3 1 3 x4 = 1 x2 + 1 x3 3 2 vengono riscritte nella forma (I − H)x = 0 semplicemente portando tutti i termini a sinistra dell’uguale: 1 x1 − x 2 = 0 3 x2 − 1 x 3 − x4 = 0 2 1 −x − x2 + x3 = 0 1 3 − 1 x2 − 1 x3 + x4 = 0. 3 2 35 Nella notazione vettoriale scriviamo invece 1 − 31 0 0 x1 1 0 x2 −1 1 − 2 −1 − 1 1 x3 0 3 1 1 x4 0 −3 −2 1 0 0 = . 0 0 Bene, visto che siamo riusciti a tradurre il tutto in un sistema lineare, sappiamo anche come risolverlo. Purtroppo però abbiamo visto al seminario che il metodo di eliminazione gaussiana (seguito dalla sostituzione) comporta un costo di O(2/3n3 ) flop. Essendo n dell’ordine dei miliardi, ci ritroveremmo a dover fare miliardi di miliardi di miliard di flop, troppi anche per i calcolatori più potenti (milioni di anni con il “Tianhe-1A”! http://www.nccs.gov/jaguar/, http://www.top500.org/). Come superiamo questo ostacolo? La risposta nella prossima sezione. 3.2 La fortuna di Google: il metodo delle potenze e tanti zeri Visto il costo non affrontabile del metodo di Gauss, abbandoniamo questa strada in favore di un’idea che si applica spesso in matematica: l’iterazione. In questo contesto, potremmo riassumere la strategia dicendo che rinunciamo alla soluzione esatta x ma, partendo da un’opportuna approssimazione iniziale x(0) , costruiamo una successione di soluzioni x(1) , x(2) , x(3) , . . . via via sempre più vicine a quella esatta (questa almeno è la nostra speranza). Quando siamo sufficientemente “vicini”, ci fermiamo. Il vantaggio consiste nel costruire queste soluzioni approssimate in modo più semplice e ad un costo computazionale molto più basso. Tornando al problema x = Hx, potremmo procedere iniziando da un certo x(0) e calcolare x(1) come x(1) = Hx(0) , poi x(2) come x(2) = Hx(1) , x(3) come x(3) = Hx(2) e via dicendo. Ad ogni passo calcoliamo dunque la soluzione “nuova” facendo il prodotto della matrice H con la soluzione “vecchia”. In generale, dopo k di questi passi ci ritroviamo con x(k) = Hx(k−1) , k = 1, 2, . . . . Ma quando ci si ferma? Potrebbe (il condizionale è d’obbligo per ora) essere ragionevole fermarsi quando due soluzioni successive, quindi x(k) ed x(k−1) , differiscono di poco, cioè quando la lunghezza del vettore differenza (o errore) e(k) = x(k) − x(k−1) è prossima allo zero, o perlomeno molto piccola. Abbiamo già visto nell’Esercizio 8 come calcolare la lunghezza di un vettore, ovvero il Teorema di Pitagora generalizzato. Nel nostro caso la lunghezza di e(k) , che indicheremo con ke(k) k, risulta (in Matlab basta usare norm) r ke(k) k = (k) (k−1) x1 − x1 2 (k) (k−1) + x2 − x2 36 2 (k) (k−1) + · · · + xn − xn 2 . Ci fermeremo quindi dopo k passi, con k tale per cui ke(k) k < TOL dove TOL sarà una tolleranza da noi fissata. L’algoritmo appena presentato è noto come metodo delle potenze (perchè secondo voi?). Matlab 11 Applichiamo il metodo delle potenze sempre con riferimento al WWW di Figura 9. Questa volta ci affidiamo a Matlab. Inseriamo H: >> H=[0,1/3,0,0;0,0,1/2,1;1,1/3,0,0;0,1/3,1/2,0] H = 0 0.3333 0 0 0 0 0.5000 1.0000 1.0000 0.3333 0 0 0 0.3333 0.5000 0 Inseriamo quindi un vettore soluzione iniziale x(0) . Supponiamo ad esempio che, inizialmente, ogni pagina abbia lo stesso pagerank, quindi 1/n = 1/4 (capiremo poi perché). >> x=[1/4;1/4;1/4;1/4] x = 0.2500 0.2500 0.2500 0.2500 Nella nostra implementazione Matlab chiameremo il vettore soluzione sempre x. Terremo conto del numero di iterazioni mediante un indice k. Siccome siamo all’inizio, diciamo che siamo al passo k = 0: >> k=0; Finalmente possiamo procedere con il metodo, che scriviamo tutto in una riga (!). Quest’ultima la ripeteremo finchè non saremo soddisfatti dell’errore (abbiamo già incontrato l’istruzione norm). >> k=k+1,e=norm(H*x-x),x=H*x k = 1 e = 0.2282 x = 0.0833 0.3750 0.3333 0.2083 >> k=k+1,e=norm(H*x-x),x=H*x k = 2 e = 37 0.1559 x = 0.1250 0.3750 0.2083 0.2917 >> k=k+1,e=norm(H*x-x),x=H*x k = 3 e = 0.0780 x = 0.1250 0.3958 0.2500 0.2292 Già dopo 3 passi abbiamo ridotto l’errore. La Tabella 1 riporta i dati sui calcoli successivi. La soluzione esatta è 0.125 0.375 x= 0.250 . 0.250 Osserviamo come si ottengono errori molto piccoli già con poche decine di passi. Inoltre, osservando il vettore pagerank soluzione x, concludiamo che, supponendo 1 l’importanza di tutto il WWW, allora 1/8 è nella pagina 1, 3/8 nella 2 e 1/4 in ciascuna delle pagine 3 e 4. Commento 4 La Tabella 1 non deve trarre in inganno: per motivi di spazio i valori di pagerank (ultime quattro colonne) sono riportati con 4 cifre significative (vedi Appendice A) , per cui essi possono sembrare esatti per k ≥ 16. In realtà quelli che si vedono sono valori arrotondati a 4 cifre. Matlab li calcola effettivamente con 15 cifre significative, fatto che corrisponde alla massima precisione del sistema di rappresentazione dei numeri di macchina. Ecco perché è inutile proseguire le iterazioni dopo che l’errore scende sotto 10−15 : tutto quello che segue la 15a cifra non avrebbe comunque senso! E dopo k passi, quanto sarà costata la nostra soluzione finale x(k) (che è comunque un’approssimazione)? Per saperlo basta capire quanto costa eseguire ogni singolo passo dell’algoritmo. Osserviamo che ogni passo comporta sempre la stessa operazione, cioè il prodotto della matrice di connettività normalizzata H volte il vettore soluzione del passo precedente: x(k) = Hx(k−1) , k = 1, 2, . . . . Quindi un singolo passo costa in genere O(n2 ) flop, come spiegato in Sezione 2.5. In totale O(kn2 ) flop se facciamo k passi. Se pensiamo che in generale bastano poche decine di passi (tipicamente k n), è già un bel risparmio. Ma non è sufficiente: siamo ancora a miliardi di miliardi di operazioni. Abbiamo visto che ogni passo del metodo delle potenze consiste in un prodotto matrice-vettore, in particolare Hx. Abbiamo imparato che le n componenti del vettore risultante si calcolano ciascuna come 38 k 1 6 11 16 21 26 31 36 41 46 51 56 61 66 71 76 e(k) 2.2822 × 10−1 1.9018 × 10−2 1.7455 × 10−3 1.6475 × 10−4 1.5752 × 10−5 1.5148 × 10−6 1.4602 × 10−7 1.4090 × 10−8 1.3601 × 10−9 1.3131 × 10−10 1.2677 × 10−11 1.2239 × 10−12 1.1816 × 10−13 1.1429 × 10−14 1.1012 × 10−15 9.3095 × 10−17 (k) x1 0.0833 0.1285 0.1247 0.1250 0.1250 0.1250 0.1250 0.1250 0.1250 0.1250 0.1250 0.1250 0.1250 0.1250 0.1250 0.1250 (k) x2 0.3750 0.3715 0.3754 0.3750 0.3750 0.3750 0.3750 0.3750 0.3750 0.3750 0.3750 0.3750 0.3750 0.3750 0.3750 0.3750 (k) x3 0.3333 0.2465 0.2502 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 (k) x4 0.2083 0.2535 0.2497 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 0.2500 Tabella 1: dati sul metodo delle potenze per il WWW di Figura 9. prodotto scalare della relativa riga della matrice per il vettore colonna. Ad esempio per la componente i-esima: (k−1) (k−1) (k) + · · · + hin x(k−1) = hi,: · x(k−1) . + hi2 x2 xi = hi1 x1 n Ma siamo sicuri che tutti gli elementi di H sono diversi da 0? È proprio qui il nocciolo della questione: hij 6= 0 se e solo se esiste il link j → i. Ma, in generale, i link esistenti tra le pagine web sono molto meno di tutti quelli possibili. Questo si traduce nel fatto che molti elementi di H sono 0 e che quindi H ha pochi elementi diversi da 0, numero che abbiamo chiamato nnz in Sezione 2.5. Qui vale esattamente lo stesso discorso fatto alla fine di quest’ultima: il costo ad ogni passo del prodotto matrice-vettore è O(nnz) e non più O(n2 ). Questa ragione è alla base della ragguardevole riduzione del costo computazionale, dato che per il WWW, il numero di link esistenti nnz è di gran lunga inferiore al quadrato del numero delle pagine web. In un’altra salsa, ogni pagina ha ben pochi link rispetto al totale delle pagine. Esempio 13 Per il WWW di Figura 9, la matrice H risulta avere n2 = 16 elementi, di cui solo nnz = 7 diversi da 0 (meno della metà). 7 è ovviamente il numero totale di link esistenti, come si può verificare osservando il grafo associato. Esempio 14 Come esempio reale, riportiamo in Figura 10 una rappresentazione della matrice H per il WWW sottostante la pagina http://www.harvard.edu, punto di accesso della Harvard University. In tale rappresentazione, ogni punto colorato è un elemento diverso da 0 della matrice, ovvero un link. Come si evince a colpo d’occhio, i link esistenti sono davvero pochi. Infatti si contano n = 500 pagine, con un totale di nnz = 2636 link (notare che n2 = 250000, circa 1000 volte tanto!). Ma quanto vale nnz per il WWW reale? Per abbozzare una stima (ma come ordine di grandezza non andremo molto distanti), ci basiamo sul fatto che, mediamente, una pagina ha pochi link entranti. 39 0 50 100 150 200 250 300 350 400 450 500 0 100 200 300 400 500 Figura 10: la matrice di connettività H del web di Harvard. Supponiamo un centinaio. Allora se assumiamo che n = 18 miliardi, seguirà nnz = 1800 miliardi. Quindi un passo del metodo delle potenze costa circa 1800 miliardi di flop. Mediamente potremmo aspettarci che k = 100 passi siano più che sufficienti a raggiungere un’accuratezza soddisfacente per la soluzione. Quindi in totale dobbiamo eseguire 180 mila miliardi di flop. A questo punto decidiamo di eseguire il calcolo con un computer capace di 2 Gflops (niente di speciale oggigiorno; 1 flops = 1 flop al secondo). Ovviamente supponiamo che la memoria sia sufficiente a contenere la matrice H (e questo invece è alquanto difficile, ma è un altro discorso...). Allora per fare 180 mila miliardi di flop ad una velocità di calcolo di 2 Gflops servono 90 mila secondi, ovvero 25 ore: una giornata abbondante. Contando che con Gauss e il “Tianhe-1A” ci volevano milioni di anni, possiamo essere più che soddisfatti! 3.3 Pagine penzolanti e ricerche personalizzate Vista la riduzione di costo ottenuta al termine della precedente sezione, sembrerebbe che abbiamo affrontato il problema nel modo giusto. Ma non dimentichiamo niente? Vediamo il prossimo esempio. Matlab 12 Conisderiamo un altro WWW di n = 4 pagine viste, la matrice di connettività normalizzata risulta: 0 21 0 0 0 0 1 0 H= 1 0 0 1 0 21 0 0 Se ora applichiamo il metodo delle potenze otteniamo: 40 rappresentato in Figura 11. Con le regole . >> H=[0 1/2 0 0;0 0 1 0;1 0 0 1;0 1/2 0 0] H = 0 0.5000 0 0 0 0 1.0000 0 1.0000 0 0 1.0000 0 0.5000 0 0 >> x=[1/4;1/4;1/4;1/4] x = 0.2500 0.2500 0.2500 0.2500 >> k=0; >> k=k+1,e=norm(H*x-x),x=H*x k = 1 e = 0.3062 x = 0.1250 0.2500 0.5000 0.1250 >> k=k+1,e=norm(H*x-x),x=H*x k = 2 e = 0.3536 x = 0.1250 0.5000 0.2500 0.1250 >> k=k+1,e=norm(H*x-x),x=H*x k = 3 e = 0.3062 x = 0.2500 0.2500 0.2500 0.2500 >> k=k+1,e=norm(H*x-x),x=H*x k = 41 4 e = 0.3062 x = 0.1250 0.2500 0.5000 0.1250 >> k=k+1,e=norm(H*x-x),x=H*x k = 5 e = 0.3536 x = 0.1250 0.5000 0.2500 0.1250 >> k=k+1,e=norm(H*x-x),x=H*x k = 6 e = 0.3062 x = 0.2500 0.2500 0.2500 0.2500 >> k=k+1,e=norm(H*x-x),x=H*x k = 7 e = 0.3062 x = 0.1250 0.2500 0.5000 0.1250 >> k=k+1,e=norm(H*x-x),x=H*x k = 8 e = 0.3536 x = 0.1250 42 0.5000 0.2500 0.1250 >> k=k+1,e=norm(H*x-x),x=H*x k = 9 e = 0.3062 x = 0.2500 0.2500 0.2500 0.2500 >> k=k+1,e=norm(H*x-x),x=H*x k = 10 e = 0.3062 x = 0.1250 0.2500 0.5000 0.1250 >> k=k+1,e=norm(H*x-x),x=H*x k = 11 e = 0.3536 x = 0.1250 0.5000 0.2500 0.1250 Si osserva dunque che dopo ogni 3 passi ci si ritrova al punto di partenza. Lo si vede meglio in Tabella 2. Il WWW dell’esempio precedente è rappresentato da una matrice H per la quale il metodo delle potenze entra in un ciclo (di periodo 3). Eppure soddisfa a tutte le ipotesi che abbiamo assunto. Non è dunque vero che tali ipotesi sono sufficienti a garantire quella che si chiama convergenza del metodo, ovvero il fatto che aumentando il numero di iterazioni ci si avvicina sempre più alla soluzione esatta, un concetto di limite: lim x(k) = x. k→∞ C’è poi un ulteriore problema: l’ipotesi che abbiamo fatto in partenza, cioè che ogni pagina abbia almeno un link in ingresso e uno in uscita (ini 6= 0 e outj 6= 0) non è affatto veritiera. Esistono infatti nel WWW reale molte pagine che non hanno link entranti (ini = 0) e molte pagine che non hanno link uscenti (outj = 0). Anzi, sono la maggior parte. Questo si traduce in una matrice di connettività C con 43 Figura 11: il grafo di un altro WWW con n = 4 pagine. k 1 2 3 4 5 6 7 8 9 10 11 12 13 14 e(k) 0.3062 0.3536 0.3062 0.3062 0.3536 0.3062 0.3062 0.3536 0.3062 0.3062 0.3536 0.3062 0.3062 0.3536 (k) x1 0.1250 0.1250 0.2500 0.1250 0.1250 0.2500 0.1250 0.1250 0.2500 0.1250 0.1250 0.2500 0.1250 0.1250 (k) x2 0.2500 0.5000 0.2500 0.2500 0.5000 0.2500 0.2500 0.5000 0.2500 0.2500 0.5000 0.2500 0.2500 0.5000 (k) x3 0.5000 0.2500 0.2500 0.5000 0.2500 0.2500 0.5000 0.2500 0.2500 0.5000 0.2500 0.2500 0.5000 0.2500 (k) x4 0.1250 0.1250 0.2500 0.1250 0.1250 0.2500 0.1250 0.1250 0.2500 0.1250 0.1250 0.2500 0.1250 0.1250 Tabella 2: dati sul metodo delle potenze per il WWW di Figura 11. 44 intere righe o intere colonne vuote (cioè di soli zeri). In particolare, le pagine che non hanno link uscenti si chiamano anche penzolanti (in analogia con la rappresentazione del relativo grafo). Se pensiamo al modello del navigatore virtuale, questo non funziona più: navigando solo tramite link, se si visita una pagina penzolante vi si rimane incastrati per sempre. Per risolvere entrambi i problemi appena menzionati, gli ideatori di Google hanno scelto una “scorciatoia” che consiste nell’assicurarsi • da una parte di non bloccare il navigatore virtuale durante la sua random walk; • dall’altra di soddisfare ad ipotesi matematiche che garantiscono la convergenza del metodo delle potenze (per qualunque scelta del vettore pagerank iniziale x(0) ). Tale duplice obiettivo viene raggiunto andando a modificare la matrice originale eliminando tutti gli zeri presenti (NB: questo non è necessario, ma è sufficiente), quindi creando una matrice sempre stocastica (a colonne) ma con elementi tutti strettamente positivi. L’operazione viene fatta in due passi partendo dalla matrice H. Il primo passo (da H ad H 0 ) serve ad eliminare le pagine penzolanti. Se la matrice originale H presenta delle colonne vuote, allora queste vengono riempite ovunque con 1/n. Quindi, partendo dalla matrice C costruita come al solito, si ottiene direttamente H 0 come c ij se outj 6= 0 outj h0ij = 1 se outj = 0. n Cosı̀ siamo sicuri di non bloccare il navigatore virtuale: se ad un dato istante questi si trova su una pagina con link uscenti, allora ne sceglie uno a caso (quindi probabilità 1/outj ) , altrimenti immette un nuovo indirizzo nella barra degli strumenti, sempre a caso (quindi probabilità 1/n dato che ci sono n possibilità). Esempio 15 Per il WWW di Figura 12 (lo stesso di Figura 9, ma con il collegamento 1 → 3 rimosso), la matrice H originale sarebbe 0 31 0 0 0 0 1 1 2 H= 0 1 0 0 . 3 0 13 12 0 La pagina 1 è penzolante, infatti la corrispondente colonna di H è vuota. Seguendo la regola appena spiegata, si modifica H in H 0 aggiungendo 1/4 su tutta la prima colonna: 1 1 0 0 4 3 1 0 1 1 4 2 H0 = 1 1 0 0 . 4 3 1 1 1 0 4 3 2 Il secondo passo (da H 0 ad H 00 ) serve ad assicurarci la convergenza del metodo delle potenze. Per realizzarlo togliamo gli zeri rimanenti di H 0 nel seguente modo. Scegliamo un numero α ∈ [0, 1], che esprime una probabilità. Imponiamo quindi al navigatore virtuale • con probabilità α di comportarsi come prima, cioè secondo H 0 ; 45 Figura 12: il grafo di un WWW con n = 4 pagine, di cui una penzolante. • con probabilità 1 − α di immettere invece un indirizzo a caso (probabilità 1/n), indipendentemente dalla presenza o meno di link uscenti. Certamente questo modello è più aderente alla navigazione sul WWW reale: infatti, le possibilità di navigazione offerte all’utente si riducono proprio a muoversi attraverso i link o a digitare nuovi indirizzi indipendentemente dalla presenza o meno di link uscenti. Matematicamente, la nuova matrice H 00 si ottiene da H 0 come 1 h00ij = αh0ij + (1 − α) . n Osserviamo che in questo secondo passo stiamo semplicemente aggiungendo la quantità costante (1 − α)/n in ogni posizione della matrice αH 0 . Quindi: 1 1 1 · · · n n n 1 1 ··· 1 n n 0 H 00 = αH + (1 − α) .. .. . . n.. . . . . 1 1 1 n n n ··· 1 1 ··· 1 1 − α 1 1 ··· 1 0 = αH + .. .. . . .. . n . . . . 1 1 ··· 1 Ma come possiamo esprimere diversamente una matrice con tutti 1? Lo possiamo fare costruendo il 46 vettore colonna u= 1 1 .. . 1 e facendo il prodotto righe-colonne di questo (colonna: u ∈ Rn×1 ), con il suo trasposto (riga: uT ∈ R1×n ), ottenendo appunto la matrice Rn×n di tutti 1: 1 1 1 ··· 1 1 1 1 ··· 1 uuT = .. 1 1 · · · 1 = .. .. . . .. . . . . . . 1 1 1 ··· 1 Osservate che per quest’ultimo passaggio non abbiamo fatto altro che applicare il prodotto righe-colonne ad un vettore colonna per uno riga, cioè il contrario del prodotto scalare, che corrisponde al prodotto righe-colonne di un vettore riga per uno colonna. Abbiamo cosı̀ chiuso la questione lasciata in sospeso alla fine della Sezione 2.2. Applichiamo quanto appena visto al passaggio da H 0 ad H 00 , ottenendo cosı̀ uuT . n Riassumendo, questa formula ci dice che il navigatore virtuale esce da una certa pagina secondo H 0 con probabilità α o immettendo un nuovo indirizzo a caso con probabilità 1 − α. Ma quanto vale α? Google dichiara di utilizzare α = 0.85. Aldilà che questo sia vero o meno, certo è che se α = 0, allora il navigatore si muove sempre immettendo indirizzi nuovi a caso: H 00 = αH 0 + (1 − α) uuT , H = n mentre se α = 1 il navigatore si muove sempre secondo H 0 : 00 H 00 = H 0 , cioè secondo i link esistenti, o immettendo un indirizzo nuovo a caso solo se la pagina in cui si trova è penzolante. Potremmo dunque affermare che una scelta di α prossimo a uno è senz’altro più fedele alla realtà. Ma la questione non finisce qui come vedremo. Esempio 16 Riprendiamo la matrice H0 = 1 4 1 4 1 4 1 4 1 3 0 0 0 12 1 . 1 0 0 3 1 1 0 3 2 associata al WWW di Figura 12 e supponiamo α = 0.85. Otteniamo allora 1 1 1 1 1 1 0 0 0.25 0.32 0.04 0.04 4 3 4 4 4 4 1 1 1 1 1 1 0 2 1 4 4 4 4 4 0.25 0.04 0.46 0.88 H 00 = 0.85 1 1 0 0 + 0.15 1 1 1 1 ' 0.25 0.32 0.04 0.04 4 3 4 4 4 4 1 1 1 1 1 1 1 0 0.25 0.32 0.46 0.04 4 3 2 4 4 4 4 47 . Osserviamo come la matrice finale H 00 rimane stocastica (a colonne). Il suo significato finale non cambia rimanendo sempre una matrice di transizione di probabilità: ad esempio, l’elemento h23 = 0.46 in riga 2 e colonna 3 indica che il passaggio dalla pagina 3 alla pagina 2 avviene con il 46% di probabilità. Matlab 13 Con Matlab: >> H=[0,1/3,1/2,0;0,0,0,1;0,1/3,1/2,0;0,1/3,0,0] H = 0 0.3333 0.5000 0 0 0 0 1.0000 0 0.3333 0.5000 0 0 0.3333 0 0 >> u=ones(n,1) u = 1 1 1 1 >> H1=H;H1(:,1)=u/n H1 = 0.2500 0.3333 0.5000 0 0.2500 0 0 1.0000 0.2500 0.3333 0.5000 0 0.2500 0.3333 0 0 >> alfa=0.85; >> H2=alfa*H1+(1-alfa)*(u*u’)/n H2 = 0.2500 0.3208 0.4625 0.0375 0.2500 0.0375 0.0375 0.8875 0.2500 0.3208 0.4625 0.0375 0.2500 0.3208 0.0375 0.0375 Abbiamo usato anche la nuova istruzione ones, il cui significato dovrebbe risultare chiaro. Cosa più importante, osserviamo come Matlab esegue qualunque prodotto con “*”, arrangiandosi a capire se sta moltiplicando scalari, vettori o matrici (e se questo si può fare!). Ora, provate voi ad eseguire il metodo delle potenze sulla matrice H 00 . Nell’esempio precedente vi è stato chiesto di applicare il metodo delle potenze alla matrice H 00 . Osserviamo però che questa non ha nemmeno uno zero. Quindi il costo che paghiamo è O(kn2 ) flop. Abbiamo dunque perso tutto quanto avevamo guadagnato prima? La risposta è fortunatamente negativa. Basta solo ragionare e non agire di fretta. Supponiamo allora di aver già costruito H 0 e riconsideriamo la matrice H 00 = αH 0 + (1 − α) 48 uuT . n Il metodo delle potenze diventa, assegnato x(0) , x(k) = H 00 x(k−1) , k = 1, 2, . . . . Ma abbiamo visto che, essendo H 00 priva di zeri, paghiamo il costo pieno. Se invece sostituiamo l’espressione di H 00 nel generico passo del metodo e applichiamo le proprietà distributiva ed associativa (Esercizio 5 per le matrici, ma vale anche per i vettori ovviamente!) otteniamo uuT 0 (k) x = αH + (1 − α) x(k−1) n (uuT )x(k−1) = αH 0 x(k−1) + (1 − α) n T (k−1) u(u x ) = αH 0 x(k−1) + (1 − α) , k = 1, 2, . . . . n Ma quanto vale uT x(k−1) ? Vediamo: T u x (k−1) = 1 1 ··· 1 (k−1) x1 (k−1) x2 .. . (k−1) (k−1) (k−1) + x2 + · · · + x(k−1) , = x1 n xn quindi questo prodotto (scalare) mi restituisce semplicemente la somma del pagerank di tutto il WWW al passo k − 1: il pagerank totale. Per capire quanto vale, ci vuole ancora un po’ di attenzione. Se x risolve il problema originale x = H 00 x allora anche ax risolve lo stesso problema per qualunque numero scalare a, infatti H 00 (ax) = aH 00 x = ax. Questo vuol dire che se x è soluzione, allora lo sono anche tutti i vettori paralleli ad x. Dal punto di vista del nostro problema non ha importanza: se il vettore x ha le componenti in una certa proporzione, allora tale proporzione non cambia se prendo un vettore parallelo ad x. Quindi l’importanza relativa delle pagine è sempre la stessa, ed è giusto quello che a noi interessa! Allora, se dobbiamo scegliere uno tra tutti questi vettori paralleli, prendiamo per semplicità quello le cui componenti si sommano a 1, ovvero quello per cui il pagerank totale è 1. Segue quindi (k−1) 1 = x1 (k−1) + x2 + · · · + x(k−1) = uT x(k−1) . n Sostituendo nel generico passo del metodo delle potenze si ottiene infine u(uT x(k−1) ) n u 0 (k−1) = αH x + (1 − α) , k = 1, 2, . . . . n La precedente formula ci dice che ciascun passo è composto da un prodotto matrice-vettore (il primo addendo) a cui sommiamo un altro vettore (il secondo addendo). La differenza è che cosı̀ facendo il prodotto matrice-vettore coinvolge la matrice H 0 , la quale ha (di nuovo) tanti zeri, ripristinando dunque il notevole risparmio computazionale che avevamo raggiunto in precedenza! Ricordiamo che il costo finale è perciò O(k · nnz), dove nnz è il numero totale di link esistenti (non proprio...perchè?) e k il numero di passi eseguiti con il metodo delle potenze. x(k) = αH 0 x(k−1) + (1 − α) 49 Commento 5 La scelta di avere un pagerank totale unitario si presta a completare la metafora del navigatore virtuale: ciascuna componente xi , i = 1, 2, . . . , n, del vettore soluzione x rappresenta la probabilità di trovarsi sulla pagina i dopo un tempo di navigazione infinito. La soluzione rappresenta quello che si dice stato stazionario della catena di Markov associata e ogni sua componente, sotto questo punto di vista, è sicuramente un fedele indicatore dell’importanza della pagina considerata. 3.4 Pagerank finalmente?! Ora siamo pronti a raccogliere tutto quanto appreso finora in un codice Matlab. Ma questo lo dovete fare voi! Prima però dobbiamo imparare a scrivere un “programma” Matlab, quello che si chiama un m-file function: questo non è altro che un file di testo. Matlab ha il suo editor, altrimenti potete usare tranquillamente un notepad qualunque a patto che salviate il file con estensione “.m”. All’interno del corpo si scrivono le istruzioni che prevedete di eseguire, seguendo le regole di sintassi viste sinora senza alcuna differenza. L’unica caratteristica che è necessario aggiungere riguarda la relazione Input-Output (I/O), e tutto questo viene inserito nella prima riga di testo, detta “intestazione”, che comincia obbligatoriamente con la parola function. Supponiamo quindi di dover scrivere un m-file che implementa un algoritmo di risoluzione di un problema che prende in Input i dati I1 , I2 , . . . , Ir e fornisce in Output i dati O1 , O2 , . . . , Os . Allora basterà scrivere come intestazione: function [O1,O2,...,Os]=nome(I1,I2,...Is) dove nome è il nome che daremo al file, quindi nome.m. Matlab 14 Si consideri il problema di trovare le radici x1 ed x2 dell’equazione di secondo grado ax2 + bx + c = 0 assegnati i coefficienti a, b e c. Il codice Matlab radici.m riportato nel riquadro è un esempio di m-file function che risolve il problema. Si osservino le linee di commento 2, . . . , 5 precedute dal simbolo “%”. Risultano molto utili in quanto il testo del commento compare se al prompt di comando si usa l’istruzione help seguita dal nome del file: >> help radici [x1,x2]=radici(a,b,c) calcola le radici x1 ed x2 dell’equazione di secondo grado axˆ2+bx+c=0 Per eseguire basterà invece richiamare ciò che segue la parola chiave function nel testo di radici. m, specificando ovviamente gli input, ad esempio: >> [x1,x2]=radici(1,3,2) x1 = -1 x2 = -2 50 1 2 3 4 5 f u n c t i o n [ x1 , x2 ] = r a d i c i ( a , b , c ) % [ x1 , x2 ] = r a d i c i ( a , b , c ) % c a l c o l a l e r a d i c i x1 ed x2 % d e l l ' equazione di secondo grado % ax ˆ 2 + bx+c = 0 . 6 7 8 9 D e l t a =b ˆ 2 - 4 * a * c ; x1 = ( - b+ s q r t ( D e l t a ) ) / ( 2 * a ) ; x2 = ( - b - s q r t ( D e l t a ) ) / ( 2 * a ) ; Ora avete tutti gli ingredienti per costruire il vostro pagerank.m partendo da una qualunque matrice di connettività non normalizzata: ad essere onesti non li avete proprio tutti, ma ci aspettiamo che facciate delle domande! Nel frattempo vediamo qualche simulazione con quello già scritto. Esercizio 10 Costruite la matrice di connettività non normalizzata associata al web rappresentato in figura 13 e testate il vostro prank.m calcolando il pagerank con il valore di default α = 0.85. La classifica di importanza deve risultare P1 , P6 , P2 , P4 , P3 , P5 . P1 P4 P2 P3 P6 P5 Figura 13: il web di dimensione 6 per l’esercizio 10. Matlab 15 Testiamo pagerank.m sulla matrice del WWW di Harvard. Questa la possiamo caricare (e ispezionare) come >> load harvard >> whos Name Size C 500x500 Bytes 15184 51 Class logical Attributes sparse Quindi la possiamo “dare in pasto” a pagerank.m come segue: >> load harvard >> whos Name Size Bytes Class C 500x500 15184 logical >> [x,ind,e,k]=pagerank(C,0.85,1e-5,100); Attributes sparse ottenendo l’intero vettore pagerank x ordinato dalla pagina più importante alla meno importante (che non riportiamo, essendo molto lungo), il vettore ind che contiene gli indici delle pagine ordinate secondo x ed infine l’errore e ed il numero di passi fatti k. Possiamo ad esempio vedere chi sono le prime 10 pagine importanti, l’errore e i passi con >> ind(1:10),e,k ans = 7 54 53 18 9 15 1 10 222 55 e = 8.7680e-006 k = 28 Proviamo ora a ripetere l’eseprimento per diversi valori di α (sempre tra 0 e 1): >> [x,ind,e,k]=pagerank(C,0.9,1e-5,100); >> ind(1:10),e,k ans = 7 54 53 18 9 15 10 1 222 76 e = 8.9850e-006 52 k = 38 >> [x,ind,e,k]=pagerank(C,0.8,1e-5,100); >> ind(1:10),e,k ans = 7 54 53 18 15 9 1 10 222 55 e = 8.7392e-006 k = 22 >> [x,ind,e,k]=pagerank(C,0.5,1e-5,100); >> ind(1:10),e,k ans = 7 54 53 15 18 9 1 10 222 3 e = 3.4844e-006 k = 10 >> [x,ind,e,k]=pagerank(C,0.1,1e-5,100); >> ind(1:10),e,k ans = 54 53 15 7 18 9 53 α k ind 0.9 0.85 0.8 0.5 0.1 38 28 22 10 5 7 7 7 7 54 54 54 54 54 53 53 53 53 53 15 18 18 18 15 7 9 9 15 18 18 15 15 9 9 9 10 1 1 1 10 1 10 10 10 222 222 222 222 222 1 76 55 55 55 19 Tabella 3: dati sul metodo delle potenze per il WWW di Harvard al variare di α. 10 222 1 19 e = 7.0210e-007 k = 5 Che cosa notate (Tabella 3)? Dall’esempio precedente si osserva che più α è prossimo ad 1, più passi si devono compiere per raggiungere la stessa tolleranza. Contrariamente, più α è prossimo a 0, meno passi si devono compiere per raggiungere la stessa tolleranza. Questo fatto indica che il metodo delle potenze è tanto più veloce quanto più α è vicino a 0. Tutto ciò può essere dimostrato rigorosamente studiando la convergenza del metodo, ma dovremmo introdurre i concetti di autovalore e di autovettore di una matrice...ma per questi è meglio iscriversi all’università! D’altro canto possiamo notare che cambiando α cambia pure la classifica delle pagine. Quindi la questione è alquanto delicata: da una parte vorremmo essere veloci (α prossimo a 0), dall’altra vorremmo restare fedeli al WWW reale (α prossimo a 1). Affrontiamo infine un’ultima faccenda curiosa. Ricordiamo cha abbiamo modificato la matrice da H 0 ad H 00 imponendo alla soluzione x di soddisfare a x = αH 0 x + (1 − α) u(uT x) , n ovvero x = αH 0 x + (1 − α) 54 u n (8) dato che T u x= 1 1 ··· 1 x1 x2 .. . = x1 + x2 + · · · + xn = 1. xn Come abbiamo spiegato, questo equivale a scegliere tra tutti i vettori soluzione paralleli quello che fornisce un pagerank totale pari ad 1, il che è in accordo con la metafora del navigatore virtuale: deve infatti muoversi con probabilità 1 ad ogni istante. Come conseguenza si può osservare che stiamo aggiungendo al comportamento secondo i link H 0 un comportamento con probabilità 1 − α che coincide con immettere un nuovo indirizzo scelto a caso, ovvero con probabilità 1 ui = n n per ogni pagina xi , i = 1, . . . , n. Questo corrisponde ad una scelta “democratica” o imparziale. Ed è quella che porta ai risultati principali che si vedono in una normale ricerca con Google. Ma non è l’unica: cosa succede, infatti, se questo nuovo indirizzo non viene scelto cosı̀ casualmente, ma “forzando” la scelta verso una pagina piuttosto che un’altra? Matematicamente dovremmo sostituire le precedenti probabilità con nuove probabilità, diciamo pi n per la pagina xi , i = 1, . . . , n, con il vincolo che n X pi i=1 ovvero n X n =1 pi = n i=1 (come del resto accadeva per il vettore u). Ciò equivale a modificare la (8) in p x = αH 0 x + (1 − α) , n dove il vettore p= p 1 p2 · · · pn T detto vettore di personalizzazione, permette appunto di forzare in qualche modo il calcolo del pagerank in modo da dare più importanza a certe pagine piuttosto che ad altre, e questo a priori scegliendo opportunamente i vari pesi p1 , p2 , etc.. Questo è quello che succede per i cosiddetti “link sponsorizzati” che compaiono evidenziati in cima (o a destra) della normale lista di risultati. Provate infatti a cercare la parola “automobile” su http://www.google.it/. E se proprio non siete stufi, provate pure a modificare il codice pagerank.m per adattarlo a questa nuova versione! Esercizio 11 Modificate il vostro prank.m adottando la versione con vettore di personalizzazione p e, con riferimento al web rappresentato in figura 13, provate a scegliere p in modo tale da far risalire la pagina meno importante in classifica. 55 A Appendice: cifre significative, accuratezza e precisione Nel Commento 4 in Sezione 3.2 abbiamo spesso nominato il concetto di cifre significative. Brevemente, la cifra più significativa è sempre la prima da sinistra diversa da zero, quella meno significativa è l’ultima a destra (anche se zero): le cifre significative sono tutte quelle comprese tra queste (incluse). Esempio 17 Il numero 0.034 ha solo 2 cifre significative (si può scrivere infatti come 3.4 × 10−2 . Invece il numero 0.0340 ne ha 3: anche l’ultimo zero è significativo. Nella visualizzazione dei risultati Matlab abbiamo usato fino a 15 cifre dopo il punto decimale. Quindi un totale di 16 cifre significative (ad es. per mk ). Servono tutte? La risposta a questa apparentemente banale domanda richiede confidenza con i seguenti concetti: • accuratezza: numero di cifre significative esatte; • precisione: numero di cifre significative rappresentate. In base a quanto appena definito, risulta inutile usare un’elevata precisione (tante cifre) in presenza di una limitata accuratezza (poche esatte). In genere poi il vincolo è posto dalla precisione del dato meno preciso. Il seguente esempio servirà a chiarire eventuali dubbi. Esempio 18 Siano a = 1 e b = 3 e supponiamo di voler calcolare r r a 1 = . c= b 3 Il risultato corretto è c = 0.577350269189626 . . . di cui rappresentiamo 15 cifre significative esatte. Quindi diremo che c è preciso alla 15a cifra (perché rappresento 15 cifre significative) e altrettanto accurato (perché sono tutte e 15 corrette). Ad es. c = 0.577350269183210 . . . sarebbe parimenti preciso ma accurato solo alla 11a cifra (le ultime 4, in grassetto, sono errate). Supponiamo ora di calcolare prima 1 d = ' 0.33 3 rappresentando il risultato con una√precisione di sole 2 cifre (a altrettanta accuratezza essendo entrambe esatte). Se ora calcoliamo c come d otteniamo √ d = 0.574456264653803 . . . con una precisione di 15 cifre. Peccato sia limitata a sole 2 cifre, ovvero la stessa del √ che l’accuratezza a dato d. Quindi le cifre significative di d dalla 3 in poi (in grassetto) non sono affatto “significative”! L’esempio precedente ci serve da monito per evitare un utilizzo sconsiderato delle numerose cifre che possono uscire da una calcolatrice scientifica. Ricordate: l’accuratezza di un risultato è comunque limitata dal numero di cifre significative del dato meno preciso! 56 Matlab 16 Proviamo a vedere diversi formati di visualizzazione calcolando √ 0.005: >> format short >> sqrt(.005) ans = 0.0707 >> format long >> sqrt(.005) ans = 0.070710678118655 >> format long e >> sqrt(.005) ans = 7.071067811865475e-02 Come si vede dall’ultimo risultato Matlab fornisce sempre 15 cifre decimali significative, le quali semplicemente non sono tutte visibili negli altri formati pur essendo memorizzate nel calcolatore. B 1 2 3 4 5 6 7 8 9 Codici Pagerank realizzati f u n c t i o n [ x , i n d , e , k ] = p r a n k ( C , a l f a , TOL , kmax ) % [ x , i n d , e , k ] = p r a n k ( C , a l f a , TOL , kmax ) % c a l c o l a i l pagerank x a s s o c i a t o a l l a matrice % d i c o n n e t i v i t a ' C a meno d i una t o l l e r n a z a TOL % con numero d i i t e r a z i o n i massimo kmax p e r i l % metodo d e l l e p o t e n z e . i n d e ' i l v e t t o r e d e g l i % i n d i c i d e l l e p a g i n e web r e l a t i v e a C o r d i n a t o % secondo i l pagerank x . e e ' l ' e r r o r e f i n a l e % e f f e t t i v o e k i l numero d i i t e r a z i o n i e s e g u i t e . 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 %0 v e r i f i c a d i s p a r s i t a ' i f ¬ i s s p a r s e (C) d i s p ( ' ATTENZIONE : l a m a t r i c e d i c o n n e t t i v i t a ' ' non e ' ' s p a r s a ! ' ) return end %1 : i n i z i a l i z z a z i o n e n= s i z e ( C , 1 ) ;%numero p a g i n e web u= o n e s ( n , 1 ) ;%v e t t o r e u n i t a r i o c=sum ( C , 1 ) ; %numero o u t l i n k %2 : c o s t r u z i o n e m a t r i c e d i c o n n e t t i v i t a ' n o r m a l i z z a t a H1 H1= s p a r s e ( n , n ) ; f o r j =1: n i f c ( j ) 6= 0 H1 ( : , j ) =C ( : , j ) / c ( j ) ; e l s e H1 ( : , j ) = u / n ; end end %2 b i s : c o s t r u z i o n e ' g o o g l e m a t r i x ' H2 ( non s e r v e p e r i l c a l c o l o ! ! ) 57 29 30 31 32 33 34 35 36 37 38 39 40 41 H2= a l f a * H1+ ( 1 - a l f a ) * ( u * u ' ) / n ; %3 : metodo p o t e n z e p e r c a l c o l o p a g e r a n k x k =0; xnew=u / n ; e =2 *TOL ; w h i l e ( e ≥TOL)&( k ≤ kmax ) k=k + 1 ; x o l d =xnew ; xnew= a l f a * H1 * x o l d + ( 1 - a l f a ) * u / n ; e=norm ( xnew - x o l d ) ; end %4 : o u t p u t o r d i n a t o s e c o n d o p a g e r a n k x [ x , i n d ] = s o r t ( xnew , ' d e s c e n d ' ) ; 42 43 44 45 46 47 1 2 3 4 5 6 7 8 9 10 %NB: i comandi t i p o ' s p a r s e ' s e r v o n o a non t e n e r c o n t o d e g l i z e r i %n e i c a l c o l i . Ad e s e m p i o H1= s p a r s e ( n , n ) c r e a una m a t r i c e nxn d i t u t t i z e r i %ma l a memorizza come s p a r s a : quando v i e n e m o d i f i c a t a n e l l e s u c c e s s i v e %i s t r u z i o n i , comunque g l i z e r i c h e r i m a n g o n o ( t a n t i ! ) non s a r a n n o %c o n s i d e r a t i n e i c a l c o l i . f u n c t i o n [ x , i n d , e , k ] = p r a n k p e r s ( C , p , a l f a , TOL , kmax ) % [ x , i n d , e , k ] = p r a n k ( C , p , a l f a , TOL , kmax ) % c a l c o l a i l pagerank x a s s o c i a t o a l l a matrice % d i c o n n e t i v i t a ' C con v e t t o r e d i p e r s o n a l i z z a % z i o n e p a meno d i una t o l l e r n a z a TOL % con numero d i i t e r a z i o n i massimo kmax p e r i l % metodo d e l l e p o t e n z e . i n d e ' i l v e t t o r e d e g l i % i n d i c i d e l l e p a g i n e web r e l a t i v e a C o r d i n a t o % secondo i l pagerank x . e e ' l ' e r r o r e f i n a l e % e f f e t t i v o e k i l numero d i i t e r a z i o n i e s e g u i t e . 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 %0 v e r i f i c a d i s p a r s i t a ' i f ¬ i s s p a r s e (C) d i s p ( ' ATTENZIONE : l a m a t r i c e d i c o n n e t t i v i t a ' ' non e ' ' s p a r s a ! ' ) return end %1 : i n i z i a l i z z a z i o n e n= s i z e ( C , 1 ) ;%numero p a g i n e web u= o n e s ( n , 1 ) ;%v e t t o r e u n i t a r i o c=sum ( C , 1 ) ; %numero o u t l i n k %2 : c o s t r u z i o n e m a t r i c e d i c o n n e t t i v i t a ' n o r m a l i z z a t a H1 H1= s p a r s e ( n , n ) ; f o r j =1: n i f c ( j ) 6= 0 H1 ( : , j ) =C ( : , j ) / c ( j ) ; e l s e H1 ( : , j ) = u / n ; end end %2 b i s : c o s t r u z i o n e ' g o o g l e m a t r i x ' H2 ( non s e r v e p e r i l c a l c o l o ! ! ) H2= a l f a * H1+ ( 1 - a l f a ) * ( p * u ' ) / n ; %3 : metodo p o t e n z e p e r c a l c o l o p a g e r a n k x k =0; xnew=u / n ; 58 34 35 36 37 38 39 40 41 42 e =2 *TOL ; w h i l e ( e ≥TOL)&( k ≤ kmax ) k=k + 1 ; x o l d =xnew ; xnew= a l f a * H1 * x o l d + ( 1 - a l f a ) * p / n ; e=norm ( xnew - x o l d ) ; end %4 : o u t p u t o r d i n a t o s e c o n d o p a g e r a n k x [ x , i n d ] = s o r t ( xnew , ' d e s c e n d ' ) ; 43 44 45 46 47 48 %NB: i comandi t i p o ' s p a r s e ' s e r v o n o a non t e n e r c o n t o d e g l i z e r i %n e i c a l c o l i . Ad e s e m p i o H1= s p a r s e ( n , n ) c r e a una m a t r i c e nxn d i t u t t i z e r i %ma l a memorizza come s p a r s a : quando v i e n e m o d i f i c a t a n e l l e s u c c e s s i v e %i s t r u z i o n i , comunque g l i z e r i c h e r i m a n g o n o ( t a n t i ! ) non s a r a n n o %c o n s i d e r a t i n e i c a l c o l i . Riferimenti bibliografici [1] C. Moler. Numerical computing with MATLAB. mathworks.com/moler/index_ncm.html. 2004. Freely available at http://www. [2] C. Moler. Experiments with MATLAB. 2008. Freely available at http://www.mathworks. com/moler/index_exm.html. [3] L. Page, S. Brin, R. Motwani, and T. Winograd. The pagerank citation ranking: Bringing order to the web. Technical Report 1999-66, Stanford InfoLab, November 1999. Previous number = SIDL-WP1999-0120. 59