owlready2中的逆属性问题

问题描述 投票:0回答:1

我遇到了一个困难: 我在 owlready2 中创建了一个对象属性(例如:has_parent)并将其定义为另一个对象属性的逆属性(例如:has_child)。当我通过第一个属性将一个人(例如“John”)与另一个人(例如“Kevin”)关联起来以创建“John has_parent Kevin”作为三元组时,预计逆三元组“Kevin has_child John”将在推理过程之后创建。但事实并非如此。当我在推理过程之前查询“通过 has_child 属性将 Kevin 与哪个人联系起来”时,它回答:约翰! 但这并不是问题本身。当我执行推理过程,然后保存推理结果和主本体本身时,问题就出现了:本体中不存在三元组“Kevin has_child John”,推理结果中也不存在!

另一个问题是,当我在 owlready2 中为对象属性定义域和范围,并定义另一个属性作为第一个属性的逆时,预期逆属性的域和范围设置为推理后分别为第一个的值域和定义域。但事实并非如此。并且推理后没有给逆性质设定定义域和值域。

我尝试用另一种方式定义逆属性,但没有成功。

代码如下:

从 owlready2 导入 *

onto = get_ontology(“http://test.org/Family#”)

随着:

'''defining base classes'''

class Human(Thing): pass

class Man(Human): pass

class Woman(Human): pass

AllDisjoint([Man, Woman])

'''defining properties'''
class has_couple(Human>>Human): pass
class has_wife(has_couple, Man>>Woman): pass
class has_husbend(has_couple):
    inverse=has_wife
class has_child (Human>>Human): pass
class has_parent (ObjectProperty):
    inverse=has_child

'''defining individuals'''
John = Man("John")
Kevin = Man("Kevin")

'''defining relations between individuals'''
John = Man("John", has_parent=[Kevin])

打印(凯文.has_child)

'''推理'''

随着:

sync_reasoner_pellet(infer_property_values=True, infer_data_property_values = True)

打印(has_husbend.domain)

'''节省'''

onto.save(“test.owl”,格式=“rdfxml”)

inverse
1个回答
0
投票

这个答案只是关于逆性质,而不是关于定义域和范围。

我无法在文档中验证它,但我认为这是

owlready2
的设计决策,实现
owl:inverseOf
的语义,因此在查询中返回额外的三元组,但从
save()
中排除这些额外的三元组功能。

这样做的原因是一般原则,即您不应将原始本体中不存在的(冗余)三元组添加到知识库中。自动添加此类三元组可能会导致文件大小和内存需求大幅增加,这是不必要的,例如,如果存在适用于每个人拥有的属性的逆属性的定义。

此外,逆语义的自动应用可能会导致某些更复杂关系的错误事实,并且您需要人机交互或某种可解释性算法来检查结果是否正确。但是,如果您只是将派生事实输入知识库中,则不再可能区分原始事实和新事实,因此在这种情况下检查结果(甚至知道已添加新事实)不再可能。

总而言之:这是

owlready2
的预期行为。如果您想使用像 Kevin has_child John 这样的派生事实,那么您应该使用
owlready2
本身或实现
owl:inverseOf
的另一个引擎。

但是,如果您确实想要 xml 中的所有三元组,那么您可以使用

rdflib
自行输出它们,方法是循环所有实例,并为每个实例循环所有属性。

代码:

from owlready2 import *
from rdflib import Graph, URIRef, Namespace
from rdflib.namespace import RDF, RDFS, OWL

onto = get_ontology("http://test.org/Family#")

with onto:
    '''defining base classes'''
    class Human(Thing): pass
    
    class Man(Human): pass
    
    class Woman(Human): pass

    AllDisjoint([Man, Woman])

    '''defining properties'''
    class has_couple(Human>>Human): pass
    class has_wife(has_couple, Man>>Woman): pass
    class has_husband(has_couple):
        inverse=has_wife
    class has_child (Human>>Human): pass
    class has_parent (ObjectProperty):
        inverse=has_child

'''defining individuals'''
Kevin = Man("Kevin")

'''defining relations between individuals'''
John = Man("John", has_parent=[Kevin])
Mary = Woman("Mary", has_husband=[Kevin])

print("Kevin.has_child:", Kevin.has_child)
print("Kevin.has_wife:", Kevin.has_wife)

fam = Namespace("http://test.org/Family#")
graph = Graph(base="http://test.org/Family")
graph.bind('fam', fam)
A = RDF.type

for person in Human.instances():
    # add a node for this person
    graph.add((URIRef('#'+person.name), A, OWL.NamedIndividual))
    # add all rdf:type nodes (usually just 1)
    for entity_type in person.is_a:
        graph.add((URIRef('#'+person.name), A, URIRef('#'+entity_type.name)))
    # add all person-property-object triples
    for prop in person.get_properties():
        # a property can have multiple values
        for value in prop[person]:
            graph.add((URIRef('#'+person.name), fam.term(prop.name), URIRef('#'+value.name)))

# print xml, don't nest nodes (max_depth=1)
print(graph.serialize(format="pretty-xml", max_depth=1))

这将打印以下内容:

<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF xml:base="http://test.org/Family"
  xmlns:ns1="#"
  xmlns:fam="http://test.org/Family#"
  xmlns:owl="http://www.w3.org/2002/07/owl#"
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
>
  <owl:NamedIndividual rdf:about="#Mary">
    <rdf:type rdf:resource="#Woman"/>
    <fam:has_husband rdf:resource="#Kevin"/>
  </owl:NamedIndividual>
  <owl:NamedIndividual rdf:about="#Kevin">
    <rdf:type rdf:resource="#Man"/>
    <fam:has_wife rdf:resource="#Mary"/>
    <fam:has_child rdf:resource="#John"/>
  </owl:NamedIndividual>
  <owl:NamedIndividual rdf:about="#John">
    <rdf:type rdf:resource="#Man"/>
    <fam:has_parent rdf:resource="#Kevin"/>
  </owl:NamedIndividual>
</rdf:RDF>

一些注意事项:

  • 我用
    has_husband=[Kevin]
    添加了一个单独的 Mary 来测试逆 has_husband/has_wife
  • 我更正了拼写“husbend”,正确的是“husband”
  • 我尝试尽可能多地复制
    owlready2
    本身使用的 xml 语法。我无法修改的唯一区别是
    owlready2
    使用普通关系
    <has_child>
    ,而
    rdflib
    使用此代码生成
    <fam:has_child>
    ,名称空间的别名为
    fam:
© www.soinside.com 2019 - 2024. All rights reserved.