Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
纯Prolog格式Quine_Prolog_Logical Purity_Lambda Prolog_Occurs Check - Fatal编程技术网

纯Prolog格式Quine

纯Prolog格式Quine,prolog,logical-purity,lambda-prolog,occurs-check,Prolog,Logical Purity,Lambda Prolog,Occurs Check,有一份文件: 威廉·E·伯德、埃里克·霍尔克、丹尼尔·p·弗里德曼,2012年 miniKanren,活的和未标记的 通过关系解释器生成奎因 它使用逻辑编程来寻找一个方案Quine。这个 这里考虑的方案子集不仅包含lambda。 抽象和应用,还有一点列表处理 通过以下简化(已翻译为Prolog): [quote,X] ~~> X [] ~~> [] [cons,X,Y] ~~> [A|B], for

有一份文件:

威廉·E·伯德、埃里克·霍尔克、丹尼尔·p·弗里德曼,2012年
miniKanren,活的和未标记的
通过关系解释器生成奎因

它使用逻辑编程来寻找一个方案Quine。这个 这里考虑的方案子集不仅包含lambda。 抽象和应用,还有一点列表处理 通过以下简化(已翻译为Prolog):

[quote,X] ~~> X
[] ~~> []                                      
[cons,X,Y] ~~> [A|B], for X ~~> A and Y ~~> B
因此,除了lembda之外,唯一的符号是引号、[]和cons lambda抽象和绑定变量。我们将使用Prolog 方案列表的列表。目标是找到一个方案 通过Prolog对Q进行编程,得到Q~~~>Q,即对其自身进行求值

有一个复杂的因素,使得这项工作变得不平凡, [lembda,X,Y]不会对自身进行语法评估,而是 应该返回一个环境关闭。因此,评估者应该是 与Plotkin计算器不同


有什么Prolog解决方案吗?Merry X-Mas

我正在使用SWI Prolog,此处启用了发生检查(但无论如何,
dif/2
都会跳过发生检查):

测试:

查找求值为
(我爱你)
的方案表达式--此示例在miniKanren中具有历史记录:

?- evil(X, [i, love, you]), print(X).
[quote,[i,love,you]]
X = [quote, [i, love, you]] ;
[list,[quote,i],[quote,love],[quote,you]]
X = [list, [quote, i], [quote, love], [quote, you]] ;
[list,[quote,i],[quote,love],[[lambda,[_3302],[quote,you]],[quote,_3198]]]
X = [list, [quote, i], [quote, love], [[lambda, [_3722], [quote|...]], [quote, _3758]]],
dif(_3722, quote),
freeze(_3758, atom(_3758)) ;
[list,[quote,i],[quote,love],[[lambda,[_3234],_3234],[quote,you]]]
X = [list, [quote, i], [quote, love], [[lambda, [_3572], _3572], [quote, you]]],
freeze(_3572, atom(_3572)) ;
换句话说,它发现的前4件事是:

(quote (i love you))

(list (quote i) (quote love) (quote you))

(list (quote i) (quote love) ((lambda (_A) (quote you)) (quote _B)))
; as long as _A != quote

(list (quote i) (quote love) ((lambda (_A) _A) (quote you))) 
; as long as _A is a symbol
看起来方案语义是正确的。它放置的语言类型的约束非常整洁。事实上,真正的计划将拒绝

> (list (quote i) (quote love) ((lambda (quote) (quote you)) (quote _B)))
Exception: variable you is not bound
Type (debug) to enter the debugger.
但我会接受的

> (list (quote i) (quote love) ((lambda (quote) quote) (quote you)))
(i love you)
奎因怎么样

?- evil(X, X).
<loops>


但是SWI不一定用
call\u with\u depth\u limit

来限制递归。这里有一个解决方案,它使用了一点。它不使用when/2,而只使用freeze/2。有一个谓词expr/2,用于检查某个内容是否是正确的表达式,但其中没有任何闭包:

expr(X) :- freeze(X, expr2(X)).

expr2([X|Y]) :-
   expr(X),
   expr(Y).
expr2(quote).
expr2([]).
expr2(cons).
expr2(lambda).
expr2(symbol(_)).
然后使用freeze/2再次出现一个查找谓词,
等待环境列表

lookup(S, E, R) :- freeze(E, lookup2(S, E, R)).

lookup2(S, [S-T|_], R) :-
   unify_with_occurs_check(T, R).
lookup2(S, [T-_|E], R) :-
   dif(S, T),
   lookup(S, E, R).
最后是使用DCG编码的计算器,
要限制con和apply调用的总数,请执行以下操作:

eval([quote,X], _, X) --> [].
eval([], _, []) --> [].
eval([cons,X,Y], E, [A|B]) -->
   step,
   eval(X, E, A),
   eval(Y, E, B).
eval([lambda,symbol(X),B], E, closure(X,B,E)) --> [].
eval([X,Y], E, R) -->
   step,
   eval(X, E, closure(Z,B,F)),
   eval(Y, E, A),
   eval(B, [Z-A|F], R).
eval(symbol(S), E, R) -->
   {lookup(S, E, R)}.

step, [C] --> [D], {D > 0, C is D-1}.
quine(Q, M, N) :-
   expr(Q),
   between(0, M, N),
   eval(Q, [], P, [N], _),
   unify_with_occurs_check(Q, P).
主谓词逐渐增加允许的数量
cons和apply调用:

eval([quote,X], _, X) --> [].
eval([], _, []) --> [].
eval([cons,X,Y], E, [A|B]) -->
   step,
   eval(X, E, A),
   eval(Y, E, B).
eval([lambda,symbol(X),B], E, closure(X,B,E)) --> [].
eval([X,Y], E, R) -->
   step,
   eval(X, E, closure(Z,B,F)),
   eval(Y, E, A),
   eval(B, [Z-A|F], R).
eval(symbol(S), E, R) -->
   {lookup(S, E, R)}.

step, [C] --> [D], {D > 0, C is D-1}.
quine(Q, M, N) :-
   expr(Q),
   between(0, M, N),
   eval(Q, [], P, [N], _),
   unify_with_occurs_check(Q, P).
这个查询显示5个cons和apply调用足以生成一个Quine。在SICStus Prolog和Jekejeke Prolog中工作。对于SWI Prolog,需要使用以下解决方法:

?- dif(Q, []), quine(Q, 6, N).
Q = [[lambda, symbol(_Q), [cons, symbol(_Q), [cons, [cons, 
[quote, quote], [cons, symbol(_Q), [quote, []]]], [quote, 
[]]]]], [quote, [lambda, symbol(_Q), [cons, symbol(_Q), [cons, 
[cons, [quote, quote], [cons, symbol(_Q), [quote, []]]], 
[quote, []]]]]]],
N = 5 
我们可以手动验证它确实是一种非平凡的奎因:

?- Q = [[lambda, symbol(_Q), [cons, symbol(_Q), [cons, [cons, 
[quote, quote], [cons, symbol(_Q), [quote, []]]], [quote, 
[]]]]], [quote, [lambda, symbol(_Q), [cons, symbol(_Q), [cons, 
[cons, [quote, quote], [cons, symbol(_Q), [quote, []]]], 
[quote, []]]]]]], eval(Q, [], P, [5], _).
Q = [[lambda, symbol(_Q), [cons, symbol(_Q), [cons, [cons, 
[quote, quote], [cons, symbol(_Q), [quote, []]]], [quote, 
[]]]]], [quote, [lambda, symbol(_Q), [cons, symbol(_Q), [cons, 
[cons, [quote, quote], [cons, symbol(_Q), [quote, []]]], 
[quote, []]]]]]],
P = [[lambda, symbol(_Q), [cons, symbol(_Q), [cons, [cons, 
[quote, quote], [cons, symbol(_Q), [quote, []]]], [quote, 
[]]]]], [quote, [lambda, symbol(_Q), [cons, symbol(_Q), [cons, 
[cons, [quote, quote], [cons, symbol(_Q), [quote, []]]], 
[quote, []]]]]]] 

有人可能会问,occurs检查标志是否优于 在检查/2时,会显式地将\u与\u统一。与 explicit unified_with_occurses_check/2我们在lookup2/3和quine/3中放置了一个这样的调用。如果我们使用 选中标志,我们不需要手动拨打此类电话 可以依赖Prolog解释器的动态

我们在lookup2/3中删除了显式unify_与_occurs_check/2:

lookup2(S, [S-T|_], T).
lookup2(S, [T-_|E], R) :-
   dif(S, T),
   lookup(S, E, R).
在奎因/3中,使其生成和测试更少,以及 更多约束逻辑,如。使用同一变量Q两次 行为类似于推入执行的约束:

quine(Q, M, N) :-
   expr(Q),
   between(0, M, N),
   eval(Q, [], Q, [N], _).
以下是新的SWI Prolog 8.3.17的一些结果 已将其unify\u与\u发生\u检查/2修复为gether with 发生检查标志已修复:

/* explicit unify_with_occurs_check/2 */
?- time((dif(Q, []), quine(Q, 6, N))).
% 208,612,270 inferences, 11.344 CPU in 11.332 seconds (100% CPU, 18390062 Lips)

/* occurs_check=true */
?- time((dif(Q, []), quine(Q, 6, N))).
% 48,502,916 inferences, 2.859 CPU in 2.859 seconds (100% CPU, 16962768 Lips)
以及即将推出的Jekejeke Prolog 1.4.7的预览版, 它还将具有一个发生检查标志:

/* explicit unify_with_occurs_check/2 */
?- time((dif(Q, []), quine(Q, 6, N))).
% Up 37,988 ms, GC 334 ms, Threads 37,625 ms (Current 01/10/21 01:29:35)

/* occurs_check=true */
?- time((dif(Q, []), quine(Q, 6, N))).
% Up 13,367 ms, GC 99 ms, Threads 13,235 ms (Current 01/10/21 01:35:24)
非常令人惊讶的是,在两个Prolog系统中,occurs检查标志可以导致3倍的加速!结果可能表明我们显式放置unify_与_-ocurses_-check/2的方式有问题

顺便说一句:开源:

通过关系解释器生成奎因 显式统一\u与\u发生\u检查/2

通过关系解释器生成奎因 发生\u检查=真

bfs在理论上也应该有问题,如果在某个节点上有无限分支。相反,需要采用某种对角化方法。@Mostowski,我不这么认为。我在
.swiplrc
中将OC设置为
true
。BFS Prolog引擎是这里需要的
evil(X,Y)
说“创建所有可能的输入/输出对”--这在非常短的程序之外是不可行的。@MaxB此方案没有
cons
。是否存在不需要
cons
的(小型)方案奎因?如果没有,那么再多的调整搜索也不会让你有任何进展。@IsabelleNewbie谢谢!添加了
cons
。如果
使用深度限制(邪恶(X,X),6,R)调用,我将进行编辑。
找到任何东西--它仍在运行。我的版本不处理
(lambda X
,仅
。(lambda(X)
。我不知道这是允许的。但是
((lambda X)(cons X)(cons(cons)(cons)(cons)(cons X)(quote()))(quote)()(quote)())lambda X(cons)(cons X)(cons X)(cons)(cons X)(cons)(cons X)(cons)(cons)(cons)())事实上,它并不是一种奎因。它的值是
((lambda…
)三个参数。这种奎因似乎不是真的:
((lambda x)(cons)(cons)(cons)(cons)(cons)(cons)(cons)(quote)(cons)(cons x)(quote())(quote)(lambda x)(cons)(cons)(cons)(cons)(cons)(cons)(cons)(cons)(cons)(cons)(cons)(cons)(quote))))((
)注意参数的数量。
(lambda(x).
(lambda x
)不同。事实证明,这两个参数在方案中都是允许的。
/* explicit unify_with_occurs_check/2 */
?- time((dif(Q, []), quine(Q, 6, N))).
% Up 37,988 ms, GC 334 ms, Threads 37,625 ms (Current 01/10/21 01:29:35)

/* occurs_check=true */
?- time((dif(Q, []), quine(Q, 6, N))).
% Up 13,367 ms, GC 99 ms, Threads 13,235 ms (Current 01/10/21 01:35:24)