Partiamo analizzando OWL Lite. Quest’ultimo include le seguenti caratteristiche relative a RDFS:
- Class: una classe definisce un gruppo di individui accomunati dalla condivisione di alcune proprietà. Ad Esempio, Giovanni e Francesco sono entrambi membri della classe Persona. Le classi possono essere organizzate in una gerarchia di specializzazione usando il costrutto subClassOf. La più generica classe predefinita ha nome Thing; essa è la classe di tutti gli individui e una superclasse di tutte le classi OWL. Esiste anche una classe predefinita chiamata Nothing, la più specifica, che non ha alcuna istanza ed è sottoclasse di tutte le classi OWL.
- rdfs:subClassOf: una gerarchia di classi può essere creata dichiarando che una classe è una sottoclasse di un’altra. Per esempio, si può affermare che la classe Persona è una sottoclasse della classe Mammiferi. Da questo un ragionatore può dedurre che se un individuo è una Persona, allora è un Mammifero.
- Individual: gli individual sono istanze di una classe, e le proprietà possono essere usate per legare un individuo ad un altro. Per esempio, un individuo di nome Giovanni può essere descritto come un’istanza della classe Persona e la proprietà è_impiegato può essere usata per legarla all’individuo Politecnico_di_Bari.
Features di RDF Schema: | Class
rdf:Property rdfs:subClassOf rdfs:subPropertyOf rdfs:domain rdfs:range owl:Individual |
Eguaglianze / Diseguaglianze: | equivalentClass
equivalentProperty sameAs differentFrom allDifferent |
Proprietà Caratteristiche: | inverseOf
TransitiveProperty SymmetricProperty FunctionalProperty InverseFunctionalProperty |
Restrizioni sul Tipo della Proprietà: | allValuesFrom
someValuesFrom |
Restrizioni sulla Cardinalità: | minCardinality (solo 0 e 1)
maxCardinality (solo 0 e 1) cardinality (solo 0 e 1) |
Informazioni di Intestazione: | ontology
imports |
Intersezione tra Classi: | intersectionOf |
Supporto alla gestione delle Versioni: | versionInfo
priorVersion backwardCompatibleWith incompatibleWith DeprecatedClass DeprecatedProperty |
Annotation Properties: | rdfs:label
rdfs:comment rdfs:seeAlso rdfs:isDefinedBy |
Datatypes | DatatypeProperty |
Tabella OWL Lite
Le proprietà sono relazioni binarie che consentono di affermare fatti di validità generale per ogni membro della classe o fatti relativi solo ad un solo individuo. Sono distinguibili due tipi di proprietà:
- Datatype property, relazioni tra istanze di classi e RDF literals e datatype XML Schema;
- Proprietà sull’oggetto (object property), relazioni tra istanze di due classi.
All’atto di definizione di una proprietà ci sono diversi modi per esprimere i limiti della relazione. E’ possibile specificare il dominio ed il range della proprietà. Le proprietà, come le classi, possono essere organizzate in una gerarchia.
- rdfs:Property: le proprietà possono essere usate per affermare le relazioni tra individui o tra individui e valori. Esempi di proprietà includono has_Child, has_Age, e così via. La prima può essere usata per collegare istanze della classe Persona ad altre istanze della stessa classe, mentre il secondo può essere usato per collegare istanze della classe Persona con istanze di tipo Integer;
- rdfs:subPropertyOf: gerarchie di proprietà possono essere create indicando che una proprietà è una sottoproprietà di una o più proprietà. Ad Esempio, si può affermare che has_Brother è una sottoproprietà di has_Parent. Da ciò un ragionatore può dedurre che se un individuo è legato ad un altro tramite la proprietà has_Brother allora ne è legato anche tramite la proprietà has_Parents;
- rdfs:domain: il dominio di una proprietà circoscrive gli individui ai quali una proprietà può essere applicata. Se una proprietà lega un individuo ad un altro e la proprietà ha una classe come uno dei suoi domini allora quell’ individuo deve appartenere a quella classe. Per esempio, si può affermare che la proprietà has_Child ha come dominio la classe Mammiferi. Da ciò un ragionatore può dedurre che se Giovanni has_Child Anna, allora Giovanni deve essere un Mammifero. Il costrutto rdfs:domain è detto restrizione globale poiché la restrizione si applica sulla proprietà e non solo sulla proprietà associata ad una classe particolare;
- rdfs:range: il range di una proprietà circoscrive gli individui che una proprietà può avere come valore. Se una proprietà lega un individuo ad un altro e la proprietà ha una classe come suo range, allora l’altro individuo deve appartenere alla classe del range. Ad esempio si può affermare che la proprietà has_Child ha come range la classe Mammiferi. Da ciò un ragionatore può dedurre che se Giovanni è legato a Anna dalla proprietà has_Child, cioè Anna è figlia di Giovanni, allora Anna è un Mammifero. Anche il range è una restrizione globale come il dominio.
Uno dei punti di forza dello sviluppo delle ontologie è la possibilità di renderle riutilizzabili e scalabili. Questo si ottiene collegando insieme classi e proprietà in modo da massimizzare le possibilità di sviluppo. La parte più impegnativa è fondere una collezione di ontologie in un’unica base di conoscenza. Le seguenti caratteristiche di OWL (nella versione Lite) consentono di fondere diverse ontologie grazie ad uguaglianze e diseguaglianze tra classi e proprietà:
- owl:equivalentClass: due classi sono equivalenti se hanno le stesse istanze. L’equivalenza può essere usata per creare sinonimi di una classe. Per esempio, la classe Veicolo può essere una equivalentClass di Automobile. Da ciò un ragionatore potrebbe dedurre che ogni individuo istanza della classe Veicolo è anche un istanza di Automobile, e viceversa;
- owl:EquivalentProperty: serve per affermare che due proprietà sono equivalenti, ovvero che legano un individuo allo stesso insieme di individui. L’eguaglianza è usata per creare sinonimi di proprietà. Per esempio, has_Leader può essere ritenuta equivalentProperty di has_Head. Da ciò un ragionatore può dedurre che se X è legato a Y dalla proprietà has_Leader, X è legato a Y anche dalla proprietà has_Head, e viceversa. Un ragionatore potrebbe dedurre che has_Leader è una sottoproprietà di has_Head e che has_Head è sottoproprietà di has_Leader;
- owl:sameAs: serve per affermare che due individui sono lo stesso individuo. Questi costrutti possono essere usati per creare una varietà di nomi diversi che si riferiscono allo stesso individuo. Per esempio, l’individuo Mario può essere nominato anche come Mario_Rossi;
- owl:differentFrom: un individuo può esser detto diverso da altri individui. Ad esempio, l’individuo Francesco può esser definito essere differente dagli individui Mario e Anna. Quindi, se gli individui Francesco e Mario sono entrambi valori di una proprietà definita come funzionale (cioè che la proprietà deve avere un solo valore), allora c’è una contraddizione. Affermare che gli individui sono differenti può essere importante quando si usano linguaggi come OWL che non assumono che gli individui abbiano un solo nome, in quanto, senza ulteriori informazioni, un ragionatore potrebbe non dedurre che Francesco e Mario sono individui distinti;
- owl:AllDifferent: gli individui possono essere definiti come mutuamente distinti. Per esempio, Francesco, Mario, e Anna possono dirsi essere mutuamente distinti usando il costrutto allDifferent. Diversamente dal costrutto differentFrom, questo affermerà anche che Mario e Anna sono distinti (non solo che Francesco è distino da Mario e che Francesco è distinto da Anna).
Proprietà e restrizioni in OWL
In OWL esistono identificatori speciali che sono usati per fornire informazioni sui legami tra le proprietà e i loro valori. I seguenti costrutti consentono ai ragionatori di rafforzare le implicazioni riguardo gli individui e le loro proprietà:
- owl:inverseOf: una proprietà può esser definita l’inversa di un’altra. Se la proprietà P1 è definita inversa della proprietà P2, e se l’individuo A è in relazione con l’individuo B tramite la proprietà P2, allora B è in relazione con A tramite P1. Per esempio, se has_Child è inversa di has_Parent e Anna has_Parent Mario, allora un ragionatore può dedurre che Mario has_Child Anna;
- owl:TransitiveProperty: una proprietà può essere definita transitiva quando, data la coppia (x,y) e la coppia (y,z) che sono istanze della proprietà transitiva P, allora anche la coppia (x,z) deve essere un’istanza di P. Per esempio, se antenato è definito essere transitivo, e se Sara è un’antenata di Anna e Anna è un’antenata di Giulia allora un ragionatore può dedurre che anche Sara è antenata di Giulia. OWL Lite (e OWL DL) impongono la condizione collaterale alle proprietà transitive di avere maxCardinality 1. Senza questa condizione collaterale, OWL Lite e OWL DL diverrebbero linguaggi indecidibili;
- owl:SymmetricProperty: una proprietà può essere definita come simmetrica quando, data la coppia (x,y) istanza della proprietà simmetrica P, allora anche la coppia (y,x) è un’istanza di P. Per esempio, amico può essere detta una proprietà simmetrica. Allora un ragionatore a cui vien detto che Francesco è amico di Mario può dedurre che Mario è amico di Francesco;
- owl:FunctionalProperty: se una proprietà è una FunctionalProperty, allora non ha più di un valore per ciascun individuo (potrebbe non avere valori per qualche individuo). FunctionalProperty è anche una scorciatoia per affermare che la MinCardinality è 0 e che la MaxCardinality è 1. Per esempio, la proprietà ha_impiego_principale può esser definitva come una FunctionalProperty. Da ciò un ragionatore può dedurre che nessun individuo può avere più di un impiego principale, senza implicare però che tutte le Persone devono averne almeno uno.
OWL permette di esprimere restrizioni limitatamente alla sola classe cui si riferiscono. Le seguenti due restrizioni limitano il range della proprietà quando è applicata ad una classe specifica mentre le restrizioni della prossima sezione limitano i valori che possono essere usati:
- owl:allValuesFrom: la restrizione allValuesFrom si applica ad una proprietà con riferimento ad una classe. Ciò significa che quella proprietà in quella particolare classe ha un restrizione locale sul range associata ad essa, vale a dire che se un’istanza di una classe è legata tramite la proprietà ad un secondo individuo, allora il secondo individuo può essere desunto essere un’istanza della classe che restringe localmente il range. Per esempio, la classe Persona può avere una proprietà chiamata ha_Figlia vincolata ad avere allValuesFrom della classe Donna. Ciò significa che se un individuo della classe Persona, Anna, è legato tramite la proprietà ha_Figlia all’individuo Giulia, allora un ragionatore può desumere che Giulia è un’istanza della classe Donna. Questa restrizione permette alla proprietà ha_Figlia di esser usata da un’altra classe, ad esempio la classe Cat ed avere una diversa restrizione dei valori associata ad essa. In questo caso, ha_Figlia dovrebbe avere una restrizione locale su Cat quando associato alla classe Cat e dovrebbe avere una restrizione alla classe Persona quando associata alla classe Persona;
- owl:someValuesFrom: la restrizione someValuesFrom si applica ad una proprietà con riferimento ad una classe. Una particolare classe può avere una restrizione su una proprietà, e almeno un valore per quella proprietà deve essere di un certo tipo. Diversamente da allValuesFrom, someValuesFrom non restringe tutti i valori della proprietà ad essere istanze della stessa classe. Se mio_Documento è un’istanza della classe Documento_Semantic_Web, allora mio_Documento è legata dalla proprietà ha_parola_chiave con almeno un’istanza della classe Intestazione_Semantic_Web. È da notare che un ragionatore non può dedurre (come farebbe con la restrizione allValuesFrom) che i valori di ha_parola_chiave sono istanze della classe Intestazione_Semantic_Web.
Le restrizioni sulla cardinalità di OWL (e OWL Lite) sono restrizioni locali, poiché sono definite su proprietà riferite ad una classe particolare, ovvero le restrizioni vincolano la cardinalità di una certa proprietà su istanze di una certa classe. Il supporto di OWL Lite alla cardinalità è limitato poiché sono permesse solo definizioni su cardinalità con valori zero o uno (non sono permesse cardinalità con valori arbitrari, come in OWL DL e OWL Full). Vediamo alcuni costrutti che agiscono sulla cardinalità:
- owl:minCardinality: la cardinalità si applica su una proprietà con riferimento ad una classe. Se si afferma una minCardinality ad 1 su una proprietà riferita ad una classe, allora ogni istanza di quella classe deve essere legata ad almeno un individuo da quella proprietà. Questa restrizione equivale a dire che la proprietà è richiesta per tutte le istanze di una certa classe. Per esempio, la classe Persona non dovrebbe avere nessuna restrizione sulla cardinalità minima su una proprietà ha_Figlio poiché non tutte le persone hanno dei figli. Tuttavia la classe Genitore dovrebbe avere una minCardinality a 1 sulla proprietà ha_Figlio. Una volta scoperto che un individuo, Mario, è un’istanza di Genitore, un ragionatore può desumere che Mario deve avere almeno un figlio. A partire da questa sola informazione un ragionatore non può dedurre il massimo numero di ascendenti di un individuo della classe Genitore. In OWL le sole minime cardinalità ammesse sono 0 e 1. Una minima cardinalità a zero su una proprietà implica semplicemente che la proprietà è opzionale per quella classe. Per esempio, la proprietà ha_Figlio può avere una cardinalità minima a zero per la classe Persona.
- owl:maxCardinality: la cardinalità si applica su una proprietà con riferimento ad una classe. Se si afferma una maxCardinality a 1 su una proprietà nell’ambito di una classe, allora tutte le istanze di quella classe possono essere legate ad al più un individuo tramite quella proprietà. Un vincolo di maxCardinality a 1 è anche detto funzionale o proprietà unica. Per esempio, la proprietà ha_votato_in_Regione della classe Cittadino_Italiano avrà una cardinalità massima ad 1 (perché la gente può votare in una sola regione). Può essere utile per alcune classi affermare che non sono ammessi valori per una particolare proprietà cioè affermando che la massima cardinalità è zero. Per esempio, le istanze della classe Persone_non_sposate non dovrebbero essere legate a nessuna classe tramite la proprietà ha_coniuge. Questa situazione si specifica tramite una maxCardinality a zero sulla proprietà ha_coniuge associata alla classe Persone_non_sposate;
- owl:cardinality: cardinality è usato per convenienza quando si deve affermare che sia minCardinality che maxCardinality assumono il valore zero oppure uno. Per esempio, la classe Persona ha esattamente un valore per la proprietà ha_Madre_Naturale. Da ciò un ragionatore può dedurre che nessuna coppia di individui distinti della classe Madre possono esser valori per la proprietà ha_Madre_Naturale della stessa persona.
Incremental Language Description di OWL DL e OWL Full
Sia OWL DL che OWL Full condividono lo stesso vocabolario sebbene OWL DL sia soggetto ad alcune restrizioni. Grossomodo, OWL DL richiede una separazione tra i tipi (una classe non può essere anche un individuo o una proprietà, una proprietà non può essere anche un individuo o una classe). Questo implica che le restrizioni non possono essere applicate agli elementi del linguaggio stesso di OWL (cosa permessa in OWL Full). Inoltre, OWL DL richiede che le proprietà siano ObjectProperties oppure DatatypeProperties.
Di seguito viene descritto il vocabolario di OWL DL e OWL Full che estende i costrutti di OWL Lite:
Assiomi sulle Classi: | oneOf
dataRange disjointWith equivalentClass (applicata a espressioni di classi) rdfs:subClassOf (applicata a espressioni di classi) |
Combinazioni booleane di espressioni
di classi: |
unionOf
intersectionOf complementOf |
Cardinalità Arbitraria: | minCardinality
maxCardinality |
cardinality Filler Information: | hasValue |
Tabella OWL DL – Full
- owl:oneOf (enumerated classes): le classi possono essere descritte tramite enumerazione degli individui che ne fanno parte. I membri della classe sono esattamente gli individui dell’insieme di enumerazione; né più né meno. Per esempio, la classe Giorno_della_settimana può essere descritta enumerando gli individui Lunedì, Martedì, Mercoledì, Giovedì, Venerdì, Sabato e Domenica. Da ciò un ragionatore può dedurre la cardinalità massima (7) di ogni proprietà che abbia una restrizione di allValuesFrom come Giorno_della_settimana;
- owl:hasValue (property values): può essere richiesto che una proprietà abbia un certo individuo come valore. Per esempio, istanze della classe Cittadino_Italiano possono essere caratterizzate come quelle persone che hanno Nazione_Italia come valore per la loro nazionalità;
- owl:disjointWith: OWL Full permette di affermare che alcune classi sono disgiunte, come ad esempio Uomini e Donne. Da ciò un ragionatore può dedurre una inconsistenza quando si afferma che un individuo è istanza di entrambe le classi e che se A è un’istanza di Uomo allora non può esserlo di Donna;
- owl:unionOf, owl:complementOf, owl:intersectionOf (Boolean combinations): OWL DL permette un’arbitraria combinazione booleana di classi e restrizioni: unionOf, complementOf, e intersectionOf. Per esempio, usando UnionOf, possiamo affermare che una classe contiene entità che possono essere sia Cittadino_Italiano che Cittadino_Europeo. Usando complementOf, possiamo affermare che Bambini non sono Adulti (cioè, la classe Bambini è una sottoclasse del complemento della classe Adulti). La cittadinanza dell’Unione Europea potrebbe essere descritta come l’unione delle cittadinanze di tutti gli stati membri;
- owl:minCardinality, owl:maxCardinality, owl:cardinality (full cardinality): mentre in OWL Lite le cardinalità sono ristrette ad assumere almeno, al massimo o esattamente i valori zero o uno, OWL Full permette espressioni arbitrarie (intere non negative) sulla cardinalità.
OWL (Web Ontology Language) è un linguaggio di markup progettato per definire e istanziare ontologie Web.
Ma in pratica, come mi può essere utile?
Una ontologia OWL può includere le descrizioni delle classi, proprietà e delle loro istanze. Dato questo tipo di Ontologia, la semantica formale di OWL specifica come derivare le sue conseguenze logiche, ovvero i fatti che non sono presenti letteralmente nell’ontologia, ma derivati logicamente dalla semantica. Tali derivazioni logiche possono essere basate su un solo documento o su più documenti distribuiti che sono stati combinati fra loro usando dei meccanismi OWL predefiniti.
OWL utilizza gli URI per i nomi e la struttura di descrizione per il Web fornita da RDF per aggiungere le seguenti funzionalità alle ontologie:
- Capacità di essere distribuite tra molti sistemi
- Scalabilità per le necessità del Web
- Compatibilità con gli standard Web per l’ accessibilità e l’ internazionalizzazione
- Apertura e estensibilità
Dunque OWL è l’evoluzione di RDF e RDF Schema[1], dei quali arricchisce il vocabolario per descrivere proprietà e classi, relazioni tra classi (ad es. disgiunzione), cardinalità (ad es. “esattamente uno”), uguaglianza, tipi più ricchi delle proprietà, caratteristiche di proprietà (ad es. simmetria) e classi enumerate.
I sottolinguaggi di OWL
OWL fornisce tre sottolinguaggi di espressività crescente che sono stati progettati per essere utilizzati da determinate comunità di sviluppatori e utenti:
- OWL Lite è la versione più semplice e meno espressiva di OWL, che supporta le funzioni necessarie a definire una tassonomia di classi e semplici vincoli; esso supporta per esempio la cardinalità, ma solo con valori pari a uno e zero. OWL Lite è il sottolinguaggio di più facile implementazione e inoltre consente una veloce migrazione da vocabolari o altre tassonomie.
- OWL DL (OWL Description Logic) permette più espressione e mantiene la completezza computazionale e la decidibilità; esso supporta gli utenti che desiderano la massima espressività senza mancare di completezza computazionale e di decidibilità (è cioè garantito che tutte le implicazioni siano elaborate in un tempo finito). OWL DL comprende tutti i costrutti OWL, ma con alcune restrizioni, per esempio mentre una classe può essere una sottoclasse di molte altre, essa non può essere istanza di un’altra classe.
- OWL Full permette la massima espressività senza però garanzie sulla completezza e decidibilità; ad esempio una classe può essere allo stesso tempo vista come una collezione di entità (individui) e come una entità a se stante. OWL Full permette ad una ontologia di aumentare il significato di un vocabolario già definito; tuttavia è molto difficile, data la complessità del linguaggio, che un ragionatore supporti appieno tutte la potenzialità di OWL FULL.
Facendo riferimento alla seguente tabella:
Lettera o sigla della logica | Descrizione |
AL | inclusione e equivalenza tra classi, definizione di classi atomiche, classe universo, intersezione tra classi, definizioni di classi formate da elementi che prendono parte a relazioni o hanno una relazione di un certo tipo solo con elementi di una certa classe, operatore di congruenza tra individui e appartenenza di un individuo a una classe |
ALC | aggiunge ad AL la classe vuota, le classi complemento, l’unione di classi e le classi di elementi che sono in una certa relazione con elementi di una certa classe |
S | aggiunge ad ALC la definizione della transitività di una relazione |
H | inclusione e equivalenza tra relazioni |
R | disgiunzione di proprietà, riflessività, asimmetria, irriflessività, relazioni composte da altre relazioni, definizione di non-relazione tra due individui |
O(One of) | creazione di classi tramite elenco di tutti e soli gli individui contenuti |
I (Inverse) | definizione di proprietà inversa |
F (Functionality) | definizione di proprietà funzionali |
N (Number) | restrizione di cardinalità: numero di elementi che partecipano a una certa relazione minore, maggiore o uguale di un valore n |
Q (Qualified) | come N, ma la relazione può essere qualificata |
Dn (Numerable Domain) | definizione di domini (tipi di dato) a cui può portare una relazione (es. “Mario ha n anni”) |
Sottoinsiemi della logica del primo ordine
possiamo cercare di formalizzare meglio le differenze fra i tre sottolinguaggi:
- OWL Lite utilizza SHIF(Dn);
- OWL DL utilizza SHOIN(Dn);
- OWL Full utilizza tutta la logica del primo ordine, addirittura espandendola con altri predicati.
Una importante caratteristica dei sottolinguaggi OWL risiede nel fatto che ogni versione estende ed include le funzionalità del sottolinguaggio precedente mantenendo la compatibilità con le espressioni e le conclusioni che si possono trarre, mentre non vale il contrario. Questo vuol dire che una ontologia espressa in OWL Lite è pienamente compatibile con una ontologia OWL DL, e in entrambi i casi le conclusioni sono le stesse. Ciò vale anche nel caso in cui si esprima una ontologia OWL DL mediante OWL Full.
Ma qual è la versione migliore?
La scelta di quale versione di OWL utilizzare è lasciata alle necessità dello sviluppatore e dal livello di espressività di cui ha bisogno. In generale si preferisce utilizzare OWL DL perché consente più libertà di espressione, ma ciò è dovuto principalmente al fatto che attualmente non esistono piattaforme che consentono una completa implementazione di OWL Full.
A livello implementativo si può assimilare OWL Full ad una estensione di RDF, mentre OWL Lite e OWL DL possono essere visti come estensioni di un sottoinsieme del linguaggio RDF.
Ogni documento OWL è dunque un documento RDF, sebbene il viceversa non sia vero, ossia solo qualche documento RDF sarà un documento OWL valido. Di conseguenza bisogna prestare attenzione nella conversione da documenti RDF a documenti OWL, facendo in modo che ogni classe etichettata con una URI sia dichiarata di tipo owl:Class; per ogni individuo, inoltre, deve esistere almeno un’asserzione che lo inserisca in una classe (al limite nella classe genitrice owl:Thing).
Antonio Cicirelli
[1] Qui urge una precisazione: OWL è l’evoluzione di RDF ed RDFS, anche se storicamente i primi linguaggi usati per estendere RDF furono il DAML e l’OIL, sviluppati separatamente da due comunità, una americana e l’altra europea. In seguito le funzionalità di questi linguaggi sono state integrate sotto le direttive del “Joint EU/US Committee on Agent Markup Languages” per dar vita al linguaggio DAML+OIL che solo successivamente è stato sottoposto al W3C che ha definito lo standard OWL.
Il data model RDF permette di definire un modello semplice per descrivere le relazioni tra le risorse, in termini di proprietà identificate da un nome e relativi valori. Tuttavia, RDF data model non fornisce nessun meccanismo per dichiarare queste proprietà, né per definire le relazioni tra queste proprietà ed altre risorse.
RDF Schema (RDFS) permette invece di definire dei vocabolari, quindi significato, caratteristiche e relazioni di un insieme di proprietà (compresi eventuali vincoli). Inoltre consente di definire gerarchie di classi implementando il concetto transitivo di classe e sottoclasse.
Le descrizioni del vocabolario RDF Schema sono scritte a loro volta in RDF. Queste risorse sono usate per descrivere caratteristiche di altre risorse, come i domini e range delle proprietà.
In RDFS il sistema delle classi e delle proprietà è simile a quello dei linguaggi di programmazione orientati agli oggetti, come Java o C++, dai quali differisce nel fatto che invece di definire le classi in termini delle proprietà che le istanze possono avere, descrive le proprietà in termini delle classi delle risorse a cui si applicano. Ad esempio possiamo definire che la proprietà Autore appartiene al dominio Documento e che ha come range Persona. Se avessimo usato Java avremmo definito una classe Documento con una proprietà Autore di tipo Persona. Usando l’approccio di RDF diviene facile per altri definire di conseguenza proprietà addizionali del dominio; diversamente in java, volendo aggiungere nuove proprietà, si dovrebbero ridefinire le classi.
Nel caso in cui si volesse aggiungere la proprietà titolo al documento, in RDFS è sufficiente aggiungere che Titolo appartiene al dominio Documento; in Java, invece, dovrei modificare la classe esistente Documento e aggiungere la nuova proprietà Titolo.
Le classi e le proprietà in RDF sono utilizzate per definire il vocabolario di risorse esistenti in uno specifico dominio. Il vocabolario può contenere nuove risorse sulla base di specializzazioni di risorse già definite, e questo consente di considerare valido o meno dal punto di vista logico lo schema RDF. Le classi e le proprietà definite sono le seguenti:
- rdf:Resource: rappresenta una risorsa generale, cioè tutto ciò che può essere referenziato univocamente (tramite una URI). Per risorsa non si intende necessariamente una entità concreta, ma si può fare tranquillamente riferimento ad una entità astratta;
- rdf:property: sono risorse usate come predicati in una tripla. RDF considera una proprietà come una classe, e non come un semplice attributo ad essa (le proprietà possono essere utilizzate indipendentemente da una classe);
- rdf:Statement: uno statement rappresenta la concretizzazione di una tripla. È necessario che una risorsa abbia le proprietà rdf:subject, rdf:object e rdf:predicate istanziate con le corrispondenti risorse, e la proprietà rdf:type istanziata con il filler rdf:Statement;
- rdfs:subPropertyOf: serve ad indicare che una proprietà è sottoproprietà di un’altra, vale a dire che se la risorsa X è legata alla risorsa Y attraverso una proprietà P che è una subPropertyOf di una proprietà Q, allora vale la tripla T(X, Q, Y). Ad esempio se padre è subPropertyOf di genitore, allora ogni tripla avente padre come proprietà resta valida se si sostituisce genitore con padre;
- rdfs:Class, rdf:type, rdfs:subClassOf: le classi sono risorse che individuano insiemi di risorse per mezzo del costrutto rdf:type (con filler corrispondente ad una classe). Tutte le proprietà, al contrario, utilizzano il costrutto rdf:type con filler rdf:Property. Il costrutto rdfs:subClassOf esprime la possibilità di definire delle gerarchie di proprietà o di classi. In particolare la gerarchia delle classi ha un elemento genitore, cioè rdf:Resource, e ciò significa che ogni classe soddisfa implicitamente la proprietà rdfs:subClassOf con filler rdf:Resource.
- rdfs:domain, rdfs:range: tali proprietà sono utilizzate per restringere l’insieme delle risorse che possono avere una certa proprietà (dominio delle proprietà) e l’insieme dei valori ammissibili (codominio della proprietà);
- rdfs:Literal: indica un insieme di literal, ossia di valori (stringhe, interi, ecc) che possono essere assegnati ad una risorsa tramite una proprietà.
- rdfs:Container: serve per definire un contenitore di risorse, e prevede l’utilizzo di una delle tre diverse sottoclassi, rdfs:Bag, rdfs:Seq e rdf:Alt.
- rdfs:ConstraintResource, rdfs:ContraintProperty: rappresentano i vincoli connessi alle risorse e le proprietà; ad esempio rdfs:domain e rdfs:range sono istanze della classe rdfs:ConstraintProperty.
- rdfs:seeAlso, rdfs:isDefinedBy: indicano rispettivamente il riferimento ad un ulteriore luogo in cui la risorsa è descritta e i riferimenti alle informazioni di authoring della risorsa.
- rdfs:label, rdfs:comment: questi costruttori servono a descrivere una risorsa in un formato di facile comprensione per gli esseri umani. Essi possono avere cardinalità multipla per venire incontro alle esigenze di internazionalizzazione.
I Limiti di RDFS
RDFS, nonostante tutte le caratteristiche viste finora, è poco espressivo in quanto non permette di definire vincoli di esistenza e cardinalità e, inoltre, non permette di definire proprietà transitive, inverse, simmetriche. Per tali motivi si presta a modellazioni piuttosto semplici, mentre diventa impossibile usarlo in contesti complessi.
Tra i suoi limiti vale la pena ricordare anche la difficoltà nel fornire servizi di ragionamento a causa dell’assenza di ragionatori “nativi”.
A cosa serve il Data Model RDF?
RDF fornisce un modello per descrivere le risorse e le relative proprietà, dove per risorsa intendiamo qualsiasi oggetto identificabile univocamente attraverso un URI[1].
Il Data Model RDF è molto semplice, ed è basato su tre tipi di oggetti:
- Risorsa: qualunque cosa venga descritta da una espressione RDF è detta risorsa (resource). Una risorsa può essere una pagina Web, o una sua parte, o un elemento XML all’ interno del documento sorgente oppure un’intera collezione di pagine web o potrebbe anche essere un oggetto non direttamente accessibile via Web (per es. un libro, un dipinto, etc.). Le risorse sono sempre individuate da un URI, eventualmente con un anchor id;
- Proprietà: una proprietà (property) descrive un aspetto specifico, un attributo o una relazione usata per descrivere una risorsa. Ogni proprietà definisce i valori ammissibili, i tipi di risorse che può descrivere e le sue relazioni con le altre proprietà. Le proprietà associate ad una risorsa sono individuate da un nome e assumono dei valori;
- Asserzioni: una asserzione (statement) è una tupla composta da un soggetto (risorsa), un predicato (proprietà) e un oggetto (valore). In particolare l’oggetto di uno statement (il property value) può essere una espressione (una stringa, un intero o qualche altro tipo primitivo definito da XML) o un’altra risorsa. Una asserzione si esprime dicendo che il soggetto ha una proprietà il cui valore è dato dall’oggetto.
Graficamente, le relazioni tra Resource, Property e Value vengono rappresentate mediante grafi etichettati orientati, in cui le risorse vengono identificate come nodi (graficamente delle ellissi), le proprietà come archi orientati etichettati, e i valori corrispondenti a sequenze di caratteri come rettangoli.
Figura 1: Rappresentazione grafica di una generica descrizione RDF
L’insieme delle proprietà che fanno riferimento ad una stessa risorsa è chiamato descrizione (description).
Per chiarire meglio l’utilizzo di RDF possiamo ricorrere ad un piccolo esempio; consideriamo quindi le seguenti espressioni:
1) Antonio è autore del Tutorial RDF
2) L’autore del Tutorial RDF è Antonio
Queste due espressioni, per quanto possano apparire equivalenti ad un essere umano, sarebbero viste come distinte da una macchina. La vera potenza di RDF consiste proprio nella disambiguazione del significato in casi come questi; attraverso il suo semplice modello fondato su soggetto, predicato e oggetto, fornisce un metodo che permette di esprimere il significato di una espressione senza lasciare adito a dubbi nella elaborazione da parte della macchina.
Cerchiamo ora di trasformare la nostra espressione in uno statement RDF. Per prima cosa va dichiarata una risorsa che rappresenti il nostro Tutorial RDF e poi la proprietà e il valore che essa assume. Abbiamo quindi la seguente tripla:
Risorsa: http://www.example.org/Antonio/TutorialRDF.pdf
Proprietà: ha Autore
Valore: Antonio Cicirelli
Lo statement del nostro esempio verrebbe quindi rappresentato come:
http://www.example.org/Antonio/TutorialRDF.pdf ha Autore Antonio Cicirelli
e la sua rappresentazione grafica sarebbe la seguente:
Figura 2: Rappresentazione grafica di uno statement RDF
Se invece volessimo aggiungere altre informazioni sull’oggetto l’espressione cambia ancora. Se per esempio vogliamo dire:
Antonio Cicirelli, che studia presso il Politecnico di Bari e la cui e-mail è antoniocici@example.org, è l’ autore del TutorialRDF
desideriamo esprimere delle informazioni riguardo ad (about) Antonio Cicirelli, andando a trasformare il valore della proprietà autore in una entità strutturata. In RDF, un’entità di questo tipo viene rappresentata come un’ altra risorsa. Poiché nel nostro statement non viene attribuito un nome a questa entità strutturata, il diagramma risultante sarebbe il seguente:
Figura 3: Rappresentazione grafica di una proprietà con valore strutturato
Si noti che questo diagramma potrebbe anche essere letto come:
http://www.example.org/Antonio/TutorialRDF.pdf ha Autore qualcuno e questo qualcuno ha Nome Antonio Cicirelli, Email antoniocici@example.org ed Affiliation Politecnico di Bari
dove alla risorsa anonima “qualcuno” potrebbe essere assegnato un identificatore univoco come per esempio il Codice Fiscale, corrispondente ad un URI del tipo:
http://www.finanze.it/CF/CCRNTN85S20A225K
Figura 4: Rappresentazione grafica di una proprietà con valore strutturato con identificatore
In figura 4 possiamo vedere il diagramma completo dell’asserzione con l’entità strutturata che ha assunto l’identificatore univoco.
La Serializzazione RDF/XML
Un grafo RDF è comprensibile all’uomo, ma non alle macchine. Per questo ogni grafo necessita di un processo di serializzazione. Fra le serializzazioni disponibili per RDF, noi andremo ad analizzare la RDF/XML. Tale procedimento ci permette di passare dal grafo RDF ad un documento XML che può essere facilmente letto e condiviso dalle macchine.
Se consideriamo il nostro primo esempio (rappresentato graficamente in Figura 2), esso può essere espresso, utilizzando la sintassi XML, come segue:
<?xml version=”1.0″?><rdf:RDF
xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”
xmlns:a=”http://www.example.it/schema_autore/”>
<rdf:Description about=”http://www.example.org/Antonio/TutorialRDF.pdf”>
<a:autore>
Antonio Cicirelli
</a:autore >
</rdf:Description>
</rdf:RDF>
L’elemento <rdf:RDF> racchiude la definizione dello statement RDF ed al suo interno troviamo la definizione di due Namespace: il primo è relativo al Namespace RDF, mentre il secondo Namespace contiene l’URI che identifica lo schema RDF utilizzato per descrivere le regole per l’utilizzo della proprietà autore presente nel nostro statement. L’uso dei namespace XML è molto importante in quanto essi forniscono un metodo per identificare senza ambiguità la semantica e le convenzioni che disciplinano l’utilizzo di proprietà all’interno di Authority (come ad esempio la Dublin Core) che ne gestisce il vocabolario.
La descrizione del metadato è contenuta all’interno dell’elemento <rdf:Description> ed il suo attributo about identifica la risorsa alla quale si riferisce il metadato stesso. La proprietà dello statement è descritta utilizzando il tag <a:autore>, secondo le regole che sono espresse nel relativo schema RDF.
Il nostro secondo esempio di statement RDF (il cui grafo è presente in Figura 4), sarà espresso come segue:
<rdf:RDF
xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”
xmlns:a=”http://www.example.it/schema_autore/”>
<rdf:Description about=”http://www.example.org/Antonio/TutorialRDF.pdf”>
<a:autore rdf:resource=”http://www.finanze.it/CF/CCRNTN85S20A225K”/>
</rdf:Description>
<rdf:Description about=”http://www.finanze.it/CF/CCRNTN85S20A225K”>
<a:nome>Antonio Cicirelli</a:nome>
<a:email>antoniocici@example.org</a:email>
<a:affiliate>Politecnico di Bari</a:affiliate>
</rdf:Description>
</rdf:RDF>
In questo caso, all’interno dello statement RDF abbiamo la definizione di due risorse, identificate dai due elementi <rdf:Description>, che sono messe in relazione attraverso l’uso dell’attributo rdf:resource presente nell’elemento <a:autore>. In questo modo la descrizione della seconda risorsa (quella relativa all’autore del documento) viene assegnata come valore della proprietà autore della prima risorsa.
I Contenitori
In alcuni casi può essere necessario far riferimento a più di una risorsa, per esempio per descrivere il fatto che un libro è stato scritto da più autori, oppure che un documento è composto da una serie di componenti, oppure che una funzione può essere svolta da una delle persone elencate e così via.
RDF pone una soluzione a tale necessità definendo tre tipi di contenitori (container):
- Bag: è una lista non ordinata di risorse o costanti, che serve a dichiarare che una proprietà può assumere valori multipli, senza attribuire un significato particolare al loro ordine. Sono ammessi valori duplicati;
- Sequence: è una lista ordinata di risorse o costanti, usata nel caso in cui si definisce una proprietà che può assumere valori multipli e per la quale è importante l’ordine di successione degli stessi. Anche in questo caso sono ammessi valori duplicati;
- Alternative: è una lista di risorse o costanti che costituiscono una alternativa al singolo valore assunto da una proprietà.
RDF permette inoltre di definire proprietà sia dell’intero container che dei singoli elementi.
Vediamo ora un esempio di contenitore di tipo Bag che rappresenti il fatto che il nostro tutorial RDF ha due esempi che sono identificati univocamente dalla loro URL:
Figura 5: Rappresentazione grafica di un contenitore Bag
Andiamo a vedere ancora una volta il risultato della serializzazione:
<rdf:RDF
xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”
xmlns:ex=”http://www.example.it/schema_esempi/”>
<rdf:Description about=”http://www.example.org/Antonio/TutorialRDF.pdf”>
<ex:Esempio>
<rdf:Description>
<rdf:type rdf:resource=”http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag”/>
<rdf:_1 rdf:resource=”http://example.org/Antonio/rdf/Example1.pdf”/>
<rdf:_2 rdf:resource=”http://example.org/Antonio/rdf/Example2.pdf”/>
</rdf:Description>
</rdf:Description>
</rdf:RDF>
La Reificazione
Come abbiamo detto in precedenza, gli statement riguardano le risorse. In alcuni casi, tuttavia, può essere utile certificare la credibilità di un particolare statement formulando degli statement relativi ad altri statement. Per esempio:
http://example.org/Antonio/TutorialRDF.pdf ha Autore Antonio Cicirelli
viene vista da RDF come un fatto, mentre lo statement:
Pinco Pallino asserisce che http://example.org/Antonio/TutorialRDF.pdf ha Autore Antonio Cicirelli
non afferma un fatto relativo alla risorsa http://example.org/Antonio/TutorialRDF.pdf, ma un fatto relativo all’affermazione di Pinco Pallino. Per esprimere questo fatto in RDF, dobbiamo modellare lo statement come una risorsa con quattro proprietà.
Nell’ambito della comunità che si interessa di Knowledge Representation, questo processo prende il nome di reificazione (reification), e il modello di statement prende il nome di reified statement.
Per modellare questa particolare categoria di statement, RDF definisce queste quattro proprietà:
- Soggetto (subject), che identifica la risorsa sulla quale era stato formulato lo statement originale (nel nostro caso http://example.org/Antonio/TutorialRDF.pdf);
- Predicato (predicate), che definisce la proprietà nello statement originale (nel nostro caso Autore);
- Oggetto (object), in cui è identificato il valore della proprietà nello statement modellato (nel nostro caso Antonio Cicirelli);
- Tipo (type), ovvero una descrizione del tipo della nuova risorsa.
Figura 6: Rappresentazione grafica di un reified statement
La figura 6 mostra il grafo relativo al nostro esempio di statement reificato (reified statement).
Antonio Cicirelli
[1] URI (Uniform Resource Identifier) è una stringa che identifica univocamente una generica risorsa all’interno di un determinato dominio. Un esempio di URI è l’URL, ovvero quella stringa che identifica univocamente una risorsa all’interno del WWW.
Cosa è RDF?
RDF (Resource Description Framework) è un formalismo proposto come strumento base per la codifica, lo scambio e il riutilizzo di metadati strutturati, e consente l’interoperabilità tra applicazioni che si scambiano informazioni machine understandable. I settori nei quali RDF può essere utilizzato e portare vantaggi sono i più disparati, basti citare, a titolo di esempio:
- descrizione del contenuto di un sito Web, o di una pagina, o di una biblioteca digitale;
- implementazione di intelligent software agent, per lo scambio di conoscenza e un utilizzo migliore delle risorse Web;
- descrizione di un insieme di pagine, che rappresentano un singolo documento logico;
- stabilire i criteri di proprietà intellettuale delle singole pagine;
- esprimere criteri di privacy preference degli utenti e le privacy policies di un sito Web;
- con il meccanismo della firma digitale, contribuire alla creazione del Web of Trust, per le applicazioni nel commercio elettronico, la cooperazione, etc..
Riassumendo…
Il Resource Description Framework, quindi, non descrive la semantica ma bensì si occupa di fornire una base comune per poterla esprimere, permettendo di definire la semantica dei tag XML. RDF è costituito da due componenti:
- RDF Model and Syntax: definisce il data model RDF e la sua codifica XML;
- RDF Schema: permette di definire specifici vocabolari per i metadati.
Antonio Cicirelli