Costruzione di un meta-motore di ricerca usando Prolog:
Transcript
Costruzione di un meta-motore di ricerca usando Prolog:
UNIVERSITÀ CA’ FOSCARI DI VENEZIA FACOLTÀ DI SCIENZE MATEMATICHE, FISICHE E NATURALI CORSO DI LAUREA SPECIALISTICA IN INFORMATICA Approfondimento per il corso di “Linguaggi Logici” “WWW Programming with Computational Logic System” Autore: Gaglio Elia (809477) Prof.ssa: Annalisa Bossi Anno Accademico: 2006/07 Indice: Abstract……………………………………………………………………….. pag. 3 1. LogicWeb: come integrare la Programmazione Logica con il WWW 1.1 Perché integrare la LP al WWW?.............................................................pag. 4 1.2 Che cos’è LogicWeb?...............................................................................pag. 4 1.3 Un esempio pratico: un “Page Searcher” logico………………………...pag. 6 2. PiLLoW: una libreria per integrare la LP e il WWW 2.1 Perché PiLLoW è stato sviluppato?..........................................................pag. 8 2.2 Come si può scrivere una applicazione cgi-bin di base?..........................pag. 8 2.3 Trattare documenti HTML come insiemi di termini Prolog…………….pag. 9 2.4 Come effettuare l’accesso a documenti WWW…………………………pag. 11 3. Costruzione di un meta-motore di ricerca logico: 3.1 I problemi che affliggono i motori di ricerca tradizionali………….……pag. 12 3.2 Soluzione: implementazione di meta-motori di ricerca………….……...pag. 12 3.3 Le funzionalità del meta-search engine “PrologCrawler”………….……pag. 13 3.4 Interfacciamento con i motori di ricerca………………………………...pag. 13 3.5 Implementazione di “PrologCrawler”…………………………………...pag. 14 4. LP nel Web Moderno: 4.1 Dalla LP + WWW fino al “Semantic Web”……………………………..pag. 19 4.2 Metalog: come aggiungere ragionamento al Web...………………..……pag. 21 4.3 xml.pl: Parsing XML with Prolog.………………...……………….……pag. 25 5. Conclusioni…………………………………………………………………..pag. 29 6. Bibliografia……………………………………….……………………….…pag. 30 2 Abstract: Con il termine “WWW Programming with Computational Logic System” si intende la possibilità di sviluppare applicazioni Web sfruttando i paradigmi e le tecniche specifiche della programmazione logica. Obiettivo di questo approfondimento è quello di proporre un insieme di esempi che permettano di dimostrare come la programmazione logica (LP) possa essere affiancata alle moderne ed emergenti applicazioni WWW, in modo da ottenere dei vantaggi in termini di tempi e complessità nel loro sviluppo. Ecco quindi che verranno descritti degli spunti di ricerca valutati interessanti e che hanno permesso tale integrazione. Gli articoli analizzati sono stati inseriti in ordine cronologico, al fine di far notare come nel corso degli anni siano stati realizzati lavori sempre più apprezzabili e come la congiunzione LP e WWW abbia portato a spunti e lavori interessanti. Il primo articolo proposto descrive LogicWeb, un progetto di ricerca svolto dall’Università di Melbourne nel periodo a cavallo del 1996/97 e che è stato un buon punto di partenza per proporre alcune applicazioni WWW “logiche”. Tra di esse si è scelto di presentare un PageSearcher, ovvero un’applicazione che permette di effettuare delle ricerche di pagine Web sulla base di una lista di keywords passate in input. In seguito sono state proposte altre soluzioni per sviluppare applicazioni WWW in modo semplice e veloce, sfruttando librerie e strumenti di base che permettano un risparmio di tempo e di sforzi. Un esempio del genere viene da PiLLoW, una libreria sviluppata nel 1997 e che permette la generazione di documenti HTML, trattandoli come insieme di termini di Herbrand. Partendo da questi strumenti sono stati realizzati diversi lavori, tra i quali si può citare, ad esempio, un meta-motore di ricerca logico sviluppato in un progetto di ricerca dell’Università di Pisa nel 1999 e denominato “PrologCrawler”. Quest’ultimo progetto risulta essere interessante sia per l’obiettivo che si prefigge (l’eliminazione di alcuni problemi che affliggono le ricerche effettuate nel web mediante i classici motori di ricerca), sia per il metodo di sviluppo che sfrutta in modo esplicito alcune tecniche della programmazione logica. Dopo aver proposto tali esempi viene riportata una conclusione del lavoro, includendo una considerazione sull’importanza della LP nel Web moderno, il cosiddetto “Semantic Web”, introdotto esplicitamente dal consorzio W3C nel 2001. Verrà proposto un primo caso di studio, nel quale si analizzerà Metalog, un progetto del 2004 basato sull’idea della costruzione di un sistema “query/logical” che permetta di effettuare ragionamenti sugli oggetti presenti nel Web garantendo un livello che sia il più possibile “user-friendly”. Infine si analizzerà il modulo xml.pl, il quale permette un parsing efficiente di documenti XML e XHTML e che riveste un punto di partenza interessante per la realizzazione di diverse tipologie di applicazioni e di programmi scritti in Prolog. 3 1. LogicWeb: come integrare la Programmazione Logica con il WWW: 1.1 Perché integrare la LP al WWW? LogicWeb nasce dall’idea di poter integrare la programmazione logica con il World Wide Web (WWW). Come tutti sanno la programmazione logica è basata sulla Logica Matematica, dove la computazione è costituita da un insieme di assiomi e di regole, da cui poter fare delle deduzioni. Le proprietà che essa garantisce sono molto apprezzabili e solide. Tra di esse possiamo includere: - una vista dichiarativa dei programmi che si possono realizzare, - un modo uniforme per rappresentare i dati e la computazione, - una semantica di base ben fondata. Negli ultimi anni si è assistito ad uno sviluppo enorme di Internet e di tutte le applicazioni ad esso collegate. In particolar modo, le applicazioni che manipolano Database, i tools di ricerca di informazioni ed altre applicazioni, sono diventate la chiave per un utilizzo efficiente del WWW. Da qui è nata l’idea di integrare il tutto con la programmazione logica, visti i vantaggi che essa garantisce e che sono stati illustrati precedentemente. Infatti le pagine web scritte in HTML standard hanno un “comportamento statico e scarsamente programmabile”. Difatti: - - La semantica dei links cliccabili in una pagina è fissata ad una semplice relazione attraverso la quale la pagina richiesta viene scaricata e visualizzata. In questo modo la pagina che contiene il link e la pagina che viene referenziata non hanno risposta della dereferenziazione che viene effettuata. Una pagina web non può processare query più generali di un semplice hyperlink. Non ci sono modi per una pagina di poter collezionare e manipolare dati da altre risorse e in più generale di poter creare delle relazioni tra pagine. Proprio da questi limiti si è studiato un modo per rendere il Web e le sue applicazioni più programmabile, e maggiormente trattabile da un punto di vista semantico. 1.2 Che cos’è LogicWeb? L’idea di base di LogicWeb è quella di poter trattare le pagine web come dei moduli di programmazione logica. In questo modo le pagine possono diventare delle entità di informazione, che possono essere interrogate mediante le query utente. L’utilizzo della programmazione logica permette di estendere i fondamenti teorici che essa rispetta al mondo WWW, permettendo quindi dei grossi miglioramenti a livello applicazione. In particolare, si riescono ad ottenere vantaggi specifici in fase di ricerca di informazioni, grazie all’utilizzo della tecnica del backtracking, nelle applicazioni di pattern matching visto l’utilizzo delle tecniche di unificazione e si ha la possibilità di definire una semantica per ogni tipo di estensione Web. LogicWeb permette una corrispondenza tra le pagine Web e i programmi logici costituiti da fatti e regole. Da ciò nascono dei moduli detti LogicWeb modules, che permettono di dare una semantica a tutto ciò di cui disponiamo in ambito WWW. Infatti, una pagina web caratterizzata dall’avere una URL <URL> corrisponde ad un modulo il cui nome è il termine m_id(<URL>). Tale modulo contiene i seguenti due fatti: my_id(<URL>) che permette di memorizzare la URL della pagina; 4 h_text(<HTML source>) che permette di memorizzare il codice HTML della pagina; In questo modo è possibile modellare una semplice pagina web. I vantaggi che si ottengono da ciò sono molto interessanti: la pagina può essere parserizzata al fine di estrarre un insieme di fatti, come ad esempio una collezione di links: <A HREF="http://www.cs.mu.oz.au/~swloke/logicweb.html">LogicWeb</A> è rappresentabile dal seguente fatto: link("LogicWeb","http://www.cs.mu.oz.au/~swloke/logicweb.html"). E’ chiaro quindi che si possono definire altre clausole associate ad una pagina web, le quali permettono di definire il comportamento della pagina stessa e di effettuare delle query. Tutte queste clausole vengono denominate “live clauses”. Le live clauses permettono di effettuare delle operazioni interessanti attraverso le diverse pagine web, sfruttando l’utilizzo di nuovi operatori che estendono i programmi logici Prolog “classici”. Tra essi si possono citare: - context switching: mediante questo operatore un modulo LogicWeb può utilizzare le clausole di un altro modulo. La sintassi è la seguente: m_id (<URL>)#>Goal In questo modo è possibile richiamare il goal Goal anche se non fa parte del modulo corrente. Mediante l’operatore #> è possibile effettuare la referenziazione di un modulo esterno (dove il modulo rappresenta la pagina Web di url URL), il quale verrà automaticamente caricato nel sistema client che ne fa la sua richiesta (nel caso in cui non sia stato già caricato con qualche operazione precedente). Esiste anche l’operatore :>, che funziona allo stesso modo del predicato prima descritto, ad eccezione del fatto che fallisce nel caso in cui la pagina a cui si punta non sia stata già caricata. - union: permette l’unione di due moduli LogicWeb. Tale operatore è utile nel momento in cui bisogna effettuare la valutazione di una query rispetto a due o più moduli logici. La sintassi risulta essere la seguente: lw_union (ListOfModules)#>Goal In questo modo è possibile effettuare la valutazione del goal Goal mediante l’unione dei moduli inseriti in ListOfModules. - relationship: è stato definito un predicato attraverso il quale è possibile definire una relazione tra coppie di pagine. La sua sintassi è la seguente: related (<URL1>,<URL2>) E’ chiaro perciò che l’utilizzo combinato di questi nuovi operatori porta ad un grosso vantaggio nello sviluppo di applicazioni di svariato tipo, in particolar modo quelle relative alla ricerca di parole o oggetti presenti all’interno delle pagine web. Infatti è molto interessante la possibilità che viene offerta di poter combinare tra loro componenti di pagine differenti in un'unica nuova pagina. 5 1.3 Un esempio pratico: un “Page Searcher Logico”: Un esempio interessante di applicazione realizzabile web realizzabile con Prolog e con alcuni operatori introdotti in precedenza è un Page Searcher, ovvero un’applicazione che permette di effettuare delle ricerche di pagine Web, passando in input una o più keywords. La maggior parte dei siti presenti nel Web offre dei motori di ricerca basati su indici realizzati da robot. In questo esempio verranno effettuate delle ricerche sfruttando le regole definite nella programmazione logica per guidare la ricerca e poter definire il “grado di interesse” delle pagine correlate. Utilizzando la programmazione logica è possibile ottenere dei vantaggi grazie alla semplificazione dell’intera fase di ricerca, merito di una semplicità nel definire le relazioni tra le entità coinvolte (ovvero le pagine Web) e la capacità di esprimere informazioni complesse. L’algoritmo è codificato sfruttando una serie “live clauses” all’interno della pagina web pgssearch.html, attraverso la quale è possibile inserire le query di ricerca. Una volta inserita l’interrogazione l’applicazione invoca il seguente goal: ?- pgs_search(<Keywordlist>,<PassScore>,<NumOfPgs>) Il programma quindi effettua una selezione delle pagine Web di interesse esaminando il fatto located_at/2 nel file pgssearch.html. La ricerca segue i links ad altre pagine effettuando una ricerca “breadth-first” ed assegnando un punteggio a ciascuna pagina in base alla rilevanza con la keyword list definita. Naturalmente il programma mantiene traccia delle pagine visitate. In seguito, il risultato della ricerca viene proposto all’utente creando una pagina web apposita e riportando solamente le pagine che hanno superato il PassScore, ovvero il limite minimo di keyword presenti nella pagina. Il numero di risultati riportato è un parametro di input per l’utente. La misura della rilevanza di una pagina dipende dal numero di occorrenze della keyword dalla lista iniziale, o di keywords correlate alla lista originale. La relazione di correlazione è definita mediante il fatto related/2. Per ciascuna pagina visitata si effettua il parsing delle informazioni presenti nei links e si memorizza il tutto nel fatto link (<label>,<URL>). In questo modo si crea una corrispondenza tra una URL e una label e nel caso in cui una label contenga una keyword, l’URL associata viene automaticamente inserita in coda alla lista delle pagine Web da visitare. Il fatto located/2, inoltre, funge da puntatore alle pagine web da visitare. E’ interessante notare che, poiché l’insieme delle pagine definito dal fatto related/2 si sviluppa mentre vengono trovate nuove pagine, keywords considerate non correlate precedentemente possono diventare correlate in seguito. Tale comportamento è catturato dal predicato path_related/3, che permette di inferire circa la correlazione tra due keywords: path_related(X,Y,VisitedNodes):- M:>related(X,Y), not(member(Y,VisitedNodes)). path_related(X,Z,VisitedNodes):- M:>related(X,Y), not(member(Y,VisitedNodes)), path_related(Y,Z,[Y|VisitedNodes]). Forma un grafo diretto tra due keywords, nel caso siano correlate Istanziato con moduli differenti, mediante il backtracking e cercando attraverso i fatti esistenti contenuti nel fatto related/2 6 Dopo che un numero sufficiente di pagine è stato ritrovato si effettua la costruzione di una pagina di risultato, da proporre all’utente. Per effettuare la costruzione si sfruttano i seguenti predicati: build_head/2, build_body/3, build_whole/3 Ad esempio: build_head("Interesting URLs",Head) effettua un’istanziazione di Head con la stringa passata in input. Ciò è equivalente al codice HTML: “<HEAD>\n <TITLE>Interesting URLs</TITLE>\n </HEAD>” Questo semplice esempio introdotto permette di dimostrare diverse caratteristiche tipiche di LogicWeb: - E’ possibile considerare e manipolare diverse pagine Web sfruttando l’operatore #>. E’ possibile effettuare il parsing delle informazioni contenute nei link di una pagina ed effettuarne la memorizzazione. Inoltre, il parsing e la possibilità di costruire delle relazioni tra link possono essere estesi e resi più complessi. Il fatto located/2 permette di stabilire una relazione tra le pagine e quindi di arricchire le relazioni già presenti e rilevate in precedenza. 7 2. PiLLoW: una libreria per integrare la LP e il WWW: 2.1 Perché PiLLoW è stato sviluppato? La possibilità di integrare le applicazioni WWW con la programmazione logica è una area di ricerca che nel corso degli anni ha dimostrato un grosso sviluppo e dei risultati molto convincenti. In particolare molte applicazioni che oggi la fanno da padrone, come motori di ricerca, applicazioni che sfruttano Database, ecc. ben si sposano ad uno sviluppo che sfrutta le tecniche della programmazione logica. In particolare, la LP condivide molte caratteristiche presenti in linguaggi di programmazione recenti e utilizzati per la programmazione in rete. Tali caratteristiche includono la gestione dinamica della memoria, una buona robustezza di base e la possibilità di effettuare una compilazione che costruisca del bytecode. Oltre a tutto ciò la LP offre delle tecniche di meta-programmazione molto sofisticate e raffinate e una semantica ben definita. Facendo leva su tutte queste proprietà si è deciso di sviluppare una libreria apposita che permetta di costruire in modo semplice e veloce delle applicazioni Web “logiche” (ovvero che sfruttano la LP). Da quest’idea è nata PiLLoW, una libreria che genera documenti HTML o XML trattandoli come insieme di termini di Herbrand e permette la costruzione di form e di tools più complessi, utili per ricerche e parsing di documenti WWW. Vista la vastità degli esempi che possono essere proposti, ci si concentra verso quei predicati e quelle strutture di PiLLoW che permettono lo sviluppo di applicazioni WWW utilizzate per effettuare l’accesso e il parsing di documenti web. 2.2 Come si può scrivere una applicazione cgi-bin di base? Un modo semplice per scrivere un’applicazione WWW è quello di utilizzare gli script CGI. Un CGI eseguibile non è altro che un semplice file eseguibile che viene richiamato da un web server. In particolare, quando un utente seleziona un indirizzo di un file eseguibile CGI (caratterizzato quindi dall’estensione .cgi), il browser effettua una richiesta apposita che verrà interpretata da un web server e farà avviare l’esecuzione dell’eseguibile. Tutti gli output che verranno generati saranno raccolti in un buffer e in seguito verranno codificati in una pagina web passata all’utente. Ecco una rappresentazione grafica del funzionamento: Figura 1: chiamata ad uno script CGI. 8 E’ possibile scrivere eseguibili sfruttando la programmazione logica. In questo modo si potrà vedere la LP come una soluzione per progettare scripts di diversa natura, utilizzabili ad esempio in ambito Web. Un semplice esempio di un eseguibile scritto in LP è il seguente: main :- write('Content-type: text/html'), nl, nl, write('<HTML>'), write('Hello world.'), write('</HTML>'). I linguaggi logici si adattano bene ad essere dei candidati ottimali per essere utilizzati come linguaggi di scripting. Per rendere più conveniente tale passaggio è utile fornire un modo per eseguire i programmi logici come degli scripts. Ecco quindi che molti progetti di ricerca sono stati finalizzati a cercare di rendere semplice il supporto per lo scripting nei maggiori sistemi di LP. Ad esempio, è possibile sfruttare una lpshell in un sistema di LP, la quale carica il file passato come primo argomento ed avvia l’esecuzione dal predicato main/1. In un sistema UNIX è possibile lanciare il seguente programma come uno script che non necessita di compilazione: #!/usr/local/bin/lpshell main(_) :- write('Content-type: text/html'), nl, write('<HTML>'), write('Hello world.'), write('</HTML>'). 2.3 Trattare documenti HTML come insiemi di termini Prolog: Una delle caratteristiche chiave della programmazione logica è quella di effettuare il processamento sfruttando un insieme di termini di Herbrand. Ecco quindi che può venire naturale pensare di associare al codice HTML un insieme di termini. PiLLoW introduce dei predicati che permettono di definire una relazione esplicita tra una pagina WWW e un insieme di termini di Herbrand. Tali predicati sono: - output_html(F): il quale accetta F come una lista di termini HTML e invia allo “standard output” il testo interpretato come una lista di termini in formato HTML. - html2terms(Chars, Terms): permette di definire una relazione tra una lista di termini HTML e una di caratteri ASCII, i quali sono l’interpretazione dei termini in formato HTML. Tale predicato è reversibile: esiste infatti output_html/2 che trasforma termini HTML in caratteri. Ecco un insieme di strutture Prolog che rappresentano le principali funzionalità HTML esistenti: Strutture generali: Fondamentalmente HTML definisce due tipi di componenti: - HTML elements: caratterizzati da una forma tipo “<NAME Attributes>”; - HTML environment: caratterizzati da una forma <NAME Attributes> Text </NAME>. Le principali strutture Prolog che permettono di definire queste due tipologie di costrutti sono le 9 seguenti: - Name$Atts: permette di rappresentare un elemento HTML di nome Name e attributi Atts. Ad esempio: img$[src='images/map.gif',alt='A map',ismap] è convertito in HTML in questo modo: <img src="images/map.gif" alt="A map" ismap> - name(Text): rappresenta un environment HTML di nome name che include un testo Text. Ad esempio: address('[email protected]') è convertito in HTML in questo modo: <address>[email protected]</address> - name(Atts,Text): rappresenta un environment HTML di nome name, attributi Atts e che include il testo Text. Ad esempio: a([href='http://www.clip.dia.fi.upm.es/'],'Clip home') è convertito in HTML in questo modo: <a href="http://www.clip.dia.fi.upm.es/">Clip home</a> - env(Name,Atts,Text): è equivalente all’ultima strutura. Strutture specifiche: PiLLoW permette la definizione di strutture specifiche, presenti nei documenti HTML, come: - start: usata per definire l’inizio di un documento. E’ equivalente a <html>. - end: utilizzata per definire la fine di un documento. E’ equivalente a </hmtl>. - $: produce l’inizio di un nuovo paragrafo (<p>). - comment: permette l’inserimento di un commento HTML. - image(Addr): utilizzata per inserire l’indirizzo Addr di un’immagine. Questi sono solo alcune delle strutture che sono definibili. Inoltre è presente un predicato specifico, html_expansion/2, che permette di definire nuove strutture. Se aggiungiamo questa caratteristica al fatto che sono state definite in seguito delle strutture apposite per generare specifiche strutture HTML, come gli input elements delle form, capiamo che sono generabili praticamente tutte le strutture HTML esistenti. In questo modo è possibile facilitare la generazione di documenti HTML di diversa complessità e livello. 10 2.4 Come effettuare l’accesso a documenti WWW: Nelle pagine precedenti è stato descritto un metodo per generare documenti HTML in modo semplice e veloce. A questo punto è da chiedersi se sia possibile accedere in modo equivalentemente semplice ad insieme di documenti presenti in Internet. Tale caratteristica è indispensabile per la costruzione di applicazioni più complesse, come ad esempio tools di ricerca analizzatori di contenuti, ecc. Anche in questo caso PiLLoW viene in aiuto: essa fornisce infatti una rappresentazione interna per trattare le URL (Uniform Resource Locator) e fornisce un insieme di predicati che effettuano la conversione da tale rappresentazione verso una forma testuale. In particolare, i predicati utili in questo contesto sono i seguenti: - url_info(URL,Info): converte una url URL in una struttura interna denominata Info. Ad esempio: url_info(‘http://www.dsi.unive.it/llog/lezione2.pdf’, Info) ritorna: Info=http(‘www.dsi.unive.it’, 80, “/llog/lezione2.pdf”) - url_info_relative(URL,BaseInfo,Info): converte una url relativa etichettata con URL e che appare nella pagina HTML riferita da BaseInfo in una struttura url_info completa ed etichettata con Info. Ad esempio: url_info_relative(“/llog/lezione2.pdf”, http(‘www.dsi.unive.it’, 80, “/llog/lezione2.pdf”) restituisce: Info=http(‘www.dsi.unive.it’, 80, “/llog/lezione2.pdf”) - fetch_url(URL,Request,Response): permette di effettuare il fetch di un documento presente in Internet. Naturalmente URL è l’url associata al documento e definita mediante una struttura url_info. Request, invece, è una lista di opzioni che specifica i parametri della richiesta, mentre Response è una lista che include i parametri della risposta. Alcuni dei parametri di richiesta sono: head: per specificare l’interesse solo all’header del documento. timeout(Time): indica il tempo massimo di attesa per la risposta. if_modified_since(Date): ritorna un documento solo se è più nuovo della data specificata. Mentre nella lista dei parametri di risposta possiamo trovare: content(Content): ritorna in Content il documento testuale, espresso come una lista di caratteri. status(Type, Code, Phrase): ritorna lo status della risposta: Type può indicare un fallimento, un successo, un re-direct, ecc. location(URL): indica dove il documento è stato spostato. last_modified(Date): permette di ottenere la data dell’ultima modifica. - html2terms(Chars,Terms): oltre all’utilizzo precedentemente illustrato, permette di effettuare un parsing del codice HTML, ottenuto ad esempio mediante fetch_url. Il risultato che si ottiene è una lista di termini HTML presente in Terms che è normalizzata: contiene solo le strutture comment/1, declare/1, env/3 e $/2. 11 3. Costruzione di un meta-motore di ricerca logico: 3.1 I problemi che affliggono i motori di ricerca tradizionali: La continua espansione del World Wide Web (WWW) ha reso indispensabile la costruzione e il mantenimento di di tools per la ricerca delle informazioni presenti in rete. Ecco quindi che oggi possiamo disporre di diversi motori di ricerca, i quali presentano delle caratteristiche implementative differenti tra loro. Esistono però dei problemi di diversa natura dietro queste applicazioni, i quali rendono le ricerche spesso difficili e caratterizzate da dei risultati poco soddisfacenti. Tra queste problematiche possiamo citare: − − − il metodo di operare da parte dei diversi motori di ricerca risulta essere sempre lo stesso: esistono degli spiders che effettuano delle scansioni costanti della rete al fine di effettuare delle indicizzazioni delle pagine presenti. Nella realtà però, la percentuale di pagine che sono effettivamente indicizzate è piccolo. molto spesso le risposte che vengono fornite nel momento in cui un motore di ricerca viene interrogato sono errate. Ad esempio, molto spesso capita di imbattersi in pagine che non esistono più, o pagine scorrelate rispetto alle keywords passate in input alla query. il numero di risposte che viene fornito all'utente è troppo elevato e ridondante. Resta il fatto che questo problema è di difficile misurazione, visto che la qualità dei risultati forniti varia dal caso trattato. Per poter sopperire a queste carenze si è pensato di affiancare ai motori di ricerca tradizionali dei meta-motori di ricerca che permettano di ottenere dei risultati migliori sfruttando in modo ottimizzato e combinato i tool di ricerca già presenti nel WWW. 3.2 Soluzione: implementazione di meta-motori di ricerca: Un meta-motore di ricerca effettua ricerche nel Web combinando i risultati forniti dai diversi motori di ricerca già esistenti. L'idea quindi è semplice: sfruttare in modo combinato le risorse presenti nel WWW in modo da sopperire alle carenze precedentemente illustrate. Un meta-motore di ricerca fornisce un'interfaccia utente simile a quella standard di un motore di ricerca e lavora integrando le risposte dei diversi motori di ricerca interpellati in fase di esecuzione della query formulata dall'utente. Anche la presentazione dei risultati risulta essere simile alla procedura standard di ricerca, infatti viene collezionata e presentata all'utente una pagina contenente i risultati ottenuti. L'idea di fondo per sopperire alle carenze di un motore di ricerca standard è quello di poter combinare i diversi risultati che ritornano più motori di ricerca. Infatti il modo di operare dei motori di ricerca risulta differente da tool a tool. Esistono motori che inviano la query senza nessuna analisi sintattica, altri permettono formulazioni di query con diverse sintassi ed altri ancora permettono la formulazione di query avanzate. Anche la fase di presentazione dei risultati presenta delle differenze sostanziali: in alcuni casi viene effettuata una semplice append dei risultati ottenuti, senza effettuare nessun processamento. In altri casi vengono effettuati dei passaggi di rimozione dei risultati duplicati, in modo da fornire dei risultati più apprezzabili per l'utente. 12 3.3 Le funzionalità del meta-search engine “PrologCrawler”: Nelle prossime pagine verrà descritto come è possibile realizzare un meta-motore di ricerca denominato “PrologCrawler system”. Per realizzare tale tool si sfrutterà il compilatore SICStus Prolog e la libreria PiLLoW, precedentemente descritta. Le funzionalità del meta-motore possono essere descritte in base al metodo di esecuzione della query utente e al tipo di processamento effettuato per ottenere la collezione dei risultati. PrologCrawler supporta l'utilizzo dei connettivi logici AND, OR, NOT all'interno delle stringhe della query. Nel momento in cui l'utente inserisce la query viene effettuato una sua conversione sulla base della sintassi del motore di ricerca che dovrà essere interpellato. Ad esempio: Specifica Query Mickey AND mouse NOT goofy Query inviata ad “Excite” Mickey AND mouse AND NOT goofy Query inviata a “Yahoo” + Mickey + mouse - goofy Un'altra caratteristica chiave di PrologCrawler è la possibilità lasciata all'utente di specificare il numero massimo di risultati che debbano essere riportati nella pagina di visualizzazione finale. La fase di processamento dei risultati ottenuti è stato suddiviso in due parti, sulla base del livello di complessità di operazioni da eseguire: − − Simple Processing: esso include una fase di ordinamento dei risultati (sulla base di diversi criteri, quali ordine alfabetico, titolo, indirizzo, rilevanza, ecc.), rimozione degli indirizzi duplicati e rimozione delle “pagine secondarie”che sono considerate ridondanti. Ad esempio, se si ottiene la pagina “www.dsi.unive.it/llog/slides” allora tutte le pagine tipo “www.dsi.unive.it/llog/slides/cap1.pdf” saranno considerate secondarie ed eliminate. Advanced Processing: questa fase include un check per verificare l'esistenza dei links che sono ritornati all'utente. In caso di links fasulli essi verranno eliminati dalla lista. Alla fine di queste diverse fasi PrologCrawler fornirà il risultato finale all'utente in formato HTML standard, mettendo insieme le diverse parti delle pagine che sono ritornate dai motori di ricerca che sono stati interrogati. 3.4 Interfacciamento con i motori di ricerca: Una fase da dover affrontare è come interfacciare PrologCralwer con i motori di ricerca commerciali che vengono utilizzati. Infatti il meta-motore di ricerca lavora in background e si presentano due problemi, risolvibili con delle scelte fatte ad hoc: − Come interrogare il motore di ricerca? Per poter risolvere questo problema si possono utilizzare le caratteristiche degli script CGI (Common Gateway Interface) sfruttati dai motori di ricerca. Infatti una query utente genera un indirizzo URL che lancia un programma di ricerca nel server. Ad esempio, se si effettua una ricerca sfruttando la keyword “prolog” si genera una nuova pagina che ha il seguente indirizzo (l'esempio è basato sul motore di ricerca Altavista): http://www.altavista.com/cgi-bin/query?pg=q&kl=XX&q=prolog 13 Tale pagina lancia il programma query col parametro q settato con la stringa “prolog”. − Come si possono estrarre i risultati della ricerca dalla pagina HTML ritornata dal motore di ricerca? La soluzione introdotta in PrologCrawler è quella di analizzare il codice HTML della pagina ritornata al fine di filtrare i links e di invocare altri processi correlati. 3.5 Implementazione di “PrologCrawler”: Il sistema PrologCrawler è stato scritto sfruttando SICStus Prolog 3.7.1 e la libreria PiLLoW, espressamente pensata per la progettazione di applicazioni WWW di questo genere. Il funzionamento di PrologCrawler è semplice: l'utente utilizza un browser per aprire PrologCrawler, il quale sfrutta uno script CGI per poter essere accessibile da una pagina HTML standard. Mediante questa pagina web l'utente può formulare la query. In seguito lo script CGI lancia il programma che effettua la meta-ricerca e ritorna i risultati in una nuova pagina che è ritornata e visualizzata sempre mediante il browser. Figura 2: Le interazioni in Prolog Crawler. Il sistema interno è caratterizzato da un modulo Main, il quale passa i parametri di ricerca e gestisce l'esecuzione degli altri moduli. Infatti, dopo aver ricevuto i parametri di input il modulo Main attiva il modulo Search, il quale è incaricato di inviare la query ai motori di ricerca e di collezionare i risultati relativi. Il modulo Search attiva una serie di istanze del modulo Queryengine (esiste un'istanza per ciascun motore di ricerca interpellato). L'esecuzione di queste diverse istanze avviene in parallelo e i risultati vengono poi collezionati dal modulo Search, il quale riporta il tutto al Main. In seguito il modulo Main attiva il modulo Process, il quale ha il compito di elaborare l'insieme dei risultati ottenuti dai motori di ricerca disponibili. Il modulo Process può effettuare una “simple processing”, rimuovendo i duplicati e i links secondari, oppure una “advanced processing” effettuando il check dei links realmente esistenti. Infine il moduloSorting effettua l'ordinamento della lista sulla bse dei criteri prestabiliti e il modulo BuildHTML è incaricato di costruire il risultato da passare al browser dell'utente. 14 Figura 3: la struttura interna del sistema. Il modulo Main: All'interno del modulo Main possiamo trovare le seguenti clausole. Nel caso in cui venga effettuata una ricerca semplice si invoca la clausola: run(simple(Query,Nres,Ord),ResultsPage):s_search(Query,Nres,Results), s_process(Nres,Results,FilteredResults), sort(FilteredResults,Ord,SortedResults), build_html(SortedResults,ResultsPage). Argomento di input: contiene i parametri di ricerca Argomento di output: istanziato con un (la query utente, il numero di risultati richiesti e il termine Prolog che rappresenta la pagina criterio di ordinamento dei risultati). HTML ritornata all’utente Nel caso di una ricerca avanzata la clausola invocata risulta simile alla precedente, ad eccezione di due parametri addizionali, MaxTime che indica il tempo massimo di risposta ed E_check, il quale è un flag che indica l’esistenza della risposta associata. Ecco la struttura: 15 run(adv(Query,Nres,Ord,MaxTime,E_check),ResultsPage):a_search(Query,Nres,MaxTime,Results), a_process(Nres,E_check,Results,FilteredResults) sort(FilteredResults,Ord,SortedResults), build_html(SortedResults,ResultsPage). In entrambi i casi i moduli “Search” e “Process” sono invocati mediante due predicati ai quali sono passati i parametri in input presenti nella testa della clausola. Naturalmente esistono predicati differenti a seconda che la ricerca effettuata sia semplice o avanzata. Come illustrato in precedenza il modulo Search attiva diverse istanze del modulo Queryengine, le quali lavorano in parallelo. Ciascuna di queste istanze è incaricata di inviare la query ad uno dei motori di ricerca impiegati. Il modulo Queryengine viene attivato invocando una system call exec, ovvero un’operazione di sistema che viene utilizzata in SICStus Prolog per passare un comando ad una nuova shell per un’esecuzione. Quando una delle istanze di Queryengine termina, crea un file contenente i risultati. Il modulo Search quindi effettua un check per l’esistenza di tali files nell’attesa della terminazione di tutte le istanze. Il problema più grosso da dover affrontare per l’esecuzione di una query in diversi motori di ricerca è data dalle sintassi differenti che i motori impiegano. Per poter arginare tale problema il modulo Queryengine è stato progettato in 3 sotto-moduli: Figura 4: il modulo Queryengine. Il modulo build_url ha il compito di costruire la URL necessaria per far partire il motore di ricerca attraverso una ricerca espressa dalla query associata. In particolare, la struttura di tale sotto-modulo è la seguente: 16 build_url(Engine,Query,Nres,URL):convert_query(Query,Engine,NewQuery), __engine_data(Engine,Engine_URL,Str1,Str2), compose(Engine_URL,Str1,NewQuery,Str2,Nres,URL). Termine utilizzato per passare il Predicato che è impiegato per trasformare la stringa della nome del motore di ricerca query nella sintassi specifica del motore di ricerca usato Proviamo a rendere più chiara la spiegazione sfruttando un semplice esempio. Se avessimo la seguente chiamata: build_url(nlight,’prolog+cgi’,20,URL) il termine con funzionalità output “URL” verrebbe istanziato in questo modo: http(’northernlight.com’,80,’/nlquery.fcg?qr=prolog+AND+cgi&us=20’) che rappresenta l’URL: http://northernlight.com/nlquery.fcg?qr=prolog+AND+cgi&us=20 Continuiamo l’analisi del modulo build_url analizzando il predicato engine_data/4, il quale è definito come un insieme di clausole che contengono le informazioni sintattiche sul modo in cui le stringhe che rappresentano le query sono formate nei diversi motori di ricerca. Ecco quindi uno spaccato di questo predicato: engine_data(altavista,‘www.altavista.com’, ‘/cgi-bin/query?pg=aq&q=’, []). engine_data(excite,‘search.excite.com’, ‘/search.gw?c=web&search=’,‘&perPage=’). engine_data(nlight,’northernlight.com’, ‘/nlquery.fcg?qr=’,’&us=’). ... Naturalmente nella costruzione di un meta-motore di ricerca non potevano mancare alcune parti di codice nelle quali si sfruttano delle primitive presenti all’interno della libreria PiLLoW. Infatti, il modulo Fetch, sfrutta delle primitive sviluppate per l’accesso a pagine WWW. Tale modulo è presente all’interno del predicato get_page/3, il quale, come mostrato qui sotto, data un’URL e un intero che rappresenta il TimeOut per la connessione utilizzata, ritorna il contenuto della pagina web corrispondente, nella forma di un termine Prolog. 17 get_page(URL,TimeOut,PageTerm):fetch_url(URL,[timeout(TimeOut),from(‘[email protected]’)], Answer), -----member(content_type(text,html,_),Answer), -----member(content(Page),Answer), html2terms(Page,PageTerm). Mediante fetch_url si ottiene il codice HTML Primitiva utilizzata per convertire il contenuto (inserito in “Answer”) della pagina puntata HTML della pagina “Page” in termini Prolog dall’URL passata insieme ad altri parametri. Proprio la conversione effettuata da html2terms/2 è di particolare utilità per il modulo Parse, sottomodulo di Queryengine. Il compito di tale modulo è quello di analizzare la pagina HTML prodotta dall’altro sotto-modulo Fetch per ottenere la lista dei risultati ritornati dal motore di ricerca. html2terms/2 lavora in questo modo: dato un tag nella forma: <tagname attributes> text </tagname> effettua una conversione nel termine: env(tagname,attributes,text) Tale conversione viene effettuata in modo ricorsivo. Inoltre la struttura del termine originale viene preservata e il modulo Parse può sfruttare il meccanismo dell’unificazione per estrarre ricorsivamente la lista dei risultati dalla corrispondente struttura ad albero. Proprio l’idea di sfruttare il meccanismo dell’unificazione per l’analisi dei contenuti di una pagina HTML, semplifica notevolmente lo sviluppo e l’intera procedura, rispetto ad una soluzione standard basata su una tecnica di matching tra stringhe. 18 4. LP nel Web Moderno: 4.1 Dalla LP + WWW fino al “Semantic Web”: Il successo del World Wide Web è sicuramente promosso ed incoraggiato da nuove forme di comunicazione e di business. In particolare, i contenuti che si possono trovare all’interno del Web sono cresciuti in modo esponenziale nel corso degli ultimi anni ed è quindi necessario che essi siano “machine-undrestandable”, ovvero comprensibili ad una macchina, affinché possano essere interpretati ed indicizzati in modo efficace. Per riuscire ad ottenere questo risultato si è passati a definire una nuova tipologia di linguaggio: XML. L’obiettivo di XML è di disporre di un meccanismo di scambio di dati che sia efficiente e che, allo stesso tempo, garantisca una sintassi semplice e un grado di strutturazione ben definita. In linea con questi principi si è poi passati a riportare nel Web le tecniche di Knowledge Representation (KR) per descrivere la semantica dei contenuti web e permettere delle inferenze su di essi. Da queste idee, il W3C introdusse nel 2001 il “Semantic Web”, ribattezzato il Web del futuro. In merito ad esso, Tim Berners Lee disse: “I computer devono avere accesso a collezioni strutturate di informazioni e ad insiemi di regole di inferenza che possano essere usate per condurre ragionamenti automatizzati.” “La sfida del Semantic Web è perciò quella di fornire un linguaggio che possa esprimere sia dati che regole.” “Aggiungere la logica al Web è il primo compito che ha il Semantic Web oggi. Essa è il mezzo per poter esprimere un insieme di regole di inferenza.” Ecco quindi che per poter risolvere i problemi che affliggono il Web, ovvero l’ambiguità delle informazioni presenti al suo interno e la mancanza di informazione machine-undrestandable, è necessario mettere insieme diverse componenti, correlate tra loro in modo stretto attraverso una struttura a pila e nella quale la logica riveste un ruolo centrale: Figura 5: Lo stack del “Semantic Web”. 19 Sfruttando la logica è possibile effettuare dei ragionamenti automatici sulle informazioni presenti nel Web. In particolare gli obiettivi del livello logico sono quelli di sfruttare l’insieme di asserzioni che si possono trovare nel Web per poter derivarne conoscenza e realizzare dei sistemi in grado di formulare ogni principio logico. In questo modo si permette ai computer di ragionare per inferenza. Ad esempio, se si verificasse una situazione del genere: Un'azienda decide che se qualcuno vende più di 100 dei suoi prodotti, questi diventa membro del club del Super Venditore. Un programma logico ora può seguire questa regola per fare una semplice deduzione: "John ha venduto 102 cose, così John è un membro del Club del Super Venditore". Una volta costruiti questi sistemi "logici", essi potranno essere utilizzarli per provare qualcosa. In questo modo persone in tutto il mondo potranno scrivere istruzioni logiche e la macchina potrà seguire questi link "semantici" per costruire dimostrazioni. Quando si riescono a costruire sistemi che seguono la logica, diventa naturale utilizzarli come prove. Ad esempio: I record delle vendite aziendali mostrano che Jane ha venduto 55 cruscotti e 66 rotelle. Il sistema di inventariato ci dice che cruscotti e rotelle sono entrambi differenti prodotti dell'azienda. Le regole matematiche incorporate dichiarano che 55+66=121 e che 121 è più di 100. E, come già sappiamo, chi vende più di 100 prodotti diventa membro del club del Super Venditore. Il computer mette insieme queste regole logiche in una prova che Jane è un Super Venditore. Figura 6: Utilizzo di regole logiche nel Semantic Web. In questo modo si potrà costruire un Web di processori di informazione. I più intelligenti saranno dei "motori euristici" che seguiranno queste regole costruite per disegnare conclusioni, e posizionare i risultati ottenuti sul Web come un insieme di prove. 20 4.2 Metalog: come aggiungere ragionamento al Web: Grazie all’enorme diffusione che il Web ha ottenuto negli ultimi anni, la necessità di disporre di un “Web intelligente” è diventata una caratteristica sempre più ricercata. Da questo spunto è nato Semantic Web, un progetto proposto dal W3C. Esso fa uso di un “linguaggio semantico”, denominato RDF, che permette di effettuare dei ragionamenti. In particolare, RDF non definisce esplicitamente la semantica, ma fornisce una base per poterla esprimere. Infatti ogni risorsa presente o citata nel Web potrà essere descritta e sarà vista come un oggetto unico, identificabile mediante una URI (Uniform Resource Identifier). Il data model RDF è così composto: - Resources: ogni cosa descritta da un’espressione RDF è detta risorsa. - Properties: una proprietà è un aspetto specifico, una relazione, una caratteristica, ecc. - Statements: è una t-upla composta da un soggetto (risorsa), un predicato (proprietà) e un oggetto (valore). Ad esempio, considerando l’espressione: Oreste Signore è l’autore del DocumentoX” Otterremmo la seguente tripla: Resource: http://www.w3c.it/Oreste/DocX Property: author Value: Oreste Signore Figura 7: rappresentazione grafica di uno statement RDF. Partendo da queste basi si è potuto definire il progetto Metalog, il primo sistema basato su un insieme di query logiche per il Semantic Web. Esso è stato definito per sopperire due carenze evidenti del Web: la mancanza di ragionamento e quindi la possibilità di comprendere il significato delle informazioni trattate, e la possibilità di portare queste tecnologie avanzate alla più grossa fetta di utenza possibile. Metalog sfrutta un interfaccia costruita in PNL (Pseudo Natural Language), il quale è molto simile al linguaggio naturale e quindi permette un interfacciamento semplice con le tecnologie più complesse presenti nel Semantic Web. In particolare, Metalog interfaccia il PNL con un’estensione logica della semantica definita con RDF, detta MLL (Metalog Logical Level) e basata su un’estensione del modello RDF stesso, detta MML (Metalog Model Level). In questo modo si ha un arricchimento di RDF grazie all’impiego di un modello che offra una vista logica delle informazioni. Metalog Model Level (MML): MML è un’ estensione di RDF che sfrutta un insieme di operatori logici. Tutti i nuovi operatori forniti sono rappresentati in modo uniforme nel modello RDF: un operatore denotato con la URI α, 21 avente gli operandi β1,….,βk, è codificato in questo modo: MML fornisce gli operatori logici di base, denotati in questo modo: ml:and, ml:or ed ml:imply. Viene anche fornito un operatore di negazione e i classici operatori di negazione (>=, <=, ecc.). Infine viene fornito un ml:name extension, utilizzato per etichettare le variabili. Metalog Logic Level (MLL): MLL è la logica che esprime la semantica di MML. Essenzialmente è un sottoinsieme di equazioni della logica del prim’ordine. Ecco come viene effettuato il mapping tra MML e MLL: - ml:and, ml:or ed ml:imply, not sono convertiti nella congiunzione, disgiunzione, implicazione e negazione logica; - gli operatori matematici sono mappati secondo la loro logica naturale; - i letterali e gli URI Reference sono mappati in costanti; - ml:name, ml:annotation, ml:ns sono mappati in costanti distinte; - ciascuna tripla (S,P,O) viene mappata in P(S,O); - i container che trattano insiemi di k oggetti sono mappati in operatori k-ari SEQk, applicati a ciascuno dei k operandi, descritti in questo modo: Pseudo Natural Language (PNL): Come detto precedentemente, un obiettivo di Metalog è quello di fornire un interfaccia che sia semplice ed intuitiva per qualsiasi utente. Perciò Metalog utilizza dei “discorsi”, che sono sentenze in PNL. Ad esempio, definiamo il seguente discorso: 22 Quando questo programma viene caricato in Metalog, viene colorato in modi differenti, al fine di comprendere le diverse parti del discorso. La prima, la seconda, la quinta e la settima sentenza sono colorate di rosso, essendo dei commenti (superflui al discorso). La terza e la quarta sentenza sono colorate di verde, essendo delle rappresentazioni (utili per denotare delle associazioni). Infine la sesta e l’ottava sentenza sono colorate di blu, essendo delle asserzioni o query. Un’asserzione è una sentenza dove definiamo precisamente qualcosa e che termina con (.), mentre una query è una sentenza dove chiediamo qualcosa a Metalog e termina con (?). Perciò i tre tipi di sentenza definiti in Metalog sono: - rappresentazioni; - asserzioni; - query. Come lavora Metalog? Come è stato detto in precedenza, il PNL fornisce un livello superiore al logic layer. Il metodo per passare da un livello all’altro è quello di effettuare un parsing accurato al fine di estrarre il significato logico corrispondente delle diverse sentenze. In particolare, Metalog sfrutta un insieme di keywords riservate, e la posizione all’interno della sentenza determina il loro significato. A ciascuna sentenza vengono quindi inserite tali keywords riservate, il nome, le variabili, ecc. e poi si procede alla sua traduzione. Le tre classi principali di keywords riservate sono le seguenti: - congiunzione (and); - disgiunzione (or); - implicazione (then, imply, implies). Metalog definisce anche altre classi di keywords, tra le quali operatori matematici di base (add, plus, sub, ecc.), operatori per confronti ed uguaglianze, ecc. Uno dei cardini di Metalog è l’utilizzo di PNL. Esso è stato pensato come un linguaggio di semplice lettura (e di conseguenza semplice da capire) e che permette una non ambiguità in tutto ciò che si scrive. Infatti vengono utilizzati dei simboli speciali (come (,)) che permettono di eliminare qualsiasi ambiguità dalle sentenze. Esiste però uno svantaggio da pagare: non è possibile scrivere tutto ciò che si vuole, infatti è disponibile un livello di costruzione delle sentenze semplice e limitativo. Metalog computabile: Nel caso in cui si voglia analizzare MLL, è necessario definire un insieme caratterizzato dal possedere delle proprietà computazionali che possano essere sfruttate in modo efficiente. Ad esempio, si può sfruttare la programmazione logica (caratterizzata dalle clausole di Horn) ed utilizzare Prolog come mezzo di interfacciamento. In questo modo le regole di mapping sono chiare e possono essere così descritte: 23 E’ da notare il fatto che la regola 1 è differente dalla 2 solo perché essa viene applicata nel momento in cui si sta effettuando la traduzione di una sentenza. Nel caso dei contenitori di operandi è stata definita una tabella di mapping apposita: Costruzione di query con Metalog: Dopo aver descritto il metodo utilizzato per scrivere discorsi più o meno complessi con Metalog, si passa ad uno studio del metodo di costruzione di query. Supponendo di disporre di un sistema in cui è definita una relazione di derivazione (ad esempio, a --| b significa che da a segue b), un linguaggio di query dovrebbe essere in grado di rispondere a domande del tipo “è vero che da a derivo b?”. Esiste però il problema di dover esprimere la relazione di derivazione con un linguaggio naturale (come inglese, italiano, ecc.). La via d’uscita è quella di esprimere una semplice classe di query per chiedere se qualcosa è vero, oppure no. Ciò può essere sintetizzato in questo modo --| a, e in linguaggio naturale corrisponde a “è vero che …?”. A questo punto è possibile sfruttare la seguente relazione: (a --| b) sse (--| se a allora b) In questo modo ci si può liberare della relazione di derivazione e sfruttare questa strategia per esprimere le query. Metalog vede le query come delle particolari sentenze che terminano con (?) e non effettua una combinazione del meccanismo di inferenza con l’interfaccia fornita. Uno dei maggiori obiettivi del progetto Metalog è quello di fornire delle risposte che siano il più possibili significative. Ciò è possibile sfruttando un processo di istanziazione delle risposte (dove le variabili libere sono legate ai risultati, come in Prolog) denominato feedback. Esso si basa su una ricomputazione della risposta per cercare di modellarla in una forma simile al linguaggio naturale. 24 Per ottenere ciò si usano delle annotazioni speciali, le quali codificano a livello RDF le informazioni. Ad esempio, una query potrebbe ritornare: JOHN IS “tall like tower” insieme ad un set opportuno di rappresentazioni, utili per comprendere la risposta. In questo modo l’informazione riguardante le rappresentazioni non viene persa durante la fase in cui si sfrutta un motore di inferenza e si riesce, quindi, a creare un informazione “user-friendly”. 4.3 xml.pl: Parsing XML with Prolog: L’XML (eXtensible Markup Language) è stato introdotto dal consorzio W3C. Esso è uno standard di descrizione di documenti e permette di definire nuovi linguaggi di marcatura (come XHTML), specializzati nel descrivere una particolare tipologia di documento. In questo modo si vuole raggiungere l’obiettivo di poter effettuare degli scambi di dati efficienti attraverso la rete. Negli ultimi anni sono state definite delle librerie che permettono di effettuare il parsing di documenti XML tramite Prolog. Dai primi progetti orientati verso una parserizzazione di documenti più vicini ad HTML (la libreria PiLLoW ne è un esempio), sono emersi nuovi spunti di ricerca. Un esempio viene dalla definizione del modulo xml.pl. Esso permette di effettuare il parsing di documenti XML con Prolog (il modulo può essere utilizzato senza problemi in SICStus) e fornisce un insieme di applicazioni Prolog con un “Document Value Model” associato. La bontà di tale progetto di ricerca è testimoniata dal numero di applicazioni in cui è stato usato efficacemente. Inoltre, il codice e un’applicazione Windows che sfrutta xml.pl, sono stati resi free, in modo da incoraggiare l’utilizzo di Prolog con XML. Specifiche: xml.pl include 3 predicati di base. In particolare, il primo predicato è caratterizzato dal possedere 2 modalità differenti: xml_parse({+Controls},+?Chars,?+Document) Questo predicato effettua il parsing di Chars, una lista di codice, da/verso una struttura dati nella forma tipica XML: (<attributes>, <content>), dove: <attributes> è una lista di attributi del tipo <name> = <char data> presenti nel documento. <content> è una lista che comprende insiemi di occorrenze tra: pcdata( <char data>) testo comment( <char data>) commenti XML namespace( <URI>, <prefix>, <element>) element( <tag>, <attributes>, <content>) <tag>..</tag> che include <content> oppure <tag /> se è vuoto. instructions( <name>, <char data>) <? <name> <char data> ?> cdata( <char data>) <![CDATA[ <char data>]]> doctype( <tag>, <doctype id>) DTD <!DOCTYPE .. > 25 E’ interessante notare che nel passaggio Chars Document, il parsing non richiede dei documenti che siano strettamente ben formati secondo le specifiche XML. Infatti, se Chars non rappresenta un documento XML ben formato, il documento Document verrà istanziato ad un termine così definito: malformed(<attributes>,<content>) dove <content> può includere: unparsed( <char data> ) testo non parserizzato out_of_context( <tag> ) <tag> non chiuso Invece, nel passaggio Document Chars il parsing richiede che il documento Document sia ben formato secondo XML. Nel caso in cui si rilevi un errore, un’eccezione “Domain” viene sollevata, in modo da rilevare sotto-termine che ha causato l’errore. La lista di elementi etichettata con Controls è così strutturata: extended_characters(<bool>) per settare l’utilizzo di caratteri usati in XHTML format( <bool>) utilizzata per rimouovere eventuali layout remove_attribute_prefixes( <bool>) utile per la rimozione di prefissi ridondanti allow_ampersand( <bool>) usata per ammettere i carateri ampersand (&) in PCDATA Nel passaggio Document Chars è anche previsto: format( <bool>) usato per indentare l’elemento a cui è associato. xml_subterm(+XMLTerm,?Subterm) Questo predicato unifica Subterm con un sottotermine di Term. In particolare esso è molo utile quando si vuole testare o cercare un sottotermine annidato all’interno di un documento. Ad esempio: Si vogliono trovare nel documento “books.xml” tutti I titoli dei capitoli che contengono la parola “XML”, senza riguardo del suo livello di profondità: xml_query( q9, element(results, [], Titles) ) :element_name( Title, title ), append( "XML", _Back, Suffix ), input_document( 'books.xml', Books ), findall( Title, ( xml_subterm( Books, Title ), xml_subterm( Title, TextItem ), text_value( TextItem, TextValue ), 26 append( _Prefix, Suffix, TextValue ) ), Titles ). xml_pp(+XMLDocument) PrediEcato utilizzato per effettuare la stampa in output del documento XMLDocument. L’idea che ha portato alla definizione del modulo xml.pl è basata sul fatto che un termine Prolog può rappresentare un documento che ha la stessa struttura de documento stesso, creando quindi una corrispondenza tra termini Prolog e codice XML: Ad esempio, data un’immagine SVG così definita: <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/.../svg10.dtd" [ <!ENTITY redblue "fill:red; stroke:blue; stroke-width:1"> ]> <svg xmlns="http://www.w3.org/2000/svg" width="500" height="500"> <circle cx=" 25 " cy=" 25 " r=" 24 " style="&redblue;"/> </svg> Può essere convertita in termini Prolog: xml( [version="1.0", standalone="no"], [ doctype( svg, public( "-//W3C//DTD SVG 1.0//EN", "http://www.w3.org/.../svg10.dtd" ) ), namespace( 'http://www.w3.org/2000/svg', "", element( svg, [width="500", height="500"], [ element( circle, [cx="25", cy="25", r="24", style="fill: red; stroke: blue; stroke-width: 1"], [] ) ] ) ) ] ). 27 xml.pl permette una manipolazione efficiente di ciascuna tipologia di nodo presente all’interno di un documento XML. Infatti, la maggior parte delle tipologie di nodi sono rappresentate mediante dei funtori Prolog differenti tra loro, mentre i dati sono rappresentati come stringhe: <tag> atomi <name> atomi <URI> atomi <char data> stringa <bool> true o false L’utilizzo di funtori distinti tra loro per le strutture di mark-up permette un utilizzo efficiente della ricorsione per trattare i documenti stessi, mentre associando ai dati degli insiemi di stringhe si possono ottenere delle facilitazioni nello sviluppo di applicazioni per il pasrsing di tali contenuti. 28 5. Conclusioni: Attraverso un insieme di esempi pratici presentati nelle sezioni precedenti, si è cercato di dimostrare come la LP possa essere affiancata al mondo del World Wide Web. In particolare, nel corso dell’ultimo decennio sono stati concentrati molti sforzi di ricerca per sfruttare le caratteristiche della LP, in modo da ottenere un insieme di applicazioni Web che potessero essere più complete e che avessero associata una semantica ben definita. Gli esempi proposti hanno messo in luce come la ricerca di un insieme di informazioni o di documenti attraverso il Web, possa essere nettamente migliorata sfruttando i paradigmi di programmazione della LP. L’obiettivo principale che essa aveva inizialmente in tali progetti (LogicWeb, PiLLoW, ecc.) era proprio quello di introdurre una struttura ben definita alle applicazioni Web. Ma la LP può essere utilizzata anche per altre tipologie di applicazioni, come ad esempio la costruzione e la consultazione di Database deduttivi, la possibilità di costruire pagine Web rappresentandole come termini dell’universo di Herbrand e sfruttandone tutte le proprietà associate, ecc. Proprio lo stile di programmazione ad alto livello che essa permette, rappresenta una caratteristica chiave che rende lo sviluppo di applicazioni più rapido e semplice e tale da permettere di associarvi una semantica. Ciò è dimostrato anche dal largo impiego che viene fatto della LP all’interno del Semantic Web e del ruolo chiave che essa riveste nello sviluppo del Web moderno. I primi lavori proposti si collocano in uno scenario in cui il WWW non prevede ancora delle strutture e dei linguaggi ben definiti come XML. Proprio queste caratteristiche hanno spinto i ricercatori a sfruttare la LP per poter dare una struttura di base per le applicazioni e i contenuti presenti nel Web. L’introduzione di XML da parte del W3C come linguaggio che permetta di definire una struttura di base per i dati, ha accentuato maggiormente il ruolo della logica e della LP come componenti base per la definizione di una semantica che permetta di progettare sistemi intelligenti su cui fare deduzioni. Inoltre essa può essere affiancata ad HTML e XML e risulta un’ottima componente per costruire dei parser efficienti. Proprio l’idea di poter effettuare un mapping tra le strutture dei documenti Web e termini Prolog ha portato a costruire librerie ed estensioni molto interessanti, come xml.pl, che possono essere affiancate a diverse release Prolog (es. SICStus). Il ruolo centrale di logica e LP all’interno del Semantic Web è dimostrato anche dalla loro posizione occupata all’interno dello stack in cui sono riportate le componenti fondamentali e le associazioni che intercorrono tra loro. Il caso di studio riportato (Metalog) è un primo esempio di come si possa aggiungere intelligenza e una vista logica delle informazioni presenti nel Web, mantenendo un grado di semplicità che permetta di rivolgere a qualsiasi fascia d’utenza tali concetti. Si può quindi concludere dicendo che è stato fatto molto in merito all’introduzione della logica e della LP nel mondo Web e partendo da queste idee si dovrebbero concentrare ancora di più gli sforzi di ricerca, in modo che alcune problematiche, quali, ad esempio, la scarsa efficienza nel momento in cui si debbano costruire applicazioni che sfruttino in modo massiccio un insieme di operazioni di rete, possano essere superate, rendendo la LP una componente sempre utilizzabile nel momento in cui si vogliano costruire applicazioni WWW. 29 6. Bibliografia: [1] LogicWeb: Using Logic Programming to Extend the World Wide Web, Seng Wai Loke Department of Computer Science, The University of Melbourne, Australia, 1997 [2] Logic Programming with the World-Wide Web, Seng Wai Loke Department of Computer Science, The University of Melbourne, Australia, 1996 [3] The PiLLoW/CIAO Library for Internet/WWW Programming using Computational Logic Systems, D. Cabeza, M. Hermenegildo, and S. Varmaa, 1st Workshop on Logic Programming Tools for INTERNET Applications, JICSLP, 1997. [4] A Prolog Meta-Search Engine for the World Wide Web, Emanuele Bolognesi & Antonio Brogi Department of Computer Science University of Pisa, 1999. [5] W3C Semantic Web Activity, http://www.w3.org/2001/sw/. [6] Towards a People’s Web: Metalog, Massimo Marchiori, Department of Computer Science, University of Venice & W3C Consortium, 2004 [7] SICStus Prolog User’s Manual, Swedish Institute of Computer Science, Release 3.12.2 Maggio 2005. 30