1

我想将具有有限域的新 lvar 放入映射中,并在我的代码的另一部分中建立它们之间的关系。考虑下面的片段:

(l/run 1 [q]
       (l/fresh [x y z a b c]
                (fd/in x y z (fd/interval 0 100)) ; establish domain for x y z
                (let [w {:a x :b y :c z}] ; store x y z in a map
                  (l/all
                    (l/featurec w {:a a :b b :c c}) ; extract x y z as a b c
                    (fd/+ a b c))) ; a relationship
                (l/== q [a b c])))

==> Error printing return value at clojure.core.logic/verify-all-bound$verify-all-bound* (logic.clj:2136).
Constrained variable <lvar:a__5787> without domain

有没有办法做到这一点?

4

1 回答 1

1

Featurec 并非旨在允许派生值(请参阅core.logic/featurec 文档中的链接示例)。

通常,您可以期望以“c”结尾的 core.logic 函数是“约束函数”,专门用于过滤(“约束”)已经从以前的逻辑函数派生的可能值的集合/域。这是库作者的一个有用的命名约定,而且据我所见,core.logic 的用户也试图坚持使用它。

但是,正常的统一对于这个特定的问题很有效。

(l/run* [q]
   (l/fresh [x y z a b c]
            (fd/in x y z (fd/interval 0 3)) ; establish domain for x y z
            (let [w {:a x :b y :c z}] ; store x y z in a map
              (l/all
                (l/== w {:a a :b b :c c}) ; extract x y z as a b c
                (fd/+ a b c))) ; a relationship
            (l/== q [a b c])))
=> ([0 0 0] [1 0 1] [0 1 1] [0 2 2] [2 0 2] [1 1 2])

或者,如果您只想要某些值,只需提取 lvar 并单独统一:

(l/run* [q]
   (l/fresh [x y z a b c]
            (fd/in x y z (fd/interval 0 2)) ; establish domain for x y z
            (let [w {:a x :b y :c z}] ; store x y z in a map
              (l/all
                (l/== a (w :a)) (l/== b (w :b)) ; extract x y z as a b c
                (fd/+ a b c))) ; a relationship
            (l/== q [a b c]) ))
=> ([0 0 0] [1 0 1] [0 1 1] [0 2 2] [2 0 2] [1 1 2] [1 2 3] [2 1 3] [2 2 4])

(还要注意我们没有统一c和z,所以c可以在区间之外)

如果需要,可以列出所需的 lvar 和相应的键,然后使用everyg为每对添加关系:

(l/run* [q]
  (l/fresh [x y z a b c]
    (fd/in x y z (fd/interval 0 2)) ; establish domain for x y z
    (let [w {:a x :b y :c z}
          targlist [a b c]
          wantedlist [:a :b :c]] ; store x y z in a map
      (l/all
       (everyg #(l/==
                 (get targlist %)
                 (w (get wantedlist %)))
               (range (count targlist))) ; extract x y z as a b c
       (apply fd/+ [a b c]))) ; a relationship
    (l/== q [a b c])))
=> ([0 0 0] [1 0 1] [0 1 1] [0 2 2] [2 0 2] [1 1 2])
于 2021-12-22T08:23:35.587 回答