1
Il linguaggio Fortran 90: 4. Array: Vettori e Matrici
2
Vettori
• Gruppi di variabili dello stesso tipo memorizzate in locazioni contigue di memoria.
• La i-esima posizione dell’array a è indicata con a(i)
• Gli elementi di un array sono normali variabili
a(1) a(5)a(2) a(3) a(4)
3
Dichiarazione di variabili vettore• REAL, DIMENSION (20) :: a
L’attributo DIMENSION serve per dichiarare la lunghezza del vettore• CHARACTER(len=20), DIMENSION (50) :: cognome
Indica un vettore di 50 elementi ognuno dei quali è una stringa di 20 caratteri• Costanti di tipo array:
(/ 1, 2, 3, 4, 5 /)• Inizializzazione di un array:
INTEGER, DIMENSION (5) :: a = (/ 1, 2, 3, 4, 5 /)• DO i=1, 5
a(i)=iEND DO
• Il range di variabilità può essere fissato altrimenti:REAL DIMENSION (inf : sup) :: a
4
Somma di due vettori! File: somvett1.for! Scopo: esempio di uso di array
PROGRAM somma_vettori ! Questo programma calcola la somma di due vettori a 3 componenti
! *** SEZIONE DICHIARATIVA *** !IMPLICIT NONE INTEGER, PARAMETER :: dimensione = 3 INTEGER, DIMENSION(dimensione) :: v1, v2 ! i due vettori letti INTEGER, DIMENSION(dimensione) :: somma ! il vettore somma INTEGER :: i! indice di ciclo per scandire le componenti dei vettori
! *** SEZIONE ESECUTIVA *** !! lettura primo vettore WRITE(*,*) 'Immetti il primo vettore!' DO i = 1, dimensione ! leggiamo il vettore una componente alla volta WRITE(*,*) 'Componente ', i, ' ? ' READ (*,*) v1(i) END DO
5
Somma di due vettori (cont.)! lettura secondo vettore WRITE(*,*) 'Immetti il secondo vettore!' DO i = 1, dimensione ! leggiamo il vettore una componente alla volta WRITE(*,*) 'Componente ', i, ' ? ' READ (*,*) v2(i) END DO
! calcolo vettore somma DO i = 1, dimensione somma(i) = v1(i) + v2(i) ! N.B. si potrebbe fare direttamente somma = v1 + v2 END DO
! stampa del vettore somma WRITE(*,*) 'Il vettore somma e'':' DO i = 1, dimensione WRITE(*,*) 'Componente ', i, ' : ', somma(i)END DO STOP
END PROGRAM somma_vettori
6
Passaggio di Parametri Vettore
• Array fittizi di forma presuntaUna procedura non conosce in generale la dimensione dei parametri effettivi array passati alla procedura
• Array fittizi non specificano la dimensione dell’array• REAL, DIMENSION (:) :: aINTEGER :: iDO i = LBOUND (a,1), UBOUND (a,1)
a (i) = 0END DO
• In alternativa occorre passare come parametro la dimensione degli array
7
Passaggio di Parametri di Tipo Vettore
! File: util-vet.for
MODULE operazioni_su_vettori ! Questo modulo contiene alcune unita‘ che effettuano operazioni su! Vettori:! - leggi_vettore : subroutine per la lettura di un vettore di interi! di lunghezza arbitraria ! - stampa_vettore : subroutine per la stampa di un vettore di interi! di lunghezza arbitraria ! - somma_vettori : funzione per la somma vettoriale di due vettori di! interi di lunghezza arbitraria (passata come parametro)! - somma_vettori_sub : subroutine per la somma vettoriale di due! vettori di interi di lunghezza arbitraria. Analoga alla precedente! ma non e' necessario passare la lunghezza.
CONTAINS
8
Passaggio di Parametri di Tipo Vettore (cont.)
SUBROUTINE leggi_vettore (vet)
IMPLICIT NONE ! ** DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, INTENT(IN OUT), DIMENSION(:) :: vet ! il vettore di input ! ** DICHIARAZIONE VARIABILI LOCALI INTEGER :: i ! indice di ciclo DO i = LBOUND(vet,1), UBOUND(vet,1) WRITE(*,*) 'Componente ', i, ' ? ' READ (*,*) vet(i) END DO RETURN
END SUBROUTINE leggi_vettore
9
Passaggio di Parametri di Tipo Vettore (cont.)
SUBROUTINE stampa_vettore (vet)
! DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, DIMENSION(:), INTENT(IN) :: vet ! Vettore di input ! DICHIARAZIONE VARIABILI LOCALI INTEGER :: i ! indice del ciclo
DO i = LBOUND(vet,1), UBOUND(vet,1) WRITE(*,*) 'Componente ', i, ':', vet(i) END DO RETURN
END SUBROUTINE stampa_vettore
10
Passaggio di Parametri di Tipo Vettore (cont.)
FUNCTION somma_vettori (vet1, vet2, dim)
IMPLICIT NONE ! ** DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, DIMENSION(:), INTENT(IN) :: vet1, vet2 ! i vettori di input INTEGER, INTENT(IN) :: dim ! la lunghezza dei vettori ! ** DICHIARAZIONE TIPO FUNZIONE INTEGER, DIMENSION(dim) :: somma_vettori ! ** DICHIARAZIONE VARIABILI LOCALI INTEGER :: i ! indice del ciclo
DO i = LBOUND(vet1,1), UBOUND(vet1,1) somma_vettori(i) = vet1(i) + vet2(i) END DO RETURN
END FUNCTION somma_vettori
11
Passaggio di Parametri di Tipo Vettore (cont.)SUBROUTINE somma_vettori_sub (vet1, vet2, ris) IMPLICIT NONE ! ** DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, DIMENSION(:), INTENT(IN) :: vet1, vet2 ! i vettori di input INTEGER, DIMENSION(:), INTENT(OUT) :: ris ! il vettore di output INTEGER :: i ! indice del ciclo
! *** SEZIONE ESECUTIVA DO i = LBOUND(vet1,1), UBOUND(vet1,1) ris(i) = vet1(i) + vet2(i) END DO RETURN
END SUBROUTINE somma_vettori_sub
12
Passaggio di Parametri di Tipo Vettore (cont.)
! File: somvett2.for! Scopo: Uso di sottoprogrammi che manipolano array unidimensionali di! due vettori a 3 componenti, usando le SUBROUTINE
PROGRAM somma_vettori_2
! *** SEZIONE DICHIARATIVA *** !USE operazioni_su_vettori IMPLICIT NONE INTEGER, PARAMETER :: dimensione = 3INTEGER, DIMENSION(dimensione) :: v1, v2 ! i due vettori letti INTEGER, DIMENSION(dimensione) :: somma ! il vettore somma
13
Passaggio di Parametri di Tipo Vettore (cont.)
! *** SEZIONE ESECUTIVA *** !WRITE(*,*) 'Immetti il primo vettore!' CALL leggi_vettore(v1) ! lettura secondo vettore WRITE(*,*) 'Immetti il secondo vettore!' CALL leggi_vettore(v2) ! calcolo vettore somma con la funzione somma = somma_vettori(v1,v2,dimensione) ! stampa del vettore somma WRITE(*,*) 'Il vettore somma e'':' CALL stampa_vettore(somma) ! calcolo vettore somma con la subroutine CALL somma_vettori_sub(v1,v2,somma) ! stampa del vettore somma WRITE(*,*) 'Il vettore somma (calcolato in altra maniera) e'':' CALL stampa_vettore(somma) STOP
END PROGRAM somma_vettori_2
14
Ordinamento di un Vettore
• Ordinare un vettore di n interi in modo non decrescente.
10 16 12 3
1 123 6 10
15
Algoritmo di Ordinamento
loop1: DO i=1, n-1 “Tova la posizione k_min del minimo intero nelle posizioni da i a n”“Scambia l’elemento nella posizione i con l’elemento nella posizione k_min”
END DO loop1
16
Ordinamento di un Vettore (Cont.)
“Trova la posizione k_min del minimo intero nelle posizioni da i a n”k_min = iloop2: DO j=i+1, n
IF (a(j) < a(k_min)) k_min = jEND DO loop2
“Scambia l’elemento nella posizione i con l’elemento nella posizione k_min”tmp = a(i) a(i) = a(kmin)a(kmin) = tmp
17
Ordinamento di un Vettore (Cont.)SUBROUTINE ordinavett(v)! Scopo: ordinamento di un vettore di interi
IMPLICIT NONE ! Dichiarazione parametri formali
INTEGER, DIMENSION (:), INTENT (IN OUT) :: v ! Dichiarazione variabili locali INTEGER :: i, j, k_min, i_min, i_max, tmp i_min = LBOUND(v,1) i_max = UBOUND(v,1) loop1: DO i=i_min, (i_max - 1) k_min = i loop2: DO j=i+1, i_max IF (v(j) < v(k_min)) k_min = j END DO loop2 tmp = v(i) v(i) = v(k_min) v(k_min) = tmp END DO loop1 RETURN
END SUBROUTINE ordinavett
18
Ordinamento di un Vettore (Cont.)! File: test_ordinavett.for! Scopo: testare la subroutine ordinavett(v) che ordina un vettore di interi
PROGRAM test_ordinavett
USE operazioni_su_vettori IMPLICIT NONE INTEGER, PARAMETER :: dimensione = 3INTEGER, DIMENSION(dimensione) :: v ! vettore da leggere e ordinare
WRITE(*,*) 'Immetti il vettore di interi da ordinare ' CALL leggi_vettore(v)! stampa del vettore inserito WRITE(*,*) 'Vettore inserito: ' CALL stampa_vettore(v)! ordino il vettore somma con la funzione ordinavett(v)CALL ordinavett(v)! stampa del vettore ordinato WRITE(*,*) 'Vettore ordinato: ' CALL stampa_vettore(v)STOP
END PROGRAM test_ordinavett
19
Matrici • Vettori a due dimensioni
• Ogni elemento è indicato da un indice di riga ed un indice di colonna
• L’elemento della matrice di indice di riga i ed indice di colonna j è indicato con a(i,j)
1 2 3 4 5
2
3
4
1
20
Dichiarazione di Matrici
• INTEGER, DIMENSION (5,10) :: a• REAL, DIMENSION (0:100, 5:20) :: valori• Inizializzazione di una Matrice
INTEGER, DIMENSION (7,10) :: mat
DO i=1, 7
DO j=1, 10
mat(i,j) = 0
END DO
END DO
21
Gestione delle matrici
! File: mod_matr.for
MODULE modulo_matrici ! Questo modulo contiene alcune unita‘ che effettuano operazioni su! matrici:! - leggi_matrice : subroutine per la lettura di una matrice! bidimensionale di interi di forma arbitraria ! - stampa_matrice : subroutine per la stampa di una matrice! bidimensionale di interi di forma arbitraria ! - somma_matrici : funzione per la somma vettoriale di due matrici! bidimensionali di interi di forma arbitraria! - prodotto_matrici : funzione che calcola il prodotto di due! matrici di interi
CONTAINS
22
Gestione delle matrici (cont)SUBROUTINE leggi_matrice (mat)
IMPLICIT NONE ! ** DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, INTENT(IN OUT), DIMENSION(:,:) :: mat ! matrice di input ! ** DICHIARAZIONE VARIABILI LOCALI INTEGER :: i, j, r_min, r_max, c_min, c_max r_min = LBOUND (mat,1) r_max = UBOUND (mat,1) c_min = LBOUND (mat,2) c_max = UBOUND (mat,2)
WRITE(*,*) 'Inserisci matrice', (r_max-r_min+1), ' *',(c_max-c_min+1) DO i = r_min, r_max DO j = c_min, c_max WRITE(*,*) 'componente ', i, j, ' : ' READ (*,*) mat(i,j) END DO END DO RETURN
END SUBROUTINE leggi_matrice
23
Gestione delle matrici (cont)SUBROUTINE stampa_matrice (mat)
IMPLICIT NONE ! ** DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, INTENT(IN), DIMENSION(:,:) :: mat ! matrice di input ! ** DICHIARAZIONE VARIABILI LOCALI INTEGER :: i, j, r_min, r_max, c_min, c_max r_min = LBOUND (mat,1) r_max = UBOUND (mat,1) c_min = LBOUND (mat,2) c_max = UBOUND (mat,2)
DO i = r_min, r_max WRITE(*,*) 'riga', i DO j = c_min, c_max WRITE(*,*) ' col.', j, ' =', mat(i,j) END DO END DO RETURN
END SUBROUTINE stampa_matrice
24
Somma di MatriciSUBROUTINE somma_matrici(a, b, c)
IMPLICIT NONE ! Dichiarazioni parametri fittizi INTEGER, DIMENSION(:,:), INTENT (IN) :: a, b INTEGER, DIMENSION (:,:),INTENT (OUT) :: c ! Dichiarazione variabili locali INTEGER :: i, j, r_min, r_max, c_min, c_max
r_min = LBOUND (a,1) r_max = UBOUND (a,1) c_min = LBOUND (a,2) c_max = UBOUND (a,2) DO i = r_min, r_max DO j = c_min, c_max c(i,j) = a (i,j) + b (i,j) END DO END DO RETURN
END SUBROUTINE somma_matrici
25
Moltiplicazione tra Matrici
• Date due matrici a(n:m) e b(m:p) calcolare la matrice prodotto c(n:p).
DO i=1, n DO j=1, p
END DO
END DO
m
1kj)b(k, k)a(i, j)c(i,
26
Moltiplicazione tra Matrici (cont.)SUBROUTINE prodotto_matrici (a,b,c,n,m,p)
IMPLICIT NONE ! Dichiarazioni parametri formali INTEGER, INTENT(IN) :: n, m, p INTEGER, DIMENSION (n,m), INTENT (IN) :: a INTEGER, DIMENSION (m,p), INTENT (IN) :: b INTEGER, DIMENSION (n,p), INTENT (OUT) :: c ! Dichiarazione variabili locali INTEGER :: i, j, k
DO i = 1, n DO j = 1, p c(i,j) = 0 DO k = 1, m c(i,j) = c(i,j) + a(i,k) * b(k,j) END DO END DO END DO RETURN
END SUBROUTINE prodotto_matrici
27
Calcolo del minimo locale
• Data una matrice a(n:m) calcolare per ogni elemento a(i,j) il minimo tra a(i,j) e gli elementi adiacenti.
3
6102
12
6
5
1 31
a b
28
Calcolo del minimo locale (cont.)SUBROUTINE minimo_locale(a,b,n,m)
IMPLICIT NONE INTEGER, INTENT(IN) :: n, m INTEGER, DIMENSION(n,m), INTENT (IN) :: a INTEGER, DIMENSION (n,m),INTENT (OUT) :: b ! Dichiarazione variabili locali INTEGER :: i, j, k, l, i1,i2, j1, j2,min IF ((n < 2) .OR. (m < 2)) THEN b = a ELSE loop1: DO i = 1, n loop2: DO j = 1, m
“Calcolo del minimo locale nell’intorno di a(i,j) ed assegnazione a b(i,j)”
END DO loop2 END DO loop1 END IF RETURNEND SUBROUTINE minimo_locale
END MODULE modulo_matrici
29
Calcolo del minimo locale (cont.)“Calcolo del minimo locale nell’intorno di a(i,j)”:
IF (i == 1) THEN i1 = 1 ELSE i1 = i-1 END IF IF (i == n) THEN i2 = n ELSE i2 = i+1 END IF IF (j == 1) THEN j1 = 1 ELSE j1 = j-1 END IF IF (j == m) THEN j2 = m ELSE j2 = j+1 END IF
30
Calcolo del minimo locale (cont.)
min = a(i,j) loop3: DO k = i1, i2 loop4: DO l = j1, j2 IF (a(k,l) < min) min = a(k,l) END DO loop4 END DO loop3 b(i,j) = min
31
Potenza elettrica erogata
• Per ogni istante di tempo si conosce la potenza elettrica erogata da n generatori.
• L’osservazione delle potenza erogata prosegue per m istanti di tempo
• Scrivere una SUBROUTINE che calcoli la potenza media erogata da ogni generatore lungo gli m istanti di tempo ed una SUBROUTINE che calcoli la potenza totale erogata dagli n generatori ad ogni istante di tempo
32
Potenza elettrica erogata(cont.)
• I dati di input alla procedura sono rappresentati in una matrice di reali erogati(n,m) di n righe ed m colonne.
• I dati di output sono rappresentati in un vettore media(n) ed un vettore totale(m)
33
Potenza elettrica erogata(cont.)
• Esempio: 4 generatori, 5 istanti di tempo1 2 3 4 5
2
3
4
1 30.0 26.7 24.9 28.1 31.4
18.2
36.6
24.4
28.22
119.2totale
media
34
Potenza elettrica erogata(cont.)Calcolo della potenza media
SUBROUTINE pot_media (erogati, n, m, media)! Scopo: calcolo della potenza media erogata da ogni generatore
! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE ! Dichiarazione parametri formali REAL, DIMENSION(:,:), INTENT(IN) :: erogati INTEGER, INTENT(IN) :: n, m REAL, DIMENSION(:), INTENT(OUT) :: media ! Dichiarazione variabili locali INTEGER :: i,j REAL ::temp
35
Potenza elettrica erogata(cont.)Calcolo della potenza media
! *** SEZIONE ESECUTIVA *** ! DO i=1, n ! Calcola la potenza media del generatore i temp = 0. DO j=1, m ! Scandisci gli m istanti di tempo temp = temp + erogati(i,j) END DO media(i) = temp / m END DO RETURN
END SUBROUTINE pot_media
36
Potenza elettrica erogata(cont.)Calcolo della potenza totale
SUBROUTINE pot_totale (erogati, n, m, totale)! Scopo: calcolo della potenza totale erogata da ogni generatore
! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE ! Dichiarazione parametri formali REAL, DIMENSION(:,:), INTENT(IN) :: erogati INTEGER, INTENT(IN) :: n, m REAL, DIMENSION(:), INTENT(OUT) :: totale ! Dichiarazione variabili locali INTEGER :: i,j REAL ::temp
37
Potenza elettrica erogata(cont.)Calcolo della potenza totale
! *** SEZIONE ESECUTIVA *** ! DO i=1, m ! Calcola la potenza totale erogata al tempo i temp = 0. DO j=1, n ! Scandisci gli n generatori temp = temp + erogati(j,i) END DO totale(i) = temp END DO RETURN
END SUBROUTINE pot_totale
38
Calcolo dei prodotti scalari
• Una matrice x(n:m) memorizza le componenti di n vettori ad m dimensioni
• Scrivere una SUBROUTINE che calcoli il prodotto scalare tra tutte le coppie di vettori
• Il risultato e’ formato di n**2 prodotti scalari che memorizziamo in una matrice prod (n:n)
39
Calcolo dei prodotti scalari
EX: m=3
v1 = x(1,1) i + x(1,2) j+ x(1,3) k
v2 = x(2,1) i + x(2,2) j+ x(2,3) k
v1 v2 = x(1,1) * x(2,1) + x(1,2) * x(2,2) + x(1,3) * x(2,3)
40
Calcolo dei prodotti scalari (cont.)
SUBROUTINE prodotto_scalare (x, n, m, prod)! Scopo: calcolo dei prodotti scalari tra tutte le coppie di n righe! di una matrice x(n,m).! Ritorna la matrice dei prodotti scalari prod(n,n)
! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE !Dichiarazione parametri formali INTEGER, INTENT(IN) :: n, m REAL, DIMENSION(:,:), INTENT(IN) :: x ! x(i,j) memorizza la j-ma componente dell’i-mo vettore REAL, DIMENSION(:,:), INTENT(OUT) :: prod ! Prod(i,j) memorizza il prodotto scalare tra il vettore i ed il ! vettore j !Dichiarazione variabili locali INTEGER :: i, j, k REAL :: tmp
41
Calcolo dei prodotti scalari (cont.)
! *** SEZIONE ESECUTIVA *** ! DO i = 1, n DO j = 1, n tmp = 0.0 DO k = 1, m tmp = tmp + x(i,k) * x(j,k) END DO WRITE(*,*)'prod(',i,j,') = ',tmp prod (i,j) = tmp END DO END DO RETURN
END SUBROUTINE prodotto_scalare