Du triplet SPARQL à l'ontologie OWL — 24 exercices pour maîtriser
le Web Sémantique, de la théorie à la pratique.
Ce TD comporte 24 exercices répartis sur les trois dernières parties du cours. Chaque exercice est indépendant, mais la progression est conçue pour être suivie dans l'ordre.
Triplets · graphe · unification · Prolog · Turtle
Traduis les phrases suivantes en triplets RDF (sujet → verbe → objet) :
Écris chaque triplet sous la forme <sujet> <verbe> <objet>.
À partir des triplets de l'exercice 1, dessine le graphe de connaissances correspondant (sur papier ou avec un outil de dessin).
Questions :
mortel(X) ← homme(X), quel nouveau triplet peux-tu déduire ?Applique l'algorithme d'unification aux paires de termes suivantes. Pour chaque paire, indique si l'unification réussit et, si oui, donne la substitution résultante.
homme(X) et homme(socrate)a_mangé(socrate, Y) et a_mangé(X, pomme)mortel(X) et mortel (arité différente)est_un(X, Y) et est_un(socrate, homme)a_mangé(socrate, X) et a_mangé(Y, Y)père(Z, fils(Z)) et père(jean, fils(paul))Un meurtre a été commis au manoir. Tu disposes des faits et règles suivants :
% Faits est_dans(le_cadavre, la_bibliothèque) est_dans(l_arme, le_salon) a_le_motif(colonel_moutarde, l_héritage) a_le_motif(professeur_violet, l_héritage) est(le_cadavre, mort) % Règles suspect(X) ← a_le_motif(X, l_héritage) est_dans(X, Y) ∧ est_dans(Z, Y) → est_avec(X, Z) coupable(X) ← suspect(X) ∧ est_avec(X, l_arme)
Applique le chaînage avant pour déterminer qui est coupable. Montre chaque étape de déduction.
Écris un fichier famille.pl au format Prolog qui contient :
parent(jean, marie), parent(marie, paul), parent(paul, sophie), parent(jean, luc)grandparent(X, Y) ← parent(X, Z) ∧ parent(Z, Y)ancetre(X, Y) récursive (indice : cas de base + cas récursif)Teste ton fichier avec le mini-Prolog du cours : python raisonnement.py.
Dans le code du mini-Prolog (fichier raisonnement.py), le chaînage avant est implémenté avec une boucle qui répète l'unification jusqu'à stabilisation.
auteur_classique(X) ← a_ecrit(X, Y) ∧ est_consideré(Y, chef_d_oeuvre) et des faits correspondants.[DÉDUCTION] règle 3 → nouveau fait : mortel(socrate).return dans une fonction récursive.Voici un fichier Turtle :
@prefix : <http://example.org/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
:Socrate rdf:type :Homme .
:Homme rdf:type :Classe .
:Platon rdf:type :Homme .
:Socrate :aMangé :Pomme .
:Pomme rdf:type :Fruit .
mini_fuseki.py, localise le parseur Turtle et explique en 2-3 phrases comment il transforme ce texte en triplets.En t'appuyant sur les exemples du cours, donne trois différences entre un graphe RDF et un graphe orienté classique (comme ceux qu'on voit en cours de maths).
Exemple de point de départ : les arêtes sont étiquetées par des URIs, pas par des lettres ou des nombres.
OWL · classes · propriétés · restrictions · constructeurs · raisonnement
Organise les classes suivantes en hiérarchie OWL (⊑) :
Animal · Mammifère · Oiseau · Chien · Chat · Canari · ÊtreVivant · Végétal · Rose · Cactus · Carnivore
Quelques contraintes :
Canari est un Oiseau.Chien est un Mammifère et un Carnivore.Chat est aussi un Mammifère et un Carnivore.Carnivore est un Animal (les végétaux ne mangent pas de viande).Est-ce que la hiérarchie est un arbre ? Pourquoi ?
L'ornithorynque pond des œufs (comme les oiseaux) mais allaite ses petits (comme les mammifères). Il est aussi venimeux (comme... un serpent ?).
Définis une hiérarchie OWL qui modélise correctement l'ornithorynque sachant que :
Oiseau ⊑ Animal, pond_des_oeufs (propriété)Mammifère ⊑ Animal, allaite (propriété)Monotrème ⊑ Mammifère (les monotrèmes sont des mammifères qui pondent des œufs)Ornithorynque ⊑ Monotrème et Ornithorynque ⊑ ∃ a_pour_venin.VeninQuestions :
Ornithorynque ⊑ Oiseau serait-il faux ?Soit les axiomes suivants :
Domaine(a_mangé) = Animal
Range(a_mangé) = Aliment
a_mangé(Socrate, Pomme)
Pomme ⊑ Aliment
Socrate ⊑ ÊtreHumain (sans déclaration de classe explicite)
Socrate est un Animal ? Pourquoi ?Pomme est un Aliment ?a_mangé(Socrate, Pomme) et que le domaine est Animal, alors Socrate EST un Animal. C'est la base de l'inférence de types en OWL. Flippant, non ?Un restaurant souhaite modéliser ses plats en OWL :
Végétarien ⊑ Plat ⊓ ∀ contient.VégétalVégan ⊑ Végétarien ⊓ ∀ contient.¬AnimalPlatDeMer ⊑ Plat ⊓ ∃ contient.PoissonPlatTraditionnel ⊑ Plat ⊓ ∃ contient.ViandeQuestions :
Poisson est-il Végétarien ? Justifie.Oeuf (qui est un Animal sans être Viande) est-il Végétarien ? Est-il Végan ?Végétarien et PlatDeMer ? Quelle pizza ?En utilisant les constructeurs OWL (⊓ ⊔ ¬ ∃ ∀), traduis les phrases suivantes en expressions logiques :
= 1 (cardinalité). Pour « au moins deux », utilise ≥ 2. En OWL, ∃ signifie « au moins un », ∀ signifie « seulement des ». C'est la nuance entre « j'ai mangé une pomme » (∃) et « je ne mange que des pommes » (∀).Une ontologie contient les axiomes suivants :
Chat ⊑ Animal
Chien ⊑ Animal
Chat ⊑ ∀ a_pour_meilleur_ami.¬Chien
Félix ⊑ Chat
Médor ⊑ Chien
a_pour_meilleur_ami(Félix, Médor)
Chat ⊑ ∀ a_pour_meilleur_ami.¬Chien, quels nouveaux faits peut-on déduire ?À l'aide du mini-raisonneur du cours, détermine la classification de l'individu Rex sachant que :
Chien ⊑ Animal
BergerAllemand ⊑ Chien
Rex ⊑ BergerAllemand
Rex ⊑ ∃ a_pour_métier.{chien_policier, chien_d_aveugle}
Animal ⊑ ∃ a_besoin.Manger
Quelles sont toutes les classes auxquelles appartient Rex ? Détaille le chemin de classification.
ChienActeur ⊓ ChienDeGuerre ⊓ StarInternationale. Bref, un chien avec une ontologie bien remplie.
En te basant sur la démo raisonnement.py --owlready, écris un script Python qui :
Animal, Chien, Chat avec Chien ⊑ Animal et Chat ⊑ Animalrex et felix avec leurs typesTeste-le avec python ton_script.py.
La Pizza Ontology est le « Hello World » du Web Sémantique. Voici un extrait :
Pizza ⊑ ∃ a_ingrédient.Fromage (toute pizza contient du fromage)
PizzaVégétarienne ⊑ Pizza ⊓ ∀ a_ingrédient.¬Viande
PizzaMargherita ⊑ PizzaVégétarienne
PizzaMargherita ⊑ ∀ a_ingrédient.{Mozzarella, Tomate, Basilic}
PizzaMargherita est bien une PizzaVégétarienne ? Démontre-le.PizzaVégane qui ne contient aucun ingrédient d'origine animale.Fromage et qu'on la déclare PizzaVégane ? Explique.Dans le code du mini-raisonneur OWL (raisonnement.py), implémente une détection de contradiction :
Pour corser le tout :
C ⊑ D signifie que tout individu de C est aussi dans D (⊑ = sous-classe ou équivalence).SPARQL · Fuseki · API · serveur HTTP · déploiement
Écris une requête SPARQL pour chacune des questions suivantes (base : l'ontologie de la famille) :
a_pour_enfant.Teste-les sur le serveur SPARQL : python mini_fuseki.py --exemple puis http://localhost:8080/sparql.
En utilisant la même base, écris les requêtes SPARQL suivantes :
FILTER + COUNT ou double pattern)Sophie sur exactement 3 générations.?x :a_pour_enfant ?y . ?y :a_pour_enfant ?z donne les grands-parents. C'est la magie des property paths : ?x :a_pour_enfant+ ?z donne tous les ancêtres en une ligne.À partir de la base de connaissances familiale, utilise CONSTRUCT pour :
:est_ancetre_de à partir des relations :a_pour_enfant.CONSTRUCT est l'équivalent en SPARQL du « faire quelque chose avec les données » plutôt que juste les regarder. En SQL, pour créer une nouvelle table, tu fais CREATE TABLE AS SELECT. En SPARQL, c'est CONSTRUCT { ... } WHERE { ... }. Les gars du W3C n'ont pas choisi la simplicité, mais ils ont choisi la puissance. Comme disait un sage : « SPARQL, c'est le SQL du Web Sémantique, en moins lisible mais plus puissant. »
Le serveur mini_fuseki.py expose une API REST sur /sparql. En utilisant curl :
SELECT * WHERE { ?s ?p ?o } LIMIT 10 via GET.application/sparql-query).Accept: application/sparql-results+json pour obtenir du JSON.requests ou urllib) et affiche les résultats dans un tableau formaté.{} doivent être échappées en shell. Utilise --data-urlencode ou mets la requête dans un fichier. Et n'oublie pas -g si tu utilises curl avec des accolades — sinon curl les interprète comme des ranges et ça part en vrille. L'expérience de plusieurs heures de debug, je te l'offre.Dans le code de mini_fuseki.py, ajoute une fonctionnalité au choix :
OFFSET et LIMIT (déjà implémenté en partie, mais pas exposé dans l'interface web).DESCRIBE <uri> qui retourne tous les triplets concernant une ressource.ASK qui retourne true ou false selon qu'un pattern existe./export qui retourne toute la base en Turtle.SELECT est implémenté dans le serveur. Tu peux copier la structure et modifier le parseur SPARQL pour supporter la nouvelle forme. C'est l'exercice le plus long du TD, mais aussi le plus gratifiant : après ça, tu pourras dire « j'ai contribué à un serveur SPARQL ». Sur LinkedIn, ça claque.En t'inspirant du script publish.sh et du service systemd fournis avec les cours :
deploy.sh qui déploie le cours vers un serveur de ton choix (paramétrable : ./deploy.sh user@host).make deploy qui appelle ton script.scp. Puis avec rsync. Puis avec des pipelines CI/CD. Aujourd'hui, tu es à l'étape scp, mais avec un script. C'est le début d'une longue et belle relation avec l'automatisation. Dans 5 ans, tu auras un pipeline Kubernetes qui déploie ton ontologie OWL sur 12 serveurs en haute disponibilité. Tout commence ici.
Utilise ce tableau pour suivre ta progression :
| # | Exercice | Difficulté | Concept clé | ✔ |
|---|---|---|---|---|
| 1 | Triplets RDF | ★ | sujet-verbe-objet | ☐ |
| 2 | Graphe de connaissances | ★ | navigation, classes vs individus | ☐ |
| 3 | Unification | ★★ | substitution, MGU, occur check | ☐ |
| 4 | Chaînage avant | ★★ | moteur d'inférence | ☐ |
| 5 | Fichier Prolog | ★ | faits, règles, récursion | ☐ |
| 6 | Moteur d'inférence | ★★★ | détection de cycles, trace | ☐ |
| 7 | Parseur Turtle | ★★ | préfixes, URIs, expansion | ☐ |
| 8 | RDF vs graphe | ★ | métagraphe, réification | ☐ |
| 9 | Hiérarchie de classes | ★ | ⊑, sous-classe, héritage | ☐ |
| 10 | Héritage multiple | ★★ | ornithorynque, OWL vs héritage simple | ☐ |
| 11 | Propriétés et inférence | ★★ | domaine, range, déduction de types | ☐ |
| 12 | Restrictions OWL | ★★ | ∀, ∃, cardinalités | ☐ |
| 13 | Constructeurs logiques | ★★★ | ⊓, ⊔, ¬, ∀, ∃ | ☐ |
| 14 | Cohérence d'ontologie | ★★★ | contradiction, ⊥ | ☐ |
| 15 | Classification | ★★ | chemin de classification | ☐ |
| 16 | Owlready2 | ★ | API Python, création d'ontologie | ☐ |
| 17 | Pizza Ontology | ★★ | Owlready2, restrictions | ☐ |
| 18 | Détection de contradiction | ★★★★ | raisonneur maison | ☐ |
| 19 | Premières requêtes SPARQL | ★ | SELECT, WHERE, triplets | ☐ |
| 20 | Jointures et FILTER | ★★ | property paths, FILTER | ☐ |
| 21 | CONSTRUCT | ★★ | création de graphe | ☐ |
| 22 | API REST SPARQL | ★★★ | curl, JSON, parsing | ☐ |
| 23 | Nouvelle fonctionnalité Fuseki | ★★★★ | DESCRIBE, ASK, export | ☐ |
| 24 | Déploiement automatique | ★★★ | CI/CD, backup, notification | ☐ |
⊓ ⊔ ¬ ∃ ∀ ⸎ ☐