
Convoluzione e integrali (teoria)
L’operatore di convoluzione è spesso utilizzato nell’elaborazione dei segnali, dove modella l’effetto di un sistema lineare tempo-invariante su un segnale arbitrario. Nella teoria della probabilità, la somma di due variabili casuali indipendenti è distribuita secondo la convoluzione delle loro distribuzioni individuali, il che è l’esempio che riporteremo in seguito.
Convoluzione… nella pratica (teoria della probabilità)
Un approccio più utilitaristico alla convoluzione di quello precedente è quello (ispirato al canale Youtube 3blue1brown) di considerarla con la tecnica dell’anti-diagonalizzazione, ovvero: poniamo di avere due dati con numeri da 1 a 6, e di voler considerare di base tutte le possibili combinazioni di facce. Possiamo enumerarle in prima istanze, ed esse saranno:
- 1 e 1
- 1 e 2
- 1 e 3
- …
fino a 6 e 6, chiaramente.
È interessante notare che è possibile porre le facce del dado a sulle colonne e quelle del dado b sulle righe al fine di ottenere una matrice 6×6. Qui potete vedere il risultato, in cui per non perdere generalità abbiamo inserito a1 al posto di 1 sul primo dado, b1 al posto di 1 sul secondo dado e così via. La distribuzione degli indici non dovrebbe, in teoria, confondere: basta considerare come sono stati distribuiti sulla prima riga e sulla prima colonna, e prenderli come riferimento per ogni casella.
Se andiamo a considerare le anti-diagonali che ho evidenziato di seguito, vederemo che sono esattamente 11 in tutto. Esse rappresentano il meccanismo di ri-combinazione usato dalla convoluzione, che consiste nel sommare le componenti nelle varie combinazioni possibili. Sono combinazioni di lunghezza diversa, questa è la chiave per capire la convoluzione. Poi vengono sommati e a quel punto otterremo:
- a1 · b1
- a2 · b1 + a2 · b1
- a1 · b3 + a2 · b2 + a3 · b1
- a1 · b4 + a2 · b3 + a3 · b2 + a4 · b1
- …
- …
- …
- …
- …
- a5 · b6 + a6 · b5
- a6 · b6
Questo significa che la convoluzione di due variabili con 6 valori darà luogo ad una nuova serie di 11 variabili distinte.
Se ad esempio riduciamo la dimensione dell’istanza ai due vettori (1, 2, 3) e (4, 5, 6), le ricombinazioni saranno di 5 elementi (5 quanti sono le anti-diagonali di una matrice di dimensione 3×3, senza complicarci troppo il calcolo):
(1, 2, 3) * (4, 5, 6) = (1·4, 1·5+2·4, 1·6 + 2·5 + 3·4, 2·6 + 3·5, 3·6) = (4, 13, 28, 27, 18)
Convoluzione in Python
Per Python c’è la libreria numpy e la funzione predefinita convolve, come dicevamo. Essa restituisce la convoluzione discreta e lineare di due sequenze unidimensionali. Se v è più lungo di a, gli array vengono scambiati prima del calcolo.
Convoluzione in C++
Questo codice definisce una funzione convolution che prende due vettori di interi f e g e restituisce il risultato della convoluzione tra di essi. Si scorrono entrambi gli array per eseguire la convoluzione, considerando i valori degli array in posizioni adeguate e accumulando i risultati nella variabile result. Infine, il risultato della convoluzione viene stampato nel main.
#include <iostream>
#include <vector>
std::vector<int> convolution(const std::vector<int>& f, const std::vector<int>& g) {
int sizeF = f.size();
int sizeG = g.size();
int sizeResult = sizeF + sizeG - 1; // La dimensione del risultato della convoluzione
std::vector<int> result(sizeResult, 0);
for (int i = 0; i < sizeResult; ++i) {
for (int j = 0; j < sizeG; ++j) {
if (i - j >= 0 && i - j < sizeF) {
result[i] += f[i - j] * g[j];
}
}
}
return result;
}
int main() {
std::vector<int> f = {1, 2, 3};
std::vector<int> g = {4, 5, 6};
std::vector<int> result = convolution(f, g);
std::cout << "Risultato della convoluzione: ";
for (int val : result) {
std::cout << val << " ";
}
std::cout << std::endl;
return 0;
}