OpenLink Virtuoso: Trouver si deux noeuds sont connectés à une certaine distance

StackOverflow https://stackoverflow.com/questions/3914522

  •  29-09-2019
  •  | 
  •  

Question

Comment puis-je trouver la distance entre 2 noeuds dans un graphique à l'aide Virtuoso? J'ai lu les documentations de transitivité, mais ils vous limiter à un prédicat par exemple:.

SELECT ?link ?g ?step ?path
WHERE
{
  {
    SELECT ?s ?o ?g
    WHERE
      {
        graph ?g {?s foaf:knows ?o }
      }
  } OPTION (TRANSITIVE, t_distinct, t_in(?s), t_out(?o), t_no_cycles, T_shortest_only,
  t_step (?s) as ?link, t_step ('path_id') as ?path, t_step ('step_no') as ?step, t_direction 3) .
  FILTER (?s= <http://www.w3.org/People/Berners-Lee/card#i>
  && ?o = <http://www.advogato.org/person/mparaz/foaf.rdf#me>)
}
LIMIT 20

traverse seulement foaf:knows et aucun type prédicat. Comment puis-je étendre à « tout prédicat »? Je ne ai pas besoin le chemin réel, juste un vrai / faux (ASK requête). Modification du FOAF:. SAIT p semble comme un matraquage

Je procède actuellement un ensemble de récursive SKO pour savoir si deux noeuds sont connectés à une distance spécifique, mais cela ne semble pas efficace.

Était-ce utile?

La solution

Vous devriez pouvoir utiliser ?p au lieu de foaf:knows dans votre requête pour déterminer s'il y a un chemin entre les nœuds. Par exemple:.

SELECT ?link ?g ?step ?path
   WHERE
   {
     {
       SELECT ?s ?o ?g
       WHERE
         {
           graph ?g {?s ?p ?o }
         }
     } OPTION (TRANSITIVE, t_distinct, t_in(?s), t_out(?o), t_no_cycles, T_shortest_only,
     t_step (?s) as ?link, t_step ('path_id') as ?path, t_step ('step_no') as ?step, t_direction 3) .
     FILTER (?s= <http://www.w3.org/People/Berners-Lee/card#i>
     && ?o = <http://www.advogato.org/person/mparaz/foaf.rdf#me>)
   }
   LIMIT 20

Autres conseils

Voici une approche qui fonctionne s'il y a au plus un chemin entre les noeuds qui vous intéressent. Si vous avez des données comme celle-ci (note qu'il y a des propriétés différentes reliant les ressources):

@prefix : <https://stackoverflow.com/q/3914522/1281433/>

:a :p :b .
:b :q :c .
:c :r :d .

Ensuite, une requête comme ce qui suit trouve la distance entre chaque paire de noeuds. Le chemin de la propriété se compose (:|!:) une propriété qui est soit : ou autre chose que : (à savoir, quoi que ce soit). Ainsi (:|!:)* est zéro ou plusieurs occurrences d'un bien; il est un chemin générique. (La technique utilisée ici est décrite plus en détail dans Est-il possible d'obtenir la position d'un élément dans une collection RDF SPARQL? .)

prefix : <https://stackoverflow.com/q/3914522/1281433/>

select ?begin ?end (count(?mid)-1 as ?distance) where {
 ?begin (:|!:)* ?mid .
 ?mid (:|!:)* ?end .
}
group by ?begin ?end
order by ?begin ?end ?distance
--------------------------
| begin | end | distance |
==========================
| :a    | :a  | 0        |
| :a    | :b  | 1        |
| :a    | :c  | 2        |
| :a    | :d  | 3        |
| :b    | :b  | 0        |
| :b    | :c  | 1        |
| :b    | :d  | 2        |
| :c    | :c  | 0        |
| :c    | :d  | 1        |
| :d    | :d  | 0        |
--------------------------

Pour tout savoir s'il y a un chemin entre deux nœuds qui est inférieur à une longueur particulière, vous utilisez une requête ask au lieu d'un select, fixer les valeurs de ?begin et ?end, et limitons plutôt la valeur de count(?mid)-1 que liant à ?distance. Par exemple, il est un chemin de :a à :d de longueur inférieure à trois?

prefix : <https://stackoverflow.com/q/3914522/1281433/>

ask {
 values (?begin ?end) { (:a :d) }
 ?begin (:|!:)* ?mid .
 ?mid (:|!:)* ?end .
}
group by ?begin ?end
having ( (count(?mid)-1 < 3 ) )
Ask => No

Par contre, il y a un chemin de :a à :c avec une longueur inférieure à 5:

prefix : <https://stackoverflow.com/q/3914522/1281433/>

ask {
 values (?begin ?end) { (:a :c) }
 ?begin (:|!:)* ?mid .
 ?mid (:|!:)* ?end .
}
group by ?begin ?end
having ( (count(?mid)-1 < 5 ) )
Ask => Yes
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top