Sei sulla pagina 1di 11

DEFINIZIONE

E GESTIONE DI MATRICI IN JAVA Domenico Sacc


1. Tipo Matrice: array of array
Abbiamo visto come in Java sia possibile utilizzare gli array, che rappresentano vettori di elementi tutti dello stesso tipo. Ad esempio: int [ ] X; char [ ] Y; double [ ] Z; String [ ] W; definiscono X come array di interi, Y come array di caratteri, Z come array di double e W come array di stringhe. E possibile anche definire array di array, ad esempio int [ ] [ ] X; definisce che X un array di elementi, ciascuno a sua volta costituito da array di interi. Quindi X una matrice bidimensionale di interi. Per dimensionare un array necessario utilizzare il costrutto new, ad esempio: X = new int [10] [5] fissa a 10 il numero di righe di X, individuate con appositi indici che vanno da 0 a 9, e a 5 il numero di colonne per ogni riga X[i], gli indici di colonna vanno da 0 a 4 e gli elementi della riga vanno X[i][0] a X[i][4] . Si noti che X[i] di tipo array di interi mentre X[i][j] un intero. E possibile anche stabilire la dimensione dellarray nel momento della sua definizione: int [ ] [ ] X = new int [10] [5]; E anche possibile ridimensionare un array di array. Ad esempio int [ ] [ ] X = new int [10] [5]; for ( int i =0; i < 10; i++ ) for ( int j =0; j < 5; j++ ) X[i] [j]=i*j; // vengono inizializzati gli elementi di X X = new int [4] [4]; // ora X una matrice quadrata 4 x 4 // attenzione che i 50 elementi precedenti ora sono cancellati for ( int i = 0; i < 4; i++) X [i]= new int [i]; // ora X una matrice triangolare! int [ ] [ ] Y = new int [4] [ ] for ( int i = 0; i < 4; i++) Y [i]= new int [i]; // ora Y una matrice triangolare! E quindi anche possibile definire una matrice in cui ogni riga ha un numero differente di colonne. Si noti che nella definizione di Y, le colonne sono state dimensionate a zero per poi essere dimensionate in vario modo per ciascuna riga.

2. Operazioni su Matrice
Date due matrici A e B conformi (cio il numero n di righe di A uguale al numero di righe di B e il numero m di colonne di A uguale al numero di colonne di B), possiamo calcolare la matrice C come somma di A e B. Cio per 0 <= i < n, 0 <= j < m, C[i][j] = A[i][j]+B[i][j]. Presentiamo di seguito un metodo per il calcolo della somma che restituisce true se la somma stata effettuata e false diversamente (cio le matrici non sono conformi).
static boolean sommaMatrici( double[] [] A, double [][] B, double [][] C) { // somma di due matrici: C = A+B // Le 3 matrici devono essere conformi (stesse dimensioni) if ( A.length != B.length || A[0].length != B[0].length || A.length != C.length || A[0].length != C[0].length ) return false; // matrici non conformi

for ( int i = 0; i < A.length; i++) for ( int j =0; j < A[0].length; j++ ) C[i][j] = A[i][j]+B[i][j]; return true; }

La complessit delloperazione di somma (nm) ovvio che si tratta di un algoritmo ottimale (non possibile fare di meglio in quanto vanno trascritti tutti i valori su C e questi sono in numero di n m). In modo simile pu essere definita loperazione di sottrazione. Unaltra classica operazione sulle matrice il calcolo della trasposta. Data una matrice A di dimensioni n x m, la sua trasposta una matrice AT di dimensioni m n tale che per ogni 0 <= i < n, 0 <= j < m, AT[j][i] = A[i][j]. Presentiamo di seguito un metodo per restituisce la trasposta di una matrice.
static double [] [] trasposta ( double [][] A) { // AT la trasposta della matrice M double [][] AT = new double [A[0].length][A.length]; for ( int i = 0; i < A.length; i++ ) for ( int j = 0; j < A[0].length; j++ ) AT[j][i] = A[i][j]; return AT; }

La complessit delloperazione ancora (n m) anche in questo caso che si tratta di un algoritmo ottimale (non possibile fare di meglio in quanto vanno trascritti tutti i valori su C e questi sono in numero di n m). Vediamo ora come calcolare il prodotto scalare di due matrici A e B conformi (cio il numero di colonne di A uguale al numero di righe di B). Il risultato una matrice C che ha lo stesso numero di righe di A e lo stesso numero di colonne di B. Siano n il numero di righe di A, p il numero di colonne di A (pari al numero di righe di B) e m il numero di colonne di B. Per ogni 0 <= i < n, 0 <= j < m, C[j][i] = 0 <= k < p A[i][k] x B[k][j]. Presentiamo di seguito un metodo per il calcolo del prodotto scalare che restituisce true se il prodotto stato effettuato e false diversamente (cio le matrici non sono conformi).
static boolean moltiplicaMatrici( double[][] A, double []] B, double [][] C) { if ( A[0].length != B.length || A.length != C.length || B[0].length != C[0].length ) return false; // matrici non conformi for ( int i = 0; i < C.length; i++) for ( int j =0; j < C[i].length; j++ ) { C[i][j] = 0; for ( int k = 0; k < A[0].length; k++ ) C[i][j] += A[i][k]*B[k][j]; } return true; }

La complessit delloperazione ancora (n p m) che diventa (n3) nel caso di matrici quadrate. In questo caso non si tratta di un algoritmo ottimale in quanto il lower bound del problema (n2). In effetti esistono algoritmi che effettuano il prodotto in tempo (nq) con q intorno a 2.5.

3. Matrici Triangolari
Una matrice quadrata A di dimensioni n x n triangolare inferiore se tutti gli elementi sopra la diagonale principale sono uguali a 0, cio per 0 <= i < n, i < j < m, C[i][j] = 0. Presentiamo di seguito un metodo per la verifica se una matrice quadrata sia triangolare inferiore.
static boolean eTriangolareInferiore( double [] [] A ) { boolean verificato = true; for ( int i = 0; i < A.length-1 && verificato; i++ ) for ( int j = i+1; j < A[0].length && verificato; j++) verificato = A[i][j] == 0; return verificato; }

Calcoliamo il numero N di confronti effettuati dal metodo. Per i = 0, vengono effettuati n-1 confronti, per i = 1, n-2 confronti, , per i = n-2, 1 confronto e per i = n-1, 0 confronti. Quindi N = (n-1) + (n-2) + + 1 = n (n-1) / 2. Quindi la complessit (n2). Una matrice quadrata A di dimensioni n x n triangolare superiore se tutti gli elementi sotto la diagonale principale sono uguali a 0, cio per 0 <= i < n, 0 <= j < i, C[i][j] = 0. Presentiamo di seguito un metodo per la verifica se una matrice quadrata sia triangolare superiore.
static boolean eTriangolareSuperiore( double [] [] A ) { boolean verificato = true; for ( int i = 1; i < A.length && verificato; i++ ) for ( int j = 0; j < i && verificato; j++) verificato = A[i][j] == 0; return verificato; }

Anche in questo caso il numero N pari a n (n-1) / 2 e la complessit (n2). Un caso degenere di matrice triangolare una matrice diagonale in cui tutti gli elementi sopra e sotto la diagonale principale sono uguali a 0, cio per 0 <= i < n, 0 <= j < n, i j, C[i][j] = 0. Presentiamo di seguito un metodo per la verifica se una matrice quadrata sia diagonale.
static boolean eDiagonale( double [] [] A ) { boolean verificato = true; for ( int i = 0; i < A.length && verificato; i++ ) for ( int j = i+1; j < A[0].length && verificato; j++) verificato = A[i][j] == 0 && A[j][i] == 0; return verificato; }

La complessit del metodo (n2).

4. Risoluzione di un Sistema di Equazioni Lineari


Sia dato il seguente sistema S di n equazioni lineari in n incognite:

a0,0 x 0 a1,0 x 0 S ai,0 x 0 an 1,0 x 0

+ a0,1 x1 + a1,1 x1 + ai,1 x1 + an 1,1 x1

+ + a0, j x j + + a1, j x j + + ai, j x j + + an 1, j x n 1

+ + a0,n 1 x n 1 + + a1,n 1 x n 1 + + ai,n 1 x n 1

= b0 = b1 = bi

+ + an 1,n 1 x n 1 = bn 1

In forma matriciale S pu essere scritto come A XT = BT, dove A la matrice nn dei coefficienti ai,j, XT il trasposto del vettore X delle incognite xi e BT il trasposto del vettore dei termini noti bi (cio XT e BT hanno dimensioni n1).

a0,0 a1,0 a j ,0 an 1,0

a0,1 a1,1 ai,1 an 1,1

a0, j a1, j ai, j an 1, j A

a0,n 1 x 0 b0 a1,n 1 x1 b1 ai,n 1 x i = bi an 1,n 1 x n 1 bn 1 XT BT

La risoluzione del sistema consiste nel determinare il vettore X delle incognite. Affrontiamo questo problema considerando per prima il caso semplice in cui la matrice A sia triangolare superiore (o singolare, cio tutti gli elementi sulla diagonale principale aj,j sono diversi da 0. Il inferiore) e non sistema ha quindi questo formato:

a0,0 x 0 S

+ a0,1 x1 + + a0, j x j + a1,1 x1 + + a1, j x j a j, j x j

+ + a0,n 1 x n 1 + + a1,n 1 x n 1

= b0 = b1

+ + a j ,n 1 x n 1 = b j an 1,n 1 x n 1 = bn 1

In questo caso la risoluzione immediata in quanto sufficiente calcolare xn-1 = bn-1/an-1,n-1 dallultima equazione e quindi sostituire questo valore per xn-1 nella penultima equazione: an 2,n 2 x n 2 + an 2,n 1 x n 1 = bn 2 per calcolare xn-2 = (bn-2 an-2,n-1 bn-1/an-1,n-1)/an -2,n -2 e cos via. Il sistema S triangolare superiore pu essere quindi risolto dal seguente metodo si noti che per valutare una eventuale singolarit della matrice, va verificato se sulla diagonale non ci sia qualche elemento uguale a zero:
static boolean risSistemaTriangSup( double [] [] A, double [] B, double [] X ) { if ( diagonaleConZero(A) ) return false; for ( int i = X.length-1; i >= 0 ; i-- ) { X[i] = B[i]; for ( int j=i+1; j < A[0].length; j++) X[i] -= X[j]*A[i][j]; X[i] = X[i]/A[i][i];

} return true; }

Poich ci sono due cicli di 'for' innestati, la funzione ha complessit (n2); quindi essa ha una complessit ottima in quanto per calcolare le incognite non possibile evitare di scandire gli elementi nel triangolo non-zero della matrice che sono in numero di n(n+1)/2 = (n2). Si noti che abbiamo assunto che le matrici A e B e il vettore X abbiano dimensioni conformi per cui non effettuato alcun controllo responsabilit del metodo chiamante verificare tale conformit prima della chiamata. Il metodo diagonaleConZero :
static boolean diagonaleConZero( double [] [] A ) { boolean esisteZero = false; for ( int i = 0; i < A.length && !esisteZero; i++ ) esisteZero = A[i][i] == 0; return esisteZero; }

La complessit ovviamente (n). Prima di procedere alla risoluzione del caso generale di un sistema di equazioni lineari, mostriamo la risoluzione anche per il caso di matrice triangolare inferiore.
static boolean risSistemaTriangInf( double [] [] A, double [] B, double [] X ) { if ( diagonaleConZero(A) ) return false; for ( int i = 0; i < X.length ; i++ ) { X[i] = B[i]; for ( int j=0; j < i; j++) X[i] -= X[j]*A[i][j]; X[i] = X[i]/A[i][i]; } return true; }

Per risolvere un sistema generale di equazioni lineari sufficiente far precedere la funzione 'risSistemaTriangSup' da un passo di triangolarizzazione della matrice, ad esempio applicando la ben nota eliminazione gaussiana nel seguente modo. Per rendere la matrice A triangolare superiore, procediamo nel seguente modo. Cominciamo con azzerare tutti i coefficienti della colonna 0 sotto la diagonale, cio aj,1, 1 j n-1, in modo che la matrice diventi:

a0,0 x 0 + a0,1 x1 a1,1 x1 S ai,1 x1 an 1,1 x1

+ + a0, j x j + + a1, j x j + + ai, j x j

+ + a0,n 1 x n 1 + + a1,n 1 x n 1 + + ai,n 1 x n 1

= b0 = b1 = bi

+ + an 1, j x n 1 + + an 1,n 1 x n 1 = bn 1

A tale scopo lequazione 1 viene modificata sottraendo ad essa la riga 0 moltiplicata per a1,0/a0,0 in modo che il coefficiente di x1 nella riga 1 (cio a1,0) diventi zero. Quindi per ogni j, 0 j n-1, ogni coefficiente a1,j viene modificato in a1,j a0,j a1,0/a0,0 e il termine noto b1 viene modificato in b1 b0

a1,0/a0,0. Allo stesso modo si annulla il coefficiente ai,0 di x0 nelle altre righe i sottostanti, sottraendo a ciascuna di esse la riga 0 moltiplicata per ai,0/a0,0. Passiamo ora ad annullare i coefficienti sotto la diagonale della colonna 1; pertanto, per ogni riga i, 2 i n-1, annulliamo il coefficiente ai,1 di x1 sottraendo ad essa la riga 1 moltiplicata per ai,1/a1,1. Si noti che il coefficiente ai,0, che era stato modificato a 0 nel passo precedente, rimane tale in quanto per esso la sottrazione comporta la modifica in ai,0 a1,0 ai,1/a1,1 , che vale 0 essendo anche a1,0 = 0.

a0,0 x 0 + a0,1 x1 + a0,2 x 2 + a1,1 x1 + a1,2 x 2 + S ai,2 x 2 + an 1,2 x 2 +

+ a0, j x j + a1, j x j + ai, j x j + an 1, j x n 1

+ + a0,n 1 x n 1 + + a1,n 1 x n 1 + + ai,n 1 x n 1

= b0 = b1 = bi

+ + an 1,n 1 x n 1 = bn 1

Iteriamo il procedimento per tutte le altre colonne j. Per annullare i coefficienti sotto la diagonale della colonna j, per ogni riga i, j+1 i n-1, annulliamo il coefficiente di xj sottraendo alla riga i la riga j moltiplicata per ai,j/aj,j. Al passo j-mo il sistema diventa:

a0,0 x 0 + a0,1 x1 + a0,2 x 2 + a1,1 x1 + a1,2 x 2 + S

+ a0, j x j + a1, j x j a j, j x j

+ + a0,n 1 x n 1 + + a1,n 1 x n 1 + + ai,n 1 x n 1

= b0 = b1 = bj

an 1, j x n 1 + + an 1,n 1 x n 1 = bn 1

Alla fine delle iterazioni il sistema diventa triangolare superiore a meno che la matrice A non sia singolare e non ammetta, quindi, soluzioni. Per la verifica di singolarit, sufficiente verificare che, ad passo j della triangolarizzazione, non sia effettuata una divisione per aj,j sia diverso da 0 ogni altrimenti verrebbe effettuata una divisione per zero. Ma il fatto che un qualche aj,j sia zero non comporta necessariamente che la matrice sia singolare; infatti l'anomalia potrebbe essere eliminata con un opportuno scambio di righe. Ad esempio, la matrice

0 1 1 1
pu essere triangolarizzata semplicemente scambiando le due righe. Introduciamo quindi nell'algoritmo di triangolarizzazione la possibilit di scambiare una riga i con una riga successiva se il coefficiente aj,j sulla diagonale nullo. Otteniamo cos un metodo per risolvere un sistema generale di equazioni lineari che realizza il metodo di eliminazione di Gauss:
static boolean risSistemaEquazioni ( double [][] A, double [] B, double [] X) { boolean singolare = false; for ( int i = 0; i < A.length-1 && !singolare; i++ ) { if ( A[i][i] == 0 ) singolare = !scambiaRiga(A,B,i); for ( int j = i+1; j < A.length && !singolare; j++ ) { double d = A[j][i]/A[i][i]; for ( int k = i+1; k < A.length; k++ ) A[j][k] -= d*A[i][k]; /***

B[j] -= d*B[i]; } } if ( !singolare ) risSistemaTriangSup(A,B,X); return !singolare; } static boolean scambiaRiga( double [] [] A, double [] B, int i ) { boolean trovatoNonZero = false; for ( int j = i+1; j < A.length && !trovatoNonZero; j++ ) if ( A[i][j] != 0 ) { trovatoNonZero=true; double temp = B[i]; B[i]=B[j]; B[j]=temp; for (int k = i; k < A.length; k++) { temp = A[i][k]; A[i][k]=A[j][k]; A[j][k]=temp; } } return trovatoNonZero; }

Il metodo scambiaRiga ha una complessit (n) in quanto il for pi interno eseguito al pi una volta. Pertanto, poich la complessit del metodo risSistemaTriangSup (n2) come abbiamo gi mostrato precedentemente, la complessit del metodo risSistemaEquazioni determinata dalla istruzione asteriscata dentro i tre cicli di 'for' per cui essa (n3). L'algoritmo di risoluzione non ottimale poich esistono algoritmi che risolvono un sistema di equazioni in tempo (nk) con 2 < k < 3. Si noti che la complessit del problema (n2) in quanto la semplice scansione di tutti i coefficienti del sistema richiede un tempo quadratico. Tale limite pu essere abbattuto nel caso di matrici sparse (cio con un numero limitato di valori diversi da zero) tramite algoritmi ad hoc.

5. Compressione di una Matrice


Sia data una superficie piana di dimensioni X e Y. Supponiamo che la dimensione Y sia suddivisa in n parti uguali e quella X in m parti uguali - la superficie quindi rappresentabile da una griglia di n m celle rettangolari. Supponiamo ora di aver memorizzato un valore per ciascuna cella ad esempio, se la superficie unarea territoriale, il valore potrebbe essere la piovosit annuale. I valori possono essere rappresentati con una matrice A di dimensioni n m. Supponiamo di voler ora comprimere la rappresentazione della superficie attraverso una riduzione del numero di celle ad esempio delle celle iniziali. Possiamo quindi costruire una matrice compressa della superficie attraverso una matrice B di dimensioni ridotte, le cui celle hanno come valori le medie delle celle originarie compresse Ad esempio, data la matrice A di dimensioni 12 8:

la matrice con fattore di compressione 4 la matrice B di dimensione 3 2 : in quanto le sei celle di B rappresentano la compressione dei valori dei 6 gruppi di celle di A, come indicati di seguito: Utilizzando un fattore di compressione 3, la matrice B ha dimensione 4 3 e rappresenta i seguenti valori: rappresentano la compressione dei valori dei 12 gruppi di celle di A, come indicati di seguito::


Si noti che i 4 gruppi sul bordo destro hanno dimensione 3 2 in quanto lapplicazione del fattore di riduzione 3 al numero di colonne 8 d il valore 2,667 (arrotondato a 3). In alcuni casi pu essere richiesto che nella aggregazione di celle sia effettuata la somma dei valori piuttosto che la loro media ad esempio nel caso che i valori rappresentino la popolazione in una cella territoriale. Di seguito presentiamo un metodo che effettua la compressione a partire dalla matrice A, del fattore di compressione fC, che deve essere un intero maggiore di 1, e dallindicazione tramite il parametro S_M se si tratta di effettuare la somma (S_M = S) o la media altrimenti:

static double [][] compressione ( double [][] A, int fC, char S_M ) { int n = A.length; int m = A[0].length; int nc = (int) Math.ceil(n / (double) fC); //approssimazione per eccesso int mc = (int) Math.ceil(m / (double) fC); //approssimazione per eccesso double [][] B = new double[nc][mc]; for ( int i = 0; i < nc; i++ ) for ( int j = 0; j < mc; j++ ) B[i][j]=aggregazione(A,i*fC,j*fC, fC, S_M); return B; } static double aggregazione ( double[][] A, int i, int j, int fC, char S_M) { double somma =0; int nElem = 0; for ( int ic=i; ic<A.length && ic < i+fC; ic++) for ( int jc=j; jc<A[0].length && jc < j+fC; jc++) { somma += A[ic][jc]; nElem++; } if ( S_M == S ) return somma; else return somma/nElem; }

Il metodo aggregazione ha una complessit C = (fC2) a causa dei due for innestati, ciascuno ripetuto al pi fC volte. La complessit del metodo compressione ha complessit (nc mc C2); poich nc = n/fC, mc = m/fC, abbiamo (n m C2/ fC2). Quindi essendo C = (fC2), la complessit della compressione (n m) e quindi si tratta di un metodo ottimale in quanto per comprimere i valori di A necessario scorrerli tutti.

6. Punto di Sella di una Matrice


Sia data una matrice M bidimensionale n m. Un punto di sella un elemento M[i][j] di M tale che esso contemporaneamente il minimo elemento della riga i e il massimo elemento della colonna j. I generale una matrice pu avere 0, 1 o pi punti di sella. Il calcolo di un eventuale punto di sella di molto interesse nella Teoria dei Giochi che una disciplina che studia situazioni di competizione e di cooperazione tra due o pi soggetti (giocatori, decisori, operatori economici, produttori e consumatori di beni) razionali ed intelligenti. Come esempio di gioco con due soggetti (A e B) non cooperativo (cio A e B sono avversari) a somma zero (cio il guadagno di A e pari alla perdita di B e viceversa), supponiamo che lUniversit della Calabria abbia deciso di aprire due punti di vendita di snack sul ponte assegnandoli ai due soggetti, con il solo vincolo che ciascuno dei due punti di vendita sia allocato o a uno dei due estremi, o al centro, o a 1/4 del ponte o a 3/4 del ponte. I due soggetti presentano in busta chiusa la localizzazione prescelta. Il calcolo del punto di sella ci permette di prevedere quale saranno le scelte effettuate dai due soggetti. Il guadagno di A rappresentato dalla frazione di potenziale domanda che riuscir ad attrarre il suo punto di vendita. Si supponga che la domanda sia uniformemente distribuita sul ponte e che la scelta da parte dei clienti di un punto di vendita dipende dalla sua distanza. Ovviamente A cercher di massimizzare la frazione di domanda da lui servita. Al contrario B cercher di minimizzare tale frazione di domanda (e quindi massimizzare la sua frazione). Il problema pu essere formalizzato dalla matrice M di dimensioni 5 5, riportata di seguito, in cui sulle righe sono riportate tutte le possibili decisioni di A e sulle colonne quelle di B e i valori M[i][j] memorizzano la frazione di domanda catturata da A, se egli colloca il suo punto di vendita nella posizione i e contemporaneamente B colloca il suo punto di vendita nella posizione j. Ad esempio i valori della riga 0 riportano le frazioni di domanda per A nel caso di allocazione del suo punto di vendita allinizio del ponte per le varie scelte possibili per B: 1/2 se anche B posizione il suo punto vendita allinizio del ponte in tal caso si dividono la

domanda 1/8 se B posiziona il suo punto di vendita a 1/4 in tal caso tutti i clienti da 1/4 in poi vanno da B e quelli compresi tra 0 e 1/4 si dividono tra A e B 1/4 se B posiziona il suo punto di vendita a 1/2 in tal caso tutti i clienti da 1/2 in poi vanno da B e quelli compresi tra 0 e 1/2 si dividono tra A e B 3/8 se B posiziona il suo punto di vendita a 3/4 in tal caso tutti i clienti da 3/4 in poi vanno da B e quelli compresi tra 0 e 3/4 si dividono tra A e B 1/2 se B posiziona il suo punto di vendita alla fine del ponte in tal caso tutti i clienti si divideranno equamente tra i due punti di vendita. Allo stesso modo si calcolano i valori delle altre righe. Pertanto la matrice M : Avendo a disposizione M, il soggetto A calcoler per ogni riga i il valore minimo, che rappresenta la sua minima quota di mercato se dovesse decidere di allocare il punto vendita in i. La sua scelta allora ricadr sulla riga i che ha il valore minimo pi grande nella fattispecie la posizione i=2 a met del ponte. Anche B riesce a costruire la matrice M ma i suoi calcoli li far per colonna. Per ogni colonna j, egli calcola il valore massimo, che rappresenta la massima quota di mercato di A se B dovesse decidere di allocare il punto vendita in j. Poich egli vuole minimizzare la quota di mercato di A, la scelta di B ricadr sulla colonna j che ha il valore massimo pi piccolo nella fattispecie la posizione j=2 a met del ponte. Lelemento M[2][2] un punto di sella ( il minimo della riga 2 e il massimo della colonna 2) e costituisce la situazione di equilibrio, cio due soggetti A e B razionali e avversari alla fine opteranno per tale scelta.: entrambi posizioneranno il proprio punto di vendita a met del ponte. Per verificare che non ci sono altri punti di sella, riportiamo di seguito i valori minimi di riga e i valori massimi di colonna: Pur non essendoci altri punti di equilibrio, tuttavia esistono altre 8 scelte che permettono ai due avversari di suddividersi equamente le quote di mercato (cio valori della matrice pari a 1/2: a. entrambi collocano il punto di vendita alla stessa estremit del ponte (2 possibilit)

10

b. entrambi collocano il punto di vendita a 1/4 o a 3/4 del ponte (altre 2 possibilit) c. A colloca il suo punto di vendita ad una estremit e B allaltra (ulteriori 2 possibilit) d. A colloca il suo punto di vendita a 1/4 e B a 3/4 o viceversa (ultime 2 possibilit) E interessante notare che delle 8 altre possibilit, le ultime due (punto d) sono vantaggiose per la clientela in quanto riducono il totale degli spostamenti in effetti ogni cliente al massimo si dovr spostare di 1/4 di ponte per arrivare al punto di vendita mentre nella soluzione del punto di sella i clienti agli estremi dovranno percorrere met del ponte. Ma nonostante questo vantaggio, tale soluzione non sar scelta dai due soggetti spontaneamente il soggetto A non proporr la collocazione a 1/4 per timore che B scelga la collocazione a met. Lunico modo per pervenire alle soluzioni di cui al punto d che ci sia una regolamentazione da parte di un soggetto terzo, nel nostro caso lUniversit. Possiamo ora mostrare il metodo calcoloPuntiSella, che restituisce tutti gli eventuali punti di sella di una matrice. Il metodo riceve come parametro la matrice M, gli indici di riga (iPuntiSella) e gli indici di colonna (jPuntiSella) degli eventuali punti di sella e restituisce il numero di punti di sella. I due array iPuntiSella e jPuntiSella sono stati dimensionati dal metodo chiamante con n m elementi per il caso estremo che tutti gli elementi di M siano punti di sella. Il metodo calcoloPuntiSella restituisce il numero effettivo di punti di sella nel caso dellesempio dei due punti di vendita sul ponte dellUniversit, viene restituito 1 e i due array iPuntiSella e jPuntiSella contengono ciascuno un solo valore, in particolare iPuntiSella[0] = 2 e jPuntiSella[0] = 2, che stabiliscono che lunico punto di sella M[2][2].
static int calcoloPuntiSella ( double [][] M, int [] iPuntiSella, int [] jPuntiSella ) { int n = M.length; int m = M[0].length; double [] minRiga = new double[n]; for ( int i=0; i < n; i++) minRiga[i]=minimoRiga(M,i); double [] maxColonna = new double [m]; for ( int j=0; j < m; j++) maxColonna[j]=massimoColonna(M,j); int nPuntiSella = 0; for ( int i = 0; i < n; i++) for (int j =0; j < m; j++) if ( M[i][j] == minRiga[i] && M[i][j] == maxColonna[j]) { iPuntiSella[nPuntiSella]=i;jPuntiSella[nPuntiSella]=j; nPuntiSella++; } return nPuntiSella; } static double minimoRiga ( double[][] M, int i ) { double minimo =M[i][0]; for ( int j=1; j<M[0].length; j++) if ( M[i][j]<minimo) minimo = M[i][j]; return minimo; } static double massimoColonna ( double[][] M, int j ) { double massimo =M[0][j]; for ( int i=1; i<M.length; i++) if ( M[i][j]>massimo) massimo = M[i][j]; return massimo; }

E facile verificare che la complessit dellalgoritmo (n m), cio lalgoritmo ottimale non essendo in generale possibile calcolare i punti di sella senza consultare tutti i valori di M.

11