Reflexive tuples block certain rule-driven inferences

Abierto
#224 2 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
35/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Estancado
Stack tecnológico
clojure
Área
databases

Línea de trabajo

Empieza ejecutando la reproducción mínima en Clojure/JVM del issue y compara su resultado vacío con las dos consultas simplificadas y el resultado de Datomic. Rastrea la inferencia Datalog impulsada por reglas en torno a las tuplas reflexivas y la expansión indirecta de reglas; se considera terminado cuando la consulta original devuelve los cuatro pares de entidades esperados sin introducir regresiones en los casos simplificados.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

This is a thorny bug that only seems to happen when an entity is directly related to itself via some attribute. I've only tried this on the JVM, not in cljs. Here is the most minimal example I can construct:

(let [conn
      (ds/create-conn
        {:a {:db/valueType :db.type/ref}
         :b {:db/valueType :db.type/ref}})

      [x y]
      (map - (range))

      _
      (ds/transact! conn [{:db/id x
                           :a     y}
                          {:db/id y
                           :a     y
                           :b     x}])]
  (ds/q '{:find  [?p ?q]
          :in    [$ %]
          :where [(bar ?p ?q)]}
    @conn
    '[[(foo ?p ?q)
       [?p :b ?q]]

      [(bar ?p ?q)
       (baz ?p ?r)
       (baz ?q ?r)]

      [(baz ?p ?q)
       [?p :a ?r]
       (foo ?r ?q)]]))
;; => #{}

Removing a level of indirection yields the correct result -- both entities are related to themselves and to one another through rule bar:

(let [conn
      (ds/create-conn
        {:a {:db/valueType :db.type/ref}
         :b {:db/valueType :db.type/ref}})

      [x y]
      (map - (range))

      _
      (ds/transact! conn [{:db/id x
                           :a     y}
                          {:db/id y
                           :a     y
                           :b     x}])]
  (ds/q '{:find  [?p ?q]
          :in    [$ %]
          :where [(bar ?p ?q)]}
    @conn
    '[[(bar ?p ?q)
       (baz ?p ?r)
       (baz ?q ?r)]

      [(baz ?p ?q)
       [?p :a ?r]
       [?r :b ?q] ;; inlining rule `foo`
       ]]))
;; => #{[0 0] [1 0] [1 1] [0 1]}

Likewise through this equivalent simplification:

(let [conn
      (ds/create-conn
        {:a {:db/valueType :db.type/ref}
         :b {:db/valueType :db.type/ref}})

      [x y]
      (map - (range))

      _
      (ds/transact! conn [{:db/id x
                           :a     y}
                          {:db/id y
                           :a     y
                           :b     x}])]
  (ds/q '{:find  [?p ?q]
          :in    [$ %]
          :where [;; inlining rule `bar`
                  (baz ?p ?r)
                  (baz ?q ?r)]}
    @conn
    '[[(foo ?p ?q)
       [?p :b ?q]]

      [(baz ?p ?q)
       [?p :a ?r]
       (foo ?r ?q)]]))
;; => #{[0 0] [1 0] [1 1] [0 1]}

Compare the equivalent Datomic Datalog, which yields the correct result for the original query and rules (as well as for both simplified versions):

(let [uri
      "datomic:mem://throwaway-db"

      db
      (do
        (d/delete-database uri)
        (d/create-database uri)
        (-> uri d/connect d/db))

      db1 ;; install schema first
      (:db-after
       (d/with db
         [{:db/id          (d/tempid :db.part/db)
           :db/ident       :a
           :db/cardinality :db.cardinality/one
           :db/valueType   :db.type/ref}
          {:db/id          (d/tempid :db.part/db)
           :db/ident       :b
           :db/cardinality :db.cardinality/one
           :db/valueType   :db.type/ref}]))

      [x y]
      (repeatedly (fn [] (d/tempid :db.part/user)))

      db2
      (:db-after
       (d/with db1
         [{:db/id x
           :a     y}
          {:db/id y
           :a     y
           :b     x}]))]
  (d/q '{:find  [?p ?q]
         :in    [$ %]
         :where [(bar ?p ?q)]}
    db2
    '[[(foo ?p ?q)
       [?p :b ?q]]

      [(bar ?p ?q)
       (baz ?p ?r)
       (baz ?q ?r)]

      [(baz ?p ?q)
       [?p :a ?r]
       (foo ?r ?q)]]))
;; => #{[17592186045418 17592186045419] [17592186045419 17592186045418] [17592186045419 17592186045419] [17592186045418 17592186045418]}
Lenguaje dominante
Clojure
Estrellas
5.8k
Forks
318
Métricas de merge de PR
Sin PR fusionados en 30 d

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de tonsky/datascript

Todos los issues de tonsky/datascript

Issues similares

Más issues de Clojure

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.