Constructeurs et restrictions, propriétés de classes
Introduction
Dans ce chapitre, nous verrons comment manipuler l’ensemble des constructeurs OWL en Python avec Owlready. Nous verrons aussi les différents raccourcis que propose Owlready pour faciliter l’utilisation des constructeurs et en particulier des restrictions.
Créer des constructeurs
Les constructeurs OWL permettent de définir des constructions logiques à partir de classes, d’individus et de propriétés (voir chapitre Les ontologies OWL, section Restrictions et section Union, intersection et complément).
Les restrictions sont créées avec la syntaxe propriété.type(valeur), en utilisant les mêmes mots-clefs pour les types que dans Protégé :
-
propriété.some(Classe) pour une restriction existentielle
-
propriété.only(Classe) pour une restriction universelle
-
propriété.value(individu ou donnée) pour une restriction de valeur (role-filler)
-
propriété.exactly(cardinalité, Classe) pour une restriction de cardinalité exacte
-
propriété.min(cardinalité, Classe) et
-
propriété.max(cardinalité, Classe) pour les restrictions de cardinalité minimale ou maximale
Les opérateurs logiques NON, ET et OU (complément, intersection et union) sont obtenus de la manière suivante :
-
Not(Classe)
-
And([Classe1, Classe2,...]) ou Classe1 & Classe2 & ...
-
Or([Classe1, Classe2,...]) ou Classe1 | Classe2 | ...
Un ensemble d’individus est obtenu de la manière suivante :
-
OneOf([individu1, individu2,...])
L’inverse d’une propriété est obtenu de la manière suivante :
-
Inverse(Propriété)...
Accéder aux paramètres des constructeurs
Les propriétés suivantes permettent d’accéder aux informations contenues dans les principaux constructeurs (pour la liste complète des constructeurs et de leurs propriétés, se référer au manuel de référence en annexe, section Constructeurs (classe ClassContruct et descendantes)) :
-
Opérateurs logiques ET et OU (intersection et union, classe And et Or respectivement) :
-
Attribut Classes : la liste des classes sur lesquelles portent l’intersection ou l’union
-
Restrictions (classe Restriction) :
-
Attribut property : la propriété sur laquelle porte la restriction
-
Attribut type : le type de la restriction (une valeur parmi les constantes SOME, ONLY, VALUE, MAX, MIN et EXACTLY)
-
Attribut value : la valeur sur laquelle porte la restriction (une classe pour les types SOME, ONLY, MAX, MIN et EXACTLY, un individu ou une valeur pour le type VALUE)
-
Attribut cardinality : le nombre de relations concernées (uniquement disponible pour les restrictions de type MAX, MIN et EXACTLY)
Par exemple, si l’on reprend la classe Streptocoque et sa définition équivalente, nous pouvons l’analyser de la manière suivante :
>>> onto.Streptocoque.equivalent_to[0]
bacterie.Bactérie
& bacterie.a_pour_forme.some(bacterie.Ronde) ...
Restrictions comme propriétés de classe
Owlready permet d’accéder à l’ensemble des constructeurs OWL, comme nous l’avons vu dans les deux sections précédentes. Cependant, la création des constructeurs ou l’accès aux informations qui y sont contenues est souvent complexe et laborieux. C’est pourquoi Owlready propose également plusieurs raccourcis pour faciliter l’utilisation des constructeurs. Nous avons déjà vu un exemple de raccourci pour accéder aux restrictions existentielles comme s’il s’agissait de propriété de classe, au chapitre Accéder aux ontologies en Python, section Restrictions existentielles.
En effet, les restrictions sont souvent utilisées pour représenter les relations entre classes. Les relations entre deux classes sont plus complexes que celles entre deux individus. Dans ce dernier cas, soit la relation existe (ce qui correspond à un triplet dans le quadstore), soit elle n’existe pas. Au contraire, une classe rassemble plusieurs individus, ce qui conduit à plusieurs cas de figure :
-
Tous les individus de la première classe sont en relation avec au moins un individu de la seconde classe : c’est la restriction existentielle (« some » dans Protégé).
-
Tous les individus de la première classe sont en relation avec uniquement des individus de la seconde classe : c’est la restriction universelle (« only » dans Protégé).
-
Chaque individu de la première classe est en relation avec chaque individu de la seconde classe : OWL ne permet pas directement de créer ce type de relation entre classes, cependant il est possible d’obtenir un résultat équivalent en réifiant la propriété, c’est-à-dire en la transformant en une classe associée à deux propriétés.
Owlready permet de traduire les relations entre deux classes en propriétés de classe, et vice versa. Cela permet de créer ou de lire facilement des constructeurs correspondant aux formes suivantes :
-
(Propriété some Classe)
-
(Propriété value individu)
-
(Propriété only (Classe or ... ))
-
(Propriété only ({ individu,... }))...
Classes définies
Owlready permet également d’utiliser les propriétés de classe pour créer des classes définies, avec des définitions de la forme suivante :
Classe_parente1 and Classe_parente2 ...
and (Propriété some Classe) ...
and (Propriété value individu) ...
and (Propriété only (Classe ... or { individu,... }))
Pour cela, Owlready utilise l’annotation booléenne spéciale defined_class pour indiquer qu’une classe est définie. Si cette annotation est vraie (True) pour une classe, Owlready générera une définition à partir des propriétés de classe, à la place des restrictions vues à la section précédente. La valeur par défaut est faux (False) pour cette annotation.
L’exemple suivant crée une nouvelle classe définie de Bactérie :
>>> with onto:
... class Corynebacterium(onto.Bactérie):
... defined_class = True
... gram_positif = False
... a_pour_forme = onto.Allongée
... a_pour_regroupement = [onto.EnAmas]
Notez la première ligne du corps de la classe, « defined_class = True », qui indique qu’il s’agit...
Exemple : créer l’ontologie des bactéries en Python
Le programme suivant, donné à titre d’illustration, permet de recréer l’ontologie des bactéries de zéro, entièrement en Python, en utilisant des constructeurs. La création d’une ontologie en Python peut sembler plus laborieuse qu’avec Protégé, mais elle présente aussi des avantages : en particulier, il est possible de copier-coller des définitions, ce qui permet de créer rapidement des classes similaires.
# Fichier creer_onto.py
from owlready2 import *
onto = get_ontology("http://lesfleursdunormal.fr/static/ \
_downloads/bacterie.owl#")
with onto:
class Forme(Thing): pass
class Ronde(Forme): pass
class Allongée(Forme): pass
AllDisjoint([Ronde, Allongée])
class Regroupement(Thing): pass
class Isolé(Regroupement): pass
class ParDeux(Regroupement): pass
class EnAmas(Regroupement): pass
class EnChaîne(Regroupement): pass
class EnChaînette(EnChaîne): pass
class EnFilament(EnChaîne): pass
AllDisjoint([Isolé...
Exemple : peupler une ontologie avec des classes définies
Dans cet exemple, nous allons reprendre le peuplement de l’ontologie des bactéries. Nous effectuerons cette fois-ci un peuplement avec des classes (comme au chapitre précédent, section Peuplement par des classes), mais en utilisant des définitions avec des relations d’équivalence. Nous réutiliserons le même fichier CSV que précédemment (appelé peuplement_classes.csv) :
Le peuplement peut être réalisé de deux manières : soit en utilisant les propriétés de classe (ce qui est l’option la plus simple), soit en utilisant les constructeurs (ce qui est plus compliqué, mais peut être nécessaire si vous souhaitez créer des définitions plus complexes que celles générées par Owlready).
1. Peuplement en utilisant les propriétés de classe
Le programme suivant utilise les propriétés de classe pour peupler l’ontologie des bactéries avec des classes définies, à partir des données du fichier CSV ci-dessus :
# Fichier peuplement_classes_definies1.py
from owlready2 import *
import csv, types
onto = get_ontology("bacterie.owl").load()
onto.gram_positif.class_property_type = ["some"]
onto.a_pour_forme.class_property_type = ["some", "only"]
onto.a_pour_regroupement.class_property_type = ["some"]
onto_classes = get_ontology("http://lesfleursdunormal.fr/static/ \
_downloads/bacterie_classes_definies.owl")
onto_classes.imported_ontologies.append(onto)
f = open("peuplement_classes.csv")
reader = csv.reader(f)
next(reader)
with onto_classes:
for ligne in reader:
identifiant, parent, gram_positif, forme, regroupement = ligne
if parent: parent = onto[parent]
else: parent = Thing
...