Consideriamo questo problema di derivazione numerica:
Consideriamo questo problema di derivazione numerica:
Consideriamo due casi:
\[f'(x) = \lim_{h \rightarrow 0} \frac{f(x+h) - f(x)}{h}\]
A questo punto:
Idealmente:
In realtà non è una grande idea:
\[h = \left\{\begin{aligned} & \sqrt{\varepsilon} x & \text{ if } |x| > tol \\ & \sqrt{\varepsilon} & \text{ altrimenti} \end{aligned} \right.\]
Proviamo ad abbozzare una implementazione:
function df = derive(...)
if abs(x) > 1e-6 % Scelta di h
h = sqrt(eps) * x;
else
h = sqrt(eps)
end
df = 1/h * (f(x+h) - f(x)) % Calcolo della derivata
else
x
(il punto per cui calcolare la derivata)…Proviamo ad abbozzare una implementazione:
function df = derive(...)
if abs(x) > 1e-6 % Scelta di h
h = sqrt(eps) * x;
else
h = sqrt(eps)
end
df = 1/h * (f(x+h) - f(x)) % Calcolo della derivata
else
f
stessa!Alcuni algoritmi utilizzano funzioni come parametri
In Matlab si può fare:
In derive
, trattiamo un parametro come un nome di funzione
function df = derive(f, x)
if abs(x) > 1e-6 % Scelta di h
h = sqrt(eps) * x;
else
h = sqrt(eps)
end
df = 1/h * (f(x+h) - f(x)) % Calcolo della derivata
else
f
(si riconosce dalla parentesi)f
è una variabile locale, che contiene una funzioneIn Matlab si può fare:
Da qualche parte dobbiamo definire \(f\):
Quando invochiamo derive
(e.g. con \(x=1\)) non possiamo usare:
f
…In Matlab si può fare:
Da qualche parte dobbiamo definire \(f\):
Quando invochiamo derive
dobbiamo usare una sintassi speciale:
@
dice a Matlab che f
non va eseguita…Complessivamente abbiamo:
derive(f, 1) % Invocazione
function y = f(x) % Funzione da derivare
y = ...
end
function df = derive(f, x) % Approssimazione della derivata
df = ...
end
Come al solito, trovate il codice nello start-kit
Supponiamo di vole derivare:
\[f(x) = x^2 \log x\]
Matlab ci fornisce un costrutto più compatto: le funzioni anonime
Si tratta di un modo alternativo per definire una funzione
La sintassi è:
@(<p1>, <p2>, ...) <espressone>
Il costrutto restituisce una funzione senza nome:
<p1>
, <p2>
… sono i parametri formali<espressione>
Si può memorizzare la funzione in una variabile, e.g.:
f
…x^2
In prima battuta, potremmo pensare di scrivere:
In realtà, non funziona!
f
è già una variabile che contiene una funzioneLa forma corretta è quindi semplicemente:
A differenza della funzioni “normali”…
Le funzioni anomime hanno accesso alle variabili dell’ambiente in cui sono definite
Per esempio:
x
(il parametro)a
!Consideriamo ancora l’oscillatore (discretizzato) di Van Der Pol:
\[\begin{align} x^{(t+1)} &= x^{(t)} + h y^{(t)} \\ y^{(t+1)} &= y^{(t)} + h \left(\mu (1 - x^{(t)2})y^{(t)} - x^{(t)}\right) \\ \end{align}\]
…Ed il suo codice di simulazione:
X = [];
T = 1:1000; % Istanti di tempo
xc = [x0, y0]; % Stato iniziale
for t = T
X(t, :) = xc; % Salvo lo stato corrente
xc = f(xc, h, mu); % Genero lo stato futuro
end
Per essere “puliti”, dovremmo definire una funzione
Per prima cosa, incapsuliamo il codice in una nuova funzione:
Per essere “puliti”, dovremmo definire una funzione
Quindi, identifichiamo i parametri:
function X = simulate(..., T, ...)
X = [];
xc = [x0, y0];
for t = T
X(t, :) = xc;
xc = f(xc, h, mu);
end
end
T
sia un parametro…Per essere “puliti”, dovremmo definire una funzione
Quindi, identifichiamo i parametri:
X0
…f
Per essere “puliti”, dovremmo definire una funzione
Ci rimane ancora un problema:
function X = simulate(f, T, X0)
X = [];
xc = X0;
for t = T
X(t, :) = xc;
xc = f(xc, h, mu); % <--- QUI!!
end
end
h
e mu
sono specifici per il nostro oscillatore…simulate
non è davvero genericaSoluzione 1: includere h
e mu
nella definizione della funzione
function X = simulate(f, T, X0)
X = [];
xc = X0;
for t = T
X(t, :) = xc;
xc = f(t, xc); % Passo solo lo stato
end
end
t
, è utile per alcuni sistemi…Soluzione 1: includere h
e mu
nella definizione della funzione
A parte avremo:
Soluzione 1: includere h
e mu
nella definizione della funzione
Nel complesso, potremmo avere:
T = 1:300;
X0 = [0.5, 0.5];
X = simulate(@vdp, T, X0); % Funzione come valore
function xf = vdp(t, xc)
...
end
Funziona, ma ha dei grossi difetti:
h
e mu
sono hard-coded nella funzione vdp
…Soluzione 2: usare una funzione anonima
Partiamo dalla versione corrente del codice:
Soluzione 2: usare una funzione anonima
Ridefiniamo vdp
in modo che riceva solo i parametri appropriati
Soluzione 2: usare una funzione anonima
Definiamo una funzione anonima con l’interfaccia richiesta da simulate
…
Soluzione 2: usare una funzione anonima
…E che non faccia altro che chiamare vdp
Soluzione 2: usare una funzione anonima
function es_vdp()
h = 0.1; % Spostato
mu = 1; % Spostato
T = 1:300;
X0 = [0.5, 0.5];
f = @(x, t) vdp(x, h, mu); % Chiama solo vdp!
X = simulate(@vdp, T, X0);
end
Quando f
viene eseguita, invoca vdp(x, h, mu)
x
è uno dei parametri di f
, ma h
e mu
nof
è definita!Useremo molto spesso le funzioni anonime in questo modo:
ftransition
ha solo i suoi parametri “naturali”…f
la “avvolge” (fa da wrapper)…simulate
Come al solito, trovate il codice nello start-kit
Consideriamo una variante dell’oscillatore di Van Der Pol
In particolare, vediamo la versione discretizza e “forzata”:
\[\begin{align} x^{(t+1)} &= x^{(t)} + h y^{(t)} \\ y^{(t+1)} &= y^{(t)} + h \left(\mu (1 - x^{(t)2})y^{(t)} - x^{(t)} - A \sin(\omega h t) \right) \\ \end{align}\]
Il termine \(A \sin(\omega h t)\) si dice guida (driver):
Il valore della guida non dipende dallo stato, ma solo dal tempo
Partendo dal file es_forced_vdp.m
nello start-kit:
Confrontate i risultati con l’oscillatore “normale” (in es_dp.m
):
Come differiscono i due andamenti? E le due traiettorie?
Ricordate il nostro esempio di random walk 1D?
Formalmente, era caratterizzato dalla ricorsione:
\[x^{(t+1)} = x^{(t)} + d\]
\[d = \left\{\begin{aligned} & +1 & \text{ con probabilità } p \\ & -1 & \text{ altrimenti} \end{aligned}\right.\]
Nel file es_walk.m
è definita la funzione di transizione, con interfaccia:
simulate
La nostra random walk è un esempio di sistema stocastico
Ma in media come si comporta il sistema?
Per determinarlo possiamo:
Per esempio possiamo:
Un istogramma è un grafico che si ottiene nel modo seguente:
Un esempio (l’altezza di un neonato, campione di 200 valori)
Un istogramma è un grafico che si ottiene nel modo seguente:
In Matlab potete usare:
Nel file es_many_walks.m
Come varia l’istogramma al variare di \(p\)?
arrayfun
arrayfun
Matlab fornisce la funzione:
f
ad ogni elemento nel vettore x
…y
Nel file es_arrayfun.m
si definisca una funzione:
…Che replichi il comportamento di quella di Matlab
Consideriamo un semplice modello per un utente web
Il nostro utente si comporta così:
Consideriamo un semplice modello per un utente web
Possiamo descrivere la rete come un grafo, e.g.:
Proviamo a tradurlo in equazioni
Per lo stato, facciamo una scelta un po’ strana:
All’inizio, tutte le pagine sono equiprobabili:
Proviamo a tradurlo in equazioni
Calcolare lo stato futuro vuol dire:
Formalmente, la probabilità \(x_i^{(t)}\) di essere su \(i\) al passo \(t+1\):
\[x_i^{(t+1)} = \underbrace{p}_{\text{mi stanco}} \overbrace{\frac{1}{n}}^{\text{reset}} + \underbrace{(1-p)}_{\text{non mi stanco}} \sum_{j = 1}^n \overbrace{x_j^{(t)}}^{\text{sono su $j$}} \underbrace{P_{i,j}}_{\text{link per $i$}}\]
Se ci fate caso, la funzione di transizione è lineare
Per i sistemi dinamici lineari, è comodo usare la notazione matriciale:
\[x^{(t+1)} = p \frac{1}{n} + (1-p) P x^{(t)}\]
Vogliamo definire un simulatore per il modello appena visto
Il file es_surfer.m
nello start-kit:
Definisce la funzione:
..Che implementa la ricorsione:
\[x^{(t+1)} = p \frac{1}{n} + (1-p) P x^{(t)}\]
Definite il codice di simulazione:
Le probabilità finali:
È esattamente quello per cui il modello di esempio è nato!
Sapete chi l’ha inventato?
BTW: l’algoritmo si chiama pagerank
Vogliamo utilizzare un sistema dinamico per prevedere il tempo
Supponiamo che (sommariamente) valgano le regole seguenti:
Per lo stato, ragioniamo di nuovo in termini di probabilità:
Per le transizioni, avremo:
\[\begin{align} x_g^{(t+1)} = x_g^{(t)} P_{g,g} + x_b^{(t)} P_{g,b} \\ x_b^{(t+1)} = x_g^{(t)} P_{b,g} + x_b^{(t)} P_{b,b} \end{align}\]
\[x^{(t+1)} = P x^{(t)} \quad \text{ con: } P = \left(\begin{array}{cc} P_{g,g} & P_{g,b} \\ P_{b,g} & P_{b,b} \\ \end{array}\right) \]
Si parta dal file es_weather.m
nello start-kit
Si definisca la funzione di transizione:
xc
è lo stato corrente (\(x_g^{(t)}, x_b^{(t)}\))…P
è la matrice \(P\) di transizione…Si sviluppi il codice di simulazione:
Sia data una popolazione che segue il modello logistico
\[x^{(t+1)} = r\, ^{(t)} \left(1 - \frac{x^{(t)}}{N}\right)\]
Dove:
Vogliamo studiare il comportamento del modello mediante simulazione
A partire dal file es_logi.m
nello start-kit:
Definite la funzione di transizione:
xf
xc
, e dai valori di r
e k
Definite il codice di simulazione:
r
e k
sono definiti nel codiceI modelli preda-predatore:
Tipicamente ci sono due elementi nel vettore dello stato:
Simulando il sistema:
Consideriamo questo modello preda-predatore:
\[\begin{align} & H^{(t+1)} = \overbrace{r \left(1 - \frac{H^{(t)}}{k} \right) H^{(t)}}^{\text{crescita logistica}} - \overbrace{s\, H^{(t)} P^{(t)}}^{\text{prede eliminate}} \\ & P^{(t+1)} = \underbrace{u\, P^{(t)}}_{\text{calo in assenza di prede}} + v \underbrace{\left( s\, H^{(t)} P^{(t)} \right)}_{\text{prede eliminate}} \end{align}\]
Nello start-kit, partite dal file es_logi_pp.m
Implementare la funzione di transizione:
xc(1)
sia il numero di prede e xc(2)
quello di predatoriDefinite il codice di simulazione nella funzione principale:
Provate a fare delle variazioni!
Aumentate e diminuite (solo) \(s\):
Aumentate e diminuite (solo) \(r\):
Aumentate e diminuite (solo) \(u\):
Riuscite a spiegare intuitivamente le ragioni?
Dopo una serata di bagordi, Gigi deve tornare a casa a piedi
Intuitivamente \(p\) controlla il livello di sobrietà
Vogliamo osservare il moto di Gigi nel tempo
Cosa è lo stato \(x^{(t)}\) per il nostro problema?
Lo \(X^{(t)}\) deve contenere abbastanza informazioni per determinare \(X^{(t+1)}\)
Lo stato è un vettore di due componenti:
\[X = (x, d)\]
…E vale la ricorsione:
\[\begin{align} & d^{(t+1)} = \left\{\begin{aligned} & d^{(t)} & \text{ con probabilità } p \\ & -d^{(t)} & \text{ altrimenti } \end{aligned}\right.\\ & x^{(t+1)} = x^{(t)} + d^{(t+1)} \end{align}\]
A partire dal file es_drunkard.m
nello start-kit:
Definite la funzione di transizione:
xc(1)
= posizione, xc(2)
direzione dell’ultimo spostamentoSimulate l’andamento della posizione di Gigi nel tempo:
Proviamo a studiare il “comportamento medio” di Gigi:
Nel file es_many_drunkards.m
, come nel caso della random walk:
Come varia l’istogramma al variare di \(p\)?
Nel file di funzione es_findidx.m
, definire la funzione:
function I = my_findidx(X, V)
X
scalare e V
vettore, che restituisca nel vettore I
…V
sono uguali a X
Per esempio:
for
Si verifichi la correttezza nella funzione principale es_findidx
:
randi
Come ottenere lo stesso risultato con le funzioni predefinite?
find
?Nel file di funzione es_mprod.m
, si definisca la funzione:
Si definisca una funzione:
A
e B
Si verifichi la correttezza:
Suggerimento: ogni prodotto riga/colonna è un prodotto scalare!
Nel file di funzione es_shift.m
, definite la funzione:
W
, identico a V
…Per esempio:
Verificate la correttezza:
Suggerimento:
W(ii)
con W(ii+1)
in sequenza