【发布时间】:2021-07-08 20:44:34
【问题描述】:
我目前正在通过 The Reasoned Schemer 和 Racket 学习 miniKanren。
我有三个版本的 minikanren 实现:
-
理性的计划者,第一版(麻省理工学院出版社,2005 年)。我叫它
TRS1https://github.com/miniKanren/TheReasonedSchemer
附言。它说
condi已被conde的改进版本取代,它执行交织。 -
理性的计划者,第二版(麻省理工学院出版社,2018 年)。我叫它
TRS2https://github.com/TheReasonedSchemer2ndEd/CodeFromTheReasonedSchemer2ndEd
-
理性的计划者,第一版(麻省理工学院出版社,2005 年)。我叫它
TRS1*
我对上面的三个实现做了一些实验:
第一次实验:
TRS1
(run* (r)
(fresh (x y)
(conde
((== 'a x) (conde
((== 'c y) )
((== 'd y))))
((== 'b x) (conde
((== 'e y) )
((== 'f y)))))
(== `(,x ,y) r)))
;; => '((a c) (a d) (b e) (b f))
TRS2
(run* (x y)
(conde
((== 'a x) (conde
((== 'c y) )
((== 'd y))))
((== 'b x) (conde
((== 'e y) )
((== 'f y))))))
;; => '((a c) (a d) (b e) (b f))
TRS1*
(run* (r)
(fresh (x y)
(conde
((== 'a x) (conde
((== 'c y) )
((== 'd y))))
((== 'b x) (conde
((== 'e y) )
((== 'f y)))))
(== `(,x ,y) r)))
;; => '((a c) (b e) (a d) (b f))
请注意,在第一个实验中,TRS1 和 TRS2 产生了相同的结果,但 TRS1* 产生了不同的结果。
似乎TRS1 和TRS2 中的conde 使用相同的搜索算法,但TRS1* 使用不同的算法。
第二次实验:
TRS1
(define listo
(lambda (l)
(conde
((nullo l) succeed)
((pairo l)
(fresh (d)
(cdro l d)
(listo d)))
(else fail))))
(define lolo
(lambda (l)
(conde
((nullo l) succeed)
((fresh (a)
(caro l a)
(listo a))
(fresh (d)
(cdro l d)
(lolo d)))
(else fail))))
(run 5 (x)
(lolo x))
;; => '(() (()) (() ()) (() () ()) (() () () ()))
TRS2
(defrel (listo l)
(conde
((nullo l))
((fresh (d)
(cdro l d)
(listo d)))))
(defrel (lolo l)
(conde
((nullo l))
((fresh (a)
(caro l a)
(listo a))
(fresh (d)
(cdro l d)
(lolo d)))))
(run 5 x
(lolo x))
;; => '(() (()) ((_0)) (() ()) ((_0 _1)))
TRS1*
(define listo
(lambda (l)
(conde
((nullo l) succeed)
((pairo l)
(fresh (d)
(cdro l d)
(listo d)))
(else fail))))
(define lolo
(lambda (l)
(conde
((nullo l) succeed)
((fresh (a)
(caro l a)
(listo a))
(fresh (d)
(cdro l d)
(lolo d)))
(else fail))))
(run 5 (x)
(lolo x))
;; => '(() (()) ((_.0)) (() ()) ((_.0 _.1)))
请注意,在第二个实验中,TRS2 和 TRS1* 产生了相同的结果,但 TRS1 产生了不同的结果。
似乎TRS2 和TRS1* 中的conde 使用相同的搜索算法,但TRS1 使用不同的算法。
这些让我很困惑。
有人可以帮我解释一下上述每个 minikanren 实现中的这些不同的搜索算法吗?
非常感谢。
----添加一个新的实验----
第三次实验:
TRS1
(define (tmp-rel y)
(conde
((== 'c y) )
((tmp-rel-2 y))))
(define (tmp-rel-2 y)
(== 'd y)
(tmp-rel-2 y))
(run 1 (r)
(fresh (x y)
(conde
((== 'a x) (tmp-rel y))
((== 'b x) (conde
((== 'e y) )
((== 'f y)))))
(== `(,x ,y) r)))
;; => '((a c))
但是,run 2 或 run 3 会循环。
如果我使用condi 而不是conde,则run 2 有效,但run 3 仍然循环。
TRS2
(defrel (tmp-rel y)
(conde
((== 'c y) )
((tmp-rel-2 y))))
(defrel (tmp-rel-2 y)
(== 'd y)
(tmp-rel-2 y))
(run 3 r
(fresh (x y)
(conde
((== 'a x) (tmp-rel y))
((== 'b x) (conde
((== 'e y) )
((== 'f y)))))
(== `(,x ,y) r)))
;; => '((b e) (b f) (a c))
这没关系,只是顺序不符合预期。
注意(a c) 现在是最后一个了。
TR1*
(define (tmp-rel y)
(conde
((== 'c y) )
((tmp-rel-2 y))))
;;
(define (tmp-rel-2 y)
(== 'd y)
(tmp-rel-2 y))
(run 2 (r)
(fresh (x y)
(conde
((== 'a x) (tmp-rel y))
((== 'b x) (conde
((== 'e y) )
((== 'f y)))))
(== `(,x ,y) r)))
;; => '((a c) (b e))
但是,run 3 循环。
【问题讨论】:
-
看起来像是将结果流组合成一个结果流的各种方式的结果,例如可以看出here 以及从那里链接的答案。
-
顺便说一句,我不知道你可以这样写
(define (tmp-rel-2 y) (== 'd y) (tmp-rel-2 y)),没有任何特殊的minikanren形式包含两个目标...... -
@WillNess 当我问这个问题时,我正在阅读 The Reasoned Schemer。我对第 3:24 帧的结果感到困惑。当时,这本书还没有解释回溯机制。 (此机制在第 6 章中解释。)
-
@WillNess 所以我想我现在可以解释第 3:24 帧了,虽然我还没有读完整本书。原因(非正式地)是
TR1发出一个值后,它会回到最近的回溯点。但是由于我还没有读完整本书,所以我现在无法对这个问题添加答案。 -
@WillNess 第一版。
标签: scheme racket logic-programming minikanren reasoned-schemer