标签: failure-slice

Prolog继承符号表示不完整的结果和无限循环

我开始学习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)

这个结果有两个问题:

  1. 并非所有结果都显示,请注意结果X = 6,Y = 1缺失.
  2. 它不会停止,除非我按Ctrl + C然后选择中止.

所以...我的问题是:

  1. 这是为什么?我尝试转换"prod"和"sum".结果代码给了我所有结果.再说一遍,为什么?它仍然是死循环.
  2. 如何解决?

我在无限循环中阅读了另一个答案.但我很感激有人根据这个场景做出回答.这对我很有帮助.

prolog infinite-loop successor-arithmetics non-termination failure-slice

41
推荐指数
2
解决办法
2855
查看次数

回溯递归谓词

假设我们有以下谓词(这是Prolog中编程的一个例子):

[F0] isInteger(0).
[F1] isInteger(X):- isInteger(Y), X is Y+1.
Run Code Online (Sandbox Code Playgroud)
  1. 查询的第一个结果是Integer(R),标记位于F0,并返回R = 0

  2. 如果用户按下; ,标记放在F1,我们移动到subgoal(isInteger(Y),满足F0)和R = 1.

我理解上面的内容.现在我的问题是:

  1. 如果用户按下; 再次,标记在哪里?搜索如何继续返回R = 2?我试图理解本书第78-79页中的图像,但我不清楚.我发现的在线教程不会在递归的情况下处理回溯.

我正在寻找任何解释存在递归的回溯的教程,希望能够帮助我理解堆栈内容的图像.

提前谢谢Suzanne

prolog failure-slice

9
推荐指数
1
解决办法
1443
查看次数

Prolog程序以任何顺序查找两个列表的相等性

我想编写一个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.相反,程序挂在中间.可能是什么原因?

list prolog any failure-slice

8
推荐指数
1
解决办法
1万
查看次数

好的Prolog代码的特点?

有什么设计启发式的人必须掌握好写Prolog?我听说需要一名经验丰富的程序员大约两年才能熟练掌握Prolog.有效地使用递归是其中的一部分,但这似乎是一个相对较小的障碍.究竟是什么给程序员带来了这么多麻烦?我应该在示例代码中寻找什么来判断其质量?

prolog failure-slice logical-purity

8
推荐指数
1
解决办法
920
查看次数

为什么这个命令导致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)

prolog failure-slice

7
推荐指数
1
解决办法
194
查看次数

如何阻止prolog无限地检查不可能的解决方案?

假设以下程序:

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

7
推荐指数
1
解决办法
596
查看次数

Prolog - 无限循环

我想检查元素是否在列表中间.我搜索中间元素然后我检查是否是列表的成员,但我得到无限循环.

我的谓词:

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])我时,我没有得到结果.解释器不会中断处理.

prolog failure-slice

7
推荐指数
3
解决办法
738
查看次数

正则表达式匹配Prolog

我正在尝试进行正则表达式匹配.我已经写出了所有的功能,但是他们没有按照他们的意愿工作.据我所知,当我尝试比较列表时,它有一个问题.
例如,"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)

regex prolog dcg failure-slice

6
推荐指数
2
解决办法
2569
查看次数

prolog dcg限制

我想用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.

prolog dcg failure-slice

6
推荐指数
2
解决办法
327
查看次数

更好地终止s(X)-sum

(让我在中期问题的浪潮中偷偷摸摸.)

两个自然数之和的通用定义是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具有终止条件:

nat_nat_sum2(A,B,C) terminates_if b(A);b(B);b(C).
Run Code Online (Sandbox Code Playgroud)

(如果是,请显示.如果不是,请说明理由)

换句话说,如果新定义的一个参数是有限的和基础的,则新定义nat_nat_sum2/3应该终止.


细则.只考虑纯粹的,单调的Prolog程序.也就是说,除了(=)/2和之外没有内置插件 …

termination prolog successor-arithmetics failure-slice

6
推荐指数
1
解决办法
342
查看次数