我开始学习Prolog,并首先了解了继承符号.
这就是我在Prolog中发现编写Peano公理的地方.
参见PDF的第12页:
sum(0, M, M).
sum(s(N), M, s(K)) :-
sum(N,M,K).
prod(0,M,0).
prod(s(N), M, P) :-
prod(N,M,K),
sum(K,M,P).
Run Code Online (Sandbox Code Playgroud)
我把乘法规则放到了Prolog中.然后我做查询:
?- prod(X,Y,s(s(s(s(s(s(0))))))).
Run Code Online (Sandbox Code Playgroud)
这意味着基本上找到6的因子.
结果如下.
X = s(0),
Y = s(s(s(s(s(s(0)))))) ? ;
X = s(s(0)),
Y = s(s(s(0))) ? ;
X = s(s(s(0))),
Y = s(s(0)) ? ;
infinite loop
Run Code Online (Sandbox Code Playgroud)
这个结果有两个问题:
所以...我的问题是:
我在无限循环中阅读了另一个答案.但我很感激有人根据这个场景做出回答.这对我很有帮助.
prolog infinite-loop successor-arithmetics non-termination failure-slice
假设我们有以下谓词(这是Prolog中编程的一个例子):
[F0] isInteger(0).
[F1] isInteger(X):- isInteger(Y), X is Y+1.
Run Code Online (Sandbox Code Playgroud)
查询的第一个结果是Integer(R),标记位于F0,并返回R = 0
如果用户按下; ,标记放在F1,我们移动到subgoal(isInteger(Y),满足F0)和R = 1.
我理解上面的内容.现在我的问题是:
我正在寻找任何解释存在递归的回溯的教程,希望能够帮助我理解堆栈内容的图像.
提前谢谢Suzanne
我想编写一个Prolog程序来查找两个列表的相等性,其中元素的顺序
无关紧要.所以我写了以下内容:
del(_, [], []) .
del(X, [X|T], T).
del(X, [H|T], [H|T1]) :-
X \= H,
del(X, T, T1).
member(X, [X|_]).
member(X, [_|T]) :-
member(X, T).
equal([], []).
equal([X], [X]).
equal([H1|T], L2) :-
member(H1, L2),
del(H1, L2, L3),
equal(T, L3).
Run Code Online (Sandbox Code Playgroud)
但是当我提供输入时equal([1,2,3],X).,它并没有显示所有可能的值X.相反,程序挂在中间.可能是什么原因?
有什么设计启发式的人必须掌握好写Prolog?我听说需要一名经验丰富的程序员大约两年才能熟练掌握Prolog.有效地使用递归是其中的一部分,但这似乎是一个相对较小的障碍.究竟是什么给程序员带来了这么多麻烦?我应该在示例代码中寻找什么来判断其质量?
我有以下prolog代码片段:
num(0).
num(X) :- num(X1), X is X1 + 1.
fact(0,1) :-!.
fact(X,Y) :- X1 is X-1, fact(X1,Y1), !, Y is Y1 * X.
fact(X) :- num(Y), fact(Y,X).
Run Code Online (Sandbox Code Playgroud)
有人可以解释为什么以下命令导致堆栈溢出?提前致谢.
fact(6).
Run Code Online (Sandbox Code Playgroud) 假设以下程序:
nat(0).
nat(s(N)) :- nat(N).
/* 0+b=b */
plus(0,B,B) :- nat(B).
/* (a+1)+b = c iff a+(b+1)=c */
plus(s(A),B,C) :- plus(A,s(B),C).
Run Code Online (Sandbox Code Playgroud)
它适用于添加两个数字,但是当我尝试查询以下类型时:
plus(Z,Z,s(0)).
Run Code Online (Sandbox Code Playgroud)
它继续搜索可能的值Z很长时间后应该很明显没有解决方案(即Z>s(0))
我熟悉cut(!)运算符,我的直觉说解决方案与它有关,我只是不确定如何在这种情况下使用它.
prolog logic-programming backtracking successor-arithmetics failure-slice
我想检查元素是否在列表中间.我搜索中间元素然后我检查是否是列表的成员,但我得到无限循环.
我的谓词:
remove_first([_,H1|T], [H1|T]).
remove_last([_],[]).
remove_last([H|T], [H|T2]) :- remove_last(T, T2).
remove_first_and_last([X],[X]).
remove_first_and_last(In, Out) :-
remove_first(In, Out1),
remove_last(Out1, Out).
middle([X], [X]).
middle(In, X) :-
remove_first_and_last(In, Out),
middle(Out, X).
member(X, [X|_]).
member(X, [_|T]) :- member(X, T).
is_middle(X, In) :-
middle(In, Out),
member(X, Out), !.
Run Code Online (Sandbox Code Playgroud)
当我打电话is_middle(1,[2,1,3])然后我就变成了现实.但是当我打电话给is_middle(1,[2,2,3])我时,我没有得到结果.解释器不会中断处理.
我正在尝试进行正则表达式匹配.我已经写出了所有的功能,但是他们没有按照他们的意愿工作.据我所知,当我尝试比较列表时,它有一个问题.
例如,"re_contains(a,a)." 给出真实(显然),"re_contains(union(a,b),a)".
但是,只要我将其列为清单,它就会失败."re_contains(seq(a,b),[a,b])." 返回false.附加应该通过所有可能的组合来查找匹配,但这些功能都不能正常工作.这让我觉得我可能错过了一个基本案例.但我认为"re_contains(X,L): - X == L." 应该照顾它.我必须在这里寻找重要的东西.
这是我的代码:
re_contains(empty, []).
re_contains(X, L) :-
X == L.
re_contains(seq(X, Y), L) :-
append(L1, L2, L),
re_contains(X, L1),
re_contains(Y, L2).
re_contains(union(X, _), L) :-
re_contains(X, L).
re_contains(union(_, Y), L) :-
re_contains(Y, L).
re_contains(kleene(X), L) :-
append([Car|L1], L2, L),
re_contains(X, [Car|L1]),
re_contains(kleene(X), L2).
re_contains(kleene(_),[]).
Run Code Online (Sandbox Code Playgroud) 我想用DCG作为发电机.截至目前,语法是
s-->a,b.
a-->[].
a-->a,c.
c-->[t1].
c-->[t2].
b-->[t3].
b-->[t4].
Run Code Online (Sandbox Code Playgroud)
我想生成所有s地方的长度a是< someNumber.
使用?- phrase(a,X),length(X,Y),Y<4.i可以获得 a少于4项的所有内容.但是,当所有组合都用尽时,系统(SWI-Prolog 6.2.5)似乎停滞不前.有时候,这里也提出了类似的问题.但是,作为Prolog的新手,我无法使用上面的语法.有任何想法吗?
更新:(canrememberthename)有一个评论被删除,不知何故.无论如何,有人建议between(1,4,Y),length(X,Y),phrase(a,X).用来设定限制.将代码更改为后,这很有效a-->c,a.
(让我在中期问题的浪潮中偷偷摸摸.)
两个自然数之和的通用定义是nat_nat_sum/3:
nat_nat_sum(0, N, N).
nat_nat_sum(s(M), N, s(O)) :-
nat_nat_sum(M, N, O).
Run Code Online (Sandbox Code Playgroud)
严格来说,这个定义过于笼统,因为我们现在也取得了成功
?- nat_nat_sum(A, B, unnatural_number).
Run Code Online (Sandbox Code Playgroud)
同样,我们得到以下答案替代:
?- nat_nat_sum(0, A, B).
A = B.
Run Code Online (Sandbox Code Playgroud)
我们将此答案替换解释为包括所有自然数,而不关心其他术语.
鉴于此,现在让我们考虑它的终止属性.实际上,考虑以下故障切片就足够了.也就是说nat_nat_sum/3,如果此切片未终止,则不仅不会终止.这次他们完全一样!所以我们可以说iff.
nat_nat_sum(0, N, N) :- false. nat_nat_sum(s(M), N, s(O)) :- nat_nat_sum(M, N, O), false.
这个失败切片现在暴露了第一个和第三个参数之间的对称性:它们都以完全相同的方式影响非终止!因此,虽然他们描述了完全不同的东西 - 一个是加数,另一个是和 - 它们对终止具有完全相同的影响.可怜的第二个论点没有任何影响.
可以肯定的是,不仅故障片在其读取的公共终止条件(使用cTI)中是相同的
nat_nat_sum(A,B,C)terminates_if b(A);b(C).
Run Code Online (Sandbox Code Playgroud)
对于那些未被这种情况覆盖的情况,它也会完全相同,例如
?- nat_nat_sum(f(X),Y,Z).
Run Code Online (Sandbox Code Playgroud)
现在我的问题:
是否有另一个定义
nat_nat_sum/3具有终止条件:Run Code Online (Sandbox Code Playgroud)nat_nat_sum2(A,B,C) terminates_if b(A);b(B);b(C).(如果是,请显示.如果不是,请说明理由)
换句话说,如果新定义的一个参数是有限的和基础的,则新定义nat_nat_sum2/3应该终止.
细则.只考虑纯粹的,单调的Prolog程序.也就是说,除了(=)/2和之外没有内置插件 …