Cap.VII: Sistemi Di Rappresentazione Di Conoscenza Basati Su Logica -Sviluppo Di Un Sistema Per La Gestione Degli Appartamenti Per Studenti Fuorisede.
Sistemi Relazionali E Sistemi Basati Su Logica Per Lo Sviluppo Di Applicazioni Di Interrogazione Di Basi Di Dati.
Quando si sono illustrate le caratteristiche degli agenti software si è accennato ai sistemi per permettere loro di acquisire conoscenza. Si sono anche descritti nel capitolo sugli agenti software i comportamenti e i servizi per i quali sono stati pensati. Nello specifico del loro utilizzo nel campo del commercio elettronico si è immaginato uno scenario ove gli agenti degli acquirenti potranno automaticamente contrattare un acquisto, con i rispettivi agenti-venditori.
Lo sviluppo di applicazioni così avanzate porta a sottolineare la necessità di fornire strumenti di rappresentazione di conoscenza molto più evoluti di quelli attuali.
A questo proposito in questo lavoro si è pensato di effettuare una prova delle funzionalità offerte da un sistema di rappresentazione di conoscenza basato su logica a concetti (DescriptionLogic) come NeoClassic.
Questa prova è consistita nello sviluppare un sistema di "agenzia virtuale" per la gestione per gli appartamenti affittati agli studenti fuori-sede.
Al di là di alcuni aspetti specifici del problema, questa applicazione presenta analogie con tutti quei sistemi che permettono agli utenti di personalizzare prodotti e servizi.
Si pensi, ad esempio, al caso della prenotazione di una camera presso un albergo, ove l'utente ha la possibilità di scegliere, oltre al tipo di sistemazione (in genere camera singola o doppia), tutta una serie di servizi accessori (il posto auto, la televisione in camera, un terzo letto, etc.).
Come secondo esempio si pensi al caso dell'acquisto di un'auto nuova, con un'ampia possibilità di personalizzare la propria richiesta, scegliendo tra una lista più o meno lunga di optionals e/o pacchetti (pacchetto sicurezza, pacchetto sport, etc.).
Internet favorirà, certamente, lo sviluppo di sistemi dedicati a compiti di questo genere (se ne è già diffusamente parlato nella parte introduttiva di questo lavoro); un aspetto che subito risulta evidente è la somiglianza tra il problema della "personalizzazione" e il problema della "configurazione" di un prodotto, problema per il quale sono stati sviluppati i sistemi come NeoClassic.
Infatti se si permette all'utente di personalizzare il prodotto secondo i suoi gusti, bisogna altresì verificare sia la "correttezza" che la "completezza" della personalizzazione, spesso legate ad informazioni ignote al cliente.
Per tornare all'esempio relativo alla vendita di un'auto, un utente potrà certamente scegliere di aggiungere alla sua nuova auto l'accessorio "aria-condizionata", ma a patto di non aver in precedenza scelto un'automobile che non sia in grado di montare tale accessorio (per es. di cilindrata inferiore ai 1000 c.c.).
Viceversa, se un utente inserisce per la sua auto la richiesta di una versione "sportiva", sarà compito del sistema di tradurre questa richiesta in tutta una serie di optionals (esempio assetto ribassato, cerchi maggiorati, etc.).
Un' altra esigenza, in comune con ambiti legati alle transazioni di tipo business to business riguarda la necessità di fornire anche strumenti che permettano una maggiore interazione fra cliente e fornitore, per favorire la fase di contrattazione tra le parti. Si è provato ad utilizzare un sistema di rappresentazione di conoscenza per cercare di fornire soluzioni ai problemi qui brevemente esposti.
Descrizione Del Sistema Neoclassic*
*Questo capitolo è ripreso dalla tesi di G.Rotondi: "nometesi" (cap 4)-
corso di laurea in elettronica - seduta di laurea aprile 2000. Si rimanda al cap.3 dello stesso lavoro per un approfondimento sui sistemi di configurazione.
NeoClassic è il più recente sistema esperto sviluppato nei laboratori dell'AT&T. NeoClassic fa parte del "gruppo" CLASSIC [1], una famiglia di configuratori basati su logica descrittiva. In CLASSIC le informazioni che riguardano un particolare dominio vengono rappresentate in termini di descrizioni, concetti (tipi di individui), ruoli (attributi), regole e individui (istanze dei concetti) [2-3].
Il tutto è arricchito da un meccanismo di regole di inferenza di tipo forward chaining. La principale caratteristica di tale famiglia di prodotti è la semplicità del linguaggio di descrizione della base di conoscenza.
NeoClassic, attualmente, mette a disposizione tre tipi di interfacce: un'API (Application Programming Interface) scritta in C++ [4], una GUI (Graphical User Interface) per piattaforma WinNT/Win9x e un'interfaccia a caratteri. Il fatto che NeoClassic sia distribuito con i sorgenti consente un pieno controllo sulle capacità di rappresentazione della base di conoscenza e rende possibile estendere le funzionalità del sistema esperto scrivendo vere e proprie classi C++ personalizzate.
Nei prossimi paragrafi vedremo quali sono le capacità descrittive di NeoClassic [5-6]. Tuttavia, prima di cominciare, è bene introdurre il concetto di individuo. NeoClassic distingue tra individui che fanno parte del dominio che ci interessa modellare - detti CLASSIC Individuals - ed individui che aiutano a descrivere i CLASSIC Individuals - detti HOST Individals. Ad esempio, in un dominio in cui ci interessa modellare la domanda e la richiesta di posti-letto, un individuo di tipo CLASSIC potrebbe essere il posto-letto, mentre un individuo di tipo HOST potrebbe essere il costo ad esso relativo.
Descrizioni
Il concetto di descrizione è alla base dei sistemi di configurazione come NeoClassic. Una descrizione ha lo scopo di una serie di attributi (o ruoli) e caratteristiche ad un individuo. Una descrizione serve, in qualche modo, a definire una classe di individui, cioè una serie di attributi e vincoli che caratterizzano tutte le istanze di quella classe.
Un esempio di descrizione potrebbe essere: Le persone con età compresa tra 30 e 40 anni con al massimo 5 amici e i cui amici sono medici. In NeoClassic tale descrizione viene espressa dal seguente esempio:
(and Persona
(all età (and (minimum 30)
(maximum 40)))
(atMost
5 amici)
(all
amici Medico)
)
Codice Neoclassic
Si tratta, evidentemente, di un simbolismo molto vicino al linguaggio umano e ciò rende NeoClassic lo strumento ideale per descrivere le informazioni che caratterizzano un particolare dominio. Se nella base di conoscenza viene inserito un individuo Giuseppe che è una Persona di 35 anni con al massimo 2 amici Medici, allora NeoClassic classificherà automaticamente Giuseppe sotto la descrizione appena vista.
DESCRIZIONI DI TIPO CLASSIC
Dal momento che NeoClassic distingue gli individui di tipo CLASSIC dagli individui di tipo HOST, anche le descrizioni devono essere di tipo CLASSIC e di tipo HOST (dal momento che lo scopo di una descrizione è di definire le caratteristiche di un individuo).
Per la definizione delle descrizioni di tipo CLASSIC, NeoClassic mette a disposizione una serie di operatori (si tratta di funzioni logiche o matematiche) e restrizioni (si tratta di vincoli che devono essere soddisfatti da un particolare attributo).
L'operatore and consente di definire tipi di individui che soddisfano contemporaneamente più descrizioni. Ad esempio una PersonaVegetariana potrebbe essere definita in questo modo: (and Persona Vegetariana). Con (and) si indica la descrizione universale, cioè una descrizione a cui appartengono tutti gli individui della base di conoscenza.
L'operatore oneOf serve a definire un elenco di individui che rappresentano tutte le possibili istanze di una descrizione. Ad esempio, la descrizione (oneOf Bianco Rosso Rosato) rappresenta l'insieme degli individui che possono caratterizzare un vino. Cioè, un vino può essere esclusivamente Bianco, Rosso o Rosato. L'operatore oneOf consente di definire una descrizione particolare che rappresenta l'insieme vuoto. Si indica con (oneOf) ed è una descrizione che non contiene individui.
La restrizione all consente di associare ad un attributo una particolare descrizione. La descrizione (all cibo Pianta), ad esempio, potrebbe servire a definire un attributo cibo di tipo Pianta che caratterizza un individuo di tipo PersonaVegetariana. Una restrizione di tipo all potrebbe essere incoerente. Un esempio potrebbe essere il concetto GenitoreConFigli_Incoerente definito in questo modo: (all figli (and Maschio Femmina)). Nessun individuo può essere contemporaneamente Maschio e Femmina, pertanto un concetto del genere sarà destinato a non contenere mai degli individui.
Le restrizioni atLeast e atMost consentono di stabilire il numero minimo e massimo (rispettivamente) di individui che possono andare a riempire un ruolo (per ruolo si intende un attributo a valori multipli). Ad esempio un genitore con esattamente un figlio potrebbe essere descritto in questo modo: (and (atLeast 1 figlio) (atMost 1 figlio)). Anche in questo caso è possibile che si arrivi a definire qualcosa di incoerente. Un esempio potrebbe essere: (and (atLeast 27 anni) (atMost 10 anni)). Una descrizione di questo tipo non avrà mai delle istanze che la soddisfino.
L'operatore fills serve ad indicare la lista degli individui che riempiono un dato ruolo.
Ad esempio una Persona che si chiama Mario Vincenzo Rossi potrebbe essere descritta da: (and Persona (fills nome Mario Vincenzo) (fills cognome Rossi)).
E' possibile estendere le capacità descrittive di NeoClassic scrivendo del codice C++ che determina se un particolare individuo soddisfa una certa descri zione. Come accennato prima, ciò rende NeoClassic uno strumento estremamente potente e flessibile.
DESCRIZIONI DI TIPO HOST
Così come è possibile descrivere individui di tipo CLASSIC è anche possibile descrivere individui di tipo HOST. Un individuo di tipo HOST deve necessariamente appartenere ad uno dei tipi predefiniti: Numerico (Intero o Reale) e Stringa. Per le descrizioni di tipo HOST sono disponibili operatori e restrizioni analoghi a quelli visti nel paragrafo precedente.
Gli operatori and e oneOf e la restrizione all hanno lo stesso significato che avevano nelle descrizioni di tipo CLASSIC. Nel contesto di individui numerici ad esempio potremmo avere una descrizione del tipo (all giorno-settimana (and INTEGER (oneOf 1 2 3 4 5 6 7)) che descrive l'attributo giorno-settimana.
Gli operatori minimum e maximum consentono di definire il limite minimo e massimo (rispettivamente) di un individuo di tipo HOST. Ad esempio potremmo definire una persona giovane mediante la descrizione (all età (and INTEGER (minimum 1) (maximum 30)).
Anche per le descrizioni di tipo HOST è possibile ampliare le capacità predefinite di NeoClassic definendo classi C++ personalizzate (un esempio potrebbe essere una funzione in grado di verificare se un HOST Individual di tipo INTEGER è un numero primo).
Concetti CONCETTI PRIMITIVI E CONCETTI DEFINITI
Mentre un concetto HOST ha una semantica completamente definita dalla descrizione che gli è stata associata, un concetto CLASSIC non sempre assume un significato ben definito al momento della sua creazione. I concetti CLASSIC possono essere di due tipi: definiti o primitivi.
Un concetto definito ha una semantica ben precisa già al momento della creazione. Supponiamo, ad esempio, di definire il concetto Vegetariano in modo che soddisfi la descrizione (all cibo Pianta). Vegetariano è un concetto definito perché ha un significato ben preciso: include tutti gli individui che mangiano esclusivamente piante. Ciò ha una forte implicazione nel meccanismo di inferenza di NeoClassic. Infatti, potrei benissimo definire un nuovo concetto MangiatoreDiPianteVerdi, mediante la descrizione (all cibo PiantaVerde), e NeoClassic comunque classificherebbe MangiatoreDiPianteVerdi come un Vegetariano. In poche parole, NeoClassic riesce a classificare i concetti anche se la definizione del concetto "figlio" non include il nome del concetto "padre".
Un concetto primitivo, invece, non ha alcuna semantica al momento della creazione. Ad esempio, supponiamo di definire Mammifero come concetto primitivo. Per classificare un nuovo concetto (ad esempio Cane) sotto Mammifero devo necessariamente esplicitare il concetto "padre" nella definizione del concetto "figlio".
NeoClassic implementa anche un tipo particolare di concetto primitivo che si chiama concetto primitivo disgiunto. Un concetto primitivo disgiunto fa parte di un gruppo di concetti (detto disjoint group) che sono disgiunti, nel senso che gli individui che appartengono ad uno di tali concetti non possono essere classificati sotto gli altri concetti dello stesso disjont group. Un esempio potrebbe essere il disjoint group tipo-persona che contiene due concetti disgiunti Uomo e Donna. Un individuo può essere Uomo o Donna e non può soddisfare contemporaneamente le due descrizioni.
CONCETTI PREDEFINITI IN NEOCLASSIC
Ciascuna base di conoscenza di NeoClassic nasce con una serie di concetti predefiniti che rappresentano i concetti "padre" da cui vengono derivati tutti gli altri concetti. Il concetto Thing occupa la posizione più alta nella gerarchia delle classi e rappresenta la descrizione universale (cioè tutti gli individui ne fanno parte). Il concetto ClassicThing è classificato sotto Thing e rappresenta i concetti e le descrizioni di tipo CLASSIC in genere. Il concetto HostThing - sempre classificato sotto Thing - congloba tutti i concetti e le descrizioni di tipo HOST. Sotto HostThing sono classificati i concetti predefiniti NUMBER, INTEGER, FLOAT e STRING.
Individui
Gli individui sono le istanze dei concetti. Come già detto in precedenza, ci sono due tipi di individui, quelli di tipo CLASSIC e quelli di tipo HOST. Gli individui di tipo CLASSIC rappresentano oggetti del mondo reale, mentre quelli di tipo HOST rappresentano numeri o stringhe.
La creazione di un individuo avviene tramite la funzione createIndividual. Durante la creazione di un individuo è possibile specificare sia concetti che descrizioni. Ad esempio una Persona Susanna che ha 80 anni e che ha un figlio che si chiama Gianni può essere descritta in questo modo:
(createIndividual
Susanna
(and Persona (fills età 80) (fills figlio Gianni)))
Esempio codice Neoclassic
Ruoli
I ruoli rappresentano le proprietà degli individui di tipo CLASSIC. Ciascun ruolo può essere "riempito" da individui di tipo CLASSIC o di tipo HOST.
La funzione che consente di creare ruoli è createRole. Una volta creato il ruolo è possibile imporre dei vincoli su di esso mediante gli operatori all, fills e le restrizioni oneOf, atLeast, atMost, minimum, maximum. Ecco un esempio di ruolo (zona) applicato ad un particolare concetto (APPARTAMENTO):
(createRole
zona)
(createConceptAPPARTAMENTO
(and TOP
(atMost 1 zona)
(atLeast
1 zona)…………………))
codice Neoclassic
Nell'esempio precedente sono state usate le restrizioni atMost e atLeast per informare NeoClassic che è un attributo a singolo valore. Ciò è necessario perché un ruolo, in generale, è un attributo a più valori. Tuttavia esiste un modo più sintetico per definire direttamente un ruolo come attributo a singolo valore:
La parola chiave true indica un attributo a singolo valore
(createRole
zona true)
(createConcept
APPARTAMENTO
(atLeast
1 zona))
Codice Neoclassic
Regole
NeoClassic mette a disposizione tre tipi di regole: simple rule, computed description rule, computed filler rule. Tutte le regole sono implementate mediante un meccanismo di tipo forward chaining (vedi paragrafo 3.2.1).
Una simple rule è costituita da un concetto antecedente e da una descrizione conseguente. La sintassi è la seguente: (createRule nome-regola concetto-antecedente descrizione-conseguente). Un esempio potrebbe essere:
(createRule
assegnazione-codice-fiscale
PERSONA
(and
(all
codice-fiscale CODICE-FISCALE)
(atLeast 1 codice-fiscale)
(atMost
1 codice-fiscale)))
Codice Neoclassic
Questa regola assegnerà ad ogni PERSONA un codice-fiscale che è un attributo di tipo CODICE-FISCALE. Tale regola verrà lanciata ogni volta che viene creato un individuo di tipo PERSONA.
Una computed description rule è simile ad una simple rule, eccetto per il fatto che la descrizione conseguente è costituita da una funzione scritta in C++ che prende il nome di computed description. Una computed description viene valutata solo nel momento in cui la regola viene applicata e non è nota durante creazione della regola.
Una computed filler rule offre tutte le funzionalità di una computed description rule, in più consente di specificare un ruolo che potrà essere riempito con individui calcolati a run-time al momento di applicazione della regola.
Basi Di Conoscenza
Una base di conoscenza è semplicemente una collezione di concetti, individui, ruoli e regole. NeoClassic supporta la creazione di più basi di conoscenza. Concetti, individui ruoli e regole di una base di conoscenza sono accessibili solo all'interno di tale base di conoscenza.
Aggiornamenti Di Una Base Di Conoscenza
Ogni base di conoscenza rappresenta una struttura dati complessa a causa del fatto che ogni nuova aggiunta di informazioni fa scaturire il meccanismo di inferenza di NeoClassic. Tale meccanismo aggiorna la base di conoscenza in maniera coerente con le informazioni introdotte. Con NeoClassic è sempre possibile aggiungere informazioni alla base di conoscenza, ma non è sempre possibile rimuoverle. In particolare, non è possibile modificare la definizione di un concetto e non è possibile rimuovere individui. E' possibile, tuttavia, aggiungere nuove informazioni ad un individuo e rimuoverle in maniera dinamica. Nei prossimi paragrafi vedremo come questo sia possibile.
Aggiunta E Rimozione Di Informazione Sugli Individui
La funzione addToldInformation consente di associare nuove descrizioni e nuovi ruoli ad individui già presenti nella base di conoscenza. Ecco un esempio: (addToldInformation Maria (fills figlio Gianni)).
La funzione removeToldInformation consente di rimuovere informazioni precedentemente associate ad un individuo. Non consente, tuttavia, di cancellare informazioni dedotte da NeoClassic attraverso il meccanismo di inferenza. Ecco un esempio: (removeToldInformation Maria (fills figlio Gianni)).
Il fatto di poter aggiungere e rimuovere informazioni in maniera dinamica rende NeoClassic uno strumento particolarmente adatto a simulare situazioni della vita reale che sono per loro natura mutevoli.
Meccanismi Di Inferenza Di Neoclassic
Ogni base di conoscenza è costituita da una tassonomia di concetti e individui che viene aggiornata man mano che nuove informazioni vengono introdotte. NeoClassic si serve dei dati inseriti dall'utente per dedurre tutte le informazioni possibili che riguardano concetti e individui [7].
Il meccanismo di inferenza è separato per i concetti e per gli individui. Nei prossimi paragrafi vedremo di cosa si tratta.
MECCANISMO DI INFERENZA PER I CONCETTI
Allo scopo di dedurre tutte le possibili informazioni che riguardano un concetto, NeoClassic attraversa tre fasi:
Normalizzazione
Ereditarietà
Classificazione Normalizzazione
Durante la fase di normalizzazione, NeoClassic fondamentalmente si preoccupa di:
Ereditare informazioni dai concetti "padre". In questa fase NeoClassic raccoglie tutti i ruoli associati al concetto "padre" e li associa al concetto "figlio".
Combinare le diverse descrizioni che riguardano uno stesso ruolo. Dopo questo stadio, ogni ruolo sarà caratterizzato da un'unica descrizione che tiene conto, in maniera sintetica, di tutte le informazioni associate a quel ruolo. Ad esempio supponiamo che ad un ruolo età siano associate due descrizioni: (all età (and INTEGER (oneOf 20 25 30 35))) (ad esempio da parte del concetto "padre") e (all età (and INTEGER (oneOf 20 30))) (ad esempio da parte del concetto "figlio"). Dopo la normalizzazione la descrizione associata a quel ruolo sarà: (all età (oneOf 20 30)) (ottenuta come intersezione delle due restrizioni).
Controllare la consistenza di descrizioni e concetti. Ereditarietà
In questa fase NeoClassic si prepara a derivare la tassonomia dei concetti. In particolare, per ogni concetto determina quali sono i concetti "padre" ed i concetti "figlio". A questo punto non è ancora nota la gerarchia completa dei concetti, nel senso che si hanno informazioni solo sui singoli concetti. Tali informazioni dovranno poi essere sintetizzate al fine di creare l'albero dei concetti. Classificazione
La classificazione dei concetti implica la ricerca di tutti i "genitori", di tutti i "figli" e di tutte le istanze di un concetto. A questo punto la tassonomia delle classi è completa.
Servendosi della gerarchia delle classi, NeoClassic applica le regole - specificate nella base di conoscenza - e quindi riclassifica gli individui.
MECCANISMO DI INFERENZA PER GLI INDIVIDUI
Le fasi previste per la normalizzazione degli individui sono:
Normalizzazione
Propagazione
Ereditarietà
Classificazione
Normalizzazione
La normalizzazione di un individuo è analoga a quella di un concetto. Lo scopo è quello di determinare tutti gli attributi caratteristici di un individuo. Si tratta, cioè, di associare all'individuo tutti i ruoli che caratterizzano i concetti a cui l'individuo appartiene. In più, NeoClassic verifica se ci sono individui inconsistenti. In tal caso l'individuo non viene aggiunto alla base di conoscenza.
Propagazione
In questa fase NeoClassic prende in considerazioni i singoli ruoli associati ad un individuo e ne determina il tipo. Facciamo un esempio per capire meglio di cosa si tratta:
(createConcept
GENITORE-DI-UN-MEDICO
(and PERSONA
(atLeast 1 figlio)
(all figlio MEDICO)))
(createIndividual Mario)
(createIndividual Francesco
(and GENITORE-DI-UN-MEDICO (fills figlio Mario)))
Codice Neoclassic
Durante la fase di propagazione sull'individuo Francesco, NeoClassic prende in considerazione l'attributo figlio che assume il valore Mario. Tenendo conto del fatto che Francesco è un GENITORE-DI-UN-MEDICO - che è caratterizzato dall'aver un figlio MEDICO - NeoClassic deduce che Mario è un MEDICO.
Ereditarietà
In questa fase NeoClassic determina tutte le descrizioni che vengono soddisfatte dall'individuo in questione. Cioè ricava tutti i concetti sotto cui l'individuo può essere classificato.
Classificazione
Durante la classificazione di un individuo, NeoClassic prende in considerazione tutti i concetti di cui l'individuo fa parte, applica le regole definite nella base di conoscenza e riclassifica l'individuo nella gerarchia.
Query Possibili Su Una Base Di Conoscenza Implementata Con Neoclassic
Le operazione che un utente può generalmente effettuare su una base di conoscenza NeoClassic sono:
Ottenere la lista degli individui che rientrano in un certo concetto (le istanze di un concetto). Per questa operazione sono definite due primitive: la prima, getInstances, permette di recuperare tutti gli individui che soddisfano un concetto, la seconda, getDirectInstances, solo quegli individui che non siano stati classificati in concetti più specifici. Se, per esempio, ho definito i due concetti UOMO e UOMO-ANZIANO il primo comando applicato al concetto UOMO restituirà tutti gli uomini presenti nella base di conoscenza, mentre il secondo restituirà tutti gli uomini eccetto gli anziani.
Recupero della lista di tutti i CONCETTI sotto i quali è classificato un certo individuo. Ad esempio l'individuo Paolo potrà essere classificato nella base di conoscenza sotto i concetti UOMO, STUDENTE, etc.
Ottenere la lista completa delle caratteristiche di un individuo, cioè l'elenco dei fillers sui ruoli definiti per l'individuo. Ad esempio di una certa PERSONA potrò essere interessato a conoscere i dettagli relativi ai ruoli età, indirizzo, città, etc.
Conoscere i vincoli sui ruoli definiti per un individuo (es. un GIOVANE non può avere un'età maggiore di 18 anni).
Caratteristiche Distintive Dei Sistemi DL Su Altri Sistemi Di Rappresentazione Di Conoscenza.
Il sistema NeoClassic appartiene alla categoria di sistemi DL capaci di eseguire automaticamente la classificazione dei concetti, sollevando l'utente dal compito di stabilire una gerarchia per i concetti introdotti.
Questa proprietà risulta utile in quei casi in cui gli oggetti rappresentati abbiano una gran quantità di caratteristiche (role) e si voglia automaticamente raggruppare tali oggetti (individui) in categorie.
In un sistema tipo NeoClassic è possibile formulare richieste più complesse rispetto a quanto ottenibile dai database tradizionali (basati essenzialmente su ricerca di parole chiave); in questo caso sono possibili anche richieste generiche del tipo: voglio l'elenco di tutte le PERSONE proprietarie di almeno 2 APPARTAMENTI di categoria "lusso").
Un'altra caratteristica del sistema NeoClassic, comune ad altri sistemi basati su logica, è data dalla possibilità di estendere piuttosto facilmente il dominio di interesse.
Questo significa che NeoClassic prevede una rappresentazione incompleta delle caratteristiche di un individuo, con la possibilità di aggiungere in tempi successivi ulteriori informazioni; questo viene realizzato mediante una serie di accorgimenti implementativi:
La gestione dei role: è possibile definire solo parzialmente le caratteristiche di un filler su un certo role, indicando sia il numero massimo di fillers ammessi sul role (es. il role età del concetto PERSONA ha esattamente 1 filler ) sia le caratteristiche (il role età è necessariamente un intero positivo).
La conoscenza aggiunta ad un certo individuo può permettere di riclassificarlo in un concetto più specifico (a seguito di un'informazione aggiuntiva una PERSONA potrà essere classificata in UOMO, poi in MARITO etc.).
Infine da ultimo vorrei sottolineare l'importanza delle regole che permettono di aggiungere ad un certo individuo tutta una serie di informazioni che implicitamente scaturiscono da una certa asserzione (es. se ho definito Paolo come MARITO posso dedurre, dalla definizione del concetto MARITO, l'esistenza di un filler sul role ha-moglie). Anche i roles sono stati pensati per aggiungere informazione su un individuo, nel caso in cui, questa volta per asserzione, il sistema lo abbia classificato sotto un certo concetto.
Spiegati i punti di forza del sistema NeoClassic passiamo ad esaminare i punti di debolezza rispetto a sistemi più tradizionali.
Sicuramente un aspetto in cui i sistemi relazionali offrono servizi superiori è nella possibilità di effettuare manipolazioni sui risultati di una query (es. voglio il totale delle vendite in Europa relative al mese di Maggio). In secondo luogo un sistema come NeoClassic si rivela poco efficiente in situazioni ove non sia necessaria una elaborata classificazione degli individui, oppure in situazioni ove siano presenti regole il cui antecedente sia costituito da più individui (es. se ho due persone con età uno il doppio dell'altra…). Infine il sistema NeoClassic non gestisce dati temporali con la stessa efficienza dei database tradizionali.
Sviluppo Di Un Sistema Per La Gestione Degli Appartamenti Per Studenti Fuorisede Basato Su Neoclassic
Analisi Del Problema
Passiamo adesso al sistema per la gestione degli appartamenti per fuorisede realizzato con NeoClassic.
Il punto di partenza del lavoro è, come sempre in questi casi, quello di definire le caratteristiche del problema che si vuole affrontare.
Il primo aspetto del problema è rappresentato dall'esigenza di far incontrare la domanda e l'offerta; fatto ciò bisogna definire un meccanismo per la contrattazione tra le parti coinvolte che sia il più efficiente possibile in termini di transazioni conclusesi positivamente.
Attualmente lo strumento più diffuso per risolvere il primo punto (incontro tra domanda e offerta) è rappresentato dalle piccole inserzioni sui giornali, oppure dagli annunci affissi in bacheche improvvisate nei pressi delle facoltà, seguiti da contatti telefonici per lo scambio di informazioni aggiuntive.
I limiti di questa soluzione sono evidenti: difficoltà nella localizzazione dell'offerta e necessità di recarsi sul posto per effettuare le ricerche del posto-letto.
Inoltre i dettagli dell'offerta presentati, sono spesso in numero ridotto, cosicché da una parte lo studente è costretto ad una serie di telefonate per chiedere ulteriori dettagli sull'offerta presentata, dall'altra i proprietari devono rispondere più volte alle stesse domande, determinado una fase di contrattazione eccessivamente laboriosa.
Una soluzione più efficiente è rappresentata dalle agenzie di intermediazione, spesso gestite da associazioni di studenti.
In questo caso si rende possibile la memorizzazione delle offerte/domande in modo efficiente e si favorisce la presentazione di informazioni più complete e dettagliate.
Questa soluzione si risolve in un vantaggio sia per lo studente, che immediatamente ha a disposizione un panorama di offerte più ampio e articolato che in precedenza, ma anche per il proprietario, che delega all'agenzia il compito di fornire le informazioni agli studenti e buona parte della fase di contrattazione, intervenendo solo in fase di chiusura del contratto.
Inoltre un ulteriore vantaggio di questo sistema consiste nella possibilità di registrare, oltre le offerte di posti letto, anche le domande giunte dagli studenti (rimaste in sospeso a causa di mancanza di appartamenti adatti) .
L'aspetto comune dei due sistemi precedenti è dato dal fatto che entrambi si basano su una transazione di tipo bilaterale; sicuramente il prezzo è un dato fisso dell'offerta e non è oggetto di trattativa, mentre vi è estrema varietà di caratteristiche di elementi accessori che l'utente/studente può aggiungere alla sua richiesta di base (il posto auto, la vicinanza ad una certa facoltà, alcuni comfort, etc.).
Il secondo sistema presentato offre però dei vantaggi che nel primo caso sono assenti, come si è visto.
Tali vantaggi non derivano solo dall'uso di un sistema di archiviazione delle domande/offerte più completo, ma anche dalla capacità dell'agenzia di intermediazione di indirizzare, in caso di offerte non esattamente corrispondenti alle preferenze, la richiesta del cliente/studente verso soluzioni "simili" attualmente disponibili. In secondo luogo l'agenzia, a seguito di richieste di particolari servizi/accessori provenienti dagli studenti, si occupa di inoltrare (verso i venditori/proprietari ) richieste di informazioni mancanti.
Intermediazione: L'agenzia Reale E Agenzia "Virtuale"
Pensiamo allora di voler realizzare un sistema analogo all'ultimo descritto in modo informatizzato, per ottenere possibilmente un miglioramento in termini di efficienza e di costo, pensando casomai di portare questo servizio su Internet, per permettere ai proprietari, ma soprattutto agli studenti, di consultare a distanza questa "agenzia virtuale".
Dal punto di vista tecnico una implementazione di tale sistema può sembrare semplice: si potrebbe utilizzare un classico database relazionale per raccogliere le offerte dei proprietari e le richieste degli studenti.
Ben presto si è costretti ad osservare come questa implementazione del sistema risulti troppo rigida, ben lontano dalla flessibilità e dalle capacità di intermediazione offerti da un sistema di agenzia reale.
La rigidità del sistema si può osservare soprattutto nella fase di interrogazione del database, con frequenti fallimenti nell'individuazione di "soluzioni" alle richieste degli utenti, che si vedono costretti a riformularle da zero per mancanza di risultati, senza peraltro avere alcuna spiegazione dei motivi di tali fallimenti.
Confrontando le richieste di diversi utenti si possono evidenziare le caratteristiche di bassa tipizzazione ed estrema varietà delle query che gli utenti sottopongono al sistema.
Per illustrare questo concetto parto da un esempio (abbastanza significativo per la sua complessità).
L'esempio potrebbe essere quello di un gruppo di tre fuorisede appartenenti alle facoltà di Ingegneria, Medicina, Economia e Commercio che cercano un appartamento con posto auto, riscaldamento, telefono, fissando una spesa max. di £.250.000 a testa tutto compreso. Ogni servizio verrà d'ora in poi indicato con il termine di preferenza (da questo esempio, e da altri analoghi, si è partiti per definire le informazioni di base di questa applicazione (zona dell'appartamento, disponibilità dei posti, dettaglio dei costi richiesti).
Tuttavia l'aspetto che va evidenziato è che il gruppo non ritiene i servizi (preferenze) richiesti ugualmente importanti; alcuni sono certamente ritenuti più importanti degli altri, anzi alcuni sono ritenuti indispensabili, altri, invece, accessori (teoria dell'utilità multiattributo). Se considero più gruppi risulta che la graduatoria delle preferenze non è assoluta, bensì ogni gruppo avrà sia una propria lista di preferenze che, soprattutto, la sua graduatoria di tali preferenze, ad alcune delle quali non sarà disposto a rinunciare.
Per esempio per un gruppo potrà essere importante il riscaldamento, per un altro può esserlo di più il posto auto. Addirittura anche un aspetto, quale la vicinanza ad una particolare facoltà, potrebbe essere un elemento non sempre fondamentale.
Ecco dunque il motivo per cui un sistema tradizionale di database non risulta molto efficiente nella gestione di query su oggetti multi-attributo: non potendo conoscere a priori la graduatoria delle preferenze dell'utente il sistema assegna lo stesso "peso" a ciascuno degli elementi oggetto della richiesta, ritenendoli altresì tutti "indispensabili", portando così a scartare tutte le soluzioni non perfettamente coincidenti con la richiesta formulata.
Premesso che la soluzione di un problema così complesso potrebbe costituire da solo oggetto di una tesi di ricerca operativa, abbiamo provato a realizzare un sistema con NeoClassic che avesse come obiettivo quello di avvicinarsi, per quanto possibile, al grado di efficienza di un'agenzia reale, secondo quanto già emerso dalle considerazioni precedenti.
Obiettivi Di Progetto
Alla fine si sono definite 5 "servizi funzionali" che il sistema avrebbe cercato di implementare, spiegando al contempo perché utilizzare un sistema basato su DL come NeoClassic (anziché uno relazionale) per implementarli.
I servizi individuali sono stati:
1. Supporto all'utente in fase di interrogazione della base di dati.
2. Creazione di vincoli di correttezza sulla richiesta formulata.
3. Gestione richiesta di nuovi servizi.
4. Meccanismi di memorizzazione query.
5. Meccanismi di deduzione di dati collegati ai dati inseriti.
Nota: d'ora in poi intenderò per utente lo studente che interroga la base dati circa la disponibilità di posti-letto.
Supporto All'utente In Fase Di Interrogazione Della Base Di Dati.
Nella fase di formulazione della sua richiesta l'utente dovrebbe in qualche modo introdurre tale richiesta in modo incrementale, partendo casomai dalla definizione di quei servizi che ritiene indispensabili.
Successivamente potrebbe raffinare la ricerca in modo "guidato": il sistema gli dovrebbe indicare i servizi disponibili da poter aggiungere.
L'uso di un sistema come NeoClassic sembrerebbe essere promettente da questo punto di vista, data la possibilità di navigare nella gerarchia dei concetti verso concetti (quindi servizi) sempre più specifici. Potrei addirittura indicare all'utente quali sottocategorie di concetti sono popolate e quali non lo sono.
Creazione di vincoli di correttezza logica sulla richiesta formulata/ sull'offerta inserita.
Questo servizio estende il semplice controllo di tipo sul dato inserito (esempio il prezzo sarà un numero intero) ottenibile da un tradizionale dbase.
Posso infatti prevedere controlli di compatibilità funzionale (es. non potrò indicare il desiderio di avere più di una facoltà nelle immediate vicinanze di un appartamento, oppure non potrò chiedere un appartamento con piscina in centro città), o ancora controllare che il dato inserito appartenga ad un certo set (esempio potrei controllare che una certa facoltà esista veramente), o ancora indicare inconsistente l'affermare di avere più di 2 posti liberi in una camera doppia.
L'inserimento di queste funzioni è garantita da un sistema come NeoClassic in virtù della sua nascita come sistema dedicato alla configurazione, un ambito applicativo in cui la definizione di regole di compatibilità funzionale/strutturale è una necessità fondamentale. Se volessi ottenere queste sofisticate funzioni di controllo su sistemi dbase tradizionali dovrei ricorrere a strati di software esterni al sistema di gestione dei dati (JavaScript, Java).
Gestione Richiesta Di Nuovi Servizi / Nuove Offerte.
Immaginiamo che uno studente voglia richiedere, tra le altre cose, la presenza di un giardino. È ragionevole pensare che tale dato non sia stato inserito dai proprietari.
In questo caso la capacità di NeoClassic di gestire facilmente un'ampliamento nella descrizione delle caratteristiche degli appartamenti, deve permettere di sottoporre, in maniera più o meno automatica, una richiesta ai proprietari sulla presenza o meno del giardino e inserire nella base di conoscenza questo dato ulteriore.
Realizzare questo servizio significa che NeoClassic è in grado di sapere con certezza se un certo servizio è presente nell'appartamento, è assente, oppure non è stata fornita indicazione a tal proposito dal proprietario dell'appartamento.
Meccanismi Di Memorizzazione Query.
Nel caso in cui uno studente non abbia trovato una sistemazione soddisfacente, il sistema dovrebbe essere in grado di memorizzare la richiesta per poi avvertirlo qualora si venga a trovare un appartamento rispondente alla richiesta memorizzata.
Meccanismi Di Deduzione Di Dati Collegati Ai Dati Inseriti E/O Loro Manipolazione.
Molto spesso, operando secondo logica a concetti (o della programmazione ad oggetti), è possibile dedurre, da alcuni dati inseriti, un gran numero di informazioni. Se, per esempio, ho definito il concetto di AUTO e asserisco che l'individuo xxx è un'auto, potrò dedurre che xxx ha un motore, 4 ruote etc.
Utilizzando la possibilità di scrivere regole e di definire funzioni di tipo ComputedFillers si sono realizzate le seguenti funzioni:
deduzione facoltà vicine e raggiungibili da info su ubicazione appartamento.
L'intero comprensorio cittadino è stato infatti diviso in 12 zone.
Pensando di fornire ai proprietari una mappa cliccabile della città si potrebbe ricavare la zona in cui l'appartamento si trova. A partire da questo dato le regole definite permettono di ricavare informazioni sull'eventuale presenza di una facoltà nelle immediate vicinanze, oppure semplicemente la lista delle facoltà che, ragionevolmente, sono raggiungibili a piedi entro un tempo max di 20'.
Al di là della semplicità di questo esempio, questo è un caso in cui si gestisce un problema in cui alcune particolari informazioni sono note solo al sistema e non ai suoi utenti (ho già accennato al problema dei vincoli tecnici nel caso della vendita di un' auto).
In questo caso i proprietari non dovranno informarsi su quali facoltà sono vicine all'appartamento offerto, in quanto tale informazione sarà aggiunta automaticamente una volta inserita l'indicazione della zona in cui esso si trova.
Similmente il sistema pone allo studente la richiesta di quali facoltà voglia raggiungere, provvedendo autonomamente a considerare gli appartamenti nelle zone opportune della città.
calcolo del numero dei posti letto totali e dei vani totali.
In questo caso definire la lista delle camere singole, doppie, etc. mi permette di calcolare il numero totale dei posti letto presenti nell'appartamento (è un'informazione deducibile) senza dover inserire manualmente questo dato.
calcolo prezzo posti letto a partire dal totale richiesto (singola +30%).
In questo caso si è pensato di fornire un servizio al proprietario dell'appartamento: una volta che egli abbia inserito il totale mensile richiesto per l'intero appartamento, una opportuna funzione permette di determinare le quote derivanti sui singoli posti-letto.
Si è deciso di calcolare in modo differente la quota spettante a ciascun posto-letto a seconda che esso si trovi o meno in una camera singola.
Per semplicità si è deciso di fare in modo che il costo di un posto in una camera singola sia del 30% superiore al costo del posto nelle altre camere-letto.
deduzione dinamica dello stato dell'appartamento (appartamento libero).
Le capacità di classificazione di NeoClassic permettono di eseguire dinamicamente una valutazione sullo stato dei posti dell'appartamento: questo significa che non solo è possibile, tramite opportune regole, aggiornare i dati sul numero di posti disponibili, ma anche rilevare il presentarsi di condizioni di particolare interesse come per esempio la disponibilità completa di un appartamento (=> tutti i posti letto sono liberi).
Descrizione Del Sistema Ottenuto, Dinamica Del Sistema
Descrizione Appartamento
Premesso che lo studente è alla ricerca di un posto-libero in un appartamento con determinate caratteristiche e/o servizi, la modellazione dell'appartamento e dei posti-liberi è stata sviluppata secondo uno sviluppo ad oggetti.
Il punto di partenza della descrizione è l'APPARTAMENTO (d'ora in poi indicherò in maiuscolo quelli che sono stati definiti come concetti e in corsivo minuscolo i ruoli, mentre gli individui in minuscolo non corsivo).
Seguendo un approccio tipico della configurazione, ove descrivo un oggetto complesso composto da più parti (corrispondenti ad oggetti fisici o meno), che a loro volta possono essere decomposte in sotto parti elementari, ho cercato di individuare le diverse parti che insieme costituiscono un appartamento.
Ho quindi creato il concetto primitivo COMPOSIZIONE padre dei concetti VANO, PROPRIETARIO, ZONA (sono tutti concetti primitivi disgiunti).
Ciò significa che una generica istanza del concetto APPARTAMENTO sarà un oggetto (formato da) avente dei vani, un proprietario, una zona.
Il legame tra un istanza di APPARTAMENTO e gli individui che ne rappresentano i vani, la zona e il proprietario viene realizzato attraverso dei ruoli ( vano1, vano2, zona, recapiti-proprietario).
Tra i concetti finora definiti il VANO può essere ulteriormente specificato, a seconda del fatto di essere un vano che abbia dei posti letto o meno. Definisco quindi un gruppo disgiunto di concetti primitivi (attraverso il DisjointGroup vani-letto) figli del concetto VANO: SINGOLA, DOPPIA, TRIPLA, etc.
In effetti tali concetti sono una specializzazione di VANO caratterizzati dalla proprietà di possedere dei posti-letto.
Esaminiamo la definizione data per camera DOPPIA:
Questa definizione mi permette di fare alcune precisazioni.
La camera DOPPIA è caratterizzata dal role ha-posto che può contenere al più 2 fillers; tali fillers in effetti non sono semplicemente dei posti letto, ma dei posti-letto liberi.
Quindi in una camera DOPPIA ci potranno essere, al più, 2 posti liberi disponibili.
Chiarito ciò, dovrebbe essere intuibile il significato della definizione di DOPPIA-LIBERA e DOPPIA-CON-1-POSTO-LIBERO:
Lo stesso principio è stato seguito per definire tutti gli altri vani letto (SINGOLA, TRIPLA, QUADRUPLA) e con i loro sotto-concetti (SINGOLA-LIBERA, TRIPLA-LIBERA,TRIPLA-CON-1-POSTO-LIBERO, TRIPLA-CON-2-POSTI-LIBERI, et.)
Si noti come l'approccio seguito abbia portato a definire un altro concetto, POSTO-LIBERO, al di sotto del concetto COMPOSIZIONE, proprio per completare la descrizione di quei vani che presentano (sono composti da) dei posti-letto.
Per il corretto funzionamento del sistema, nella fase di inserimento dell'appartamento nella base di conoscenza, dovrò prima indicare per i vani letto a quale tipologia appartengano (SINGOLA, DOPPIA, et.), poi dovrò aggiungere individui sul role ha-posto lasciando al sistema il compito di classificare il vano letto secondo la disponibilità di posti-liberi.
Oltre le informazioni di base sull'appartamento, ne ho previsto altre aggiuntive realizzate tramite roles:
Il nome scelto per ciascun role è autoesplicativo circa il tipo di informazione conenuta. Tramite l'insieme di questi role posso fornire una serie piuttosto dettagliata di informazioni sull'appartamento e posso formulare una serie di query piuttosto ampia.
Inserimento Di Un'offerta
A questo punto posso effettivamente dare una definizione minima di APPARTAMENTO:
(createConcept APPARTAMENTO (and TOP
(all numero-bagni INTEGER)
(all zona ZONA (all
facolta'raggiungibili FACOLTA')(all mensile-affitto INTEGER)(atLeast 1
recapiti-proprietario)(all recapiti-proprietario PROPRIETARIO)) radice)
Codice Neoclassic
nella fase di introduzione di una istanza di APPARTAMENTO tale descrizione può essere ampliata a piacimento come illustra il seguente esempio:
(fills zona zona5) (fills
info-occupanti Matera)(fills info-occupanti Ragazzi)
(fills vano5 vano_v5app70)(fills
vano99 gd)))
(addToldInformation
gd VANO)
Codice Neoclassic
tale operazione corrisponde alla creazione di una nuova offerta.
Vediamo ora come opera il sistema una volta inseriti questi dati.
Ho cominciato con la creazione dei vani dell'appartamento app70.
Tale appartamento sarà costituito da 5 vani (3 singole, 1 doppia, 1 vano tipo salone/cucina/studio) su ciascun vano-letto ho indicato i posti liberi aggiungendo un opportuno numero di fillers sul ruolo ha-posto.
Infine, ho indicato l'informazione sul totale mensile richiesto (£ 800.000), su alcune spese aggiuntive, sulla zona, e infine sugli occupanti (Ragazzi).
Note:
1- L'indicazione del vano99 è fittizia, cioè non indica la presenza di un vano; essa ha il solo scopo di indicare al sistema che sono stati indicati tutti i vani presenti nell'appartamento e che può avviare le operazioni di conteggio dei vani e dei posti disponibili.
2- Attualmente il sistema è in grado di accettare appartamenti fino ad 8 vani, con al più vani letto da 4 posti (quadruple).
Ecco alla fine della fase di inserimento dei dati sull'appartamento app70 le informazioni dedotte da NeoClassic:
nel corso della sperimentazione effettuata ho ricavato che bisogna osservare delle precise regole durante la fase di inserimento dell'appartamento nel sistema, pena errori gravi di funzionamento.
Quando si inserisce un nuovo appartamento bisogna seguire attentamente l' ordine:
1- creare individuo appartamento (senza indicarlo APPARTAMENTO)
2- creare individui vani (senza tipizzarli)
3- collegare appartamento ai suoi vani (compreso vano99)
4- dichiarare il tipo per i vani e aggiungere info sui posti
5- dichiarare il vano99 VANO
(errori commessi in caso contrario: mancato conteggio posti totali posti ==0)
esempio:
Il punto essenziale è dichiarare l'appartamento prima dei suoi vani
Un altro problema che può capitare consiste in alcuni errori che si presentano allorquando viene rimossa un'informazione dall'appartamento.
Ad es. si abbia l'appartamento yy su cui abbia definito il recapito proprietario nn sul role recapito-proprietario.
Se ora rimuovo tale informazione il sistema "sballa" i conto dei costi .
Premesso che ovviamente non esiste un legame di dipendenza "logica" tra il dato rimosso e l'oggetto dell'errore, posso solo dedurre che questo errore sia legato a dettagli implementativi di NeoClassic a "basso livello".
Tale problema della rimozione dei dati, invece, non si presenta se il dato rimosso non riguarda un individuo collegato direttamente all'appartamento tramite un role, ma collegato solo indirettamente (es. se rimuovo il posto2 dalla doppiaxx che ho inserito sul vano1 dell' appartamentoyy il sistema non presenta alcun comportamento anomalo).
A questo problema ho trovato 2 soluzioni:
1. portare le informazioni più soggette a modificarsi ad un livello più alto rispetto all'appartamento (come nell'esempio sopra), creando un ruolo informazioni in cui inserisco un individuo che appunto rappresenta un'informazione su cui posso definire a piacimento dei ruoli.
Faccio un esempio per chiarezza:
per aggiungere le informazioni all'appartamento, al momento della sua definizione dovrò aggiungere (fills informazioni infoapp1).
In questo caso APPARTAMENTO-OCCUPATO-DA-RAGAZZI sarà ad es:
i problemi riscontrati possono essere risolti se si provvede a salvare e poi riaprire la Kb. Il questo caso, alla riapertura, di NeoClassic il sistema fornirà nuovamente dati corretti. Chiudo e riapro => tutto ok.
RECUPERO DESCRIZIONE DI UN APPARTAMENTO
Un'ipotesi oggetto di valutazione è stata quella di recuperare la descrizione dell'appartamento mediante i concetti in cui veniva classificato. Tale soluzione si è rivelata inefficiente; illustro, con un esempio, i problemi riscontrati.
Immaginiamo di partire dalla semplice base di conoscenza e dai vani inseriti.
In questo caso getParents restituisce una serie di concetti che descrivono esaustivamente e correttamente l'appartamento.
La query MyQuery3 ha, per così dire, "assorbito" l'informazione rappresentata dal concetto APPARTAMENTO LIBERO.
È facile intuire come il problema si aggraverebbe aggiungendo un numero maggiore di query.
Una soluzione possibile sarebbe quella di chiamare la query in modo tale che il suo nome fornisca indicazioni sul suo contenuto (descrizione).
Questo lo si potrebbe ottenere formulando le query (sia nel loro nome che nella descrizione) con una serie di "blocchettini" già disponibili da combinare.
Un esempio di questo approccio è il seguente:
questa query è ottenuta combinando 2 blocchetti predefiniti (UNA-SINGOLA-LIBERA, OCCUPATO-DA-RAGAZZE); si noti come sia possibile unire i blocchi di definizione per dare un nome significativo alla nuova query.
Pultroppo anche questa strada non è priva di problemi perché il comando getParents di NeoClassic, sebbene debba restituire solo un insieme minimale di concetti genitori, comunque restituisce un set rindondante di concetti con il risultato di fornire informazioni molto confuse.
Con la r ho indicato i concetti che corrispondono a query dell'utente.
Questa soluzione, dato il meccanismo di classificazione di NeoClassic e la modalità con cui sono stati definiti i concetti sui posti liberi e sui prezzi (atLeast), potrebbe forse funzionare solo quando il sistema arriverà a regime, cioè quando gli utenti avranno sottoposto al sistema un set di qury tali da esaurire tutte le possibili combinazioni delle richieste.
A questo punto la soluzione percorribile è quella di ricorrere al comando getDefinition , abbinato ad una oculata definizione del nome dei roles.
Il meglio che sono riuscito ad ottenere è rappresentato da quest'altro esempio:
non è proprio l'ideale (ogni posto libero è rappresentato da un codice), però non vedo alternative migliori. In questo esempio ci sono 3 singole-libere nell'appartamento perché ho tre codici di singole-libere.
Formulazione Di Una Query
Per la formulazione della query ritengo ancora valida l'idea di formularle mediante "l'assemblaggio" di sottoquery elementari, collegato al meccanismo di "naming" delle stesse che consiste semplicemente nel collegare le stringhe che compongono la descrizione.
Faccio un esempio di inserimento query:
Questa query rappresenta una richiesta di un appartamento libero da 4 posti letto di cui 2 in camera singola.
Ecco come erano state definite le sotto-query elementari:
evitata la duplicazione di query aventi la stessa descrizione (saranno rifiutate in quanto avranno lo stesso nome).
si riusciranno ad ottenere tempi di recupero dati dal sistema poco sensibili al numero degli individui inseriti: a regime il sistema esaurirà tutte le possibili query formulabili fornendo prestazioni addirittura migliori in quanto gli individui saranno già tutti preclassificati.
Come ultimo vantaggio vi è quello di inserire query che possano essere anche viste come ampliamento di descrizione della Kb, avendone assegnati nomi significativi. Sebbene al momento il sistema non sfrutti questa "feature", si potrebbe pensare di partire da questa osservazione per realizzare la "navigazione nei concetti" una volta che il sistema è a regime.
Nota: Seguendo questo approccio nella formulazione delle query, bisognerà provvedere alla gestione dell'eccezione sollevata dal sistema riguardo la presenza di un concetto avente lo stesso nome di quello che si è cercato di inserire.
Inserimento Richieste Di Nuove Caratteristiche E Storage Query Da Parte Degli Studenti
Faccio un esempio di come ho pensato di realizzare l'inserimento di una richiesta di nuovi servizi non ancora presenti nella Kb e la fase di richiesta delle nuove informazioni presso i proprietari.
Ho diviso le fasi relative a questa sitiuazione in 5 passi.
1. Partiamo dal caso di una richiesta di un APPARTAMENTO-LIBERO, con QUATTRO-POSTI-LETTO, riscaldamento (autonomo) + telefono.
Supponiamo che queste ultime due richieste corrispondano a servizi che non erano precedentemente presenti nella Kb; questo si traduce nel fatto che, nella maschera di inserimento delle richieste, non vi sono blocchi di costruzione query con i servizi riscaldamento e telefono.
Compilando dei campi predisposti, l'utente potrà comunicare al sistema i nuovi servizi oggetto di richiesta.
Il sistema genera quindi i due ruoli corrispondenti ai nuovi servizi richiesti:
(createRole riscaldamento) (createRole telefono);
inoltre il sistema chiede se ciascun ruolo debba essere specificato ulteriormente.
Immaginiamo che l'utente indichi autonomo per il riscaldamento, mentre non indichi ulteriori specifiche necessarie per il telefono. Ecco l'azione del sistema che crea i concetti CON-TELEFONO, SENZA-TELEFONO, CON-RISCALDAMENTO, SENZA RISCALDAMENTO, CON-RISCALDAMENTO-AUTONOMO che costituiranno i nuovi mini-blocchi per creare query.
2. Per preparare l'azione di invio delle richieste delle nuove informazioni presso i proprietari, il sistema genera il concetto corrispondente alla query meno i nuovi elementi richiesti.
Questi appartamenti verranno classificati in SOTTOPORRE-PROPRIETARI perché l'ho definito come (and APPARTAMENTO(atLeast 1 richieste).
4. creo infine il concetto che corrisponde alla richiesta completa dello studente che viene così registrata con i nuovi blocchi relativi alle nuove richieste
(createconcept
APPARTAMENTO-LIBERO-QUATTRO-POSTI-LETTO-CON-RISCALDAMENTO-AUTONOMO-CON-TELEFONO(
and APPARTAMENTO-LIBERO QUATTRO-POSTI-LETTO CON-RISCALDAMENTO-AUTONOMO
CON-TELEFONO))
Codice Neoclassic
5. creo infine la regola di notifica per lo studente che ha registrato la query
Come risultato delle operazioni effettuate, nel momento in cui la query registrata sarà soddisfatta verrà spedito un messaggio allo studente. Ciò sarà agevolato dalla creazione di un nuovo concetto SOTTOPORRE-STUDENTI così definito:
(and APPARTAMENTO(atLeast 1 email-studente))
Tale sistema di registrazione - richiesta può essere utilizzato anche nel caso di query che non richiedano nuovi servizi al sistema, ma che devono essere registrate in quanto al momento non soddisfatte da alcuna offerta presente (in questo caso eseguirò il solo passo 5 della lista precedente).
Gestione Voci Non In Elenco Relative A Tipologie Di Servizi Già Presenti
Tale situazione verrà gestita in modo identico al caso di definizione di un nuovo tipo di richiesta (passi 1-5), salvo che, nella fase 1, il sistema automaticamente non inserirà i ruoli e i concetti già presenti.
Inserimento Di Nuove Caratteristiche Da Parte Dei Proprietari
Questo caso non è molto diverso dal precedente; in effetti sarà ripetuto il passo 1 del caso precedente, poi sarà inserita la definizione dell'afferta relativa al nuovo appartamento inserito nella Kb.
Navigazione Nella Base di Conoscenza (sviluppo di un supporto all' utente per raffinare la query ottenendo comunque un risultato non vuoto)
La soluzione che si era formulata al problema posto, consisteva nel dare la possibilità all'utente d navigare nella lista di sottoconcetti (non sono altro che richieste più dettagliate), a partire da un concetto di partenza, piuttosto generico, contenente solo alcune sue richieste di base (quelle strettamente necessarie).
Tuttavia tale funzione non è stata resa disponibile all'utente perché ritenuta inefficiente per varie ragioni.
1- Nella fase di start-up del sistema non sono presenti le tutte combinazioni di sottoconcetti di un dato concetto padre, quindi tale navigazione non sarebbe possibile. Peraltro tale navigazione presenta degli inconvenienti anche a regime, cioè quando le richieste degli utenti abbiano ricoperto tutte le combinazioni di sottoconcetti possibili; in questo caso, perché possa avere un senso tale navigazione, dovrei prevedere un meccanismo che mi indichi quali sottoconcetti sono popolati, cioè quali, tra i raffinamenti della mia richiesta portano a dei risultati non vuoti.
Un altro inconveniente che si presenterebbe in questa situazione è rappresentato dalla necessità di una opportuna forma di visualizzazione dei sottoconcetti popolati, in numero veramente ingente, nel caso di concetto di partenza piuttosto generico (la query da raffinare).
Nel caso del progetto che si è realizzato, si è pensato di fornire almeno un parziale supporto all'utente in caso di fallimento della sua richiesta, restituendogli semplicemente per ciascuna voce inserita nella sua query (posti liberi, facoltà vicina, prezzo, etc.) il numero di appartamenti che la soddisfano (per poter individuare quali voci della richiesta non possono essere esaudite da nessun appartamento presente). Questa soluzione è stata dettata soprattutto dalla necessità di realizzare il prototipo del sistema nei tempi previsti, e certo non rappresenta la soluzione ottimale del problema. Infatti anche nell'ipotesi che ogni singola parte della query sia soddisfatta, non è affatto detto che lo sia la sua intersezione.
Tuttavia, dati i vantaggi che la soluzione del problema posto comporterebbero sull'utilità del sistema, ritengo che sia opportuno proseguire a studiare delle soluzioni che cerchino di sfruttare al meglio le capacità di Neoclassic di classificare i concetti in una tassonomia; tali soluzioni sicuramente comporterebbero lo sviluppo di un software piuttosto evoluto che dialoghi con Neoclassic al fine di indicare all'utente quali delle richieste da lui poste, possano avere esito positivo.
Una ultima osservazione a quanto già detto riguarda il caso in cui è sicuramente conveniente fornire ad un utente una lista di sottoconcetti di un concetto padre: è il caso in cui tale lista sia estremamente ridotta a seguito di vincoli imposti.
Questo si verifica di frequente nel campo della configurazione, quando posso raffinare il dettaglio di una configurazione impostata in un limitato numero di possibilità.
Interfaccia del sistema con gli utenti
Finora si è descritto il funzionamento del sistema Neoclassic presentando tutti i listati di esempio nel caso in cui l'interfaccia tra il sistema e l'utente sia un'interfaccia a caratteri, utilizzando in tali esempi la sintassi e i costrutti propri di Neoclassic.
Per fare si che il sistema possa essere utilizzato da una vasta schiera di utenti, è necessario realizzare un'interfaccia verso Neoclassic più "user-friendly", che ne permetta l'utilizzo senza conoscerne i costrutti e la sintassi di base.
A tale scopo si è pensato di realizzare un sistema di consultazione via Internet del sistema di gestione dei posti per fuorisede, utilizzando uno degli strumenti comunemente utilizzati sul Web.
Questa è una classica applicazione di tipo client-server ove ho da un lato l'utente che mediante un semplice browser (il client) richiedere un servizio disponibile su di una macchina remota (il server HTTP).
L'utente richiede il servizio desiderato compilando un form ed inviando al server che gli restituirà una pagina con la risposta appropriata.
La soluzione individuata consiste nel gestire le richieste provenienti dagli utenti e le risposte inviate a questi dal server utilizzando i form HTML che vengono gestiti da uno programma ( o più programmi) CGI.
Questo ha il compito di tradurre le richieste inviate da un browser in un formato che rispetti la sintassi usata da Neoclassic, ricevere da questo le risposte a tali richieste e generare delle pagine di risposta in formato HTML da inviare al client.
Il programma CGI è semplicemente un programma scritto in C (o in un altro linguaggio) che viene compilato e installato sul server.
Passando al dettaglio del sistema di gestione dei posti per fuorisede, gli utenti, a seconda delle operazioni di loro interesse (introdurre delle offerte, indagare sulle disponibilità di posti disponibili, etc.) compileranno form differenti che aggiorneranno la base di conoscenza di Neoclassic.
I proprietari degli appartamenti inseriranno le offerte sugli appartamenti e i posti a disposizione, gli studenti accederanno a maschere per la ricerca dei posti.
A seconda dei casi, una volta riempita la maschera e inviato il form corrispondente, il browser dell'utente spedisce al corrispondente programma CGI che, esaminando la lista di coppie variabile-valore inviatagli, è in grado di generare una stringa di testo