Approfondimento 1.1 Elaborazione dell’informazione • Elaborazione dell’Informazione (EI): richiede di risolvere problemi connessi con la ricerca e/o manipolazione di informazione. • Agente risolutore per problemi di EI: esecutore. • Informazione trattata in problemi di EI: dati. • Metodo risolutivo per problemi di EI: algoritmo1. Dati • Esecutore Algoritmo EI è parte della nostra vita quotidiana: es. ricerca di un numero di telefono. Algoritmo Nome Abbonato Esecutore Numero Abbonato Elenco Telefonico • Proprietà che definiscono un algoritmo: 1. Non ambiguità: le istruzioni devono essere univocamente interpretabili dall’esecutore. 2. Eseguibilità: l’esecutore deve essere in grado di eseguire ogni istruzione dell’algoritmo in tempo finito con le risorse a disposizione. 3. Finitezza: l’esecuzione dell’intero algoritmo deve terminare in tempo finito per qualunque insieme finito di dati trattati. • Ulteriore proprietà desiderabile: 4. Efficienza: l’algoritmo deve eseguire il minor numero possibile di istruzioni (⇒ deve terminare nel più breve tempo possibile). • 1 Possibili procedure per il problema della ricerca del numero di telefono: Algoritmo: deriva dal nome del matematico persiano al-Khowarismi (IX secolo DC) tradotto in latino come Algorismus. 1. Ricerca casuale: si aprono ripetutamente pagine a caso finchè non si trova quella che contiene il nome dell’abbonato. 2. Ricerca sequenziale: si sfoglia tutto l’elenco fino a trovare il numero dell’abbonato. 3. Ricerca binaria: assumendo che i nomi degli abbonati siano in ordine alfabetico, si apre l’elenco a metà e si vede se il nome cercato è nella prima o nella seconda metà ci si concentra su quella, ripetendo il ragionamento fino a trovare il punto in cui dovrebbe esserci il nome dell’abbonato. • • • Rispettano le proprietà? • Ambiguità: che fare se ci sono omonimi nell’elenco? • Eseguibilità: sì. • Terminazione: 1 no. 2 e 3 sì (ogni passo ci porta più vicino alla soluzione). • Efficienza: crescente per 1, 2, 3 Dati organizzati in strutture dati: es. elenco ordinato di nomi permette ricerca binaria. Es.: • Struttura dati: struttura di elenco telefonico ordinato • Dati: nomi e numeri dell’elenco Modellazione di un problema di EI: rappresentazione dei dati in strutture dati e dei procedimenti risolutivi mediante algoritmi. Es. un algoritmo risolutore funzionerà su qualunque insieme di dati presenti nell’elenco. • Livelli di astrazione: progettazione mediante raffinamenti successivi • Quanto è facile trovare un algoritmo efficiente per un problema? Esempi in ordine di difficoltà: 1. Dati due numeri, trovare il maggiore: facile… 2. Ordinare una sequenza di numeri: sono noti algoritmi ottimi. 3. Cercare i cammini più corti tra tutte le coppie di città in una rete stradale: esistono algoritmi efficienti, ma non si sa se sono ottimi. 4. Cercare il cammino più corto che passa per tutte le città di una regione: sono noti solo algoritmi estremamente lenti o algoritmi efficienti che formiscono soluzioni approssimate. 5. Scrivere tutti gli n per cui l’equazione Xn+Yn=Zn ha soluzioni X,Y,Z intere: non è noto nessun algoritmo (problema di Fermat). 6. Decidere se una funzione f(x)=cost per ogni x: è dimostrato che non è possibile progettare un algoritmo risolutore. Approfondimento 1.2 Elaborazione automatica dell’informazione • Elaborazione automatica dell’informazione: esecutore = elaboratore elettronico. • Esecutore umano: algoritmi e dati espressi in linguaggio naturale. • Esecutore meccanico: algoritmi e dati espressi in linguaggio di programmazione comprensibile alla macchina. • Un programma è (tipicamente) un testo scritto in un linguaggio di programmazione e contiene: • la codifica (o implementazione) di un algoritmo • la rappresentazione delle strutture dati da esso utilizzate. • Software: programmi e dati. • Hardware: componenti fisiche di un sistema di elaborazione automatica. • Cenni storici: http://mangrove.umd.edu/~alfredo/lectures/2.html. • Architettura di Von Neumann (anni ‘40): Hardware Periferiche Unità centrale di elaborazione Memoria principale E’ tutt’ora alla base dei moderni elaboratori elettronici. • Unità centrale di elaborazione = esecutore (CPU = Central Processing Unit) Esegue programmi scritti in Linguaggio Macchina. • Memoria principale = contenitore per dati e programmi (RAM = Random Access Memory). • Periferiche = dispositivi per l’ingresso e l’uscita di dati (schermo, tastiera, mouse, stampante ecc.) e memoria secondaria - o di massa - (dischi). • Gerarchie di linguaggi di programmazione: • Linguaggi di alto livello: Fortran, Prolog, Lisp, Cobol, Ada, Basic, Pascal, C, C++, JAVA ecc. • Hanno costrutti linguistici sofisticati che permettono di esprimere algoritmi e strutture dati in modo naturale. • Sono indipendenti dalla CPU dell’elaboratore usato: programmi potenzialmente portabili. • Linguaggi di basso livello: Assembly, Linguaggio Macchina • Istruzioni molto elementari che permettono solo di operare su numeri: difficissimo da usare. • Dipendono dalla CPU dell’elaboratore usato: programmi non portabili. • Permette di scrivere programmi estremamente veloci Linguaggi di alto livello Linguaggio macchina CPU (esecutore) 1. Due possibili approcci per l’uso di linguaggi di alto livello: 2. Compilatore: programma che traduce un programma in linguaggio di alto livello in programma in linguaggio macchina. Programma in Linguaggio di alto livello Compilatore Programma in Linguaggio macchina (programma eseguibile) CPU Programmi eseguibili in codice macchina sono veloci, ma non portabili. 3. Interprete: programma che esegue direttamente programmi scritti in linguaggio di alto livello, senza bisogno di traduzione in linguaggio macchina. Programma in Linguaggio di alto livello Interprete CPU Esecuzione programmi interpretati molto più lenta di quelli compilati, ma potenziale portabilità. 1. Linguaggi di programmazione: tipicamente compilati, programmi complessi. 2. Linguaggi di comandi e di script: tipicamente interpretati, programmi semplici e per uso interattivo del calcolatore. 1. Esistono più linguaggi di programmazione che linguaggi naturali. Per lo più fortemente specializzati (pochi general-purpose): Linguaggi per il WEB (HTML), linguaggi per la composizione dei documenti (LaTeX), per basi di dati (SQL), per programmazione di Robot (Lego MindStorm), per grafica 3D (VRML) ecc. ecc. 2. Esempi in 97 linguaggi di programmazione: http://www.uni-karlsruhe.de/~uu9r/lang/html/lang-all.en.html. 1. Il linguaggio Java sviluppato da Sun Microsystems negli anni ’90, astro nascente nel panorama dei linguaggi di programmazione. Linguaggio moderno: fa tesoro dell’esperienza maturata nel passato. 1. Approccio misto in JAVA: sia compilazione che interpretazione. Programma in Java Compilatore Java Programma in Java bytecode Java Virtual Machine Java Virtual Machine Java Virtual Machine Macintosh (CPU PowerPC) PC (CPU Intel Pentium) Sun (CPU SPARC) Garantisce portabilità su diverse piattaforme. 2. Tempo di compilazione: il tempo in cui un programma viene compilato. 3. Tempo di esecuzione: il tempo in cui un programma viene eseguito. • Sintassi dei linguaggi di programmazione: stabilisce le regole che definiscono in modo non ambiguo tutte le frasi esprimibili nel linguaggio. Gli errori di sintassi in un programma sono facili da scoprire poiché vengono individuati automaticamente dal compilatore al tempo di compilazione o dall’interprete a tempo di esecuzione. • Semantica dei linguaggi di programmazione: stabilisce il significato delle frasi corrette nel linguaggio. Gli errori di semantica sono più difficili da scoprire perché sono discrepanze accidentali rispetto alle intenzioni del programmatore. Essi inoltre si manifestano a tempo di esecuzione. Es. Un programma sintatticamente corretto che calcola la somma di due numeri è semanticamente scorretto se le intenzioni del programmatore erano di calcolare il prodotto di due numeri. • Esempi di programmi in differenti linguaggi di programmazione per stampare sullo schermo la scritta: “Hello World”. Assembly Intel 80X86 section .text _start: push dword len push dword msg push dword 1 mov eax, 0x4 call _syscall add esp, 12 push dword 0 mov eax, 0x1 call _syscall _syscall: int 0x80 ret msg db len equ "Hello World",0xa $ - msg C #include <stdio.h> main() { printf("Hello World\n"); } Java import java.io.* public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World"); } } Pascal PROGRAM HelloWorld; BEGIN WRITELN('Hello World'); END. Approfondimento 1.3 Modellazione mediante oggetti • I programmi sono basati su modelli di problemi. • Modello = rappresentazione semplificata, basata su elementi astratti. Es. Un programma che scrive “Hello World” modella i caratteri che vengono visualizzati sullo schermo, ma trascura eventualmente dettagli come colore, font, dimensione, posizione ecc. Es.: Modello di Gestione di un servizio di pronto intervento. • Oggetti ( 20 Riparatori, 1000 Clienti, 1 Smistatore) • Comportamento basato su scambio di messaggi: 4. Il Cliente richiede l'intervento allo Smistatore. 5. Lo Smistatore registra la chiamata, sceglie un Riparatore e gli comunica di eseguire il lavoro. 6. Il Riparatore comunica la conclusione dell'intervento. 1. Classi (Riparatori/Clienti/Smistatore) 1. Il nostro modello può omettere molti dettagli. Es. dettagli sulla natura del lavoro eseguito dal riparatore. 1. Oggetto = Istanza di una classe Cliente 1 Cliente 2 Cliente 3 Smistatore Riparatore 1 Cliente 1 Riparatore 2 Cliente 2 Cliente 3 Classe degli Smistatori Smistatore Riparatore 1 Classe dei Clienti Riparatore 2 Classe dei Riparatori 1. Proprietà di un modello: 1. Gli elementi di un modello rappresentano cose più complesse. Es. Pensiamo ai riparatori, clienti e smistatore come “oggetti”. 2. Gli elementi di un modello sono caratterizzati da un comportamento consistente. Es. I clienti chiamano lo smistatore, questi chiama i riparatori, che effettuano il lavoro. 3. Gli elementi di un modello possono essere raggruppati in differenti categorie basate sul loro comportamento comune. Es. Pensiamo a tutti gli oggetti che modellano clienti come appartenenti alla stessa classe. 4. Le azioni degli elementi di un modello avvengono su sollecitazione di azioni provocate da altri elementi del modello. Es. Un oggetto smistatore agisce solo quando riceve un messaggio da un oggetto cliente. Un oggetto riparatore agisce solo quando riceve un messaggio dall’oggetto smistatore. Programmazione orientata agli oggetti in Java 2. Scrivere un programma in Java consiste nello scrivere frasi che definiscono classi di oggetti. Ogni programma deve contenere almeno una classe. 2. Per ogni classe si possono prevedere più comportamenti possibili per i suoi oggetti: gli oggetti di una classe “sanno” fare più cose. 3. I comportamenti degli oggetti di una classe vengono programmati in Java scrivendo frasi chiamate metodi. Ogni metodo ha un nome per identificarlo e può contenere istruzioni per: 3. creare nuovi oggetti; 4. inviare messaggi ad oggetti, in modo da farli agire; 5. risolvere problemi algoritmici. Quindi a tempo di esecuzione un oggetto Java può creare altri oggetti, mandare loro messaggi, e risolvere problemi algoritmici. 2. Gli oggetti Java non sono entità astratte, ma hanno una evidenza fisica poiché occupano spazio nella memoria del computer quando un programma viene eseguito. 4. In Java gli oggetti creati vengono automaticamente distrutti quando non servono più: tecnologia software estremamente sofisticata! Questo rende Java molto diverso da altri linguaggi come Pascal, C, C++. Ecco perché Java non fornisce istruzioni per distruggere oggetti predecentemente creati. 3. Fortunatamente, Java mette a disposizione librerie con molte classi ed oggetti predefiniti che possiamo utilizzare nei nostri programmi per gli scopi più vari. 4. Analisi del programma HelloWorld.java. • “scrivere almeno una classe”: class HelloWorld { … Definizione della classe Corpo della classe HelloWorld HelloWorld } • “i metodi definiscono i comportamenti delle classi”: class HelloWorld { public static void main(String[] args) { … Definizione del metodo Corpo del metodo main main } } • “i metodi contengono istruzioni che definiscono un comportamento”: class HelloWorld { public static void main(String[] args) { Istruzione del metodo System.out.println("Hello World"); main } } • “inviare messaggi ad altri oggetti”: System.out . Riferimento oggetto destinatario println("Hello World") ; messaggio dove System.out è un oggetto predefinito della classe PrintStream. Un messaggio in Java è costituito dal nome del metodo invocato (es. println) e da dettagli tra parentesi (argomenti) che specificano ulteriori informazioni del messaggio (es. “Hello World”). • “Java mette a disposizione librerie”: import java.io.* System.out è un riferimento ad un oggetto predefinito della classe PrintStream definita nelle librerie java.io.*. • import, class, public, static, void sono alcune delle parole chiave (keywords) del linguaggio Java e sono parole prefissate definite dalla sintassi. • HelloWorld, main, String, args, System, out, println sono invece identificatori, parole definite dal programmatore per identificare univocamente di un programma classi, oggetti ecc. Gli indentificatori non sono parole prefissate definite dal linguaggio. • In Java gli identificatori validi sono qualunque sequenza di lettere e cifre inizianti per una lettera, purchè non sia una parola chiave. Es. Program1 è un identificatore valido, mentre 1Program e static non losono. • Diversamente dal Pascal, Java è “case sensitive” come il C e il C++. Cioè le lettere minuscole e maiuscole sono diverse. Es. System è un identificatore diverso da system e da sYsTeM. Allo stesso modo static è una parola chiave, mentre Static non lo è. Quindi Static è un identificatore valido. • Modello di esecuzione del programma HelloWorld: Oggetti predefiniti Messaggio println(“Hello World”) Classe HelloWorld System.out Classe PrintStream Messaggio main() java HelloWorld • Al momento dell’esecuzione del programma HelloWorld, ad esempio invocando il comando java HelloWorld, viene inviato il messaggio main() all’oggetto predefinito della classe HelloWorld che rappresenta il nostro programma. • L’esecuzione del metodo main consiste nell’invio del messaggio println(“Hello World”) all’oggetto predefinito System.out della classe PrintStream fornita dalle librerie Java. • L’esecuzione del metodo println provoca la stampa a video della scritta “Hello World”. 2. Nota Bene: ogni programma Java deve avere una classe “principale” (es. HelloWorld) che modella l’intero programma e che ha un metodo chiamato main che viene attivato automaticamente all’avvio del programma. 3. Il significato delle parole chiave public, static, void ed import usate nel programma HelloWorld verrà discussa più avanti nel corso. Lo stesso vale per la frase: String[] arg.