Вот суть того, как я что-то делаю и какие виды вывода/моделирования включены.
Почти все, что мы используем, подпадает под OWL Lite, за исключением свойства owl:hasValue
, которое мы используем для определения сопоставления 1-1 между наборами тегов и именами классов. По этой причине текущее решение подпадает под OWL DL.
Это также означает, что нам нужен распознаватель, но, к счастью, не тот, который поддерживает OWL Full :). OWL-RL — хороший выбор, работающий с 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 }" )
Мы можем сериализовать расширенную форму графа на диск, если нам нужно использовать процессор запросов SPARQL, который не поддерживает рассуждения.
https://brickschema.org/schema/1.1.0/Brick#
owl:Class
и организованы в иерархию с помощью rdfs:subClassOf
owl:equivalentClass
skos:definition
brick:AHU_Average_Exhaust_Air_Static_Pressure_Sensor
— это просто Average_Exhaust_Air_Static_Pressure_Sensor
, который является точкой AHU.Корневые классы, которые мы определили:
Equipment
Location
Point
Tag
Substance
Quantity
(Отношения — это термин Brick для обозначения ObjectProperties совы между экземплярами классов)
На поверхностном уровне отношения работают так же, как и в оригинальном Brick. Все те же отношения все еще существуют (где я не забыл их определить), и их обратные значения определены с помощью owl:inverseOf
.
Домены и диапазоны определяются в терминах классов. Утверждение, что rdfs:range
отношения относится к классу brick:Equipment
означает, что объект отношения должен быть экземпляром класса brick:Equipment
.
Этот прототип помимо отношений включает в себя дополнительные связи. Подотношения можно использовать вместо суперотношений, чтобы добавить больше деталей к природе этих отношений. Единственный пример на данный момент — это feedsAir
, которые являются дочерним ресурсом feeds
.
Нужно выяснить, как мы можем сделать вывод о связи feedsAir
; может быть, если у двух оконечных устройств есть air
метка и связь feeds
? Это может быть что-то, что необходимо явно указать, а не предполагать.
https://brickschema.org/schema/1.1.0/BrickTag#
skos:definition
Это достигается путем объявления класса Brick (например, Air_Temperature_Sensor
) как эквивалента анонимного класса, который представляет собой owl:Restriction
, представляющий собой пересечение сущностей, имеющих определенные теги.
# 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
]
) ] .
Первый owl:Restriction
— это набор всех классов, у которых tag:Sensor
является значением одного из свойств brick:hasTag
.
Это означает, что датчик температуры :ts1
может быть определен двумя разными способами, и логик выведет остальные тройки:
# using classes
:ts1 a brick:Temperature_Sensor
# using tags
:ts1 brick:hasTag tag:Temp
:ts1 brick:hasTag tag:Sensor
Brick теперь определяет иерархию субстанций ( substances.py
) и иерархию количеств ( quantities.py
). Вещества и количества могут быть связаны с оборудованием и очками.
Не все это реализовано. В текущем прототипе датчики связаны с веществами и количествами посредством отношения brick:measures
.
:ts1 a brick:Temperature_Sensor
:ts1 brick:measures :Air
# this implies the following
:ts1 a brick:Air_Temperature_Sensor
Мы можем дополнительно подклассифицировать вещества, чтобы обеспечить контекст их определений на уровне системы или процесса:
:ts1 a brick:Sensor
:ts1 brick:measures brick:Return_Air
:ts1 brick:measures brick:Temperature
# implies...
:ts1 a brick:Return_Air_Temperature_Sensor
Brick использует ограничения OWL для уточнения классов на основе таких отношений. В этом примере, поскольку :ts1
измеряет воздух (в частности, класс brick:Air
), OWL определяет наш датчик как brick:Air_Temperature_Sensor
.
Вот как это определение выглядит в черепахе:
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 ] ) ] .
Примечание . Здесь мы используем классы в качестве значений, что отличается от остальной части Brick. Это называется «каламбур». Это сделано для того, чтобы избежать необходимости создавать экземпляры веществ для измерения нашими датчиками и т. д., но оставляет возможность реализовать это в будущем. Экземпляры веществ могут моделировать области/куски «вещества» на этапе процесса, например, воду, поступающую в охладитель, или область смешанного воздуха в вентиляционной установке.
Вместо того, чтобы теряться в сизифовой болтовне о том, как форматировать все в YAML, мы просто используем словари Python, поэтому нам не нужно беспокоиться о какой-либо (ну, не такой уж большой) логике синтаксического анализа.
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 )
На данный момент код является документацией. Посмотрите equipment.py
, point.py
и т. д., чтобы увидеть примеры и узнать, как добавить их в каждую иерархию классов.
Авторы: Гейб Фиерро