Показать все пути дерева в SPARQL

Рассмотрим дерево:

prefix : <http://example.org/random#>

    :A a :Black .
    :B a :Black .
    :C a :Red .
    :D a :Black .
    :E a :Red .
    :F a :Black .
    :G a :Black .
    :H a :Red .
    :A :hasChild :B .
    :A :hasChild :C .
    :B :hasChild :D .
    :C :hasChild :E .
    :C :hasChild :F .
    :F :hasChild :G .
    :F :hasChild :H .

Каждый нижний узел представляет один путь.

Как я могу подсчитать количество «изменений класса» при следовании по пути от корневого узла: A до каждого нижнего узла?

Смена класса происходит, если родительский и дочерний узлы имеют разные классы красный/черный. Результаты должны выглядеть следующим образом:

?bottom  ?num
:D       0
:E       1
:G       2
:H       3

Дерево RDF

Я пробовал разные подходы, такие как:

prefix : <http://example.org/random>
SELECT ?bottom (COUNT(distinct IF(?type1 != ?type2,1,0)) AS ?num)
WHERE {

       :A :hasChild* ?child, ?mid, ?bottom .

        ?child a ?type1 .
        ?mid a ?type2 .


       FILTER NOT EXISTS {?bottom :hasChild ?x}


} group by ?bottom

Это дает мне:

bottom  num

E       "2"
D       "2"
G       "2"
H       "2" 

person Grapheneer    schedule 21.02.2020    source источник
comment
что-то вроде этого, может быть: prefix : <http://example.org/random#> select ?begin ?end (sum(?change) as ?num) where { ?begin :hasChild* ?midI . FILTER NOT EXISTS { [] :hasChild ?begin } ?midI :hasChild ?midJ . ?midI a ?iType . ?midJ a ?jType . BIND(IF(?iType != ?jType, 1, 0) as ?change) ?midJ :hasChild* ?end . FILTER NOT EXISTS { ?end :hasChild [] } } group by ?begin ?end   -  person UninformedUser    schedule 21.02.2020
comment
с правильным наименованием и порядком: prefix : <http://example.org/random#> select (?end as ?bottom) (sum(?change) as ?num) where { ?begin :hasChild* ?midI . FILTER NOT EXISTS { [] :hasChild ?begin } ?midI :hasChild ?midJ . ?midI a ?iType . ?midJ a ?jType . BIND(IF(?iType != ?jType, 1, 0) as ?change) ?midJ :hasChild* ?end . FILTER NOT EXISTS { ?end :hasChild [] } } group by ?begin ?end order by ?num   -  person UninformedUser    schedule 21.02.2020
comment
Спасибо @UninformedUser! Это работает, но может ли SPARQL отображать сам путь для объяснения числа? Таким образом, :H будет числом 3, а путь будет черным/красным/черным/красным с узлами A/C/F/H. Я читал здесь, что SPARQL не может выполнять кратчайшие пути. > stackoverflow.com/questions/14388864/   -  person Grapheneer    schedule 22.02.2020


Ответы (1)


prefix : <http://example.org/random#> 

select (?end as ?bottom) (sum(?change) as ?num) 

where { 

?begin :hasChild* ?midI . 
FILTER NOT EXISTS { [] :hasChild ?begin } 
?midI :hasChild ?midJ . 
?midI a ?iType . 
?midJ a ?jType . 
BIND(IF(?iType != ?jType, 1, 0) as ?change) 
?midJ :hasChild* ?end . 
FILTER NOT EXISTS { ?end :hasChild [] } 

} group by ?begin ?end order by ?num

ответил @Uninformeduser

person Grapheneer    schedule 10.05.2020