Сколемизация пустого узла в SPARQL без итерации

Возможно ли реализовать сколемизацию пустых узлов в SPARQL без итераций? Мне кажется, что итерация необходима для сколемизации цепочек пустых узлов, таких как:

@prefix : <http://example.com/> .

[ a :A ;
  :p1 [
    a :B
  ]
] .

Операция обновления SPARQL для сколемизации может начинаться с пустых узлов, которые появляются как субъекты только в тройках без пустых узловых объектов:

DELETE {
  ?b1 ?outP ?outO .
  ?inS ?inP ?b1 .
}
INSERT {
  ?iri ?outP ?outO .
  ?inS ?inP ?iri .
}
WHERE {
  {
    SELECT ?b1 (uuid() AS ?iri)
    WHERE {
      {
        SELECT DISTINCT ?b1
        WHERE {
          ?b1 ?p1 [] .
          FILTER isBlank(?b1)
          FILTER NOT EXISTS {
            ?b1 ?p2 ?b2 .
            FILTER isBlank(?b2)
          }
        }
      }
    }
  }
  ?b1 ?outP ?outO .
  OPTIONAL {
    ?inS ?inP ?b1 .
  }
}

Эту операцию можно повторять до тех пор, пока в данных не будут обнаружены пустые узлы:

ASK {
  ?bnode ?p [] .
  FILTER isBlank(?bnode)
}

Можно ли избежать итерации и реализовать сколемизацию пустого узла за одну операцию обновления SPARQL?

(Кроме того, этот подход предполагает, что не существует «сиротских» пустых узлов (т.е. пустых узлов, которые отображаются только как объекты).)


person Jindřich Mynarz    schedule 27.11.2017    source источник


Ответы (1)


Я нашел двухэтапное решение, сколемизирующее субъектов и объекты по отдельности и сохраняющее псевдонимы пустых узлов (связи между пустыми узлами и IRI через owl:sameAs) в качестве промежуточных данных:

PREFIX :    <http://example.com/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>

####################
# Rewrite subjects #
####################

DELETE {
  ?bnode ?p ?o .
}
INSERT {
  ?iri ?p ?o .
  GRAPH :aliases {
    ?bnode owl:sameAs ?iri .
  }
}
WHERE {
  {
    SELECT ?bnode (uuid() AS ?iri)
    WHERE {
      {
        SELECT DISTINCT ?bnode
        WHERE {
          ?bnode ?p [] .
          FILTER isBlank(?bnode)
        }
      }
    }
  }
  ?bnode ?p ?o .
}
;

###################
# Rewrite objects #
###################

DELETE {
  ?s ?p ?bnode .
}
INSERT {
  ?s ?p ?iri .
}
WHERE {
  {
    SELECT ?bnode ?iri
    WHERE {
      {
        SELECT DISTINCT ?bnode
        WHERE {
          [] ?p ?bnode .
          FILTER isBlank(?bnode)
        }
      }
      OPTIONAL {
        GRAPH :aliases {
          ?bnode owl:sameAs ?_iri .
        }
      }
      BIND (coalesce(?_iri, uuid()) AS ?iri)
    }
  }
  ?s ?p ?bnode .
}
;

############################
# Clear blank node aliases #
############################

CLEAR GRAPH :aliases
person Jindřich Mynarz    schedule 28.11.2017