Lezioni di Matematica ed Elettrotecnica

Cos'è un algoritmo e come si crea

Cenni storici sull'algoritmo

La storia degli algoritmi risale a molti secoli fa. La parola “algoritmo” deriva dal nome di un matematico persiano del IX secolo chiamato Al-Khwārizmī, che ha svolto un ruolo significativo nello sviluppo di concetti matematici e nell’introduzione di metodi algoritmici.

Tuttavia, l’uso di procedure e istruzioni per risolvere problemi è presente fin dai tempi antichi. Ad esempio, gli antichi matematici babilonesi e gli egizi utilizzavano metodi algoritmici per risolvere equazioni, calcolare aree e volumi, e persino per risolvere problemi di ottimizzazione.

Un importante contributo alla teoria degli algoritmi è stato dato da matematici indiani come Brahmagupta e Bhaskara nel V e nel XII secolo. Essi svilupparono metodi algoritmici per calcolare radici quadrate e risolvere equazioni di secondo grado.

 Tuttavia, uno dei momenti più significativi nella storia degli algoritmi è stato l’avvento dei calcolatori elettronici nel XX secolo. Durante la Seconda Guerra Mondiale, i pionieri dell’informatica come Alan Turing, John von Neumann e altri svilupparono algoritmi e metodi computazionali per risolvere problemi complessi e realizzare calcoli più rapidi ed efficienti.

Negli ultimi decenni, l’evoluzione della tecnologia informatica e l’avanzamento delle reti di computer hanno portato a una crescita esponenziale nel campo degli algoritmi. Oggi, gli algoritmi sono utilizzati in diversi settori come l’intelligenza artificiale, l’analisi dei dati, la crittografia, l’ottimizzazione, la simulazione e molti altri.

Inoltre, con l’avvento di Internet, gli algoritmi hanno acquisito un ruolo ancora più prominente nella nostra vita quotidiana. Sono utilizzati per alimentare i motori di ricerca, le piattaforme di social media, i sistemi di raccomandazione, i servizi di navigazione e molte altre applicazioni con cui interagiamo regolarmente.

La storia degli algoritmi è quindi una combinazione di sviluppi concettuali, teorici e tecnologici che hanno contribuito alla loro evoluzione nel corso dei secoli, consentendo di risolvere problemi complessi e facilitando la nostra interazione con il mondo digitale.

 Come si crea un algoritmo

Gli algoritmi sono ampiamente utilizzati nel campo dell'informatica e in molti altri settori, come la matematica, la fisica e l'ingegneria.

Un algoritmo è una strategia che serve per risolvere un problema ed è costituito da una sequenza finita di operazioni (dette anche istruzioni) che consente di risolvere tutti i quesiti di una stessa classe. Esso deve essere generale, effettivo, finito e deterministico. (Vedi il paragrafo "Proprietà dell'algoritmo", in basso)

Come si crea un algoritmo? Si seguono generalmente alcuni passaggi:

  1. Definizione del problema: Bisogna comprendere chiaramente il problema da risolvere o l'obiettivo da raggiungere. È importante stabilire i requisiti e le limitazioni dell'algoritmo.

  2. Analisi del problema: È necessario analizzare il problema in modo da comprendere le sue caratteristiche e determinare quali informazioni e risorse sono disponibili.

  3. Progettazione dell'algoritmo: Durante questa fase, si definisce la sequenza di passi logici necessari per risolvere il problema. Si utilizzano strutture di controllo come cicli, condizioni e iterazioni per gestire i dati e le operazioni necessarie.

  4. Implementazione dell'algoritmo: L'algoritmo viene tradotto in un linguaggio di programmazione specifico. Questo può essere fatto utilizzando un linguaggio di programmazione ad alto livello come Python, C++, Java, o qualsiasi altro linguaggio appropriato per il problema da risolvere.

  5. Test e debug: L'algoritmo viene eseguito con una serie di input di prova per verificare che produca i risultati corretti. In caso di errori o bug, si effettuano modifiche per correggere il problema.

  6. Ottimizzazione: L'algoritmo può essere analizzato e modificato per renderlo più efficiente, riducendo il tempo di esecuzione o l'utilizzo di risorse. Questo può coinvolgere la revisione della struttura dell'algoritmo o l'utilizzo di tecniche avanzate di ottimizzazione.

È importante sottolineare che la creazione di un algoritmo richiede una buona comprensione del problema da risolvere e delle conoscenze di programmazione necessarie per tradurre l'algoritmo in un linguaggio specifico. Inoltre, il processo di creazione di un algoritmo può richiedere iterazioni e miglioramenti successivi per raggiungere una soluzione efficace e efficiente.


La matematica studia gli algoritmi come schemi o procedimenti sistematici di calcolo per risolvere problemi o espressioni matematiche.

L’informatica studia gli algoritmi come specificazioni di sequenze finite di operazioni che consentono di realizzare sistemi informatici intelligenti in grado di simulare la capacità e il comportamento del pensiero umano.


Le proprietà dell'algoritmo

1. Generalità:

Un algoritmo si definisce generale quando è in grado di risolvere tutti i problemi appartenenti a una specifica classe di problemi. In altre parole, non deve essere progettato per risolvere un solo caso specifico, ma deve essere flessibile e adattabile a una varietà di situazioni simili.

Esempio:

  • Un algoritmo per ordinare una lista di numeri deve essere in grado di ordinare qualsiasi lista di numeri, indipendentemente dalla lunghezza, dai valori contenuti o dall'ordine iniziale.
  • Il codice in Python è:
    def ordinamento_bolla(lista):
      """
      Algoritmo di ordinamento a bolla che funziona per qualsiasi lista di numeri.
      """
      n = len(lista)
      for i in range(n-1):
        for j in range(n-i-1):
          if lista[j] > lista[j+1]:
            lista[j], lista[j+1] = lista[j+1], lista[j]
      return lista
    
    # Esempio di utilizzo
    lista_numeri = [5, 2, 4, 6, 1, 3]
    lista_ordinata = ordinamento_bolla(lista_numeri)
    print(lista_ordinata)

2. Effettività:

Un algoritmo è effettivo se, per ogni problema della classe a cui si applica, è in grado di fornire una risposta in un tempo finito. In altre parole, l'algoritmo deve terminare la sua esecuzione dopo un numero finito di passi, e non deve rimanere in un ciclo infinito.

Esempio:

  • Un algoritmo per calcolare il fattoriale di un numero non è effettivo se non specifica un numero massimo di iterazioni, in quanto potrebbe impiegare un tempo infinito per calcolare il fattoriale di numeri molto grandi.
  • Il codice in Python è:
    def calcolo_fattoriale(numero):
      """
      Algoritmo per calcolare il fattoriale di un numero, con un numero massimo di iterazioni.
      """
      if numero < 0:
        raise ValueError("Il numero deve essere positivo")
      
      fattoriale = 1
      for i in range(1, numero + 1):
        fattoriale *= i
      
      return fattoriale
    
    # Esempio di utilizzo
    numero = 5
    fattoriale = calcolo_fattoriale(numero)
    print(fattoriale)

3. Finitezza:

Un algoritmo è finito se è composto da un numero finito di istruzioni. Non deve essere possibile aggiungere o modificare le istruzioni durante l'esecuzione dell'algoritmo.

Esempio:

  • Un algoritmo per giocare a scacchi non è finito se permette ai giocatori di inventare nuove regole durante la partita.
  • Il codice in Python è simile a:
    def gioca_a_scacchi(scacchiera, numero_mosse_massimo):
      # Contatore mosse
      mosse_effettuate = 0
    
      # Ciclo while che termina quando si raggiunge il numero massimo di mosse o la partita termina
      while mosse_effettuate < numero_mosse_massimo and not partita_terminata(scacchiera):
        # Mossa del giocatore bianco
        mossa_bianco = input("Inserisci la tua mossa (es. e2e4): ")
        if mossa_valida(scacchiera, mossa_bianco):
          esegui_mossa(scacchiera, mossa_bianco)
          mosse_effettuate += 1
    
        # Mossa del giocatore nero
        mossa_nero = input("Inserisci la tua mossa (es. e7e5): ")
        if mossa_valida(scacchiera, mossa_nero):
          esegui_mossa(scacchiera, mossa_nero)
          mosse_effettuate += 1
    
      # Controlla se la partita è terminata
      if partita_terminata(scacchiera):
        # Stampa il vincitore o la patta
        ...
    
    # Funzione per eseguire una mossa sulla scacchiera
    def esegui_mossa(scacchiera, mossa):
      # ...
    
    # Funzione per controllare se una mossa è valida
    def mossa_valida(scacchiera, mossa):
      # ...
    
    # Funzione per controllare se la partita è terminata
    def partita_terminata(scacchiera):
      # ...

4. Determinismo:

Un algoritmo è deterministico se, a partire dagli stessi dati di input, produce sempre lo stesso risultato in uscita. In altre parole, l'algoritmo non deve essere influenzato da fattori esterni o casuali.

Esempio:

  • Un algoritmo per generare un numero casuale non è deterministico, in quanto il risultato in uscita sarà diverso ad ogni esecuzione. Mentre il calcolo della media di una lista di numeri dà lo stesso risultato a parità di input.
  • Il codice in Python è:
    def media(lista):
    somma = 0
    for numero in lista:
    somma += numero
    return somma / len(lista)

    lista_numeri = [10, 20, 30, 40, 50]
    media_risultato = media(lista_numeri)
    print(media_risultato) # Output: 30

Perciò, queste proprietà sono fondamentali per garantire che l'algoritmo sia efficiente, affidabile e produca risultati corretti.

In sintesi:

  • La generalità garantisce l'applicabilità a una varietà di problemi.
  • L'effettività assicura la terminazione in un tempo ragionevole.
  • La finitezza limita il numero di istruzioni.
  • Il determinismo garantisce la coerenza e la ripetibilità del risultato.