Uso dei cicli

Un uso dei cicli può essere quello di creare una serie storica per
cui
yt=c+tyt-1+e
dove poniamo c e t scalari ed e~N(0,1). Realizzare questo
processo con un ciclo è immediato e ovviamente richiede di
predefinire c e theta, la numerosità n e il primo valore, dal quale
far partire la serie.
n=30;
v=zeros(n,1);
v(1)=2.1;
theta=0.6;
for i=2:n;
v(i)=v(i-1)*theta+randn(1,1);
end;
Uso dei cicli


Va ricordato che nel ciclo il “passo” del contatore non è
necessariamente 1 e inoltre può non essere un numero fisso ma
collegato ad una variabile; poniamo ad esempio che abbiamo
una matrice quadrata di ordine nxm costruita a blocchi, ossia a
blocchi quadrati nxn sui quali vogliamo. Pertanto in una matrice
6x6 possiamo identificare 6 sottomatrici 2x2 sulle quali costruire
un loop.
Poniamo di aver creato con il comando rand una matrice 6x6 di
numeri casuali; considerata ora una matrice della stessa
dimensione, vogliamo che essa presenti solo i blocchi situati
sulla diagonale. Per ottenere questo risultato dobbiamo, come al
solito, predeterminare la dimensione della matrice che
accoglierà i blocchi sulla diagonale e poi impostare il passo del
loop.
Il codice, posto m=3 e n=2 può essere il seguente:
Uso dei cicli
n=2;
m=3;
r=rand((m*n),(m*n));
d=zeros((m*n),(m*n));
for i=1:n:(m*n);
d(i:i+n-1,i:i+n-1)=r(i:i+n-1,i:i+n-1);
end;


Notiamo che la matrice d ha uguali dimensioni di r, e che il
passo di i è determinato da n, in quanto devo saltare di n in n
per poi considerare le sottomatrici nxn.
Proviamo ora in modo analogo a costruire un codice che
trasferisca tutti i blocchi usando un doppio loop:
Uso dei cicli
n=2;
m=3;
c=rand((m*n),(m*n));
z=zeros((m*n),(m*n));
for i=1:n:(m*n);
for k=1:n:(n*m);
z(i:i+n-1,k:k+n-1)=c(i:i+n-1,k:k+n-1)
end;
end;

Nel caso di doppio loop il programma esegue prima il loop
interno e finito il ciclo aggiorna il loop esterno e quindi riinizia
con il loop interno. Questo significa che l’ordine con il quale
MATLAB attribuisce i valori a i (contatore che agisce sulle righe)
e k (contatore che agisce sulle colonne) è:
Uso dei cicli
i=1;
k=1;
i=1;
k=3=1+n;
i=1;
k=5=1+n+n;
i=3=1+n;
k=1;
i=3=1+n;
k=3=1+n;
i=3=1+n;
k=5=1+n+n;
i=5=1+n+n;
k=1;
i=5=1+n+n;
k=3=1+n;
i=5=1+n+n;
k=5=1+n+n;
Uso dei cicli



Quindi inizia il ciclo delle righe, si esaurisce il ciclo delle colonne,
si aggiorna il ciclo delle righe, …
Supponiamo ora di volerci cimentare in un loop più complesso:
presa una matrice casuale quadrata di ordine n*m, poniamo di
voler trasportare su di un’altra matrice i blocchi della prima presi
in senso antiorario, e quindi vogliamo che l’ultima sottomatrice
2x2 diventi la prima nella nuova matrice e così via.
Il grado di complessità risiede solamente nel modificare gli
elementi presi in considerazione:
Uso dei cicli
n=2;
m=3;
t=rand((m*n),(m*n));
g=zeros((m*n),(m*n));
for i=1:n:(m*n);
for k=1:n:(n*m);
g(i:i+n-1,k:k+n-1)=t((m*n)-i:(m*n)-i+1,(m*n)-k:(m*n)-k+1);
end;
end;
A differenza del loop precedente ora gli indici degli elementi presi
delle due matrici sono differenti! Ovviamente consideriamo sempre
sottomatrici quadrate, ma a sx partiamo dall’ultima sottomatrice
mentre a dx partiamo dalla prima!
Cicli


I cicli for sono generalmente più efficienti dei cicli while, in
termini di velocità di calcolo.
Entrambi i tipi di cicli (for e while) possono essere bloccati
all’interno con il comando break. Questo comando risulta
particolarmente utile utilizzandolo con if (v. dopo). La struttura
del ciclo sarebbe del tipo:
for / while
if …
(se succede questo)
…..
(continua il loop e calcola questo)
elseif … (se invece succede quest’altro)
break (termina il ciclo)
end;
If statement

Il comando if valuta quando una certa condizione è vera e in tal
caso esegue il comando. La struttura del comando è:
if (se) …… (succede questo)
…. (fai questo)
elseif (se invece) …. (succede quest’altro)
…. (fai questo)
elseif (se invece) …. (succede quest’altro)
…. (fai questo)
….
else (se non è successo niente delle precedenti cose)
…. (fai questo)
end
If statement


I comandi if ed end (che termina l’if) devono necessariamente
esserci, elseif ed else possono o meno esserci.
Facciamo un esempio. Possiamo scrivere un codice che mi dia
come output la parola “quadrata” se una matrice è nxn, la
parola “rettangolare” se la matrice è rxc, con r diverso da c.
Riprendendo la struttura di prima e considerando che una
matrice o è quadrata o è rettangolare (per cui posso usare else)
la struttura (non il codice!) è la seguente:
if n° righe di A = n° colonne di A
stampa a video “quadrata”
else
stampa a video “rettangolare”
end
If statement

Associando al codice una funzione che chiamo cm (da check
matrix) potrebbe essere
function[] = cm(A);
if size(A,1) == size(A,2);
‘quadrata’
else;
‘rettangolare’
end
Relazioni logiche


Nell’uso di if risultano di fondamentale utilizzo i comandi che
permettono di stabilire relazioni logiche (maggiore di, minore di
e eguale a). L’output di questi comandi è sempre costituito da
numeri, vettori o matrici logiche, ossia composti da zeri ed uno:
 Lo zero compare quando la relazione non è rispettata
 L’uno compare se la relazione è rispettata.
I simboli da utilizzare sono:
==
uguale
~=
diverso
<
minore
>
maggiore
<=
minore o uguale
>
maggiore o uguale
Relazioni logiche


Così se scriviamo
>> 5 > 3
la risposta è 1,
>> 4 ~= 2
la risposta è 1, etc.
Diversi sono invece i connettivi logici, ossia operatori che
collegano due espressioni, che sono:
and (e anche)
&
or
|
(oppure)
not (non)
~
Relazioni logiche

Nell’ambito delle relazioni logiche e dell’algebra delle matrici,
due comandi risultano molto utilizzati:

Il comando find(..), applicato ad una matrice/vettore,
fornisce la posizione degli elementi della matrice/vettore che
soddisfano la condizione tra parentesi. Ad es.:
>> B = randn(10,4);
>> v = find(B>0.3);
v è il vettore contenente la posizione (quindi non è un
vettore logico!!) degli elementi >0.3. se applicato a matrici
gli indici scorrono in verticale, nel senso che il numero 2 è
associato all’elemento a2,1. Se non è indicata alcuna
relazione logica ma solo la matrice, fornisce la posizione
degli elementi diversi da zero.
Relazioni logiche

Il comando any(..), applicato ad un vettore, fornisce 1 se
qualche (almeno un) elemento del vettore è diverso da zero,
e quindi fornisce zero solo se tutti gli elementi del vettore
sono nulli. Applicato ad una matrice fornisce un vettore con
tanti elementi quanti i vettori colonna della matrice, con 1 se
la colonna ha almeno un elemento diverso da zero e 0 se ha
tutti elementi diversi da zero. Specificando any(matrice,k) la
funzione lavora solo sulla k-esima riga.
Relazioni logiche

L’utilità di questi operatori è grande nell’ambito matriciale
e con l’if. Ad esempio se ci stiamo chiedendo se gli
elementi di una matrice A siano o meno maggiori di 0.5,
digitando
>> A>0.5
otteniamo una matrice logica di zeri ed uno, in cui l’1 è
associato a elementi > di 0.5. Se volessimo da una
matrice ottenere solo gli elementi > di 0.5 basta fare
>> A(A>0.5)
In tal modo prima otteniamo la matrice logica, poi
selezioniamo di A solo gli elementi cui è associato 1.
Otteniamo così un vettore con tutti e soli gli elementi che
rispettano la condizione.
Relazioni logiche

Un altro esempio. Poniamo di voler considerare di una
matrice B
0.03
0.5
0.02
0.45
0.05
0.23
0.01
0.58
0.07
0.25
0.29
0.15
e di chiedere al programma di stampare a video quanti
elementi sono compresi tra 0.2 e 0.3.
Possiamo vedere il risultato confrontando due codici: uno
che utilizza solo i connettivi logici, un altro che usa anche i
loop.
Relazioni logiche

Il primo codice è brevissimo:
function[j]=mc(a);
b=a(a>0.2 & a<0.3);
j=length(b);

vengono selezionati gli elementi della matrice che siano
maggiori di 0.2 e anche minori di 0.3 (quindi compresi tra 0.2 e
0.3), e poi si estraggono da A i corrispondenti elementi, che
vengono posti in un vettore b. Dopodiché ne calcolo la
lunghezza, che coincide con il numero di elementi che
soddisfano la condizione.
Un codice con loop e if sarebbe il seguente, ma rispetto al primo
è molto più lungo e quindi inefficace:
Relazioni logiche
function[b]=mc2(A);
b=0;
for i=1:size(A,1);
for j=1:size(A,2)
if A(i,j)>0.2 & A(i,j)<0.3;
b=b+1;
end
end
End

Un modo per valutare la velocità computazionale in termini di
tempo di una funzione è scrivere nel command
tic , (funzione) , toc
Relazioni logiche

Provando a creare una matrice A=rand(100,200) e applicando
le due funzioni troverete che la prima funzione è decisamente
più veloce.
>> tic, mc(a), toc
ans =
2029
elapsed_time =
0.0500
>> tic, mc2(a), toc
ans =
2029
elapsed_time =
0.2200
Scarica

Relazioni logiche