[英]Goal ordering in Clojure's `core.logic`
以下Clojure代码使用core.logic
来解决两个不同顺序中具有相同目标的相同逻辑问题。 这种订购选择导致一个快速完成而另一个挂起。
(use `clojure.core.logic)
;; Runs quickly. Prints (1 2 3).
(clojure.pprint/pprint (run* [q] (fresh [x] (== x [1,2,3])
(membero q x))))
;; Hangs
(clojure.pprint/pprint (run* [q] (fresh [x] (membero q x)
(== x [1,2,3]))))
是否有一般解决方案或通常的做法来避免这个问题?
这是我的理解:
使用core.logic
,您希望尽早减少搜索空间。 如果首先放置membero
约束,则运行将通过搜索membero
空间开始,并回溯由==
约束生成的失败。 但是membero
空间是巨大的,因为q
和x
都不是统一的或至少是有界的。
但是如果你先把==
约束放在一边,你就用[1 2 3]
直接统一x
,现在membero
的搜索空间显然与x
的元素有关。
如果您打算使用membero
,则没有针对此问题的通用解决方案。 使用新变量调用membero
将使其生成q
为其成员的所有(读取,无限)可能列表。 当然,大于3的列表不适用 - 但是由于你已经使用了run*
,它将继续盲目地尝试大于计数3的列表,即使每个列表都会失败。
可以使用约束基础membero
在较新版本的core.logic中编写更好的membero
版本,但是在未来几个月内,人们可能会如何做到这一点的细节可能会发生变化。 直到有一个坚实的公共api来定义约束,你才会遇到那些让Prolog陷入困境的微妙排序和非终止问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.