【问题标题】:Translating the insert fact from Prolog to core.logic将插入事实从 Prolog 转换为 core.logic
【发布时间】:2014-01-29 09:52:16
【问题描述】:

我正在玩弄 core.logic 并尝试翻译一些 Prolog 代码并遇到insert 事实的无限递归(取自 R.A.O'Keefe 的“Prolog 工艺”):

 insert(L, X, [X|L]).
 insert([H|T], X, [H|L]) :-
        insert(T,X,L).

这是我到目前为止提出的(请注意前两个参数被交换以匹配conso参数列表):

 (defn insert [x l nl]
    (conde
      [(conso x l nl)]
      [(fresh [h t]
         (conso h t l)
         (insert x t l)
         (conso h l nl))]))

我遇到的问题是这些 midje 测试的最后两个事实永远不会返回。 第一个按预期工作得很好,因为这只需要第一个 conso 子句。

   (fact "Inserting works"
         (run* [q] (insert 1 [2] q)) => '((1 2)))
         (run* [q] (insert 1 [2 3] q)) => '((1 2 3)))
   (fact "We can retrieve the inserted data"
         (run* [q] (insert q [2] '(1 2))) => '(1))
   (fact "We can retrieve the list data, too"
         (run* [q] (insert 1 q '(1 2))) => '((2))))

我想我忽略了一些明显的东西,但是什么?

编辑:事实没有正确反映 Prolog 代码的行为。正确的行为是这样的:

   ?- insert([2,3], 1, Q).
   Q = [1, 2, 3] ;
   Q = [2, 1, 3] ;
   Q = [2, 3, 1].

所以,第二个checkable实际上应该是

 (fact "Inserting works"
       (run* [q] (insert 1 [2 3] q)) => '((1 2 3) (2 1 3) (2 3 1)))

【问题讨论】:

  • 使用NL=[H|R]。不能在那里使用L 而不是RL 已经用作参数。

标签: clojure prolog clojure-core.logic


【解决方案1】:

解决办法是把递归插入子句放在最后:

(defn insert [x l nl]
    (conde
      [(conso x l nl)]
      [(fresh [h t]
         (conso h t l)
         (conso h l nl)
         (insert x t l))]))

【讨论】:

  • 谢谢。我必须考虑一下为什么顺序的变化会在这里产生影响。
  • 为了说明 Prolog 版本的正确行为(参见我上面的编辑),l 应仅在第一个 conso 术语中使用,否则替换为新的 l1
【解决方案2】:

Prolog 代码几乎可以逐字转录,因为 core.logic 也支持匹配。

(defne inserto [L, X, L*] 
    ([L, X, (X . L)]) 
    ([(H . T), X, (H . L)] (inserto T, X, L)))

请注意,我保留了 Prolog 版本的顺序,而不是您版本中前两个逻辑变量的倒序。

user=> (run* [q] (inserto [2] 1 q))
((1 2))
user=> (run* [q] (inserto [2 3] 1 q))
((1 2 3))
user=> (run* [q] (inserto [2] q [1 2]))
(1)
user=> (run* [q] (inserto q 1 [1 2]))
((2))

【讨论】:

  • 请注意,@Ankur 回答了实际问题,但我认为这很有用,不适合发表评论。
  • 感谢您对匹配的提示,这确实使匹配变得更容易。然而,正如我发现的那样,这个解决方案与 Prolog 版本的行为不匹配,这可能是我弄错了 midje 事实(我已经编辑了问题以更正它)。不过,它只需要稍作改动:将递归代码中“L”的使用与 L1 交换,即([H . T), X, (H . L1)]) (inserto T, X, L1)。这允许通过回溯找到更多结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多