INF-LOG - Lez 1
INF-LOG - Lez 1
I received the Ph.D in Information Technologies (2021) and the Master Degree in Computer Engineering
(2017) both at the University of Parma.
In 2019 I have been Visiting Researcher at the Center for Applied Optimization (CAO) at the Herbert
Wertheim College of Engineering of the University of Florida (United States)
Since 2021 I am adjunct professor of Artificial Intelligence and Big Data at the University of Parma
○ Calcolo scientifico-ingegneristico
○ Gestione aziendale
○ Intelligenza Artificiale
○ Elaborazione dati
■ Marketing
■ Finanziari
■ Geografici e ambientali
○ Automazione industriale
○ Arte
○ Domotica
○ E-health
Gianfranco Lombardo, Ph.D ([email protected])
Arriviamoci per gradi
● Tuttavia l’Informatica non coincide con nessuna delle molteplici applicazioni dei calcolatori elettronici
○ Eppure accade spesso che i professionisti tendano ad essere così concentrati su di esse da
considerarle come l’essenza stessa dell’informatica
● Mito da sfatare: L’Informatica non è la scienza e la tecnologia dei calcolatori elettronici (computer)
● Quale è il punto in comune tra gli ambiti della slide precedente? In tutti, si ha la necessità di elaborare
delle informazioni per conseguire degli obiettivi tipici dell’ambito
● Non solo elaborazione! Per poter elaborare qualcosa si deve anche avere l’idea di ciò su cui vogliamo
lavorare
○ Si ha anche la necessità di rappresentare l’informazione per poterla elaborare
○ L’accento sull’informazione fornisce inoltre una spiegazione del perchè l’informatica stia
rapidamente diventando una parte integrante di tutte le attività, poiché in tutte vi è la necessità di
gestire qualche genere di informazione
■ L’informazione in altri ambiti è trattata in modo meno formale in altri ambiti, ad esempio il
giornalismo
■ Che si intende per “meno formale” e “maniera rigorosa”? Vediamo una seconda definizione
Gianfranco Lombardo, Ph.D ([email protected])
Definizione formale
● L’Informatica è la studio sistematico degli algoritmi che descrivono e trasformano l’informazione: la loro
teoria, analisi, progetto, efficienza, realizzazione e applicazione
● La definizione viene dalla Association for Computing Machinery (ACM) e sebbene sia decisamente più
complessa delle precedente vi è del tutto compatibile
● Non solo, questa definizione di Informatica mette anche in luce gli aspetti progettuali e realizzativi che
caratterizzano l’attività di un informatico
○ Analisi del problema
○ Progettazione di algoritmi per risolverlo
○ Sviluppo e realizzazione
○ Valutazione dell’efficienza
● L’amico, zio, cugino che smonta il computer o che lo formatta non è evidentemente un informatico :D
Gianfranco Lombardo, Ph.D ([email protected])
Il concetto di algoritmo
● Sequenza di passi, definiti con precisione, che portano alla realizzazione di un compito
● Difatti seguiamo algoritmi continuamente senza rendercene conto nella vita quotidiana
○ Come le informazioni sono rappresentate è cruciale affinchè l’esecutore possa comprendere i passi
da eseguire
■ Ikea taglia la testa al toro e per minimizzare i costi sceglie una rappresentazione grafica dei
propri algoritmi di montaggio di modo che possano essere comprensibili al maggior numero di
possibili esecutori
● Rinuncia a parte della precisione con una descrizione meno formale (ed infatti ogni
tanto non si capisce esattamente)
○ Come le informazioni sono rappresentate è cruciale affinchè l’esecutore possa comprendere i passi
da eseguire
■ Ikea taglia la testa al toro e per minimizzare i costi sceglie una rappresentazione grafica dei
propri algoritmi di montaggio di modo che possano essere comprensibili al maggior numero di
possibili esecutori
● Rinuncia a parte della precisione con una descrizione meno formale (ed infatti ogni
tanto non si capisce esattamente)
● Gli algoritmi vengono descritti tramite programmi: cioè sequenze di istruzioni scritte in un opportuno
linguaggio di programmazione che sia comprensibile al calcolatore
● Step 1
● Step 2
● Step 3
● Step 4
● Torna a
step 1
Rappresentazione con
Identificazione sequenza linguaggio di Esecuzione
(Problem solving) programmazione
Gianfranco Lombardo, Ph.D ([email protected])
Algoritmi e calcolatori elettronici
● Il vantaggio del calcolatore è che esegue tutti i passi dell’algoritmo in modo estremamente preciso e
veloce senza mai deviare dalla esecuzione, distrarsi o confondersi.
● Attenzione: Non devia dalla esecuzione neanche se quest’ultima è palesemente sbagliata o conduce ad
un risultato sbagliato
○ Il calcolatore è assolutamente privo di “buon senso”
○ E’ un mero esecutore che se istruito in modo preciso e non ambiguo riesce a svolgere molte
operazioni più velocemente di un essere umano
● Precisione e non ambiguità sono le qualità chiave che definiscono un algoritmo come “informatico”
○ La regola “Per fare una torta di mele occorrono tre chili di mele, tre uova e mezzo chilo di farina” si
può considerare sufficientemente precisa
○ La regola “ Legate l’arrosto con dello spago e salatelo” confida invece, per l’esecuzione, nel buon
senso del cuoco per determinare la quantità di sale necessario
● Un algoritmo è corretto se esso perviene alla soluzione del compito cui è preposto, senza difettare di
alcun passo fondamentale
○ Se l’algoritmo di montaggio della scrivania chiedesse di montare il piano orizzontale sui piedi del
mobile, chiedendo successivamente o dimenticandosi del montaggio delle gambe, sarebbe non
corretto.
● Un algoritmo è efficiente se perviene alla soluzione del problema nel modo più veloce possibile e/o
usando la minima quantità di risorse fisiche, compatibilmente con la sua correttezza.
○ Se l’algoritmo di montaggio ci chiedesse prima di montare i piedi del mobile, poi di fare altri passi,
poi di smontare i piedi e di rimontarli nuovamente dopo altri step, non sarebbe efficiente
● L’informatico cercherà sempre, nell’ambito di tutti gli algoritmi corretti che risolvono un certo problema, di
scegliere quello più efficiente
● La biblioteca è dotata di uno schedario. Ogni scheda che vi si trova contiene, nell’ordine:
○ cognome e nome dell’autore (se il libro ha più autori, sono riportati tutti i cognomi e nomi nello
stesso ordine in cui sono stampati sulla copertina del libro);
○ titolo del libro;
○ anno di pubblicazione;
○ numero dello scaffale in cui si trova;
○ numero dello scaffale in cui si trova
○ numero d’ordine della posizione attribuita al libro nello scaffale
● Supponendo di conoscere autore e titolo di un libro, definire l’algoritmo per accedere a tale libro nella
biblioteca
Gianfranco Lombardo, Ph.D ([email protected])
Algoritmo: Ricerca del libro
2. Una volta trovata questa, si segnano su un foglietto numero di scaffale e posizione del libro.
2. Una volta trovata questa, si segnano su un foglietto numero di scaffale e posizione del libro.
2. Una volta trovata questa, si segnano su un foglietto numero di scaffale e posizione del libro.
4. Una volta individuato lo scaffale, si accede alla posizione del libro, lo si preleva e, se richiesto, si scrive
sulla scheda la data del prestito e il nome di chi richiede il libro.
● Il primo passo però è un pò più complesso di come lo abbiamo formalizzato e necessita quindi di essere
espanso
● Basti pensare a quanto impiegheremmo, per eseguirlo, in una biblioteca di soli 1000 libri!
● Per fortuna, non è questo l’algoritmo che usiamo nella realtà; le operazioni che eseguiamo normalmente
per una ricerca più efficace del libro assomigliano di più all’algoritmo che segue:
3. In caso contrario, se la scheda cercata segue in ordine alfabetico quella presa in esame, si continua la
ricerca nella seconda metà dello schedario, altrimenti si continua la ricerca nella prima metà.
1. Il primo step da compiere nella realizzazione è analizzare il problema è scomporlo in macro problemi più
piccoli (sotto-problemi)
2. Raffinare i sotto-problemi fino a ricondurli a delle unità base che rappresentino singole operazioni
3. La sequenza che porta alla risoluzione di un problema non è univoca, ma possono esisterne molteplici
quindi bisogna individuare quella più efficiente
4. La sequenza di passi non è una strada a senso unico che viene percorsa dall’alto verso il basso:
a. Talvolta dobbiamo porre dei vincoli logici per determinare come proseguire
(“Se…allora…altrimenti”)
● Ci troviamo in auto e per recarci in luogo dobbiamo consultare una mappa (carta geografica o google
maps o navigatore). Per semplicità immaginiamo di essere negli anni 90 e di avere a disposizione solo
una cartina geografica del luogo.
○ Le regioni, i mari, i laghi oppure le montagne sono indicate tramite i loro confini, che ne danno una
riproduzione in scala.
○ Aiutano a comprendere la carta alcuni ausili visivi, per esempio la scelta dei colori di fondo delle
superfici: l’azzurro si usa per rappresentare superfici marine o lacustri, il verde per le pianure, il
marrone per le montagne.
● Le strade che uniscono le varie città sono descritte da linee che, approssimativamente, ne riproducono
l’andamento; il tratto utilizzato viene scelto in un insieme finito di tratti che denotano il tipo di strada
(autostrada, strada di grande comunicazione, strada secondaria ecc.).
● Infine, la lunghezza di un tratto di strada è indicata da un numero posto accanto alla linea che la
rappresenta
● ll problema di trovare la via più breve per andare in auto da una città all’altra può essere risolto mediante
un algoritmo.
c. Per ogni coppia di elementi contigui, < ci, ci+1 >, esista
un tratto di strada che li unisce
1. (Slide precedente)
2. Per ogni sequenza, si calcola la somma delle distanze dei vari tratti di strada e la si memorizza accanto
alla sequenza
3. Si individua la sequenza per cui il valore della somma delle distanze è minimo e la si sceglie come
strada più breve. Se per caso si trovasse più di un itinerario con la stessa distanza totale tra cp e ca, se
ne sceglierebbe uno arbitrariamente (per esempio il primo trovato). Se non si trova alcun itinerario, per
esempio perché cp e ca sono separate dal mare, non esiste alcuna soluzione.
● Tutti i punti necessitano di una ulteriore raffinazione in sotto-problemi, ma concentriamoci sul punto 1
● Trovare tutti gli itinerari che vanno da una città all’altra è a sua volta un problema che va risolto
mediante un opportuno algoritmo: possiamo chiamarlo un sottoproblema del problema principale,
perché la sua soluzione è necessaria per costruire la soluzione di quest’ultimo
● Se n è il numero di città riprodotte nella carta geografica, un itinerario che unisca cp a ca non può essere
costituito da un numero di tratti elementari superiore a n – 1:
○ infatti un itinerario con un numero superiore di elementi dovrebbe necessariamente passare per
una stessa città più di una volta, cosa che abbiamo escluso.
○ Basta quindi costruire tutti gli itinerari che partono da cp e hanno un numero di tratti non superiore
a n – 1, e scegliere tra questi quelli che terminano in ca
● Per costruire poi tutti gli itinerari che si dipartono da cp con un numero generico r di tratti si può usare il
seguente ragionamento:
○ Supponiamo di aver già trovato tutti gli itinerari che partono da cp e sono costituiti da r – 1 tratti
○ Otterremo gli itinerari di r tratti creando molte copie degli itinerari di r – 1 tratti e aggiungendo a
ciascuna copia un tratto ulteriore, che collega l’ultima città, cr-1, a tutte le città direttamente
collegate a essa, purché tali città non facciano già parte della sequenza originaria.
● Per iniziare, basta considerare come itinerario di lunghezza 0 un itinerario fittizio, che parte e arriva nella
città cp. A questo punto, gli itinerari di lunghezza 1 saranno tutti quelli che collegano cp alle città limitrofe,
cioè a quelle città direttamente collegate a cp da una strada.
● Abbiamo così definito i primi due passi di un algoritmo, che in n passi ci porta a generare tutti i percorsi
di n – 1 tratti che partono da cp, e quindi a risolvere il punto 1 dell’algoritmo generale
1. Partiamo da una sequenza iniziale, trascritta su un foglio di carta, che comprende la sola città cp; questa
sequenza è costituita, convenzionalmente, da 0 tratti
2. Esaminiamo le sequenze fin qui costruite, di r – 1 tratti. Chiamiamo S una generica sequenza {cp, c1,
c2, …, cr–1}
● Non è affatto detto che l’algoritmo che abbiamo trovato sia l’unica soluzione del problema, né tanto
meno la soluzione migliore; anzi, esiste una soluzione molto più efficiente del problema
● Non è ancora molto chiaro a che punto un algoritmo si possa ritenere sufficientemente specificato da
poter essere eseguito dal calcolatore
○ Come rappresento la cartina al calcolatore? come può consultarla per trovare i percorsi?
○ Prestazioni
○ Paradigma:
■ Programmazione strutturata
■ Programmazione ad oggetti
■ Programmazione funzionale
● Nella seconda metà degli anni Cinquanta, il linguaggio con cui l’uomo comunicava alla
macchina gli algoritmi cominciò ad “alzarsi di livello”, diventando in primo luogo più adatto
a codificare gli algoritmi e in secondo luogo molto più comprensibile; la fatica di tradurre il
programma nel linguaggio della macchina fu affidata alla macchina stessa (attraverso i
compilatori)
○ Analogica
● Esempio
○ La tensione prodotta dal microfono è tanto più alta quanto più elevato è il livello del suono.
○ ogni quantità è approssimata da una sequenza finita di dati (numeri), ciascuno dei
quali può assumere solo un numero finito di valori.
● I circuiti di un calcolatore lavorano a due diversi livelli di tensione (di solito 0 e 5 Volt, ma
anche 0 e 3.3 Volt)
○ I 2 livelli rappresentano, in generale, due SIMBOLI diversi, a cui associare due diversi
significati.
Es. Vero/Falso
Positivo/Negativo
Presenza/Assenza
● Rappresentazione di numeri.
● Il valore del numero dipende non solo dalla quantità rappresentata dai simboli, ma anche
dalla posizione in cui si trovano.
1 Byte = 8 bit
Nota importante:
Nota importante:
■ Tutti gli altri possibili valori nell’intervallo sono approssimati con il valore
rappresentabile più vicino
Con N bit posso rappresentare qualunque insieme numerabile (cioè che può
essere messo in corrispondenza con gli interi) di simboli.
Con due bit è possibile generare 4 configurazioni distinte (00, 01, 10, 11) che
possono essere associate a 4 informazioni distinte
Esempi di insiemi diversi di informazioni rappresentabili:
00 -> a 1 verde
01 -> b 2 rosso
10 -> c 3 giallo
11 -> d 4 blu
Codifica di caratteri
26 lettere minuscole e 26 lettere maiuscole, 10 cifre, 10 segni
aritmetici, 20 segni di interpunzione (spazi inclusi) e 3
caratteri non stampabili (a capo, tabulazione, backspace) =
95 caratteri, che rappresentano la lingua Inglese
Codifica di caratteri
26 lettere minuscole e 26 lettere maiuscole, 10 cifre, 10 segni
aritmetici, 20 segni di interpunzione (spazi inclusi) e 3
caratteri non stampabili (a capo, tabulazione, backspace) =
95 caratteri, che rappresentano la lingua Inglese
Codifica di caratteri
Per 95 simboli sono necessari 7 bit: ⎡log295⎤ =7
A metà degli anni ‘60 divenne chiaro che il codice a 7 bit non bastava per
rappresentare anche i caratteri dei linguaggi diversi dall’inglese
● Il linguaggio macchina è basato su un alfabeto detto binario in quanto comprende due soli simboli,
generalmente indicati con 0 e 1
○ Un simbolo di questo alfabeto viene detto bit.
● I codici operativi e i dati nel linguaggio macchina sono pattern (stringhe) di bit.
● Come nelle lingue naturali, nel linguaggio macchina i simboli dell'alfabeto utilizzato (1 e 0) sono
organizzati in "parole" che a loro volta costituiscono "frasi".
● Le frasi del linguaggio macchina sono dette istruzioni; ognuna di esse ordina al processore di eseguire
un'azione elementare afferente allo stato interno del computer, come la lettura di una locazione di
memoria oppure il calcolo della somma dei valori contenuti in due registri.
● Le frasi sono generalmente costituite da una parola iniziale detta codice operativo iniziale, che indica il
tipo di azione da eseguire, seguita da altre parole che specificano gli eventuali parametri (o dati) a cui
l'azione deve essere applicata
● E’ il “livello più basso” nella piramide di astrazione poichè non astraiamo rispetto
alla architettura hardware della macchina
○ Ciò che scrivo va bene per un intel-i9 ma non per un intel i5 o un AMD
MODEL SMALL
STACK 100H
.DATA
HW DB "hello, world", 13, 10,
'$'
.CODE
.STARTUP
MOV AX, @data
MOV DS, AX
MOV DX, OFFSET HW
MOV AH, 09H
INT 21H
MOV AX, 4C00H
INT 21H
END
● Tutto ciò che deve essere eseguito risiede nella memoria centrale, che nelle architetture
moderne è chiamata memoria RAM (Random Access Memory)
● Ogni qual volta un set di istruzioni deve essere eseguita la macchina svolge il seguente
ciclo di funzionamento:
○ L’unità di elaborazione, che coordina le varie attività, estrae istruzioni dalla memoria
○ le decodifica comprendendo il loro significato
○ le esegue tramite opportune funzioni all’interno dell’architettura del calcolatore
■ Svolge gli opportuni calcoli prelevando i dati sempre dalla memoria, svolge le
operazioni in binario e se richiesto memorizza i risultati in una ulteriore cella di
memoria
● I trasferimenti tra elementi funzionali diversi avvengono sempre tramite il bus di sistema
che, in funzione dell’operazione in atto, effettua il collegamento logico tra i vari elementi
funzionali coinvolti nel trasferimento (mentre il collegamento fisico è sempre presente).
● Durante ciascun intervallo di tempo una parte dell’unità di elaborazione (detta unità di
controllo) coordina l’esecuzione temporale delle funzioni che verranno svolte
internamente all’unità di elaborazione stessa o negli altri elementi funzionali.
■ La cella di memoria con tale indirizzo contiene il valore della variabile che ci
interessa.
var1
10
0CFB14A3
■ Nota: ogni cella è 1 byte, ma spesso i dati sono più grandi, es. per
rappresentare un numero intero servono 4 byte.
■ Una variabile quindi in realtà identifica sia l’indirizzo della prima cella, che il tipo
di valore che rappresenta.
■ Per leggere un intero devo quindi leggere 4 celle contigue, mettere insieme i
valori e decodificarli.
■ Nota: ogni cella è 1 byte, ma spesso i dati sono più grandi, es. per
rappresentare un numero intero servono 4 byte.
■ Una variabile quindi in realtà identifica sia l’indirizzo della prima cella, che il tipo
di valore che rappresenta.
■ Per leggere un intero devo quindi leggere 4 celle contigue, mettere insieme i
valori e decodificarli.
MODEL SMALL
STACK 100H
.DATA
HW DB "hello, world", 13, 10,
'$'
.CODE
.STARTUP
MOV AX, @data
MOV DS, AX
MOV DX, OFFSET HW
MOV AH, 09H
INT 21H
MOV AX, 4C00H
INT 21H
END
● Nella seconda metà degli anni Cinquanta, il linguaggio con cui l’uomo
comunicava alla macchina gli algoritmi cominciò ad “alzarsi di livello”, diventando
in primo luogo più adatto a codificare gli algoritmi e in secondo luogo molto più
comprensibile; la fatica di tradurre il programma nel linguaggio della macchina fu
affidata alla macchina stessa
● Poiché allora l’uso principale dei calcolatori consisteva nel risolvere problemi di
calcolo numerico, il primo linguaggio di alto livello per la programmazione dei
calcolatori fu il Fortran (nome che deriva dall’originario acronimo FORTRAN, che
stava per FORmula TRANslator), particolarmente adatto a descrivere
l’elaborazione di formule matematiche.
● COBOL e Fortran sono rimasti per lungo tempo i linguaggi di programmazione più
diffusi specie perchè utilizzati nei mainframe
● Poiché allora l’uso principale dei calcolatori consisteva nel risolvere problemi di
calcolo numerico, il primo linguaggio di alto livello per la programmazione dei
calcolatori fu il Fortran (nome che deriva dall’originario acronimo FORTRAN, che
stava per FORmula TRANslator), particolarmente adatto a descrivere
l’elaborazione di formule matematiche.
● COBOL e Fortran sono rimasti per lungo tempo i linguaggi di programmazione più
diffusi specie perchè utilizzati nei mainframe
● Esiste poi una categoria di linguaggi più rigorosamente basati su uno studio dei
principi della programmazione. Il “capostipite” di tali linguaggi è l’ALGOL
(ALGOrithmic Language) 60, che proprio per questo ha grande importanza, pur
non essendo mai stato molto utilizzato nella pratica. I linguaggi più noti di questa
famiglia sono:
○ il Pascal, introdotto inizialmente con scopi prettamente didattici, ma che ha
conosciuto anche un notevole successo in ambito industriale;
● Ciò ha portato naturalmente alla nascita di linguaggi basati su questo stile, detti
appunto linguaggi orientati agli oggetti. Tra essi menzioniamo:
○ C++
○ C# (letto C Sharp)
○ Java
● Abbiamo introdotto l’Assembly: ne esiste però uno per ogni tipo di processore