SHACL 验证结果不正确

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

我正在尝试使用 pyshacl 对照形状图验证数据图。基本上,数据图表示建筑物中两堵墙的几何表示,两堵墙之间的距离约为 12.5 米。形状图检查墙之间的距离是否小于 10 米。我使用的代码如下:

from pyshacl import validate
from rdflib import Graph
Datagraph = '''
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix bot: <https://w3id.org/bot#> .
@prefix ifc: <https://standards.buildingsmart.org/IFC/DEV/IFC2x3/TC1/OWL#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix lbd: <https://linkebuildingdata.org/LBD#> .
@prefix props: <http://lbd.arch.rwth-aachen.de/props#> .
@prefix geo: <http://www.opengis.net/ont/geosparql#> .
@prefix unit: <http://qudt.org/vocab/unit/> .
@prefix IFC4-PSD: <https://www.linkedbuildingdata.net/IFC4-PSD#> .
@prefix smls: <https://w3id.org/def/smls-owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix inst: <https://www.ugent.be/myAwesomeFirstBIMProject#> .
@prefix fog: <https://w3id.org/fog#> .

inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c353
        props:objectTypeIfcObject  inst:objectTypeIfcObject_1eec9390-5f68-4a64-aaa9-34a883f3c353 ;
        props:reference            inst:reference_1eec9390-5f68-4a64-aaa9-34a883f3c353 ;
        props:extendToStructure    inst:extendToStructure_1eec9390-5f68-4a64-aaa9-34a883f3c353 ;
        props:loadBearing          inst:loadBearing_1eec9390-5f68-4a64-aaa9-34a883f3c353 ;
        props:isExternal           inst:isExternal_1eec9390-5f68-4a64-aaa9-34a883f3c353 ;
        props:category             inst:category_1eec9390-5f68-4a64-aaa9-34a883f3c353 ;
        rdf:type                   bot:Element ;
        props:globalIdIfcRoot      inst:globalIdIfcRoot_1eec9390-5f68-4a64-aaa9-34a883f3c353 ;
        props:nameIfcRoot          inst:nameIfcRoot_1eec9390-5f68-4a64-aaa9-34a883f3c353 ;
        props:batid                inst:batid_1eec9390-5f68-4a64-aaa9-34a883f3c353 ;
        geo:hasGeometry            inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c353_geometry .

inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c353_geometry
        fog:asObj_v3.0-obj  "diAzODcyLjM3ODM0NTUyNjY4OSAtNDY2LjM1NTc3MjU3ODAzNjA3IDAuMAp2IDM4NzIuMzc4MzQ1NTI2Njg5IC00NjYuMzU1NzcyNTc4MDM2MDcgNzk5OS45OTk5OTk5OTk5OTkKdiAzODcyLjM3ODM0NTUyNjY4OSAtNDA2Ni4zNTU3NzI1NzgwMzY1IDAuMAp2IDM4NzIuMzc4MzQ1NTI2Njg5IC00MDY2LjM1NTc3MjU3ODAzNjUgNzk5OS45OTk5OTk5OTk5OTkKdiA0MTYyLjM3ODM0NTUyNjY4OSAtNDY2LjM1NTc3MjU3ODAzNjA3IDAuMAp2IDQxNjIuMzc4MzQ1NTI2Njg5IC00NjYuMzU1NzcyNTc4MDM2MDcgNzk5OS45OTk5OTk5OTk5OTkKdiAzODcyLjM3ODM0NTUyNjY4OSAtN"^^<https://www.w3.org/TR/xmlschema-2/#base64Binary> ;
        lbd:hasBoundingBox  inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c353_geometry_bb .
        
inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c353_geometry_bb
        lbd:z-max  "7999.999999999999"^^xsd:double ;
        lbd:z-min  "0.0"^^xsd:double ;
        lbd:y-max  "-466.35577257803607"^^xsd:double ;
        lbd:y-min  "-4066.3557725780365"^^xsd:double ;
        lbd:x-max  "4162.378345526689"^^xsd:double ;
        lbd:x-min  "3872.378345526689"^^xsd:double .
        
inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c0dd
        props:nameIfcRoot          inst:nameIfcRoot_1eec9390-5f68-4a64-aaa9-34a883f3c0dd ;
        props:reference            inst:reference_1eec9390-5f68-4a64-aaa9-34a883f3c0dd ;
        props:loadBearing          inst:loadBearing_1eec9390-5f68-4a64-aaa9-34a883f3c0dd ;
        props:objectTypeIfcObject  inst:objectTypeIfcObject_1eec9390-5f68-4a64-aaa9-34a883f3c0dd ;
        props:globalIdIfcRoot      inst:globalIdIfcRoot_1eec9390-5f68-4a64-aaa9-34a883f3c0dd ;
        props:category             inst:category_1eec9390-5f68-4a64-aaa9-34a883f3c0dd ;
        props:isExternal           inst:isExternal_1eec9390-5f68-4a64-aaa9-34a883f3c0dd ;
        geo:hasGeometry            inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c0dd_geometry ;
        lbd:containsInBoundingBox  inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c31b ;
        props:batid                inst:batid_1eec9390-5f68-4a64-aaa9-34a883f3c0dd ;
        props:extendToStructure    inst:extendToStructure_1eec9390-5f68-4a64-aaa9-34a883f3c0dd ;
        rdf:type                   bot:Element .

inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c0dd_geometry
        fog:asObj_v3.0-obj  "diAtODYzNy42MjE2NTQ0NzMyOTIgLTQzNTYuMzU1NzcyNTc3OTk2IDAuMAp2IC04NjM3LjYyMTY1NDQ3MzI5MiAtNDM1Ni4zNTU3NzI1Nzc5OTYgNzk5OS45OTk5OTk5OTk5OTkKdiAtODYzNy42MjE2NTQ0NzMyOTIgODI0My42NDQyMjc0MjIwMSAwLjAKdiAtODYzNy42MjE2NTQ0NzMyOTIgODI0My42NDQyMjc0MjIwMSA3OTk5Ljk5OTk5OTk5OTk5OQp2IC04OTI3LjYyMTY1NDQ3MzI5MiAtNDM1Ni4zNTU3NzI1Nzc5OTYgMC4wCnYgLTg5MjcuNjIxNjU0NDczMjkyIC00MzU2LjM1MCAxMTcgMTE4CmYgMTIyIDEyNCAxMjMKZiAxMjIgMTIxIDEyNApmIDEyNyAxMjggMTI1CmYgMTI4IDEyNiAxMjUKZiAxMjkgMTMwIDEzMQpmIDEzMiAxMjkgMTMxCg=="^^<https://www.w3.org/TR/xmlschema-2/#base64Binary> ;
        lbd:hasBoundingBox  inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c0dd_geometry_bb .

inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c0dd_geometry_bb
        lbd:z-max  "7999.999999999999"^^xsd:double ;
        lbd:z-min  "0.0"^^xsd:double ;
        lbd:y-max  "8243.64422742201"^^xsd:double ;
        lbd:y-min  "-4356.355772577996"^^xsd:double ;
        lbd:x-max  "-8637.621654473292"^^xsd:double ;
        lbd:x-min  "-8927.621654473292"^^xsd:double .
'''
Shapegraph = ''' 
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix bot: <https://w3id.org/bot#> .
@prefix ifc: <https://standards.buildingsmart.org/IFC/DEV/IFC2x3/TC1/OWL#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix lbd: <https://linkebuildingdata.org/LBD#> .
@prefix props: <http://lbd.arch.rwth-aachen.de/props#> .
@prefix geo: <http://www.opengis.net/ont/geosparql#> .
@prefix unit: <http://qudt.org/vocab/unit/> .
@prefix IFC4-PSD: <https://www.linkedbuildingdata.net/IFC4-PSD#> .
@prefix smls: <https://w3id.org/def/smls-owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix inst: <https://www.ugent.be/myAwesomeFirstBIMProject#> .
@prefix fog: <https://w3id.org/fog#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

ifc:geometricconstraintshape a sh:NodeShape ;
        sh:targetClass bot:Element;
        sh:sparql[
            sh:message "The geometric constraint is violated" ;
            sh:select """
            SELECT $this
            WHERE{
                inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c353 geo:hasGeometry $this .
                $this lbd:hasBoundingBox ?wall1bb.
                ?wall1bb lbd:x-min ?x_min.
                inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c0dd geo:hasGeometry $this .
                $this lbd:hasBoundingBox ?wall2bb.
                ?wall2bb lbd:x-max ?x_max.
                FILTER (ifc:computedistance(?x_min,?x_max)<=10.0) .
                } """ ;
            ] .
        
ifc:computedistance a sh:SPARQLFunction;
    rdfs:comment "Finds the distance between the two elements";
    sh:parameter[
        sh:path lbd:x_min ;
        sh:datatype xsd:double;
        sh:description "The inner x coordinate of the wall on the right side";
        ];
    
    sh:parameter[
        sh:path lbd:x_max ;
        sh:datatype xsd:double;
        sh:description "The outer x coordinate of the wall on the left side";
        ];
    
    sh:returnType xsd:double;
    sh:select"""
    SELECT (BIND(($x_min - $x_max)/1000) AS ?result)
    WHERE {
        }
    """.
'''

r = validate(data_graph = Datagraph, shacl_graph = Shapegraph, data_graph_format="ttl", shacl_graph_format="ttl", inference = "rdfs", debug = True, abort_on_error = False, meta_shacl = False, serialize_report_graph = "ttl")
conforms, results_graph, results_text = r

由于墙壁之间的实际距离约为12510毫米(我已将计算出的距离除以形状中的1000以将其转换为米),因此数据图不应与形状图相符。然而,就我而言,我得到的结果是“数据图符合约束”。

不确定我在塑造形状时在哪里犯了错误。任何人都可以帮助识别错误并建议如何纠正它吗?预先感谢。

我还尝试了一个更简单的查询来避免函数调用,如下所示:

ifc:geometricconstraintshape a sh:NodeShape ;
        sh:targetClass bot:Element;
        sh:sparql[
            sh:message "The geometric constraint is violated" ;
            sh:select """
            SELECT $this
            WHERE{
                inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c353 geo:hasGeometry $this .
                $this lbd:hasBoundingBox ?wall1bb.
                ?wall1bb lbd:x-min ?x_min.
                inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c0dd geo:hasGeometry $this .
                $this lbd:hasBoundingBox ?wall2bb.
                ?wall2bb lbd:x-max ?x_max.
                BIND ((?x_min - ?x_max)/1000 AS ?result) .
                FILTER (?result<=10.0) .
                } """ ;
            ] .

但是,我没有得到正确的结果。

为了避免由于目标节点不正确而导致的任何问题,我以另一种形式编写了查询,如下所示:

ifc:computedistance a sh:SPARQLFunction;
    rdfs:comment "Finds the distance between the two elements";
    sh:parameter[
        sh:path ifc:op1 ;
        sh:datatype xsd:double;
        sh:description "The inner x coordinate of the wall on the right side";
        ];
    
    sh:parameter[
        sh:path ifc:op2 ;
        sh:datatype xsd:double;
        sh:description "The outer x coordinate of the wall on the left side";
        ];
    
    sh:returnType xsd:double;
    sh:select"""
    SELECT ?result
    WHERE {
        BIND ((($op1 - $op2)/1000) AS ?result).
        }
    """.
    
ifc:lessThan a sh:SPARQLFunction;
    rdfs:comment "Returns if op1<op2.";
    sh:parameter[
        sh:path ifc:op1;
        sh:datatype xsd:double;
        sh:description "The difference between the two coordinates";
        ] ;
    
    sh:parameter[
        sh:path ifc:op2;
        sh:datatype xsd:double;
        sh:description "The constraint value to be checked against";
        ] ;
    
    sh:returnType xsd:boolean ;
    sh:select """
        SELECT ?result
        WHERE {
            BIND (IF(?op1<?op2, true, false) AS ?result).
            }
        """.

ifc:geometricconstraintshape a sh:NodeShape ;
        sh:targetClass bot:Element;
        sh:expression[
            sh:message "The geometric constraint is violated" ;
            ifc:lessThan(
                [
                    ifc:computedistance(
                        [sh:path (inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c353_geometry_bb lbd:x-min)]
                        [sh:path (inst:wall_1eec9390-5f68-4a64-aaa9-34a883f3c0dd_geometry_bb lbd:x-max)]
                        )
                    ]
                10.0
                );
            ].
        
'''

但是,数据图仍然确认形状图中的所有约束值。

python sparql rdflib shacl
1个回答
0
投票

还有几个遗留问题:

  • 您可能需要添加类型:
    sh:sparql [a sh:SPARQLConstraint; ...
  • sh:targetClass bot:Element
    针对该类的所有节点。您希望将其限制为墙壁,并且不在约束中使用 2 个固定墙壁实例
  • 你必须非常清楚查询中的
    $this
    是什么:它是目标节点(
    bot:Element
    Wall
    ,但绝对不是几何体)
  • 两面墙都在寻找
    geo:hasGeometry $this
    ,但两面墙不可能具有相同的几何形状,因此失败
  • sh:sparql
    each 目标节点上运行。而且由于每个查询都必须将
    $this
    与所有其他墙壁进行比较,因此复杂性变得非常高。最好在
    sh:target [a sh:SPARQLTarget; sh:select """...
    中找到违规行为,然后仅使用
    sh:sparql [a sh:SPARQLConstraint
    来填充 ViolationReport 变量

请参阅https://transparency.ontotext.com/spec/#validation-rules周围的示例。注意:“SPARQL 检查”不是 SHACL 检查,它是一个发现问题的简单 SPARQL 查询。

© www.soinside.com 2019 - 2024. All rights reserved.