UNIVERSITÀ DELLA CALABRIA Facoltà di Scienze Matematiche Fisiche e Naturali Corso di laurea in Informatica



Documenti analoghi
Sommario. Definizione di informatica. Definizione di un calcolatore come esecutore. Gli algoritmi.

Excel. A cura di Luigi Labonia. luigi.lab@libero.it

Appunti sulla Macchina di Turing. Macchina di Turing

INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI INTRODUZIONE AGLI ALGORITMI

APPUNTI DI MATEMATICA LE FRAZIONI ALGEBRICHE ALESSANDRO BOCCONI

RISOLUTORE AUTOMATICO PER SUDOKU

1. PRIME PROPRIETÀ 2

risulta (x) = 1 se x < 0.

Capitolo 2. Operazione di limite

f(x) = 1 x. Il dominio di questa funzione è il sottoinsieme proprio di R dato da

4 3 4 = 4 x x x 10 0 aaa

Correttezza. Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 1. Dispensa 10. A. Miola Novembre 2007

Lezione 8. La macchina universale

SISTEMI DI NUMERAZIONE E CODICI

Funzioni funzione dominio codominio legge argomento variabile indipendente variabile dipendente

Dimensione di uno Spazio vettoriale

EXCEL PER WINDOWS95. sfruttare le potenzialità di calcolo dei personal computer. Essi si basano su un area di lavoro, detta foglio di lavoro,

Statistica e biometria. D. Bertacchi. Variabili aleatorie. V.a. discrete e continue. La densità di una v.a. discreta. Esempi.

Corso di Informatica

Processo di risoluzione di un problema ingegneristico. Processo di risoluzione di un problema ingegneristico

Matematica in laboratorio

Lezioni di Matematica 1 - I modulo

Esercizio 1 Dato il gioco ({1, 2, 3}, v) con v funzione caratteristica tale che:

Uso di base delle funzioni in Microsoft Excel

GHPPEditor è un software realizzato per produrre in modo rapido e guidato un part program per controlli numerici Heidenhain.

(anno accademico )

Introduzione al MATLAB c Parte 2

LUdeS Informatica 2 EXCEL. Seconda parte AA 2013/2014

MODELLO RELAZIONALE. Introduzione

Capitolo 13: L offerta dell impresa e il surplus del produttore

Linguaggi e Paradigmi di Programmazione

I database relazionali sono il tipo di database attualmente piu diffuso. I motivi di questo successo sono fondamentalmente due:

SISTEMI INFORMATIVI AVANZATI -2010/ Introduzione

Siamo così arrivati all aritmetica modulare, ma anche a individuare alcuni aspetti di come funziona l aritmetica del calcolatore come vedremo.

Programma Gestione Presenze Manuale autorizzatore. Versione /08/2010. Area Sistemi Informatici - Università di Pisa

Le funzioni continue. A. Pisani Liceo Classico Dante Alighieri A.S A. Pisani, appunti di Matematica 1

Interesse, sconto, ratei e risconti

LE FUNZIONI A DUE VARIABILI

Corrispondenze e funzioni

Logica Numerica Approfondimento 1. Minimo Comune Multiplo e Massimo Comun Divisore. Il concetto di multiplo e di divisore. Il Minimo Comune Multiplo

ESEMPIO 1: eseguire il complemento a 10 di 765

1 Applicazioni Lineari tra Spazi Vettoriali

Database 1 biblioteca universitaria. Testo del quesito

Calcolatori: Algebra Booleana e Reti Logiche

Obiettivo Principale: Aiutare gli studenti a capire cos è la programmazione

Appunti di informatica. Lezione 2 anno accademico Mario Verdicchio

1 Giochi a due, con informazione perfetta e somma zero

ALGEBRA DELLE PROPOSIZIONI

Convertitori numerici in Excel

GUIDA RAPIDA PER LA COMPILAZIONE DELLA SCHEDA CCNL GUIDA RAPIDA PER LA COMPILAZIONE DELLA SCHEDA CCNL

LE SUCCESSIONI 1. COS E UNA SUCCESSIONE

lo PERSONALIZZARE LA FINESTRA DI WORD 2000

Lezione 9: Cambio di base

CALCOLO COMBINATORIO

Generazione Automatica di Asserzioni da Modelli di Specifica

Procedura per creare un archivio storico remoto nelle 24 ore giornaliere

Interesse, sconto, ratei e risconti

COS È UN LINGUAGGIO? LINGUAGGI DI ALTO LIVELLO LA NOZIONE DI LINGUAGGIO LINGUAGGIO & PROGRAMMA

OSSIF WEB. Manuale query builder

CONCETTO DI LIMITE DI UNA FUNZIONE REALE

Rappresentazione grafica di entità e attributi

UNA LEZIONE SUI NUMERI PRIMI: NASCE LA RITABELLA

Informatica. Rappresentazione dei numeri Numerazione binaria

I Problemi e la loro Soluzione. Il Concetto Intuitivo di Calcolatore. Risoluzione di un Problema. Esempio

Corso di Calcolo Numerico

. A primi passi con microsoft a.ccepss SommarIo: i S 1. aprire e chiudere microsoft access Start (o avvio) l i b tutti i pro- grammi

Capitolo 3. L applicazione Java Diagrammi ER. 3.1 La finestra iniziale, il menu e la barra pulsanti

( x) ( x) 0. Equazioni irrazionali

Organizzazione degli archivi

FIRESHOP.NET. Gestione Lotti & Matricole.

Politecnico di Milano. Facoltà di Ingegneria Industriale. Corso di Analisi e Geometria 2. Sezione D-G. (Docente: Federico Lastaria).

Alla ricerca dell algoritmo. Scoprire e formalizzare algoritmi.

MATEMATICA DEL DISCRETO elementi di teoria dei grafi. anno acc. 2009/2010

Esercizi su. Funzioni

Il principio di induzione e i numeri naturali.

Per lo svolgimento del corso risulta particolarmente utile considerare l insieme

Indice generale. OOA Analisi Orientata agli Oggetti. Introduzione. Analisi

Rappresentazione dei numeri in un calcolatore

Per studio di funzione intendiamo un insieme di procedure che hanno lo scopo di analizzare le proprietà di una funzione f ( x) R R

Algoritmi e strutture dati. Codici di Huffman

Formattazione. ü Introduzione

Iniziamo con un esercizio sul massimo comun divisore: Esercizio 1. Sia d = G.C.D.(a, b), allora:

Università degli Studi di Ferrara - A.A. 2014/15 Dott. Valerio Muzzioli ORDINAMENTO DEI DATI

Gestione ed analisi di base dati nell epidemiologia. delle malattie infettive

Il sofware è inoltre completato da una funzione di calendario che consente di impostare in modo semplice ed intuitivo i vari appuntamenti.

Il sistema C.R.M. / E.R.M.

Lande Immortali: Riepilogo dello Stato di Avanzamento del Progetto

I PROBLEMI ALGEBRICI

Proof. Dimostrazione per assurdo. Consideriamo l insieme complementare di P nell insieme

Sistemi di Numerazione

MANUALEDIUTILIZZO MODULO CRM POSTVENDITA

Mon Ami 3000 Conto Lavoro Gestione del C/Lavoro attivo e passivo

PROCEDURA INVENTARIO DI MAGAZZINO di FINE ESERCIZIO (dalla versione 3.2.0)

Potenzialità statistiche Excel

Funzioni. Funzioni /2

Il database management system Access

PROBABILITÀ - SCHEDA N. 2 LE VARIABILI ALEATORIE

1 Serie di Taylor di una funzione

WG-TRANSLATE Manuale Utente WG TRANSLATE. Pagina 1 di 15

Dispense di Informatica per l ITG Valadier

Transcript:

UNIVERSITÀ DELLA CALABRIA Facoltà di Scienze Matematiche Fisiche e Naturali Corso di laurea in Informatica TESI DI LAUREA UN' APPLICAZIONE DELLA ANSWER SET PROGRAMMING AI ROMPICAPO LOGICI: GENERAZIONE E SOLUZIONE DI ISTANZE DIFFICILI DI KAKURO Relatore Prof. Francesco CALIMERI Candidato Leonardo RANIA Matricola 120901 Anno Accademico 2009/2010

2 INDICE INDICE... 2 INTRODUZIONE... 4 1.1 CONTRIBUTI DEL LAVORO DI TESI... 5 1.2 STRUTTURA DELLA TESI... 6 PROGRAMMAZIONE LOGICA... 7 2.1 CENNI STORICI... 7 2.2 LINGUAGGIO DATALOG... 8 2.2.1 Sintassi... 8 2.2.2 Semantica... 9 2.2.3 Semantica Operazionale... 10 2.3 PROGRAMMI DATALOG CON NEGAZIONE... 12 2.3.1 Sintassi... 12 2.3.2 Semantica... 13 2.4 PROGRAMMAZIONE LOGICA DISGIUNTIVA... 14 2.4.1 Sintassi... 15 2.4.2 Semantica... 15 2.5 IL SISTEMA DLV... 16 2.5.1 Linguaggio del Kernel... 16 2.6 INTERFACCIARE DLV CON JAVA : IL WRAPPER... 18 2.6.1 Rappresentazione dei dati : la classe Predicate, Literal, Model e Program... 18 2.6.2 Il Wrapper DLV a lavoro... 19 IL ROMPICAPO KAKURO... 23 3.1 ESEMPIO RISOLTO... 24 3.2 KAKURO NP-COMPLETE... 28

3 LAVORO SVOLTO... 29 4.1 KAKURO E ANSWER SET PROGRAMMING... 29 4.1.1 Analisi e Modellazione... 29 4.1.2 Solver in DLV... 30 4.1.3 Generatore di istanze difficili Kakuro in DLV... 32 4.2 UN'APPLICAZIONE JAVA PER IL KAKURO... 39 4.2.1 Interfaccia grafica Kakuro in Java... 39 4.3 ATTIVITÀ SPERIMENTALE... 41 4.3.1 Sistemi Testati... 41 4.3.1.1 Il sistema DLV... 41 4.3.1.2 Il sistema GnT/Smodels... 42 4.3.1.3 Il sistema Clasp... 42 4.3.1.4 Sugar e Costraint Satisfaction Problems (CSP)... 43 4.3.2 Istanze di Prova... 45 4.3.3 Risultati Ottenuti e Discussione... 46 CONCLUSIONI E SVILUPPI FUTURI... 51 BIBLIOGRAFIA... 54

4 Capitolo 1 INTRODUZIONE I rompicapi logici a griglia, o puzzle logici, alcuni dei quali diventati popolarissimi negli ultimi anni (si pensi al celebre Sudoku), rappresentano un sano hobby per molte persone. La grande popolarità di questi giochi dipende da molti fattori: da un lato, sfidano la capacità logica, matematica e spaziale di chi li affronta e, dall altro, consentono (quando non troppo difficili da risolvere!) di trascorrere un po di tempo della giornata prendendo una pausa da tutto il resto. Essendo i suddetti giochi basati su regole matematiche, è possibile ideare algoritmi che, ricevuta come argomento l istanza di uno specifico rompicapo, la risolvano (solutori). Per maggior parte di questo genere di puzzle, non è possibile progettare solutori molto efficienti in senso propriamente detto; in particolare, in tutti i casi in cui, si tratta di problemi appartenenti alla classe di complessità NP (Nondeterministic Polynomial Time); in questa classe, rientrano quei problemi per cui, ad oggi, non si conoscono algoritmi risolutivi di complessità temporale polinomiale (e cioè strettamente contenenti nella classe P), in grado di fornire una soluzione che soddisfi il puzzle (e forse non se ne conosceranno mai, visto che molti ricercatori sono convinti che P NP). Questi algoritmi, oltre ad essere computazionalmente onerosi, sono spesso difficili da tradurre in programmi eseguibili dai calcolatori sfruttando la programmazione tradizionale: richiedono spesso, infatti, intuizioni non banali. Oggi, se per l efficienza computazionale non è possibile far molto, per quella che potremmo chiamare complessità sintattica (la facilità con cui è possibile rappresentare le soluzioni in un linguaggio formale) qualcosa si può migliorare; esistono infatti, paradigmi di programmazione con cui è possibile progettare solver molto meno complessi, dal punto di vista della rappresentazione, e quindi più naturali, di quelli creati implementando un algoritmo tradizionale. A tal proposito, particolarmente utile è lo strumento della programmazione logica, all'interno della quale, nel corso degli ultimi anni, si è sviluppata la answer set programming.

5 L Answer Set Programming (ASP) è un formalismo logico che garantisce un approccio dichiarativo alla risoluzione dei problemi. Il linguaggio di ASP consente il doppio utilizzo di disgiunzione nella testa e di negazione nel corpo delle regole logiche, divenendo un linguaggio molto espressivo; grazie a ciò, ASP viene oggi riconosciuto come un metodo potente per la rappresentazione della conoscenza e per il ragionamento automatico. L idea di base della programmazione answer set è quella di rappresentare un dato problema computazionale attraverso un programma logico, che può avere uno, molti o nessun answer set (insieme delle risposte), ciascuno dei quali rappresenta una soluzione del problema dato. Tali programmi logici sono poi "dati in pasto" ad un answer set solver, ovvero un motore inferenziale. Negli ultimi anni questo tipo di approccio sta avendo una grande diffusione, grazie al fatto che, dopo anni di ricerca scientifica in ambito teorico, sono da poco disponibili diversi sistemi basati su una implementazione solida ed efficiente, quale ad esempio il sistema DLV. Questi sistemi sono di interpretare programmi answer set con migliaia di atomi e regole in pochi secondi. Ciò si traduce nella possibilità pratica di godere di maggiore semplicità realizzativa, maggior livello di astrazione e quindi una semplificazione del processo di progettazione delle soluzioni. La programmazione answer set si rivela utile anche nella risoluzione dei puzzle logici. Data un istanza di un puzzle, in molti di essi sarà possibile impostare un insieme di vincoli, ricavati dalle regole del puzzle, che verifichino la soddisfacibilità dell istanza ed, in caso affermativo, producano un insieme di soluzioni valide. 1.1 Contributi del Lavoro di Tesi Lo scopo principale di questa tesi è stato solo quello di progettare e realizzare, per il puzzle Kakuro, un solver (solutore) basato su ASP. Il lavoro, però, non si è fermato a questo. Infatti, sono stati curati anche, altri aspetti: abbiamo creato un generatore di istanze, e abbiamo integrato il tutto in un'applicazione dotata di interfaccia grafica (in JAVA).

6 Inoltre, è stato realizzato un piccolo sistema di benchmarking/testing per solutori, ed è stata portata avanti una accurata attività sperimentale. 1.2 Struttura della Tesi Nel capitolo a seguire, Programmazione Logica, è fornita un introduzione alla programmazione logica, ed in particolare alla Answer Set Programming. L ultimo capitolo, Lavoro Svolto, verte invece, sulla descrizione e formalizzazione del puzzle affrontato come problema di programmazione answer set, sulla realizzazione del generatore casuale di puzzle Kakuro e sulla descrizione dei sistemi testati nella attività sperimentale commentandone i risultati ottenuti.

7 Capitolo 2 PROGRAMMAZIONE LOGICA In questo capitolo verrà trattata la programmazione logica ed una serie di estensioni che hanno reso questo paradigma sempre più potente ed espressivo. Dunque, vengono qui introdotte le notazioni di base della metodologia di programmazione utilizzata nella realizzazione del progetto. La Sezione 2.1 contiene alcuni cenni storici. Nella Sezione 2.2 viene mostrata la sintassi e la semantica del linguaggio Datalog. Nella Sezione 2.3 si illustra la programmazione logica tradizionale con la negazione. Nella Sezione 2.4 si riportano i costrutti sintattici della programmazione logica disgiuntiva. Nella Sezione 2.5 si riportano i costrutti sintattici e la semantica del motore inferenziale, implementato nell Università della Calabria, DLV. Infine, nella Sezione 2.6 è trattata una specifica implementazione, chiamata DLV-Wrapper, per gli aspetti concernenti l interfaccia tra Java e DLV. 2.1 Cenni storici La programmazione logica ha origine negli anni '70, come supporto teorico nell ambito della ricerca nel campo dell intelligenza artificiale. Un grande passo avanti è stato compiuto grazie allo studio di Robinson sui principi di risoluzione, nel 1970, Colmerauer ha sviluppato il primo linguaggio di programmazione logica denominato PROLOG. Attualmente, la programmazione logica viene utilizzata in diversi campi, quali: rappresentazione della conoscenza, sistemi esperti, pianificazione e scheduling, riconoscimento di linguaggi naturali, ragionamento approssimato, giochi, tecniche euristiche, diagnostica medica, localizzazione di guasti ed interpretazione di dati. Ciò che differenzia principalmente la programmazione logica da quella tradizionale è la sua completa dichiaratività, infatti nel creare un programma logico non si cerca di capire come risolvere il problema, ma ci si concentra nel descriverlo, sarà poi l'interprete ad occuparsi della risoluzione. Il programmatore si concentra nella stesura di

8 fatti e relazioni che descrivono il legame tra i vari concetti che si vogliono esprimere, sarà poi il motore inferenziale a ricavarne una soluzione. Nel corso degli anni sono state introdotte varie estensioni linguistiche nell'ambito della programmazione logica, quale la possibilità di avere regole disgiuntive, predicati di aggregazione e vincoli deboli. Un linguaggio di programmazione logica molto diffuso e che utilizzeremo per trattare questo paradigma, è appunto, il DATALOG. 2.2 Linguaggio Datalog 2.2.1 Sintassi Un programma logico P è un insieme finito di regole r Rules (P). Una regola ha la seguente forma: H(r) :- B(r). dove H(r) indica la testa della regola e B(r) il corpo. La testa contiene al più un atomo, mentre il corpo è costituito da un insieme di atomi. In seguito, ci riferiremo all'atomo che si trova nella testa di una regola con a H(r), mentre per gli atomi nel corpo utilizzeremo b i B(r). In un programma logico possiamo individuare i seguenti insiemi infinitamente numerabili di simboli: - Pred (P) Insieme dei simboli di predicati; - Var (P) Insieme dei simboli di variabili; - Const (P) Insieme dei simboli di costanti. Un atomo è composto da un simbolo di predicato p e da un insieme di termini che possono essere costanti o variabili p i (Var(P) Const(P)).

9 Un atomo si presenta nella seguente forma: p(p 1,,p n ) dove p Pred(P) è il simbolo di predicato di arità n (anche uguale a 0 ), con i termini p 1,, p n, per cui p i (Var(P) Const(P)). Possiamo quindi rappresentare una regola nella seguente forma: a :- b 1,,b k. dove a è l'atomo in testa alla regola e b i (con i = 1..k) sono atomi del corpo. Una regola r con il corpo vuoto B(r) = si dice fatto, indicato con: a. Una regola r con la testa vuota H(r) = ; si dice constraint, indicato con: :- b 1,,b k. Una regola r si dice safe se ogni variabile presente nella testa, compare anche nel corpo. 2.2.2 Semantica Riportiamo innanzitutto alcune definizioni presenti in letteratura utilizzate in questo e nei successivi capitoli. Definizione 2.1 (Universo di Herbrand) Si definisce Universo di Herbrand U p l'insieme di tutte le costanti che compaiono nel programma P. Definizione 2.2 (Base di Herbrand) La Base di Herbrand B p è l'insieme di tutti gli atomi costruibili dai simboli di predicato che appaiono nel programma P, combinati con i simboli costanti presenti nell'universo di Herbrand U p.

10 Definizione 2.3 (Programma Ground) Per ogni regola r Rules(P), indichiamo con Ground(P), un insieme di regole ottenute dalla sostituzione delle variabili in r con le costanti dell'universo di Herbrand U p. La sostituzione è una funzione (X) che associa ad ogni variabile X di r un termine appartenente ad U p. Definizione 2.4 (Interpretazione) Un'interpretazione I per un programma P è un qualsiasi sottoinsieme di atomi della Base di Herbrand I B p. L'interpretazione I si dice chiusa rispetto a P, se per ogni regola r Rules(P), tale che il corpo della regola è sottoinsieme di I; anche la testa della regola è contenuta in I. Formalmente r Rules(P), H(r) I, B(r) I Definizione 2.5 (Modello Stabile) Chiamiamo modello stabile M p un'interpretazione I B p chiusa e minima, ovvero tale che, non esiste nessuna interpretazione I' chiusa, che sia un sottoinsieme di I. Teorema 2.6 Sia I il modello minimo di un programma P. Allora a j I, se e solo se, esiste una regola r Ground(P) con testa a j H(r) e corpo B(r) I. 2.2.3 Semantica Operazionale In questa sezione si illustra la procedura usata per calcolare i modelli stabili di un programma: il calcolo del minimo punto fisso dell'operatore di conseguenza immediata T p (I ). L'operatore T p (I ) trasforma interpretazioni di Herbrand in interpretazioni di Herbrand, formalmente

11 T p (I ) : 2 Bp 2 Bp. Dato un programma P ed un'interpretazione I, poniamo a T p (I ) r Ground(P) t.c. B(r) I, a H(r) Definizione 2.7 (Punto Fisso) Un elemento I si dice punto fisso per l'operatore T se si ha T(I) = I, se poi per tutti i punti fissi Y si ha X Y, allora X è il minimo punto fisso di T. Teorema 2.8 Sia P un programma logico, M p = T p ( ). La costruzione del modello si basa sulla determinazione della seguente successione: I 0 0 = T p = I 1 1 = T p = T p (T 0 p ) I i i = T p = T p (T i-1 p ) L'interpretazione calcolata al primo passo coincide con l'insieme dei fatti presenti nel programma P. Le successive iterazioni, sono invece i predicati derivati partendo dall'insieme ottenuto al passo precedente. L'iterazione si ripete fino a trovare il minimo punto fisso, ovvero fin quando non è più possibile aggiungere nuovi fatti all'insieme.

12 2.3 Programmi Datalog con negazione Un programma logico si dice negativo quando esiste almeno una regola che contiene almeno un atomo negato, altrimenti si dice not-free o positivo. 2.3.1 Sintassi Un programma logico negativo è costituito sempre da un insieme di regole aventi la seguente forma: H(r) : - B(r). La testa è sempre costituita da al più un atomo; ma il corpo, in questo caso, è dato dall'unione di due insiemi di atomi: B(r) = B + (r) B - (r) (detti rispettivamente corpo positivo e corpo negativo). Con b 1..k B + (r) indichiamo gli atomi del corpo positivo e con b k+1..n B - (r) indichiamo gli atomi del corpo negativo (ovvero atomi preceduti dalla negazione not). Un atomo, anche se negato (se l'atomo appartiene al corpo negativo), viene ugualmente chiamato letterale. Possiamo, quindi, rappresentare una regola di un programma logico negativo nella seguente forma: a : - b 1,, b k, not b k+1,, not b n. Con la negazione cambia anche la condizione di safety; infatti, in questo caso, una regola r si dice safe, se ogni variabile presente nella regola, compare anche nel suo corpo positivo.

13 2.3.2 Semantica Un programma positivo presenta sempre un modello minimo. Ma, nel caso di programmi negativi questo non è sempre vero, infatti possono esistere più modelli stabili; quindi, non ha più senso parlare di modelli minimi, parleremo invece di modelli minimali. Definizione 2.9 (Modello Minimale) Chiameremo modello minimale M p un'interpretazione I B p chiusa e minima, ovvero tale che non esiste una interpretazione I' chiusa che sia un sottoinsieme di I. Definizione 2.10 (Grafo delle Dipendenze) Il grafo delle dipendenze G P di un programma P è un grafo orientato etichettato, dove: a) i nodi rappresentano gli atomi in Ground(P); b) esiste un arco etichettato con + (chiamato arco positivo) dal nodo b i al nodo a j, se e solo se, esiste almeno una regola r Ground(P) e con a j H(r) e b i B + (r); c) esiste un arco etichettato con - (chiamato arco negativo) dal nodo b i al nodo a j, se e solo se, esiste almeno una regola r Ground(P) e con a j H(r) e b i B - (r). Definizione 2.11 (Dipendenza tra atomi) Un atomo a dipende da b, indicato con a b, se e solo se, esiste un cammino orientato da b ad a nel grafo delle dipendenze. Definizione 2.12 (Programmi Stratificati) Un programma P si dice stratificato se è possibile scegliere un modello minimale come significato, oppure, in maniera equivalente, se e solo se, non esistono cicli con archi negati nel grafo delle dipendenze G P.

14 Definizione 2.13 (Insieme Infondato) Sia P un programma ed I una sua interpretazione, un insieme X B P è un insieme infondato per P rispetto a I se per ogni regola r Rules(P), e per ogni a X tale che a H(r), almeno una delle seguenti condizioni è soddisfatta: - B(r) è falso rispetto ad I; - B + (r) X =. Definizione 2.14 (Modello minimale fondato) Un modello minimale M P per un programma logico P è fondato, se nessun suo sottoinsieme è un insieme infondato per P rispetto a M P. E possibile dimostrare che un programma stratificato ha un solo modello minimale fondato che viene preso come significato del programma. Un programma logico negativo P può essere trasformato in un programma logico positivo P che presenta i medesimi modelli stabili. La trasformazione di Gelfond-Lifschitz consente di ridurre il programma Ground(P), rispetto ad una interpretazione I, in un programma Ground(P I ) positivo, operando nel modo seguente: - Rimuovendo le regole r Rules(P) tali che B - (r) I ; - Rimuovendo tutti i restanti letterali negativi. Un modello stabile I di Ground(P) è un modello stabile per Ground(P I ). 2.4 Programmazione Logica Disgiuntiva La Programmazione Logica Disgiuntiva (DLP) è un formalismo che consente una rappresentazione semplice e naturale per problemi di elevata complessità. E stato dimostrato che la DLP ha un elevato potere espressivo, e permette di rappresentare tutti i problemi nella classe 2 P (NP NP ). L'alta espressività dei linguaggi logici disgiuntivi ha importanti implicazioni pratiche, non solo formali: i programmi logici disgiuntivi, infatti, possono rappresentare

15 situazioni reali che non possono essere espresse da programmi logici normali (senza disgiunzione). Il calcolo dei modelli stabili per un programma logico disgiuntivo risulta computazionalmente difficile. L'elevata complessità computazionale ha per molto tempo scoraggiato lo sviluppo di sistemi basati sulla DLP. Risulta, infatti, necessaria una fase di ricerca dei modelli (con una complessità NP- Hard) e poi una fase di verifica della stabilità (con una complessità conp-completo). Attualmente, questa evoluzione del paradigma di programmazione logica è stata implementata da diversi sistemi di inferenza. Il sistema DLV realizzato nell'ambito di una collaborazione tra l'università della Calabria ed il Politecnico di Vienna, è tra le prime implementazioni che supporta pienamente la programmazione logica disgiuntiva insieme ad una serie di estensioni quali le funzioni di aggregazione (somme, moltiplicazioni, conteggio, etc.) ed i vincoli deboli. 2.4.1 Sintassi Nella programmazione logica disgiuntiva, la testa di una regola può contenere più di un atomo a j H(r). Quindi sintatticamente una regola ha la seguente forma: a 1 a m : - b 1,, b k, not b k+1,, not b n. Il corpo è una congiunzione di atomi, eventualmente negativi, mentre la testa è una disgiunzione di atomi positivi. 2.4.2 Semantica La semantica di un programma logico disgiuntivo [5] è stata definita in [3, 4, Gelfond and Lifschitz]. In generale dato un modello stabile I di P, se esiste una regola r Rules(P), tale che il corpo positivo sia un sottoinsieme dell'interpretazione e non esiste letterale del corpo negato che sia anche nell'interpretazione; allora, almeno un atomo della testa deve appartenere all'interpretazione: r Rules(P), B + (r) I, B - (r) I = H(r) I.

16 In generale un programma logico disgiuntivo può presentare un numero di modelli stabili superiore a uno (o anche nessuno). 2.5 Il sistema DLV DLV è un efficiente Answer Set Programming (ASP) che implementa la coerente semantica answer set [Gelfond e Lifschitz1991] con miglioramenti per la programmazione logica con l'ereditarietà e le query, aritmetica intera e vari predicati built-in. Si tratta di un programma altamente portatile, disponibile in formato binario per diverse piattaforme. 2.5.1 Linguaggio del Kernel Il linguaggio del kernel di DLV è datalog disgiuntiva esteso con forte negazione sotto la semantica answer set [Eiter et al.1997, Gelfond e Lifschitz1991]. Sintassi: stringhe con le lettera iniziale maiuscola denotano variabili; quelle con lettere iniziale minuscola denotano costanti. Un termine è o una variabile o una costante. mentre, Un atomo è una espressione p (t 1,..., t n ), dove p è un predicato di n arità e t 1,..., t n sono termini. Un letterale l è un atomo a (in questo caso, è positivo), oppure è un atomo negato a (in questo caso, è negativo). Dato un letterale l, il suo letterale complementare è definito come a se l = a e a se l = a. Un insieme di letterali L si dice consistente, se per ogni letterale l L, il letterale complementare non è contenuto in L. Oltre a letterali sopra definiti, DLV supporta anche built-in, come #int, #succ, <, +, e *. Una regola disgiuntiva r è una formula: a 1 a m : - b 1,, b k, not b k+1,, not b n.

17 dove a 1,, a m, b 1,, b n sono letterali, m 0, n k 0, e not rappresenta la negazione. La disgiunzione a 1 a m è la testa di r, mentre la congiunzione b 1,, b k, not b k+1,, not b n è il corpo di r. Una regola senza letterali di testa (cioè m = 0) è solitamente indicata come vincolo di integrità (constraint). Se il corpo è vuoto (cioè k = n = 0), solitamente si omette il segno :-. Noi indichiamo con H(r) l'insieme di letterali in testa, e con B (r) = B + (r) B - (R) l'insieme dei letterali nel corpo, dove B + (r) = (b 1,...,b k ) e B - (r) =(b k +1,...,b n ) sono, rispettivamente, gli insiemi di letterali del corpo positivo e negativo. Un programma disgiuntivo datalog P è un insieme finito di regole. Semantica: DLV implementa la coerente semantica answer set definita originariamente in [Gelfond e Lifschitz1991]. Per ogni programma P, si definisce il suo set di risposta in due step usando l istanziazione Ground (P), seguendo [Lifschitz1996]. Una answer set di un programma P è un insieme X B, tale che X è un answer set di Ground (P) X, cioè X è un answer set del programma positivo, eventualmente ricavato attraverso la riduzione di Gelfond-Lifschitz. Il linguaggio DLV può essere usato per codificare i problemi computazionali di alta complessità (fino alla classe di complessità 2 P), in un modo altamente dichiarativo, seguendo il paradigma Guess & Check.

18 2.6 Interfacciare DLV con JAVA : il Wrapper In questa sezione verrà descritta il wrapper implementato all Università della Calabria, per rendere utilizzabile DLV, da applicazione Java. 2.6.1 Rappresentazione dei dati : la classe Predicate, Literal, Model e Program Nella sezione 2.5, abbiamo descritto la sintassi e la semantica di DLV. Ora descriviamo come input/output di DLV sono trattati tramite una libreria di oggetti. La Classe Literal fornisce dei metodi per accedere e modificare i letterali di un predicato ed è una classe interna alla classe Predicate sotto descritta. La Classe Predicate è un potente strumento, in quanto permette ad un programmatore Java di gestire dati da utilizzare come input DLV. Esso fornisce accesso completo a caratteristiche come il nome, arità e dimensione del predicato. Inoltre, fornisce delle utili interfacce per l accesso ai letterali. La Classe Model rappresenta i modelli, cioè l answer set del programma. Dal momento che i modelli sono un insieme di predicati, la classe implementa una raccolta di oggetti Predicate. Siamo in grado di recuperare un oggetto Predicate da un modello, sia specificando il nome, che in modo sequenziale. Infine, la variabile statica NOModel permette di riconoscere un programma che non ha modelli. La Classe Program rappresenta la logica del programma. DLV supporta un meccanismo flessibile che permette di specificare i programmi di immissione. Esso consente di dividere il programma in più file di testo. La classe Program estende questo meccanismo. In realtà, permette di specificare in input non solo file testuali ma anche stringhe e oggetti Predicate.

19 2.6.2 Il Wrapper DLV a lavoro In questa sezione, si mostra come richiamare DLV attraverso il wrapper DLV, con l aiuto di un esempio. E necessario costruire degli oggetti prima di poter richiamare DLV. La lista completa dei passaggi da attuare è la seguente: 1. Costruire un oggetto Program avente in ingresso i setup; 2. Costruire un oggetto DlvHandler; 3. Impostare il programma da eseguire; 4. Eseguire DLV; 5. Manipolare l uscita DLV utilizzando le classi Model, Predicate e/o Literal. Nel seguito è implementato un piccolo esempio basato sul problema della tre colorabilità (Fig 4.7). In modo informale viene ricordato il problema: dato un grafo G in input, bisogna assegnare un colore ad ogni nodo del grafo, in modo tale che nodi adiacenti abbiano sempre colori diversi. Tale problema è NP-Complete. Rappresentiamo i nodi e gli archi del grafo G con una serie di fatti utilizzando i predicati node (unario) e arc (binario). Siamo in grado di risolvere il problema attraverso la seguente logica disgiuntiva: r1 :color(x, rosso) color(x, blu) color(x, verde) :- node(x). c1 : :- arc(x,y), color(x,c), color(y,c). La regola disgiuntiva r1 indovina i colori dei vari nodi (Guess), cioè la soluzione al problema, mentre il constraint c1 controlla l ammissibilità della soluzione (Check). Salviamo la regola disgiuntiva r1 nel file guessidb.dl e una serie di nodi nel file nodeedb.dl. Scriviamo il vincolo c1 in un oggetto String ed utilizziamo un oggetto Predicate per rappresentare il predicato arc.

20 String check= :- arc(x, Y), color(x, C), color(y, C). ; Predicate p=new Predicate( arc,2); p.addliteral(p.new Literal(new String[]{" minnesota ", "wisconsin"})); p.addliteral(p.new Literal(new String [] {" illinois", "iowa"})) p.addliteral(p.new Literal(new String[]{" illinois", "michigan"})) p.addliteral(p.new Literal(new String[]{" illinois", "wisconsin"})) p.addliteral(p.new Literal(new String[]{" illinois", "indiana"})) p.addliteral(p.new Literal(new String[]{" indiana", "ohio"})) p.addliteral(p.new Literal(new String[]{" michigan", "indiana"})) p.addliteral(p.new Literal(new String[]{" michigan", "ohio"})) p.addliteral(p.new Literal(new String[]{" michigan", "wisconsin"})) Possiamo ora applicare la prima fase: // Costruire un oggetto Program avente in ingresso il setup Program pr=new Program(); //set input pr.addprogramfile("guessidb.dl"); // Aggiunta della regola disgiuntiva r1 pr.addstring("ckeck ); // Aggiunta del constraint c1 pr.addprogramfile("nodeedb.dl"); // Aggiunta dei nodi pr.addpredicate(p) // Aggiunta del predicato arc Nel seguente codice attuiamo il secondo e terzo passo:

21 // Costruire un oggetto DlvHandler DlvHandler dlv=new DlvHandler("dl.exe"); // Settaggio del programma in input dlv.setprogram(pr); // Settaggio dei parametri di invocazione dlv.setnumberofmodels(2); // calcola non più di due soluzioni dlv.setincludefacts(false); Nell ultima parte di codice attuiamo il quarto e quinto passo: try { // Esecuzione DLV dlv.run(); //Manipolazione dell output di DLV while(dlv.hasmoremodels()) // Per ogni modello, attendere DLV trovare un nuovo modello { Model m=dlv.nextmodel(); // ottiene prossimo modello if(!m.isnomodel()) { while(m.hasmorepredicates()) // per ogni predicato in m { Predicate p=m.nextpredicate(); // ottiene prossimo predicato System.out.println(p.toString()); // stampa predicato p } System.out.println( --- END Model ); } else System.out.println( I cannot find a model ); } } catch(dlvexception d) { d.printstacktrace(); }

22 catch(dlvexceptionuncheked du) { du.printstacktrace(); } finally { System.err.println(dlv.getWarnings());}//errori

23 Capitolo 3 IL ROMPICAPO KAKURO Il Kakuro è un puzzle a griglia editato da Nikoli[2]. (a) Stato iniziale Figura 3.1 : Schema Kakuro (b) Stato finale Il Kakuro è anche noto come il cruciverba dell aritmetica perché, come nel gioco di parole enigmistico lo scopo è trovare per ogni indizio (verticale od orizzontale), una parola che lo espliciti, in questo puzzle lo scopo è trovare, per ogni indizio numerico (verticale od orizzontale), un insieme di cifre la cui somma sia equivalente al primo. La differenza sostanziale tra i due giochi sta nel fatto che in quest ultimo una parola numerica avrà un vocabolario limitato a 9 simboli e non saranno ammesse ripetizioni di questi ultimi nella stessa parola. Vi saranno due tipi di caselle: le caselle indizio che saranno o completamente nere (senza indizi) o suddivise in due triangoli, a loro volta o neri (senza indizio) o contenenti un valore che sarà indizio orizzontale nel caso del triangolo superiore e verticale nell inferiore; le caselle azionabili saranno le caselle inizialmente vuote.

24 Regole Più schematicamente, al fine di completare uno schema, il giocatore dovrà inserire in ogni casella vuota un valore, rispettando le seguenti regole: 1. Il valore di ogni casella azionabile dovrà essere contenuto nell intervallo d interi [1,9] (delle cifre). 2. La somma dei valori contenuti nelle caselle di una parola dovrà essere uguale all indizio numerico corrispondente. 3. Ogni parola potrà contenere solo cifre tutte distinte tra loro. 3.1 Esempio risolto Al fine di familiarizzare con le regole del puzzle sarà risolto il Kakuro in Fig.3.1. Anzitutto si può notare che, per come concepito il gioco, esistono degli indizi che definiscono combinazioni uniche di addendi nelle caselle bianche, come ad esempio l indizio di somma 3 può aver come addendi solo 2 e 1. I. Come primo passo andremo ad inserire, dunque, queste combinazioni uniche. Gli indizi 3 e 4 che si riferiscono rispettivamente alle parole {Ed, Fd} e {Ec, Ed} richiedono combinazioni uniche: il primo richiede la somma 1+2, mentre il secondo 1+3. Le due parole hanno la casella Ed in comune, quindi questo vuol dire che la cifra in comune andrà inserita in Ed, mentre il 2 e il 3 andranno nelle due caselle rimanenti (Fig. 3.2).

25 Figura 3.2 : Primo passo II. Si può procedere allo stesso modo per gli altri blocchi con combinazioni uniche dell esempio: l indizio 16 {Ge, Gf} può essere ottenuto solo con l addizione 7+9, il 17 {Eg, Fg} solo con 8+9. Il 9 può andare in Gf, poiché la somma nell indizio orizzontale 8 {Fe, Ge} non può contenerlo. In Ge, quindi va inserito il 7. Lo stesso ragionamento vale per 9 {Eg, Fg}, grazie al quale sappiamo che in Eg va inserito 8 (Fig. 3.3). Figura 3.3 : Secondo passo III. Possiamo ora osservare che all indizio verticale 17 {Fd, Fe, Ff, Fg} mancherà una sola cifra (Ff). Sommiamo le cifre già inserite per scoprire quale: 2+1+9 = 12; 17 12 = 5. Inseriamo la cifra nell unica casella vuota. A questo possiamo anche completare l indizio orizzontale

26 23 {Df, Ef, Ff, Gf}: 1 + 5 + 9 = 15, manca un 8. Ne conseguirà che nella casella {De} dell indizio 9 {De, Df} andrà inserito 1 e, allo stesso modo, nella casella {Ce}, dell indizio 7 {Ce, De}, 6 (Fig. 3.4). Figura 3.4 : Terzo passo IV. L indizio verticale 30 {Cb, Cc, Cd, Ce} è combinazione unica 6+7+8+9, dato che il 6 è già inserito ( Ce ), nella casella Cb possiamo inserire soltanto il 7, questo perché 8 e 9 non sono compatibili con l indizio 8 {Cb, Db}. A seguito di questo ragionamento potremo completare l indizio 8 {Cb, Db} e 9 {Db, Dc}, inserendo nelle rispettive caselle vuote 1 e 8 (Fig. 3.5). Figura 3.5 : Quarto passo

27 V. Guardiamo ora l indizio verticale {Bc, Bd} che si incrocia con quello orizzontale 26 {Bc, Cc, Dc, Ec}. Se sottraiamo a 26 il 3 in {Ec}, il totale da ottenere è 23 la cui somma a 3 cifre è una combinazione unica 6 + 8 + 9. 8 è già presente, e in {Bc} si potrà inserire soltanto 6. 9 pertanto andrà in {Cc} (Fig. 3.6). Figura 3.6 : Quinto passo VI. Si può concludere lo schema considerando le cifre già presenti nell indizio orizzontale 10 {Bd, Cd}. In base agli indizi verticali che incrociano le due caselle della parola considerata avranno i seguenti valori: in {Bd} potrà essere inserito solo 2, da cui seguirà 8 in {Cd} (Fig. 3.7). Figura 3.7 : Sesto passo

28 3.2 Kakuro NP-Complete La risolubilità di uno schema Kakuro è stato dimostrato da Takahiro [6] appartenere alla classe NP-Complete. Takahiro definisce (N,l,L)-Kakuro lo stesso problema descritto in precedenza, ad eccezione che ogni linea ha un numero di celle bianche n tale che l n L, e poi le possibili cifre da inserire in griglia sono comprese tra 1 N. Quindi (9,2,6)-Kakuro è NP-Complete, (N,2,5)-Kakuro (con 7 N < ) è NP-Complete, (N,1,3)-Kakuro (con 7 N < ) è NP-Complete, (N,l,2)-Kakuro è risolvibile linearmente, e (2,l,L)-Kakuro è risolvibile linearmente. Vedere [6] per ulteriori informazioni.

29 Capitolo 4 LAVORO SVOLTO 4.1 Kakuro e Answer Set Programming 4.1.1 Analisi e Modellazione La griglia di un generico schema Kakuro di dimensione m n, con m, n N, sarà definita da due insiemi fondamentali: l insieme delle caselle indizio (eventualmente contenenti uno o due valori) e l insieme delle caselle azionabili (inizialmente vuote), ovvero: I = {(hi, vi) i è una casella indizio e hi, vi [3, 45] sono i valori degli indizi, rispettivamente, orizzontale e verticale} A = {a a è una casella azionabile } Definizione 4.1 (Parola) Data una casella indizio i I e un valore val (hi, vi) non nullo ad essa associata, definirò con parolaval l insieme di caselle azionabili che si riferisce ad esso, definito nelle precedenti sezioni come parola. (a) Parola verticale (in giallo) (b) Parola orizzontale (in riferita al valore 15 di {Cb} rosso) riferita al valore 31 di {Bc} Figura 4.2 : Due parole di una griglia

30 Il Kakuro essendo un puzzle già definito su insiemi numerici, si può modellare in ASP (più in particolare in DLV). Prima di farlo definiamo una soluzione. Definizione 4.3 (Soluzione) Una soluzione è un insieme di cifre ciascuna associata ad una casella azionabile a A che risolve lo schema. Data la Def. 4.3 potremo definire una soluzione con un insieme di variabili X = {x a a A} definite su un dominio di cifre, cioè d interi [1, 9], dove ogni x a specifichi una cifra per una casella a. In base alle regole, i vincoli da applicare ad X per ottenere una soluzione saranno per ogni valore (orizzontale o verticale) v i, con i I e tale che v, i seguenti: I. a ParolaVal X a = V ; II. a, a Parola val : x a x a 4.1.2 Solver in DLV In questa sezione è illustrato il codice per la componente in DLV (ASP) del solver Kakuro. Il solver è costruito in modo tale che effettui una serie di assegnazioni casuali nella matrice data in input (Guess) e subito dopo verifichi che tale assegnazione rispetti tutti i vincoli ricavati attraverso le regole del gioco (Check). Nello specifico, per poter risolvere un dato schema, è necessario fornire in input al risolutore una serie di dati quali : 1. riga e colonna, che rappresentano le dimensioni della matrice da risolvere; 2. cellanera, che rappresenta una serie di celle in cui non è possibile effettuare delle assegnazioni, in tale dato vengono descritte anche le celle contenenti indizi.

31 3. sommariga e sommacolonna, che rappresentano i vari indizi orizzontali e/o verticali dati insieme allo schema. Codice %SOLVER KAKURO. %ASSEGNAZIONE DEI VALORI ALLE CELLE (GUESS). assegno(1,r,c) v assegno(2,r,c) v assegno(3,r,c) v assegno(4,r,c) v assegno(5,r,c) v assegno(6,r,c) v assegno(7,r,c) v assegno(8,r,c) v assegno(9,r,c) :- not cellanera(r,c), riga(r), colonna(c). %DEFINIZIONE DEI VINCOLI. %NELLE SOMME DI RIGA E COLONNA NON SI POSSONO AVERE DUE NUMERI UGUALI. :- sommariga(r,c,sum,l), assegno(val,r,c1), assegno(val,r,c2), C1!= C2, C < C1, C1 < C2, C3 = C + L, C2 <= C3. :- sommacolonna(r,c,sum,l), assegno(val,r1,c), assegno(val,r2,c), R1!= R2, R < R1, R1 < R2, R3 = R + L, R2 <= R3. %LA SOMMA DI RIGA E COLONNA DEVE ESSERE UGUALE A QUELLA DEFINITA %NELL INDIZIO. :- sommariga(r,c,sum,l), not #sum{val, C1 : assegno(val,r,c1), CMAX = C + L, C1 <= CMAX, C < C1} = SUM. :- sommacolonna(r,c,sum,l), not #sum{val, R1 : assegno(val,r1,c), RMAX = R + L, R1 <= RMAX, R < R1} = SUM.

32 4.1.3 Generatore di istanze difficili Kakuro in DLV In questa sezione ci soffermeremo sui dettagli di generazione di schemi Kakuro fornendo alla fine il codice per la componente in DLV(ASP). Questa funzione permetterà all'utente finale di generare schemi all'interno dell'applicazione. L utente deciderà a questo punto quali siano le dimensioni della matrice e se lo schema generato debba avere unica soluzione. La generazione di uno schema concettualmente si articola in due fasi distinte: Generazione della griglia: creazione di una griglia senza valori (nemmeno per gli indizi). Inserimento dei valori nelle caselle indizio: ricerca di uno schema vero e proprio (a volte con l aiuto del solver) con valori casuali per gli indizi a partire dalla griglia creata nel passo precedente. La generazione della griglia rispetta le convenzioni strutturali sempre presenti in uno schema del Kakuro comune, in partenza si genera una griglia casuale con celle bianche, cioè celle azionabili, e celle nere, cioè celle non azionabili in cui potremmo trovare indizi. Una volta generata la griglia si generano le caselle indizio rispettando quanto segue: La prima riga e colonna deve contenere solo celle nere; Senza indizi banali, cioè indizi seguiti da una sola casella in basso o a destra; Un insieme di caselle azionabili connesso, vale a dire che vi sarà sempre almeno un cammino tra due celle bianche della griglia che passi solo per altre celle bianche. Una volta terminato l inserimento di caselle indizio nella griglia, sarà semplice capire quali tra loro debbono contenere indizi orizzontali e/o verticali: per ognuna di queste basterà considerare la casella alla destra per capire se deve contenere l indizio orizzontale, se quest ultima è azionabile allora conterrà l indizio, mentre la casella in

33 basso per capire se deve contenere l indizio verticale, se quest ultima è azionabile allora conterrà l indizio. Nel caso in cui la cella a destra (basso) non è azionabile non avremo l indizio orizzontale (verticale). (Fig. 3.14) (a) Generazione Griglia (b) Generazione celle indizio Figura 4.4 : Orientamento per caselle indizio ( in blu valori orizzontali, rosso verticali) La ricerca dei valori legali per le caselle indizio non vuote rimaste procederà come segue: S inseriranno cifre casuali nelle caselle azionabili della griglia rispettando i vincoli che : o I valori contenuti nelle caselle di una parola siano tutti diversi; o I valori inseriti appartengono al dominio [1,9] Sommando, in ogni parola, i valori ottenuti nel passo precedente si potranno ottenere i valori per le caselle indizio (Fig. 4.5). Figura 4.5 : Dai valori nelle parola si ottengono valori per le caselle indizio.

34 Codice %GUESSO IL TIPO DI CELLE DELLA MATRICE. cellanera(r,c) v cellabianca(r,c) :- riga(r), colonna(c). %CONTROLLO CHE GLI ANSWER SET GUESSATI RISPETTINO %ALCUNE REGOLE. % NON E' POSSIBILE CHE IN UNO SCHEMA LA RIGA 1 E LA %COLONNA 1 SIANO CELLE BIANCHE :- cellabianca(r,c), R = 1. :- cellabianca(r,c), C = 1.

35 %NON E' POSSIBILE CHE IN UNO SCHEMA LA RIGA E %LA COLONNA NON ABBIANO ALMENO DUE CELLE %BIANCHE ADIACENTI esisteadiacenteriga(r) :- cellabianca(r,c), cellabianca(r,c1), C1 = C + 1. esisteadiacentecolonna(c) :- cellabianca(r,c), cellabianca(r1,c), R1 = R + 1. :- riga(r), R > 1, not esisteadiacenteriga(r). :- colonna(c),c > 1, not esisteadiacentecolonna(c). %VERIFICO CHE UNA CELLA BIANCA ABBIA ALMENO UN %ADIACENTE PER RIGA ED UN ADIACENTE PER %COLONNA IN MODO TALE DA POTER FORMARE DELLE L %NELLA MATRICE. numeroadiacenticellabianca(r,c,sum1,sum2):- cellabianca(r,c), #count { C1 : cellabianca(r,c1), C1 = C + 1 } = A, #int(a), #count{r1 : cellabianca(r1,c), R1 = R + 1 } = B, #int(b), #count { C1 : cellabianca(r,c1), C = C1 + 1 } = D,#int(D), #count{r1 : cellabianca(r1,c), R = R1 + 1 } = E, #int(e), SUM1 = A + D, SUM2 = B + E. :- numeroadiacenticellabianca(r,c,sum1,sum2), SUM1 < 1. :- numeroadiacenticellabianca(r,c,sum1,sum2), SUM2 < 1.

36 %ASSEGNO VALORI UNIVOCI ALLA CELLA BIANCHE assegno(1,r,c) v assegno(2,r,c) v assegno(3,r,c) v assegno(4,r,c) v assegno(5,r,c) v assegno(6,r,c) v assegno(7,r,c) v assegno(8,r,c) v assegno(9,r,c) :- cellabianca(r,c). %DEFINISCO QUANTO CELLE VERRANNO PRESE IN %CONSIDERAZIONE NELLA SOMMA PER RIGA A PARTIRE DA %CELLANERA(R,C) CHE HA ADIACENTE DUE CELLE BIANCHE cellanerasommariga(r,c) :- cellanera(r,c), cellabianca(r,c1), cellabianca(r,c2), C1 = C + 1, C2 = C1 + 1. distanzacellenereriga(r,c,c1,dist) :- cellanerasommariga(r,c), R > 1, cellanera(r,c1), C < C1, C1 = DIST + C. successivoriga(r,c,c1) :- cellanerasommariga(r,c), #min{ C2 : distanzacellenereriga(r,c,c2,dist), C2 > C } = C1, #int(c1). hasuccessivoriga(r,c) :- cellanerasommariga(r,c), successivoriga(r,c,c1). colonnamax(c) :- #max{c1: colonna(c1)} = C, #int(c). sommacellanerariga(r,c,l) :- cellanerasommariga(r,c), successivoriga(r,c,c1), C1 = C + A, A = L + 1, #int(a), #int(l). sommacellanerariga(r,c,l) :- cellanerasommariga(r,c), not hasuccessivoriga(r,c), colonnamax(c1), C1 = L + C, #int(l). hasommacellanerariga(r,c):- sommacellanerariga(r,c,l). :- cellanerasommariga(r,c), not hasommacellanerariga(r,c).

37 %DEFINISCO QUANTO CELLE VERRANNO PRESE IN %CONSIDERAZIONE NELLA SOMMA PER COLONNA A PARTIRE %DA CELLANERA(R,C) CHE HA ADIACENTE DUE CELLE %BIANCHE cellanerasommacolonna(r,c) :- cellanera(r,c), cellabianca(r1,c), cellabianca(r2,c), R1 = R + 1, R2 = R1 + 1. distanzacellenerecolonna(r,c,r1,dist) :- cellanerasommacolonna(r,c), C > 1, cellanera(r1,c), R < R1, R1 = DIST + R. successivocolonna(r,c,r1) :- cellanerasommacolonna(r,c), #min{ R2 : distanzacellenerecolonna(r,c,r2,dist), R2 > R } = R1, #int(r1). hasuccessivocolonna(r,c) :- cellanerasommacolonna(r,c), successivocolonna(r,c,r1). rigamax(r) :- #max{r1: riga(r1)} = R, #int(r). sommacellaneracolonna(r,c,l) :- cellanerasommacolonna(r,c), successivocolonna(r,c,r1), R1 = R + A, A = L + 1, #int(a), #int(l). sommacellaneracolonna(r,c,l) :- cellanerasommacolonna(r,c), not hasuccessivocolonna(r,c), rigamax(r1), R1 = L + R, #int(l). hasommacellaneracolonna(r,c) :- sommacellaneracolonna(r,c,l). :- cellanerasommacolonna(r,c), not hasommacellaneracolonna(r,c).

38 %VERIFICO CHE L' ASSEGNAZIONE SU RIGA E COLONNA %RISPETTA IL VINCOLO DI UNICITA' :- sommacellanerariga(r,c,l), assegno(val,r,c1), assegno(val,r,c2), C < C1, C1 < C2, C3 = C + L, C2 <= C3. :- sommacellaneracolonna(r,c,l), assegno(val,r1,c), assegno(val,r2,c), R < R1, R1 < R2, R3 = R + L, R2 <= R3. %DEFINISCO QUALI SONO LE CELLE CHE ÌNDICANO LE %SOMME, QUEST'ULTIME CALCOLATE ALL'ASSEGNAMENTO %PRECEDENTEMENTE GUESSATO. sommariga(r,c,sum,l) :- sommacellanerariga(r,c,l), #sum{val, C1 : assegno(val,r,c1), CMAX = C + L, C1 <= CMAX, C < C1} = SUM, #int(sum). sommacolonna(r,c,sum,l) :- sommacellaneracolonna(r,c,l), #sum{val, R1 : assegno(val,r1,c), RMAX = R + L, R1 <= RMAX, R < R1} = SUM, #int(sum). hasommariga(r,c) :- sommariga(r,c,sum,l). hasommacolonna(r,c) :- sommacolonna(r,c,sum,l). :- sommacellanerariga(r,c,l), not hasommariga(r,c). :- sommacellaneracolonna(r,c,l), not hasommacolonna(r,c). %DIMINUISCO LA PROBABILITA' CHE IL GENERATORE %GENERI SCHEMI SBAGLIATI FACENDO SI CHE LE %SOMME DEGLI INDIZI DI RIGA SIANO UGUALI ALLE %SOMME DEGLI INDIZI DI COLONNA :- #sum{sum : sommacolonna(r,c,sum,l)} = S1, #sum{sum : sommariga(r,c,sum,l)} = S2, S1!= S2.

39 4.2 Un'applicazione JAVA per il Kakuro 4.2.1 Interfaccia grafica Kakuro in Java Questa sezione mi sofferma sui dettagli implementativi relativi all interfaccia Kakuro costruita in Java. Sono descritte le strutture dati fondamentali e le scelte per l interfaccia grafica. Strutture dati Le quattro strutture dati per definire uno schema Kakuro, sono riga, colonna, matrice logica e matrice grafica. Di seguito si analizzerà nel dettaglio come sono definite. Riga è un intero che rappresenta la cardinalità orizzontale della griglia; Colonna è un intero che rappresenta la cardinalità verticale della griglia; Matrice Logica è una matrice contenente tutti i dati relativi allo schema, come ad esempio se una cella è di indizio oppure se è azionabile; Matrice Grafica è una matrice, costruita attraverso la matrice logica, che servirà a disegnare la griglia nel frame interno dell applicazione. Frame Interno In pratica il frame interno dell applicazione disegnerà le caselle della griglia a schermo e ne modificherà il contenuto a seconda delle mosse del giocatore o dei comandi. Inizialmente il giocatore dovrà decidere se generare un nuovo schema attraverso il generatore oppure aprire uno schema già esistente o ancora riprendere una partita salvata in precedenza. Per rendere una partita più giocabile da un giocatore umano ho implementato diverse funzionalità. Ad esempio, ogni qual volta il giocatore inserirà un valore non corretto (cioè con cui non è possibile risolvere lo schema proposto) e richiamerà la funzione Check, verrà segnalata in rosso la parola cui esso fa parte, come visibile in

40 fig. 4.6. Un altra opzione che rende la partita più giocabile è l aiuto (funzione Help ) il quale aggiunge alla griglia un valore casuale utile per poter completare lo schema. Inoltre, l applicazione prevede un editor di schema Kakuro in cui, appunto, è possibile editare il proprio schema Kakuro e, se lo si vuole, farlo risolvere dal solver oppure salvarlo. Infine, si ha la possibilità di salvare una partita in corso e riprenderla in un secondo momento. Figura 4.6 : Esempio di Kakuro a partita in corso Controlli Si potranno inserire cifre nel puzzle internamente via tastiera, nel seguente modo: Con il mouse si controlla il movimento (e la selezione) tra le caselle; Con il tastierino numerico s inseriranno le cifre, dopo essersi posizionati su una casella azionabile. I numeri inseriti possono essere cancellati con Esc;

41 4.3 Attività sperimentale In questo capitolo presentiamo il risultato di una attività sperimentale, volta a testare l'efficienza di diversi sistemi impegnati nella risoluzione di istanze Kakuro. E' bene ribadire che lo scopo principale di questa attività non era quello di decidere quale fosse il sistema più efficiente: non è infatti possibile stabilirlo testando soltanto le prestazioni su un'unica classe di problemi (in questo caso, il Kakuro); tuttavia, è possibile ricavare alcune indicazioni. Inoltre, vale la pena di sottolineare che mettere in piedi un sistema di benchmarking è un task non banale, e richiede molta cura, pena la perdita di significato dei risultati dell'attività sperimentale stessa. 4.3.1 Sistemi Testati In questa attività di benchmarking, sono stati confrontati dei sistemi che utilizzano il paradigma della programmazione logica. Tra i sistemi confrontati troviamo i rivali storici dell answer set programming DLV e GNT/Smodels, ed inoltre nuovi motori inferenziali quali Clasp, vincitore dell ultima answer set programming competition, e Sugar, vincitore dell ultima costraint stratification problem competition. 4.3.1.1 Il sistema DLV DLV, è il motore inferenziale costituito nell Università della Calabria utilizzato in tutto il mio lavoro di tesi e descritto nel Capitolo 2.5.

42 4.3.1.2 Il sistema GnT/Smodels GnT, come anche DLV, è una realizzazione sperimentale della semantica dei modelli stabili per programmi logici disgiuntivi [Gelfond e Lifschitz, 1991]. L applicazione si basa su una architettura composta da due interagenti risolutori smodels per i programmi non disgiuntivi. Uno dei quali è responsabile di generare modelli di possibili candidati, finché l altro controlla la minimalità del modello generato, come richiesto da disjuctive modelli stabili. Si veda [Janhunen et al., 2006] per i dettagli. L'autore della prima versione di GnT è Patrik Simons. La versione GnT1 è sostanzialmente quella originale, solo poche righe di codice sono state aggiunte per gestire opzioni da linea di comando. La seconda versione, che è un derivato del primo, è stato sviluppato da Tomi Janhunen per accelerare calcolo. Per maggiori informazioni sul sistema GNT/Smodels si veda la documentazione ufficiale[11]. 4.3.1.3 Il sistema Clasp Clasp, come i due sistemi precedentemente descritti, è un Answer Set Solver. Esso combina le capacità di modellazione di alto livello della programmazione answer set (ASP) con avanzate tecniche d avanguardia dall area del Boolean Costraint Solving. Il primo algoritmo di Clasp si basa sul conflitto guidato senza un buon apprendimento, una tecnica che si è rilevata un grande successo per il controllo di soddisfacibilità (SAT). A differenza di altri solutori di apprendimento ASP, Clasp non si basa su un software già esistente, come un risolutore SAT o di qualsiasi altro risolutore esistente ASP. Clasp può essere applicato come risolutore ASP (in formato SMODELS, come l output di Gringo), come un solutore SAT (su una versione semplificata del DIMACS / formato CNF), o come un solutore PB ( in formato OPB). Per maggiori informazioni sul sistema Clasp si veda la documentazione ufficiale[12].

43 4.3.1.4 Sugar e Costraint Satisfaction Problems (CSP) CSP Un CSP è un problema matematicamente trattabile definibile come un insieme di oggetti che devono soddisfare un certo numero di vincoli o limitazioni. In poche parole, rappresenta le entità di un problema attraverso una collezione finita di vincoli su delle variabili che sarà risolta con dei metodi definiti di soddisfacibilità dei vincoli. Definizione Formalmente, dati due interi n, k N, un CSP è definito come una tripla <X, D, V>, dove X = {x 1,,x n } è un insieme di variabili logiche, che rappresentano le entità definite nel problema. D = {D 1,,D n } è un insieme di domini finiti tale che ad ogni x i sia associato il corrispondente dominio D i, per ogni 1 i n. V = {V 1,,V k } è un insieme di vincoli definiti sulle variabili X che ne restringeranno (in qualche modo) i domini. Più precisamente un vincolo Vi, con 1 i k, sarà una coppia <s i, R i > formata da un sottoinsieme di variabili s i X e insiemi di valori per X, in R i, che rispettano il vincolo. Un assegnamento per X sarà una funzione di qualche tipo definita dalle variabili ai domini v : X D. Un assegnamento v di X così definito soddisferà a un vincolo <s i, R i > nel caso in cui valga che (v(x 1 ),..., v(x n )) R i. Una soluzione per un CSP, così definito, sarà un assegnamento v che soddisfi tutti i vincoli di V. A seconda delle proprie necessità, si potrà cercare relativamente al problema: Una (qualsiasi) soluzione valida Una soluzione ottima (definita secondo certi criteri)

44 Tutte le soluzioni possibili La ricerca delle soluzioni potrà esser condotta in modo sistematico, assegnando ad ogni variabile di X un valore possibile del suo dominio ed, in particolare, le classi di ricerca saranno essenzialmente due: quelle che ricercheranno i valori di una soluzione costruendone pian piano una ( e.g. il backtracking che assegna un valore per volta ad ogni variabile), con un assegnazione ad un numero di variabili via via più grande, e quelle che cercheranno di assegnare a tutte le variabili un valore in modo stocastico (come tecniche di propagazione dei vincoli sulle variabili). In genere, dato che nessun metodo appartenente a queste due classi porta con sé solo vantaggi (alcune sono molto lente, altre non sono complete, cioè non trovano sempre una soluzione anche quando è noto che ce ne è almeno una), si utilizzano dei metodi ibridi. Esempio Un esempio di CSP classico è la colorazione di una mappa : data una mappa, si deve colorarla in modo tale che due aree contigue non possono avere lo stesso colore. Un problema di colorazione della mappa è visibile in Fig. 4.7 Figura 4.7 Supponendo di avere a disposizione l insieme di colori {rosso, verde, blu }, potremmo ridurre la colorazione della mappa al seguente CSP: X = {x 1, x 2, x 3 } D i = {rosso, verde, blu }, con 1 i n

45 Un insieme di vincoli V = {V j, k x j, x k sono aree contigue, con j, k [1,3], per cui valga che x j x k } Gli archi nel grafo in Fig. 4.7 rappresentano i vincoli binari tra le variabili logiche definite da V. Una volta imposti alla mappa i vincoli citati si potranno ottenere soluzioni, cioè un valore per ogni elemento di X che rispetti i vincoli, al problema utilizzando una delle due classi di ricerca sistematica accennate in precedenza. Il sistema Sugar Sugar può risolvere Constraint Satisfaction Problem (CSP) oppure Constraint Optimization Problem (COP) utilizzando la codifica Boolean Satisfiability Testing Problems (SAT) e risolvendo il problema SAT con un SAT Solver esterno. Sugar utilizza una nuova codifica SAT chiamata codifica ordine. In questa codifica, un confronto x <= a è codificato da variabili booleani diversi per ogni variabile intera x e per ogni valore intero a. Si tratta di un estensione del metodo di codifica proposto da Crawford e Baker per i problemi di schedulazione Job-shop. Per maggiori informazioni sul sistema Sugar si veda la documentazione ufficiale[13]. 4.3.2 Istanze di Prova Le istanze di prova sono state generate casualmente attraverso il generatore descritto nel Capitolo 4.1.3. Tramite quest ultimo sono state generate 20 istanze per ciascuna matrice di grandezza: 5x6, 6x6, 6x9, 7x7, 8x8.

46 4.3.3 Risultati Ottenuti e Discussione In questa sezione, presentiamo i risultati ottenuti. Nella Tabella 4.8 sono rappresentati i risultati per ogni istanza del puzzle: nella Figura 4.9, invece, sono rappresentati attraverso un grafico i risultati medi per ogni dimensione del puzzle. Per ogni istanza verranno mostrati i tempi computazionali di risoluzione, calcolati attraverso il comando time. I risultati corrispondono alla media dei tempi, calcolati ripetendo cinque volte ciascuna istanza su un singolo motore inferenziale. Possiamo reputare quest ultimi abbastanza veritieri in quanto la loro deviazione standard è molto bassa. Il risultato più evidente, prevedibile, è che Clasp, vincitore dell ultima competizione per sistemi ASP, è più veloce rispetto agli altri due solver ASP, DLV e GNT/Smodels, ed è anche più veloce rispetto al vincitore dell ultima competizione per sistemi CSP, Sugar. Per scoprire il motivo di queste differenze prestazionali bisognerebbe studiare come lavorano i vari solver al loro interno, ma tale studio esula dagli scopi di questo lavoro di Tesi. Focalizzandoci, invece, sui solver ASP "storici", DLV e GNT/Smodels, si rileva che, considerando il tempo totale di risoluzione, GNT/Smodels è in genere più veloce rispetto DLV; questo si spiega con il fatto che, la fase di grounding del sistema GNT/Smodels non è stata svolta da lparse (per problemi tecnici) ma da gringo, e questo arreca ad esso un po di vantaggio. E' il caso di osservare, però, come in alcuni schemi DLV risulta essere più veloce. Inoltre, se si considera l aspetto di rappresentazione della conoscenza, soggettivamente a vincere è la sintassi di DLV, molto più naturale rispetto alla sintassi Lparse o Gringo, che è risulta essere meno intuitiva. Per concludere il lavoro di benchmarking è stato costruito un solver CSP, con precisione in Sugar. Lo scopo non era, quello di un confronto prestazionale nudo e crudo, quanto piuttosto un confronto in termini di immediatezza ed efficacia delle capacità di rappresentazione del problema, rispetto al solver Kakuro descritto in ASP, con precisione in DLV. Anche in questo caso, come in precedenza affermato nel confronto fra i due motori inferenziali ASP, possiamo dire che la costruzione del solver

47 in DLV è molto più naturale rispetta alla costruzione del solver in Sugar, anche perché in quest ultimo bisogna descrivere le regole del gioco per ogni singola riga e colonna della matrice, mentre in ASP le regole del gioco si descrivono con quattro regole ASP, per meglio dire si descrivono attraverso quattro costraint. Possiamo notare che per una matrice N x M avente K celle indizio e Z celle nere in Sugar abbiamo: N x M regole che descrivono il dominio di appartenenza di ogni singola cella della matrice, 2*K regole, K che descrivono il vincolo di somma e altre K che descrivono il vincolo di diversità dei valori in quella determinata somma, ed infine abbiamo Z regole che descrivono le celle nere assegnando a tali celle il valore 0. Mentre in DLV abbiamo lo stesso numero di regole, qualsiasi sia la dimensione della matrice, che descrivono i vincoli del gioco: quattro costraint, due per il vincolo di somma e due per il vincolo di diversità; una quinta regola che descrive l assegnamento dei valori nelle celle della matrice ed infine due regole, o meglio fatti, che descrivono la cardinalità della matrice. Inoltre, considerando i parametri sopra descritti, abbiamo altri Z fatti che descrivono le celle nere ed altri X fatti che descrivono le celle indizio. Quindi se consideriamo una matrice 10 x 10 con 50 celle nere e 50 celle indizio in Sugar, tale schema viene descritto attraverso 250 regole mentre in DLV viene descritto attraverso 107 regole. Si può ancora notare come in ASP sia molto più naturale e semplice descrivere il problema rispetto CSP. Inoltre, confrontando i due sistemi sotto termini prestazionali, si nota che Sugar sul tempo totale è leggermente più veloce rispetto DLV, ma in alcuni schemi DLV è decisamente più veloce di Sugar. Infine, possiamo aggiungere che i tempi di esecuzione non dipendono strettamente dalla grandezza della matrice, come ci aspettavamo, infatti, una matrice 7 x 7 è risolta molto più velocemente rispetto una matrice 5 x 6. Possiamo quindi presupporre che il tempo di esecuzione sia strettamente legato al numero di celle bianche presenti nella matrice, cioè celle nelle quali bisogna "guessare" il valore esatto in modo tale che si rispettino i vincoli del gioco. Inoltre, come si può visualizzare nel grafico di Figura 4.9 il motore inferenziale più stabile, cioè il solver che impiega più o meno lo stesso tempo per qualsiasi tipologia di schema, considerando tutti i sistemi testati, è Sugar, mentre, prendendo in considerazione soltanto i motori inferenziali ASP è Clasp.

48 5X6 6X6 6x9 DLV-System GNT/Smodels-System Clasp-System Sugar-System 0,06000 0,13600 0,01200 0,72200 0,36000 0,12000 0,01400 0,67000 0,06400 0,11000 0,02000 0,70000 1,56200 0,33200 0,02000 0,72400 2,90600 0,41800 0,01600 0,72200 2,17600 0,57600 0,02200 0,71000 2,65800 0,54000 0,01600 0,72000 1,46400 0,31600 0,01400 0,73800 1,36100 0,31600 0,00800 0,67800 1,91400 0,22400 0,01600 0,63000 2,57200 0,41000 0,02400 0,73400 0,18200 0,37600 0,01000 0,71400 0,11800 0,32600 0,01600 0,59600 0,23800 0,45400 0,02200 0,70400 1,41200 0,50800 0,01800 0,66400 0,77600 0,17200 0,01800 0,68200 2,09200 0,51800 0,00600 0,69200 0,18200 0,29800 0,01600 0,72800 0,03200 0,20400 0,01600 0,70600 0,26000 0,31600 0,02000 0,71800 0,68800 0,07600 0,01400 0,70200 2,16400 0,11800 0,01200 0,74200 1,97200 0,10800 0,01600 0,73000 2,83800 0,10400 0,02000 0,74600 1,47600 0,12800 0,01600 0,74800 0,87400 0,10600 0,01000 0,73400 1,62800 1,01000 0,02600 0,73800 2,07600 0,12000 0,01200 0,75000 0,91800 0,08200 0,01200 0,72600 0,89400 0,07400 0,01200 0,73800 4,76200 0,10800 0,01800 0,75000 3,46400 0,11200 0,02200 0,75400 3,54200 0,09400 0,01200 0,75800 0,69800 0,08800 0,01400 0,73000 1,52800 0,07400 0,01000 0,73200 1,51800 0,12600 0,01000 0,78400 2,48800 0,09200 0,00600 0,74800 1,62200 0,09200 0,01800 0,74000 0,85200 0,08000 0,02000 0,71600 0,83000 0,90600 0,01800 0,74600 0,77000 0,02200 0,02200 0,74200 2,23800 0,01600 0,02000 0,74400 1,58000 0,02800 0,02400 0,74600 1,54400 0,01600 0,01400 0,73800 1,78200 0,02200 0,02200 0,73600 0,76000 0,02400 0,02000 0,74600 1,11800 0,02400 0,02800 0,73800 3,20000 0,02400 0,02400 0,74600 1,99400 0,01800 0,02600 0,73400 1,85800 0,01800 0,02200 0,75400 2,78200 0,02400 0,01800 0,73800 0,99800 0,02600 0,01600 0,73400 0,74800 0,02400 0,02000 0,75600 2,07400 0,01800 0,02000 0,76200 1,56000 0,02400 0,02800 0,72800 1,44600 0,02200 0,02000 0,71400 1,70800 0,02400 0,02200 0,74400 0,66200 0,01600 0,02800 0,72600 0,67000 0,01600 0,02400 0,74400 1,92400 0,02000 0,02000 0,75800

49 7x7 8x8 0,11400 0,02200 0,01400 0,74200 0,16800 0,01600 0,02000 0,75200 0,08600 0,01600 0,02000 0,73400 0,10200 0,02400 0,02000 0,74400 0,24800 0,02000 0,02600 0,68600 0,08600 0,00400 0,01400 0,71800 0,12000 0,02000 0,01200 0,70800 0,10000 0,01600 0,02000 0,71800 0,09000 0,02000 0,01800 0,67000 0,33000 0,16000 0,02000 0,75800 0,10000 0,02400 0,01800 0,73600 0,28400 0,02200 0,01800 0,73000 0,29400 0,02200 0,01400 0,74200 0,09600 0,02200 0,02000 0,74800 0,32600 0,02000 0,02400 0,74400 0,09400 0,01400 0,01000 0,70200 0,09800 0,01200 0,01400 0,75800 0,11200 0,01400 0,02000 0,73400 0,27800 0,02000 0,01800 0,78200 0,09400 0,01800 0,01600 0,77000 0,08800 0,01200 0,01200 0,72800 0,51000 0,02600 0,02200 0,78800 0,65600 0,02800 0,02200 0,78000 0,63400 0,02600 0,02200 0,77400 0,61200 0,02400 0,01600 0,77000 0,10400 0,02200 0,02400 0,77000 0,11000 0,02800 0,01600 0,77400 4,23800 0,02200 0,02200 0,65000 0,10400 0,01400 0,01400 0,50600 0,10600 0,02600 0,02400 0,72000 0,09800 0,02000 0,01200 0,75400 0,09000 0,02200 0,01800 0,68000 2,06800 0,02000 0,01800 0,77800 0,17000 0,02600 0,01800 0,67400 2,92400 0,02400 0,01600 0,71400 0,59400 0,02400 0,02800 0,76600 0,63400 0,02600 0,02000 0,78200 0,10600 0,02400 0,02800 0,77000 0,11400 0,02800 0,02200 0,77600 0,11200 0,02800 0,02000 0,77200 Tabella 4.8 : Risultati Benchmarking

Grafico 4.9 : Risultati Benchmarking 50

51 Capitolo 5 CONCLUSIONI E SVILUPPI FUTURI In questo lavoro di tesi abbiamo studiato il paradigma di programmazione dichiarativa offerta dalla Answer Set Programming. Grazie ad esso abbiamo progettato e realizzato un risolutore di schemi Kakuro, ed inoltre anche, un generatore di istanze che consente di ottenere schemi di qualunque dimensione. Tramite una integrazione del sistema ASP DLV abbiamo quindi creato un applicazione che consente di cimentarsi nel rompicapo in oggetto, provando a risolvere gli schemi generati automaticamente e sfruttando il risolutore per avere dei suggerimenti. Infine, abbiamo pianificato e condotto una rigorosa attività sperimentale, testando su un numero significativo di istanze di diversa dimensione alcuni tra i più diffusi sistemi ASP oggi disponibili ed l'attuale più quotato sistema CSP, traendo interessanti considerazioni riguardo alle prestazioni ed alla facilità di uso di questi strumenti. Di seguito illustriamo in che modo crediamo che sia possibile raffinare ulteriormente il lavoro svolto. Solver I vincoli del solver fornito in questa relazione, non rappresentano altro che una formalizzazione matematica (poi implementata) delle regole del puzzle. Sebbene questo sia sufficiente per risolvere uno schema rappresenta solo un primo passo, come i giocatori esperti sanno, nella comprensione profonda del puzzle. Dopo qualche partita, infatti, inizieranno ad emergere dei pattern di configurazioni particolari della griglia che possono portare ad escludere (o includere) certi valori dalla soluzione; l analisi di questi pattern porta il giocatore umano ad adottare tecniche sempre più raffinate di risoluzione, consentendogli di risolvere una griglia con passo sempre più spedito. Suddetti pattern sono in genere esprimibili come vincoli di alto livello su alcuni insiemi già definiti nei vincoli delle regole, e, pur non essendo necessari, applicati

52 congiuntamente ai vecchi vincoli consentiranno di restringere ulteriormente il dominio delle variabili, semplificando, il processo di calcolo. E di seguito presentato un esempio chiarificatore. (a) Figura 5.1 : domini ristretti a seconda dei valori degli indizi (b) Osservando la parola evidenziata in Fig 5.1a si potrà notare come non è possibile che questa possa contenere elementi con valori superiori a 4 perché il valore dell indizio e 5, che può essere risolto con 4+1 o 3+2. In generale, dato un valore di un indizio val, le caselle che compongono la parola dell indizio non potranno contenere un valore superiore a (val 1) per una parola di due caselle, (val 3) per una di tre, (val 6) per una di quattro. Ancora, notando, le parole evidenziate in Fig. 5.1b si scoprirà che per certi valori pari degli indizi (da 4 a 16) riferiti a parole da due caselle è sempre possibile eliminare dai possibili valori inseribili le cifre corrispondenti alla metà del valore; poiché non sono ammesse ripetizioni in una parola (es. dato un valore 6, sarà possibile risolverlo con 1+5 o 2+4, ma mai con 3+3).