Risoluzione di Problemi con gli algoritmi Ricorsivi

Slides:



Advertisements
Presentazioni simili
Dall’informazione al linguaggio macchina
Advertisements

Microsoft Excel I riferimenti.
MULTIVIBRATORI BISTABILI
Algoritmi e Strutture Dati
Informatica Generale Marzia Buscemi IMT Lucca
Un esempio di complessità computazionale
Rappresentazioni numeriche
Algebra di Boole e Funzioni Binarie
Capitolo 8 Sistemi lineari.
Problemi di soddisfacimento di vincoli Maria Simi a.a. 2005/2006.
Macchine sequenziali Capitolo 4.
Programmazione dinamica
Alberi binari di ricerca
1 Istruzioni, algoritmi, linguaggi. 2 Algoritmo per il calcolo delle radici reali di unequazione di 2 o grado Data lequazione ax 2 +bx+c=0, quali sono.
Algebra binaria Luglio 2002 Luglio 2002 Algebra binaria.
Gli alberi binari sono contenitori efficienti.
Fogli elettronici Microsoft Excel.
Capitolo 4 Ordinamento Algoritmi e Strutture Dati.
Circuiti di memorizzazione elementari: i Flip Flop
Algoritmi Paralleli e Distribuiti a.a. 2008/09 Lezione del 05/05/2009 Prof. ssa ROSSELLA PETRESCHI a cura del Dott. SAVERIO CAMINITI.
Algoritmi Paralleli e Distribuiti a.a. 2008/09 Lezione del 06/03/2009 Prof. ssa ROSSELLA PETRESCHI a cura del Dott. SAVERIO CAMINITI.
Informatica 3 Codifica binaria.
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Capitolo 1 Unintroduzione.
A.S.E.13.1 ARCHITETTURA DEI SISTEMI ELETTRONICI LEZIONE N° 13 Somma e differenza di due numeri in C2Somma e differenza di due numeri in C2 Half AdderHalf.
A.S.E.6.1 ARCHITETTURA DEI SISTEMI ELETTRONICI LEZIONE N° 6 Complemento a MComplemento a M Rappresentazione di numeri con segnoRappresentazione di numeri.
A.S.E.5.1 ARCHITETTURA DEI SISTEMI ELETTRONICI LEZIONE N° 5 Rappresentazione di numeri con segnoRappresentazione di numeri con segno –Modulo e segno (MS)
Automi Cellulari Def. formale di AC e di AC unidimensionale
Automi Cellulari Automi Cellulari Binari Unidimensionali con r>1
Algoritmi e Strutture Dati (Mod. B)
Algoritmi e strutture dati
Ricerca della Legge di Controllo
Codici binari decimali
Introduzione alla programmazione ll
Sistemi Peer To Peer (P2P) Avanzati Gennaro Cordasco Gennaro Cordasco
Algoritmi e Strutture Dati
Lezione 5. Ricapitolando…. Sistemi P2P puri Sistemi UniformiSistemi Non uniformi Abbiamo detto abbastanza KoordeNeighbor of Neighbor routing (NON)
Ricapitolando…. Sistemi P2P puri Sistemi UniformiSistemi Non uniformi Abbiamo detto abbastanza KoordeNeighbor of Neighbor routing (NON)
Lezione 5 Domande: Laverage path length di Chord con 2^b identificatori e N=2^b nodi è (giustificare la risposta) Laverage path length di Chord con 2^b.
Semantica per formule di un linguaggio proposizionale p.9 della dispensa.
Unità Didattica 1 Algoritmi
Cos’è un problema?.
Display a 7 segmenti Il display a 7 segmenti è un dispositivo composto da 7 diodi luminosi LED (Light-Emitting Diode) sagomati a forma di rettangolo o.
EXCEL FORMATTAZIONE DATI.
Cos’è una sequenza? Una sequenza è una successione finita di valori, dove ogni valore ha una durata prefissata e costante (T). I valori della sequenza.
Rappresentazione dell’informazione
Esercitazione no. 5 EXCEL Laboratorio di Informatica AA 2009/2010.
Rete Asincrona Una rete sequenziale asincrona è dotata di due ingressi E, X e di una uscita Z. L'uscita Z deve diventare 1 solamente quando durante l'ultima.
Diagramma degli stati che descrive il comportamento della rete.
Modulo 4 - Excel.
Merge-Sort(A,p,r) if p < r q = (p+r)/2 Merge-Sort(A,p,q)
Riferimenti di cella.
Progressioni aritmetiche descrizione elementare
Milano, 17 Dicembre 2013 Informatica B Informatica B Matlab Laboratorio del 14/01/2014 Responsabili di laboratorio: Gianluca Durelli:
Corso di Informatica - Foglio elettronico - Raffaele Grande
Corso di Informatica Corso di Laurea in Conservazione e Restauro dei Beni Culturali Gianluca Torta Dipartimento di Informatica Tel: Mail:
Complessità di un algoritmo
Corso di Informatica Corso di Laurea in Conservazione e Restauro dei Beni Culturali Gianluca Torta Dipartimento di Informatica Tel: Mail:
Linguaggi e Programmazione per l’Informatica Musicale
1/11/2015E. Giovannetti -- OI09.1 Olimpiadi di Informatica 2010 Giornate preparatorie Dipartimento di Informatica Università di Torino marzo –
Grafi CORDA – Informatica A. Ferrari Testi da Marco Bernardo Edoardo Bontà Dispense del Corso di Algoritmi e Strutture Dati.
Soluzione: Algoritmo Heap-Sort Un array A[1..n] può essere interpretato come un albero binario: A[1] è la radice, A[2i] e A[2i+1] sono i figli di A[i]
Lezione 13 Riccardo Sama' Copyright  Riccardo Sama' Excel: formule e funzioni.
ALGORITMO Un algoritmo è un procedimento che risolve un determinato problema attraverso un numero finito di passi. Un formalismo che permette di rappresentare.
Rappresentazione dell’Informazione
Un problema Progettare un programma per calcolare se un qualsiasi altro programma contiene un ciclo infinito –Ciclo infinito: per esempio, eseguire le.
Problemi di soddisfacimento di vincoli Maria Simi a.a. 2008/2009.
Algoritmi e Programmazione (in C) Stefano Cagnoni e Monica Mordonini
Camil Demetrescu, Irene Finocchi, Giuseppe F. ItalianoAlgoritmi e strutture dati Copyright © The McGraw - Hill Companies, srl 1 Capitolo 1 Un’introduzione.
Suggerimenti [1d5] SE la prima lettera della matrice (in alto a sinistra, matrice[0,0]) è diversa dalla prima lettera della parola (parola[0]) ALLORA siamo.
Classe IV B plesso di Ripalimosani A.S
Transcript della presentazione:

Risoluzione di Problemi con gli algoritmi Ricorsivi Laboratorio di Algoritmi e Strutture Dati Risoluzione di Problemi con gli algoritmi Ricorsivi Proff. Francesco Cutugno e Luigi Lamberti 2009-2010

Problem Solving Sia assegnato un Problema (useremo anche il termine Sistema) rappresentato da : un insieme (finito) di variabili discrete V = {X1, X2, … Xn} ciascuna associata ad un dominio D1, D2, … Dn un insieme di vincoli (relazioni tra variabili): R = {C1, C2,… Cm} Lo Stato è una combinazione dei valori delle variabili che definiscono il problema {Xi = vi  i=1,n} ; Lo Spazio degli Stati, insieme di tutte le possibili combinazioni dei suddetti valori, non coincide con il semplice prodotto cartesiano dei domini, per la presenza dei vincoli. Lo Stato Iniziale è la condizione di partenza del nostro problema (in base alla formulazione fissata).

Un’Azione (o mossa legale) è l’assegnazione di un valore ad una variabile nel rispetto dei vincoli; la modifica di una variabile, porta il Sistema descritto da uno stato ad un altro (transizione). Il numero delle azioni possibili (input del Sistema) è limitato superiormente dalla cardinalità del prodotto dei domini. La Soluzione (o Stato Obiettivo) è una particolare assegnazione completa delle variabili, soddisfacente tutti i vincoli; la soluzione può non essere unica. Un Processo è la sequenza di azioni che conduce il Sistema da uno stato ad un altro; il Processo risolutivo, sarà la sequenza di azioni per giungere dallo Stato iniziale allo Stato Finale atteso.

Diagramma degli Stati Stato1 A1 A2 A4 Stato2 Stato3 Stato4 A3 A5 A6 A7 L’evoluzione di un Sistema è descritta da un Grafo con un Nodo per ciascuno stato e un Arco uscente per ogni azione possibile in quello stato: la destinazione indica la transizione effettuata. Il diagramma degli stati diventa improponibile al crescere della complessità del problema. Il grafo può contenere cicli e può essere complicato dimostrare che l'algoritmo di ricerca termina.

Albero di Ricerca Stato1 Stato2 Stato3 Stato4 Stato5 Stato6 Stato7 A1 A2 A3 A4 A5 A6 A7 La gestione del problema è rappresentabile anche tramite un albero (che chiameremo Albero di Ricerca) ove la radice è lo Stato Iniziale, mentre le eventuali soluzioni sono da ricercarsi nelle foglie. Si elimina il problema dei cicli, ma lo stesso nodo potrebbe essere generato più volte.

Salvare Pecora e Cavoli Problema: un Agricoltore va al mercato con un Lupo, una Pecora e un grosso Cavolo; deve attraversare un fiume su una barca tanto piccola da poter portare un solo oggetto per volta. Variabili: detto 0 il lato di partenza del Fiume e 1 il lato di arrivo, avremo 4 variabili, ciascuna con due possibili valori: A  {0,1}, L  {0,1}, P  {0,1}, C  {0,1} Vincoli: Lupo, Pecora e Cavolo non sanno attraversare il fiume da soli; il Lupo mangia la Pecora, se non c’è l’Agricoltore la Pecora mangia il Cavolo, se non c’è l’Agricoltore. Azioni: l’Agricoltore può attraversare il fiume da solo (A = 1-A), o con un passeggero A=1-A L=1-L, A=1-A P=1-P, A=1-A C=1-C, che sia dal suo stesso lato (non tutte le azioni sono legali). Spazio Stati: Abbiamo 16 stati possibili con le combinazioni ALPC. 0000 è lo stato iniziale; 1111 è lo stato obiettivo (finale); 0110, 0011, 0111, 1001, 1100, 1000 sono stati da evitare; i restanti sono possibili stati intermedi

0 000 A 1 100 1 010 1 001 AL AC 1 000 0 010 1 110 0 100 0 011 1 011 0 001 1 101 0 110 0 111 0 101 1 111 AP

Backtracking Partendo dallo stato raggiunto, ad ogni passo si assegna un valore ad una variabile, rispettando i vincoli, eseguendo così una Transizione : Se è stato raggiunto lo stato finale, segnaliamo la soluzione. Se è possibile avanzare ulteriormente, ripetiamo l’analisi partendo dallo stato attuale. In caso di fallimento (vicolo cieco, violazione dei vincoli, ritorno ciclico ad un nodo già visitato) si torna indietro. Se si ritorna allo stato iniziale senza aver trovato la soluzione, vuol dire che il problema è irrisolubile Supponiamo che il problema non preveda possibili percorsi ciclici, possiamo ipotizzare il seguente algoritmo:

funzione Ricerca ( Stato_Attuale ) { Risultato = ‘Fallimento’ E = Elenco Azioni possibili secondo i vincoli // mosse legali per ogni Azione A  E, mentre Risultato = ‘Fallimento’ { Esegui A se Nuovo_Stato = Stato_Obiettivo Risultato = ‘Soluzione’ altrimenti Risultato = Ricerca ( Nuovo_Stato ) se Risultato = ‘Fallimento’ Annulla esecuzione di A // backtracking } restituisci Risultato }

Sudoku Usiamo una griglia quadrata di 81 celle: 9 righe orizzontali per 9 colonne verticali; inoltre, la griglia è divisa in 9 riquadri 3x3 (gruppi) di 9 celle ciascuno. Ciascuna riga, colonna e riquadro 3x3 contiene tutti i numeri da 1 a 9. Pertanto in nessuna riga, colonna o riquadro può esserci un numero ripetuto. Nella matrice, ogni cella vale 0 se è libera, da 1 a 9 se occupata. Chiameremo Gruppi i 9 riquadri 3x3 interni. Detta (r,c) una cella della Tavola, le coordinate della cella in alto a sinistra del suo gruppo di appartenenza saranno: rg = (r / 3) * 3 = r - r % 3 cg = (c / 3) * 3 = c - c % 3 Il gruppo sarà composto dalle nove celle (i,j) con rg <= i <= rg+2 e cg <= j <= cg+2

/*======================================================= Esempio base per la risoluzione di un Sudoku. Manca un’interfaccia utente e il caricamento dello schema iniziale --------------------------------------------------------*/ main (void) { int Tav [9][9], // Tavola di gioco Nvuote; // Numero di caselle vuote nella tavola IniziaTavola (Tav, &Nvuote); StampaTavola (Tav); if (Nvuote<1 || !VerificaVincoli(Tav)) printf("\n Il problema e` mal posto ! \n"); else if (! CercaSudoku(Tav,Nvuote) ) printf("\n NON esistono soluzioni ! \n"); else { printf("\n Soluzione trovata. \n"); StampaTavola (Tav); } getch();

/* Esamina la tavola, con ALMENO con una cella vuota, provando a riempire una qualsiasi cella vuota, ove il valore sia possibile. OUTPUT: 1 soluzione trovata e copiata sulla Tavola da gioco 0 nessuna soluzione possibile -----------------------------------------------------------------*/ int CercaSudoku ( int Tav[][9], // Tavola da esaminare int Nvuote // Numero di caselle vuote nella tavola > 0 ) { int r, c, // riga e colonna della cella da occupare N, // valore da inserire i, j, Trovato = 0; r = -1; for (i=0 ; i<9 && r == -1 ; i++) // cerca una cella vuota for (j=0 ; j<9 && r == -1 ; j++) if (Tav[i][j] == 0) {r=i; c=j;} // termina se trova una vuota for (N=9; N && !Trovato; N--) if ( VerificaLegalita(Tav, r, c, N) ) // se è possibile inserire N { Tav[r][c] = N; // se era l'ultima casella vuota, la soluzione è stata trovata Trovato = (Nvuote == 1) ? 1 : CercaSudoku (Tav, Nvuote-1); // se non è praticabile, annulla la mossa (backtracking) if (! Trovato) Tav[r][c] = 0; } return Trovato;

/* Valuta la legalità di un inserimento di un nuovo valore in una casella vuota, esaminando la riga la colonna e il gruppo. OUTPUT: 0 non è possibile inserire il valore nella cella 1 il gioco può proseguire alla ricerca di soluzioni ---------------------------------------------------------------*/ int VerificaLegalita ( int Tav[][9], // Tavola di gioco int r, int c, // riga e colonna della cella da occupare int N // valore da inserire ) { int i, j, rg, cg, // angolo del gruppo di appartenenza Congrua; // 0 = tavola inconguente Congrua = 1; for (j=0; j<9; j++) // esamina la riga if (Tav[r][j] == N) Congrua = 0; for (i=0; i<9; i++) // esamina la colonna if (Tav[i][c] == N) Congrua = 0; rg = r - r % 3; // esamina il riquadro cg = c - c % 3; for (i=0; i<3; i++) for (j=0; j<3; j++) if (Tav[rg+i][cg+j] == N) Congrua = 0; return Congrua; }

/*------------------------------------------------------------ Valuta la congruenza dell`intero schema di gioco OUTPUT: 0 La tabella contiene incongruenze 1 il gioco può proseguire alla ricerca di soluzioni --------------------------------------------------------------*/ int VerificaVincoli ( int Tav[][9] // Tavola di gioco ) { int r, c, N, Congrua = 1; // 0 = tavola inconguente for (r=0 ; r<9 ; r++) for (c=0 ; c<9 ; c++) if ( Tav[r][c] ) // esaminiamo ogni elemento gia` inserito { N = Tav[r][c]; Tav[r][c] = 0; Congrua &= VerificaLegalita (Tav, r, c, N); Tav[r][c] = N; } return Congrua;

Problemi di ottimizzazione Occorre cercare la migliore tra più soluzioni possibili, secondo una certa metrica. Il fallimento varrà -∞ funzione Ricerca ( Stato_Attuale ) { E = Elenco Azioni possibili secondo i vincoli V = elenco dei valori corrispondenti a ciascuna azione per ogni Azione Ai  E { Esegui Ai se Nuovo_Stato = Soluzione Vi = Valore della Soluzione altrimenti Vi = Ricerca ( Nuovo_Stato ) } se E ≠  Risultato = max (Valori) altrimenti Risultato = -∞ (Fallimento) restituisci Risultato }

Giochi con Avversario I Giochi a 2 giocatori “a conoscenza completa ” devono avere le seguenti caratteristiche: Il gioco è definito da una serie di regole che definiscono le mosse lecite. Le mosse sono fatte alternativamente da 2 giocatori A e B. Ogni giocatore ha informazioni complete sullo stato del gioco in ogni istante. Non c’è intervento del caso (sistema deterministico). Uno Stato Terminale rappresenta una situazione di Vittoria, Sconfitta o Pareggio per un giocatore. Diremo che un gioco è Equo, quando nessuno dei due giocatori può vincere se l’avversario gioca “al meglio ”.

Procedura Neg-Max Usiamo il backtracking ricorsivo per trovare la mossa migliore; ad ogni passo verrà scelta la mossa che è più conveniente per A o per B. La funzione di valutazione capovolge il parere dell’avversario, negando il risultato restituito dalla successiva istanza ricorsiva. Stabilito un valore positivo per la vittoria, uno negativo per la sconfitta e Zero per il pareggio: A esamina lo stato attuale del gioco e cataloga le possibili mosse. A esegue ad una ad una le mosse possibili. Se la mossa è terminale, assegna il valore (es. +1, -1, 0). Se la mossa non è terminale, consegna lo stato del gioco a B chiedendo il suo parere (ricorsione). B risponderà secondo il suo punto di vista: ad esempio restituirà +1 se è certo di vincere. A trasforma il parere di B, assumendo -1 per quella mossa. A conclude l’analisi indicando come miglior mossa quella che ha il valore più alto dal suo punto di vista.

Tic-Tac-Toe Ciascuno dei due giocatori inserisce a turno una pedina del proprio colore sul tavolo di gioco, fino a formare un Tris, ovvero una fila di tre pedine dello stesso colore, in orizzontale, in verticale o in diagonale: vince chi realizza per primo un tris; riempito il campo senza tris, la partita è Pari. Struttura Dati: Tavola[10] scacchiera del gioco; sono usate le caselle da [1] a [9] ogni casella vale 0 se vuota, 1 o 2 se occupata. Nvuote numero delle caselle ancora vuote a disposizione Who giocatore che deve muovere: 1 o 2 DoveGioco casella della prossima mossa da eseguire Finito 0 = gioco in corso 1 = gioco finito (vinto 1) 2 = gioco finito (vinto 2) 3 = gioco finito in pareggio 27 = gioco finito per abbandono

/*==================================================================== Esempio base per il gioco del Tris tra due giocatori scelti tra: -) Umano ( tramite keyboard ) -) PC ( tramite sub di valutazione mossa ). Manca un’interfaccia utente e la possibilità di scegliere chi inizia. ---------------------------------------------------------------------*/ main (void) { int Tavola[10], // scacchiera di gioco Nvuote, // numero delle caselle vuote (con valore 0) Who, // giocatore che deve muovere: 1 o 2 DoveGioco, // mossa da fare da parte di Who i, // indice generico Finito; // 0 = gioco in corso // 1,2 = gioco finito (vinto 1 o 2) // 3 = gioco finito in pareggio // 27= gioco finito per abbandono for (Nvuote = i= 9; i; Tavola[i--]=0 ); // pulizia scacchiera StampaTavola (Tavola); // visualizza la tavola Who = 1; // muove per primo il PC assegnato a 1 Finito = 0; while (! Finito) { if (Who == 1) // mossa decisa dalla funzione di valutazione { ValutaMossa (Tavola, Nvuote, Who, &DoveGioco); } else // Who == 2: mossa del giocatore umano tramite keyboard

else // Who == 2: mossa del giocatore umano tramite keyboard { DoveGioco = 0; do { i = getch(); if (i == 27) // se si vuole abbandonare il gioco Finito = 27; else if (i>=49 && i<=57 && Tavola[i-48]==0) //solo case vuote DoveGioco = i-48; } while (!DoveGioco && !Finito); if (!Finito) // se non c'è stato un abbandono { Tavola[DoveGioco] = Who; // occupa la casella if ( VerificaTris(Tavola) ) Finito = Who; // mossa vincente else if (Nvuote == 1) // se unica vuota, pareggio Finito = 3; else // passa all'avversario { Who = 3 - Who; Nvuote --; StampaTavola (Tavola); // Visualizza il campo di gioco while (!Finito); printf ("Partita terminata"); getch();

/*========================================================== Verifica se esiste un tris qualsiasi sulla tavola di gioco Considerando i valori 1 e 2 in binario, 10 e 01, l’AND di tre caselle è diverso da zero solo se sono uguali. Output : 1 l'ultima mossa effettuata ha prodotto un Tris 0 non esistono tris sulla tavola ---------------------------------------------------------*/ int VerificaTris ( int *Tav // scacchiera di gioco ) { int Fatto; Fatto = ( Tav[1] & Tav[2] & Tav[3] || // 1ø rigo Tav[4] & Tav[5] & Tav[6] || // 2ø rigo Tav[7] & Tav[8] & Tav[9] || // 3ø rigo Tav[1] & Tav[4] & Tav[7] || // 1ø colonna Tav[2] & Tav[5] & Tav[8] || // 2ø colonna Tav[3] & Tav[6] & Tav[9] || // 3ø colonna Tav[1] & Tav[5] & Tav[9] || // diagonale / Tav[7] & Tav[5] & Tav[3] ); // diagonale \ return Fatto; }

/. Valutazione della mossa migliore in un dato stato del gioco /* Valutazione della mossa migliore in un dato stato del gioco. si ferma nell'analisi quando trova una mossa vincente. Output: valore della scacchiera vista da Who che deve muovere -1 sconfitta, 0 pareggio, +1 vittoria. */ int ValutaMossa ( int *Tav, // scacchiera di gioco int Nvuote, // numero delle caselle vuote (valore 0) int Who, // giocatore che deve muovere: 1 o 2 int *DoveMeglio // casella della mossa migliore ) { int i, // indice sulle caselle della scacchiera Dove, // miglior contromossa dell'avversario Vale, // valore della contromossa MaxVale; // valore della miglior mossa possibile for (MaxVale = -INFINITO, i=9; i && MaxVale<1; i--) if (Tav[i]==0) // se la casella è vuota { Tav[i] = Who; // occupa la casella if ( VerificaTris(Tav) ) // se si è creato un tris Vale = +1; // mossa vincente else if (Nvuote == 1) // se unica vuota, pareggio Vale = 0; else // chiede il parere dell'avversario Vale = -ValutaMossa (Tav, Nvuote-1, 3-Who, &Dove); if (Vale > MaxVale) { MaxVale = Vale; *DoveMeglio = i;} Tav[i] = 0; // libera la casella } return MaxVale;

Hexagon 19 Sia assegnata una scacchiera con 19 caselle esagonali (inizialmente vuote). Due giocatori (Nero e Bianco) collocano alternativamente una pedina in una casella vuota; il primo che è costretto ad occupare due caselle adiacenti, ha perso la partita. 1. Costruire una procedura che valuti la mossa migliore da compiere in qualsiasi situazione di gioco (considerando che anche l’avversario giocherà sempre “al meglio”), utilizzando il Backtracking ricorsivo. 2. Utilizzare la suddetta procedura per stabilire se si può sicuramente vincere giocando per primi o per secondi (un pareggio è impossibile). 3. Consentire ad un umano di giocare contro il computer, sia pure con un’interfaccia spartana.

Bibliografia Web http://it.wikipedia.org/wiki/Ricorsione http://www.cad.polito.it/~bernardi/ corsi/APA_IVREA/APA2/W4/minmax.pdf http://www.di.unipi.it/~simi/ AI/SI2007/Lucidi/games.pdf http://www.cs.unibo.it/~cianca/ wwwpages/chesssite/tozzi.pdf