Analisi di Complessità degli Algoritmi

« Older   Newer »
 
  Share  
.
  1.  
    .
    Avatar

    Advanced Member

    Group
    Amministratore
    Posts
    8,544

    Status
    Offline

    Analisi di Complessità degli Algoritmi



    Una delle cose più importanti che ho imparato all'Università è valutare la complessità di un algoritmo ed è sicuramente un aspetto che fa la differenza tra un programmatore di medio-basso livello e uno invece di medio-alto.
    Finite le superiori ero consapevole che uno stesso risultato poteva essere ottenuto con algoritmi diversi, ma non avevo troppa idea che due algoritmi diversi possono risolvere lo stesso problema usando un numero di risorse radicalmente diverse.
    Imparare a creare algoritmi che ottimizzano il più possibile il consumo di risorse è fondamentale per chiunque voglia fare il programmatore.
    Ricordo che alla Laurea Triennale il mio professore di Algoritmi e Strutture Dati fece un esempio che mi colpì molto, immaginando due macchine: una con elevate prestazioni e l'altra invece con basse prestazioni.
    Sulla macchina potente è stato inserito la risoluzione di un algoritmo fortemente inefficiente, mentre sulla macchina più debole è stato inserito la risoluzione di un algoritmo fortemente efficiente: il risultato è stato che la macchina meno prestante ha calcolato più velocemente il risultato.
    Quindi non pensate di scampare alle vostre responsabilità di programmatori sperando solo in un miglioramento delle risorse hardware!

    I tipi di Complessità

    Per poter capire quante risorse consuma un nostro algoritmo è fondamentale distinguere due tipi di Complessità Computazionale:

    • Complessità Spaziale: Riferito alla memoria occupata da un algoritmo e quindi tiene conto di tutte le variabili che vengono usate dall'algoritmo, fortunatamente questo tipo di complessità è maggiormente gestibile dall'Hardware e anche dal programmatore, ad esempio ricorrendo alla deallocazione delle variabili che non servono durante l'algoritmo.

    • Complessità Temporale: Riferito al numero di istruzioni eseguite dal nostro algoritmo. Non fatevi confondere dal nome, i secondi non centrano nulla! Su questa i programmatori lavorano maggiormente ed è meno gestibile dall'Hardware


    Le tre tipologie di Scenari

    Talvolta gli algoritmi non richiedono sempre lo stesso numero di istruzioni o di memoria e quindi sostanzialmente la complessità computazionale può variare in un range di valori:

    • Caso migliore: Il numero minimo di istruzioni che un algoritmo può eseguire (indicato con Ω);

    • Caso medio: Il numero medio di istruzioni che un algoritmo può eseguire (indicato con Θ);

    • Caso peggiore: Il numero massimo di istruzioni che un algoritmo può eseguire (indicato con Ο)


    Ad esempio immaginiamo un algoritmo di ricerca lineare di un numero all'interno di un vettore di elementi.
    Il vettore è composto da N numeri, ad esempio N = 5:

    Vettore = [10,24,23,14,75]

    Se il numero che cerco è il valore 10 avrò il caso migliore poiché mi verrà restituito immediatamente il risultato.
    Se il numero che cerco è l'ultimo (75) oppure non è presente avrà eseguito 5 operazioni di confronto invece che 1 come al caso precedente.
    La media tra questi valori che posso individuare rappresenta invece il caso medio.

    In ambito informatico solitamente si analizzano i casi peggiori poiché sono quelli che riescono a creare una metrica di confronto tra algoritmi per valutare la loro efficienza.

    Un Esempio pratico

    Per aiutarvi a capire meglio vi riporto un esempio pratico che può aiutarvi a capire come funziona in modo molto elementare il calcolo della complessità temporale:

    Dato il seguente codice:

    HTML
    for(int i = 0; i<n; i++) {
    for(int j = 1; j<n; j++) {
    M1[i][j] = M2[i][j-1];
    }
    }


    Nella complessità temporale vengono conteggiate solamente le operazioni di confronto e di assegnamento, mentre le operazioni di dichiarazione di una variabile e di input/output non vengono conteggiate.

    In questo caso abbiamo un primo ciclo for che ha la seguente complessità computazionale:

    • i = 0 : comporta un'unica istruzione 1;

    • i < n : comporta n+1 confronti;

    • i++ : comporta n incrementi


    Quindi la complessità di questo primo ciclo for sarà: 1 + n + 1 + n = 2n + 2

    Mentre nel secondo ciclo for dobbiamo tenere conto che verrà eseguito n volte e quindi moltiplichiamo n per:

    • j = 1 : comporta un'unica istruzione 1;

    • j < n : comporta n confronti;

    • j++ : comporta n-1 incrementi;

    • M1[i][j] = M2[i][j-1] comporta un'unica istruzione


    Quindi la complessità del secondo ciclo for sarà: n * (1 + n + n - 1 + 1) = n * (2n + 1) = 2n2 + n

    Facendo la somma dei due cicli for: 2n + 2 + 2n2 + n = 2n2 + 3n + 2

    L'ordine di grandezza nel caso peggiore diventa O(n2) e quindi si tratta di una complessità polinomiale di tipo quadratica.

    Scala della Complessità:

    Spesso per semplificare la visualizzazione della complessità per chi fa parte del settore si usa l'ordine di grandezza per specificare vari tipi di scala: in questo caso ci sono i principali:

    • O(n!) con k>0 complessità fattoriale;

    • O(kn) con k>0 complessità esponenziale ;

    • O(nk) con k>0 complessità polinomiale (con k = 2 quadratica, con k = 3 cubica);

    • O(n·log n) complessità pseudolineare;

    • O(n) complessità lineare;

    • O(log n) complessità logaritmica;

    • O(k) complessità costante;


    • Impostando come valore di K = 2 e come valori di N i valori che vanno da 1 a 10 otteniamo il seguente grafico con i seguenti andamenti.
      Il grafico viene riportato in 3 parti evitando così di usare una scala logaritmica e semplificare anche a chi non ha conoscenze pregresse.

      Nella prima parte viene mostrato che la complessità fattoriale ottiene dei valori enormi, al punto da vedere tutte le altre funzioni attaccate sullo 0 dopo appena N = 7.

      Fattoriale



      Nella seconda parte viene rimossa la complessità fattoriale e potete notare comunque come una complessità esponenziale ottiene valori decisamente più alti di una complessità polinominiale all'aumentare di N.

      Esponenziale



      Nella terza parte viene rimossa anche la complessità esponenziale, mostrando la differenza fra le complessità rimanenti e come potete vedere quella che ottiene valori più alti all'aumentare di N è quella polinomiale.

      Polinomiale



      La differenza tra P e NP

      Fino alla complessità polinomiale si dice che i problemi sono trattabili e fanno parte della classe P.
      Verissimo che una complessità polinomiale può ottenere comunque valori molto alti e difficili da gestire per una macchina (ad esempio già una complessità polinomiale cubica può dare problemi) ma con un miglioramento dell'hardware è possibile aumentare molto il margine di miglioramento dell'esecuzione degli algoritmi.

      La classe NP invece è una classe molto ampia che non è alternativa alla classe P, anzi la contiene.
      In questa classe di problemi oltre alla classe P, rientrano tutti gli algoritmi che hanno una complessità superiore al polinomiale ma esiste un algoritmo polinomiale in grado di verificare la sua soluzione.
      Mi fermo su questa piccola introduzione che mi piacerebbe usare questo post come base per fare un interessante post su queste differenze tra P e NP!
     
    Top
    .
  2.  
    .
    Avatar

    Staff

    Group
    ForumFree Staff
    Posts
    109,420
    Location
    Slayer's Flag

    Status
    Anonymous
    troppo tecnico per gnogno
     
    Top
    .
  3.  
    .
    Avatar

    Un luogo dove qualcuno ancora pensa a te, quello è il luogo che puoi chiamare casa...

    Group
    Member
    Posts
    235

    Status
    Anonymous
    bel post, le immagini sono andate però
     
    Top
    .
  4.  
    .
    Avatar

    Advanced Member

    Group
    Amministratore
    Posts
    8,544

    Status
    Offline
    CITAZIONE (•Madda @ 31/8/2022, 21:59) 
    bel post, le immagini sono andate però

    Da telefono due non le visualizzavo, mentre da PC non ho problemi
     
    Top
    .
3 replies since 29/8/2022, 03:51   54 views
  Share  
.