Corso di laurea specialistica in

Sistemi per il trattamento dell’informazione (classe 23S: Informatica)

Corso di Laboratorio di Sistemi Intelligenti

Docente: P.Torasso

a.a. 2002/03

 

Progetto: Ruby al supermercato

Il progetto in questione ha lo scopo di far sviluppare un agente intelligente (Ruby) che deve combinare sia aspetti deliberativi che reattivi per svolgere il compito di muoversi all’ interno di un supermercato e di acquistare quanto gli viene indicato.

Il mondo in cui si deve muovere Ruby è un supermercato in cui si vendono diversi prodotti. Il supermercato è rappresentato (in modo assai semplificato) come una matrice rettangolare di celle ciascuna delle quali può contenere una parete (wall), uno scaffale (stand), l’entrata (entry) , l’uscita (exit) oppure essere vuota (empty). Si suppone che le celle siano numerate dal basso verso l’alto e da sinistra verso destra. Si suppone inoltre che l’ entrata e l’uscita sia contigue, siano localizzate nella riga 1 e che le celle davanti all’ingresso e all’uscita (cioe’ nella riga 2) siano libere.

Ciascun prodotto è contenuto in uno scaffale (stand). Uno scaffale può contenere solo item dello stesso tipo, mentre più stand possono contenere lo stesso tipo di prodotto. Per far sapere cosa contiene uno stand c’e’ una opportuna etichetta sullo stand che specifica i dati salienti del prodotto in esso contenuto (si veda deftemplate standcontent). L’etichetta può essere letta solo da una cella adiacente allo scaffale. Inoltre lo scaffale può essere aperto anche solo da un lato per cui una operazione di lettura può fallire se è fatta su un lato chiuso dello scaffale. Considerazioni analoghe valgono anche per il prelevamento di un item dallo scaffale. Questo può essere fatto solo se Ruby si trova nella cella contigua e se lo scaffale è aperto in quella posizione.

Ogni prodotto e’ caratterizzato dal nome del prodotto (nome generico o specifico), dal nome della ditta che lo produce o lo distribuisce, il tipo di confezione e il prezzo. Le informazioni sui prodotti sono definite nel deftemplate standcontent. Si noti che standcontent ha anche uno slot che specifica la numerosità degli item di quel prodotto contenuti in quell’ istante nello stand.

La lista della spesa che Ruby deve fare e’ nota a Ruby attraverso fatti di tipo goal, che specificano quanti item di un certo tipo devono essere acquistati. Si tenga presente che l’unico campo richiesto nel goal e’ quello relativo al nome del prodotto (esempio caffè o robiola), mentre non sono obbligatori i dati relativi alla ditta produttrice, al tipo di confezione e al prezzo massimo per item da acquistare. Ovviamente se queste informazioni (facoltative) sono presenti nel goal, queste sono tenute in conto da Ruby nel fare gli acquisti.

Il nostro agente robotico Ruby ha la capacità di fare solo cinque azioni:

Con questa azione Ruby avanza di una posizione (cella) nella direzione in cui è attualmente orientato. Ovviamente l’azione di muoversi ha successo se la cella in cui Ruby deve andare non è composta da un muro o da uno stand o dall’entrata. Se si cerca di fare una azione di go non permessa Ruby ha una percezione di bump (vedi sotto)

Con questa azione Ruby svolta su se stesso di 90 gradi a destra rispetto alla sua direzione corrente. Si tenga presente che le direzioni sono 4 (in particolare up, down, left, right). Ruby non cambia cella con questa operazione. Questa azione non fallisce mai.

Con questa azione Ruby svolta su se stesso di 90 gradi a sinistra rispetto alla sua direzione corrente. Ruby non cambia cella con questa operazione. Questa azione non fallisce mai.

Con questa azione Ruby può leggere l’ etichetta associata ad uno stand e quindi sapere cosa contiene lo stand stesso. Come accennato sopra l’azione ha successo solo se Ruby è in una cella adiacente a quella dello stand e se lo stand e’ aperto dal lato in cui si trova Ruby. Nel caso la lettura non sia stata possibile, lo slot item del fatto della percezione perc-read contiene fail (vedi sotto la discussione sulle percezioni)

Con questa azione Ruby può prendere un item dallo stand (ne può prendere uno solo per volta, ma ovviamente iterando l’ azione di grasp si possono prendere item nella quantità voluta). L’azione ha successo solo se Ruby è in una cella adiacente a quella dello stand e se lo stand e’ aperto dal lato in cui si trova Ruby, inoltre lo stand non deve essere vuoto. Nel caso l’ azione di grasp fallisca per uno dei motivi sopra elencati, lo slot item del fatto della percezione perc-grasp contiene fail (vedi sotto la discussione sulle percezioni)

Come nello schema classico di un agente, ad ogni istante l’agente riceve percezioni dal mondo esterno, nel nostro caso dall’ ambiente che modella il supermercato. Si suppone che l’agente abbia un sistema di visione (che non è soggetto a guasti) per cui il robot vede fino a tre celle in avanti rispetto alla sua posizione corrente. In modo più preciso, se Ruby si trova nella cella di coordinate (r,c) e la sua direzione è up riesce a vedere cosa contengono le celle (r+1,c), (r+2,c) e (r+3,c). Analoghe considerazioni valgono per le altre direzioni. E’ ovvio che la possibilità di vedere fino a tre celle in avanti è limitata dal fatto che la vista può essere impedita da una occlusione, sia essa rappresentata da un muro o da uno stand. In questi casi l’agente non può sapere cosa ci sia dietro l’ostacolo (visivo). Si noti che Ruby percepisce lo stimolo visivo qualunque sia l’ azione che viene svolta.

Come detto sopra, ad ogni istante l’ambiente fornisce a Ruby le percezioni visive che sono codificate nei fatti di tipo percepts, mentre fornisce le percezioni relative ad una operazione di read o grasp solo se nell’istante precedente Ruby ha deciso di compiere l’azione corrispondente (si vedano i fatti di tipo perc-read e perc-grasp).

All’istante iniziale Ruby non conosce nulla del supermercato, sa solo che si trova all’entrata (di cui conosce le coordinate), che la sua direzione è up, che deve fare una azione di go per entrare nel supermercato e che l’uscita si trova nella cella adiacente a destra. La lista della spesa è nota a Ruby attraverso i fatti di tipo goal.

Ruby può dire di avere assolto al compito quando si trova nella cella dell’uscita avendo comperato quanto richiesto (e con gli eventuali vincoli sulla marca, ecc.) oppure quanto ha constatato che nel supermercato non sono disponibili questi prodotti.

Un ulteriore metro per la valutazione della funzionalità del robot è quella relativa al numero di azioni elementari che Ruby deve compiere per assolvere il compito assegnato.

Al fine di semplificare lo sviluppo concettuale e implementativo di Ruby viene fornito un ambiente di simulazione in CLIPS (si veda sotto per la parte in JESS). Questo ambiente di simulazione (gran parte delle considerazioni valgono sia per l’implementazione CLIPS che JESS) prevede tre moduli. Il modulo MAIN è usato esclusivamente per la comunicazione tra gli altri due che modellano rispettivamente l’ambiente del supermercato (ENV) e Ruby (AGENT). Il modulo ENV è fornito già completamente sviluppato (anche se l’implementazione potrebbe essere migliorata) perché ha scopo di fornire le percezioni sulla base del cambiamento di stato in seguito ad una azione decisa da Ruby.

Si noti che e’ all’interno di ENV che viene definito l’ambiente del supermercato, per cui se si volesse definire un supermercato con dimensione diverse e con contenuti diversi è necessario intervenire su questo modulo (in particolare la regola di nome "creation"). Il modulo AGENT è fornito in una versione assolutamente embrionale perché lo scopo del progetto è proprio lo sviluppo di questo modulo. Nella versione fornita esso definisce solo l’interfaccia di comunicazione (fatti di tipo exec) e ad ogni istante deve essere l’utente che fornisce l’azione che Ruby deve compiere nel supermercato. Ovviamente a progetto ultimato l’agente deve essere in grado di decidere autonomamente le azioni da compiere nel modo più razionale possibile.

E’ sicuramente utile che si analizzi con una certa cura cosa fa il modulo ENV in modo da comprendere come le assunzioni sopra specificate sono rese a livello di implementazione di tipi di dati. Il file che contiene MAIN, ENV (con un particolare supermercato già rappresentato) e AGENT (nella forma appena abbozzata) è Ruby al Supermercato (CLIPS)

Si noti che Ruby deve avere delle componenti reattive (in particole integrare le percezioni che man mano riceve), ma e’ assai probabile che includa anche componenti deliberative (un possibile esempio è relativo alla necessità di pianificare il cammino che lo porta dallo stand dove ha completata la spesa alla uscita). Tecniche assai diverse possono essere utilizzate per fare questa ricerca. Nel caso che lo studente volesse sperimentare una soluzione relativamente semplice si suggerisce di prendere in considerazione una strategia iterative deepening. Lo studente può farsi una idea di come questa possa essere realizzata in un linguaggio a regola guardando la soluzione adottata per risolvere problemi nel mondo dei blocchi facendo uso di questa strategia. La soluzione in CLIPS per il problema la si trova in BlockItDeepCLIPS mentre la versione per JESS è disponibile in BlockItDeepJESS

Chi fosse interessato ad una implementazione in JESS, può consultare il documento Consigli su JESS predisposto da Andrea Bosio. In questo documento sono riassunti alcuni elementi di base per l’integrazione tra JESS e JAVA. Inoltre il file con la base di conoscenza del progetto già modificata e messa in formato adeguato per girare sotto Jess si trova qui. Inoltre vengono nella directory SUPER vengono fornite alcuni classi java che permettono di visualizzare graficamente quanto fatto da Ruby ad ogni passo a1, a2, a3, a4 a5 a6 a7 a8 a9 a10, a11 e a12

Il progetto può essere esteso in numerose direzioni. La versione corrente di Env è gia in grado di trattare il caso in cui alcune celle libere (da muri o da stand) possono contenere cartelli indicatori con la categoria merceologica che viene venduta in stand vicini a quelli in cui si trova il cartello indicatore.

Si noti che il cartello indicatore non occupa la cella nel senso che il robot può accedere alla cella in questione (il cartello è appeso al soffitto). Il Modulo ENV ritorna il contenuto del cartello nei fatti di tipo percepts con le stesse regole degli altri contenuti (un cartello non e’ visibile se sull’asse di visuale di Ruby c’è un muro o uno stand).

E’ compito di Ruby capire che la cella (i,j) è accessibile a Ruby.anche se essa contiene un cartello indicatore. Vale la pena notare che le indicazioni sul cartello sono ad un livello di granularità completamente diverso da quello che appare sulle etichette che caratterizzano lo stand. Ad esempio una etichetta può contenere "barbera" o "Robiola" mentre il cartello indicatore potrebbe contenere "bevande" oppure "reparto alimentari". Quali siano le basi di conoscenza (ontologie) che Ruby potrebbe realizzare per fare il ragionamento che porta a scoprire che rubiola si trova in un reparto alimentari e non quello degli articoli sportivi è parte della eventuale estensione del progetto.

Così è parte della eventuale estensione del progetto la decisione di quali regole euristiche utilizzare per ridurre il numero di azioni (esplorative) una volta che sia nota la localizzazione approssimativa di un determinato prodotto sulla base delle informazioni dei cartelli indicatori .