Voici l'essentiel de la façon dont je fais les choses et quels types d'inférence/modélisation sont activés
Presque tout ce que nous utilisons relève de OWL Lite à l'exception de la propriété owl:hasValue
que nous utilisons pour définir un mappage 1-1 entre des ensembles de balises et des noms de classes. Pour cette raison, la solution actuelle relève de OWL DL.
Cela signifie également que nous avons besoin d'un raisonneur, mais heureusement pas celui qui prend en charge OWL Full :). OWL-RL est un bon choix qui fonctionne avec RDFlib.
# G is our RDFlib Graph
# apply reasoning to expand all of the inferred triples
import owlrl
owlrl . DeductiveClosure ( owlrl . OWLRL_Semantics ). expand ( G )
# get namespaces
print ( list ( G . namespaces ()))
G . query ( "SELECT ?x WHERE { ?x brick:hasTag tag:Equip }" )
Nous pouvons sérialiser la forme développée du graphique sur le disque si nous devons utiliser un processeur de requêtes SPARQL qui ne prend pas en charge le raisonnement.
https://brickschema.org/schema/1.1.0/Brick#
owl:Class
et sont organisées en hiérarchie avec rdfs:subClassOf
owl:equivalentClass
skos:definition
brick:AHU_Average_Exhaust_Air_Static_Pressure_Sensor
est juste un Average_Exhaust_Air_Static_Pressure_Sensor
qui est un point d'une AHU.Les classes racines que nous avons définies sont :
Equipment
Location
Point
Tag
Substance
Quantity
(Les relations sont le terme Brick pour les propriétés d'objet hibou entre les instances de classes)
Au niveau de la surface, les relations fonctionnent de la même manière que dans la brique originale. Toutes les mêmes relations existent toujours (là où j'ai pensé à les définir), et leurs inverses sont définis à l'aide owl:inverseOf
.
Les domaines et les plages sont définis en termes de classes. Indiquer que le rdfs:range
d'une relation est de classe brick:Equipment
signifie que l'objet de la relation doit être une instance de la classe brick:Equipment
.
Ce prototype inclut des sous-relations en plus des relations. Les sous-relations peuvent être utilisées à la place de la super-relation pour ajouter plus de détails à la nature de cette relation. Le seul exemple jusqu'à présent est que feedsAir
est une sous-propriété de feeds
.
Il reste à comprendre comment nous pourrions déduire la relation feedsAir
; peut-être si les deux équipements de point final ont l'étiquette air
et une relation feeds
? C’est peut-être quelque chose qui doit être explicitement spécifié plutôt que déduit.
https://brickschema.org/schema/1.1.0/BrickTag#
skos:definition
Ceci est accompli en déclarant une classe Brick (par exemple Air_Temperature_Sensor
) comme équivalente à une classe anonyme, qui est une owl:Restriction
qui est l'intersection d'entités qui ont certaines balises.
# in turtle format
brick:Temperature_Sensor a owl:Class ;
rdfs:subClassOf brick:Sensor ;
owl:equivalentClass [ owl:intersectionOf (
[ a owl:Restriction ;
owl:hasValue tag:Sensor ;
owl:onProperty brick:hasTag
]
[ a owl:Restriction ;
owl:hasValue tag:Temperature ;
owl:onProperty brick:hasTag
]
) ] .
Le premier owl:Restriction
est l'ensemble de toutes les classes qui ont tag:Sensor
comme valeur pour l'une de leurs propriétés brick:hasTag
.
Cela signifie qu'un capteur de température :ts1
pourrait être défini de deux manières différentes et le raisonneur en déduirait les autres triplets :
# using classes
:ts1 a brick:Temperature_Sensor
# using tags
:ts1 brick:hasTag tag:Temp
:ts1 brick:hasTag tag:Sensor
Brick définit désormais une hiérarchie de substances ( substances.py
) et une hiérarchie de quantités ( quantities.py
). Les substances et les quantités peuvent être liées à des équipements et à des points.
Tout cela n’est pas mis en œuvre. Dans le prototype actuel, les capteurs sont liés aux substances et aux quantités via la relation brick:measures
.
:ts1 a brick:Temperature_Sensor
:ts1 brick:measures :Air
# this implies the following
:ts1 a brick:Air_Temperature_Sensor
Nous pouvons sous-classer davantage les substances pour fournir un contexte au niveau du système ou du processus à leurs définitions :
:ts1 a brick:Sensor
:ts1 brick:measures brick:Return_Air
:ts1 brick:measures brick:Temperature
# implies...
:ts1 a brick:Return_Air_Temperature_Sensor
Brick utilise les restrictions OWL pour affiner les classes en fonction de ces relations. Pour cet exemple, parce que :ts1
mesure l'Air (en particulier la classe brick:Air
), OWL déduit notre capteur comme une brick:Air_Temperature_Sensor
.
Voici à quoi ressemble la définition dans Turtle :
brick:Air_Temperature_Sensor a owl:Class ;
rdfs:subClassOf brick:Temperature_Sensor ;
owl:equivalentClass [ owl:intersectionOf ( [ a owl:Restriction ;
owl:hasValue brick:Temperature ;
owl:onProperty brick:measures ] [ a owl:Restriction ;
owl:hasValue brick:Air ;
owl:onProperty brick:measures ] ) ] .
Remarque : nous utilisons ici des classes comme valeurs, ce qui est différent du reste de Brick. C'est ce qu'on appelle le « jeu de mots ». Ceci afin d'éviter d'avoir à créer des instances de substances que nos capteurs pourront mesurer, etc., mais nous nous réservons la possibilité de l'implémenter à l'avenir. Les instances de substances peuvent modéliser des régions/morceaux de « trucs » dans une étape d'un processus, par exemple l'eau entrant dans un refroidisseur ou la région d'air mélangé d'une unité de traitement d'air.
Plutôt que de nous perdre dans le débat de Sisyphe sur la façon de tout formater en YAML, nous utilisons simplement des dictionnaires Python afin de ne pas avoir à nous soucier (enfin, pas tant que ça) de logique d'analyse.
definitions = {
"Lighting_System" : {
"tagvalues" : [ # Lighting_System class is equivalent to the Lighting tag
( BRICK . hasTag , TAG . Lighting ),
# if you have more required tags add them as their own tuple in the list
],
# defining subclasses. This can be nested ad-infinitum
"subclasses" : {
"Lighting" : {
"subclasses" : {
"Luminaire" : {},
"Luminaire_Driver" : {},
},
},
"Interface" : {
"subclasses" : {
"Switch" : {
"subclasses" : {
"Dimmer" : {},
},
},
"Touchpanel" : {},
},
},
},
}
}
define_subclasses ( definitions , BRICK . Equipment )
Pour l'instant, le code est la documentation. Regardez equipment.py
, point.py
, etc. pour des exemples et comment ajouter à chacune des hiérarchies de classes.
Auteurs : Gabe Fierro