如果比较回溯,我希望以下内容应该始终为真,对吧?除非它进入无限循环!
?- Y=2 , random:random(1,3,X), X =\= Y.
Y = 2,
X = 1.
?- Y=2 , random:random(1,3,X), X =\= Y.
false.
但我弄错了! 一般来说,我的问题是为什么不比较回溯?
感谢所有答案。我的困惑似乎主要来自于我对随机保持产生新随机数的期望,所以我觉得比较不是回溯,相反,原因是随机只做一次它然后失败。 我不知道某些谓词的半确定性。 但现在我可以留意了;)这样的情况。再次感谢。
答案 0 :(得分:5)
在您的示例中,无需回溯。
您在这些示例中使用的所有谓词((=)/2
,random/3
和(=\=)/2
)都是半确定性:这意味着他们要么失败,或完全一次。
换句话说,他们最多只能成功。。
因此,如果这些谓词中至少有一个失败,则查询失败。
要在回溯时生成一系列伪随机数,请使用例如repeat/0
。
警告:random/3
是不纯的谓词:即使查询完全相同,它也可能会产生不同的解决方案。它可能导致一次调用失败,另一次调用导致成功。这使得代码的测试和推理变得相当复杂。
答案 1 :(得分:1)
我认为这会有所帮助。
% Generate random value from Min to Max(with backtrack)
rand_backtrack(Min,Max,RandVal):-
create_list(Min,Max,List),
randomize_list(List,Randomized),
length(Randomized,Len),
% Choose one Variable from Randomized (From first element to last).
% When backtrack occured, next element is chosen.
between(1,Len,Idx),
nth1(Idx,Randomized,RandVal).
% create integer order list
% [Min,Min+1,Min+2,....,Max]
create_list(Max,Max,[Max]):-!.
create_list(Min,Max,[Min|Rest]):-
Min1 is Min+1,
create_list(Min1,Max,Rest).
% shuffle List.
% result always changes.
% ex.randomize_list([1,2,3,4,5,6],R) R=[4,2,6,1,3,5]
%
randomize_list([Val],[Val]):-!.
randomize_list(List,[RandVal|RestRandomized]):-
length(List,Len),
random(1,Len,RandIdx),
nth1(RandIdx,List,RandVal),
select(RandVal, List, Rest),
!,
randomize_list(Rest,RestRandomized).
?- rand_backtrack(3,19,A).
A = 6 ;
A = 4 ;
A = 8 ;
A = 13 ;
A = 15 ;
A = 16 ;
A = 9 ;
A = 18 ;
A = 7 ;
A = 3 ;
A = 12 ;
A = 10 ;
A = 17 ;
A = 11 ;
A = 14 ;
A = 5 ;
A = 19.
答案 2 :(得分:1)
Prolog适用于所谓的Horn-clauses。这意味着单独的每个术语,例如Y=2
,是要回答的问题中的单独目标。每个目标的结果是“是”或“否”,如果所有目标都回答“是”,则回答“是”。
您的代码要求如下:
%Is Y equal to 2 or can it be made equal?
%Yes, Y is a variable and can be assigned the numerical atom 2
Y=2 ,
%Give me a random number between 1 and 3.
%Is X equal to the random number or can it be made equal?
%Yes, X is a variable and can be assigned the outcome atom of random:random
random:random(1,3,X),
%is the term contained within X NOT equivalent to Y?
X =\= Y.
您可以查看现有的比较谓词,例如SWI documentation或Learn Prolog Now!。
根据您的实现,您可以使用trace
和write
输出变量中的实际原子,以便了解程序的实际工作方式。
?- trace, (Y=2 , random:random(1,3,X), write(X),nl, X =\= Y). %SWI-Prolog
无限递归看起来像p(P) :- p(P).
。它调用了它应该在答案本身内解决的问题,意味着解决p(P)
它会检查p(P)
,它永远不会结束。
仅当Prolog有选择点时才会发生回溯。选择点是决策树中的点,有多种可能的方式来满足Prolog当前正在处理的问题。 Prolog从上到下,然后从左到右工作。
想想一位被问到“哪辆车最适合我?”的汽车推销员。他有多辆可能的车可以卖给你,所以他会开始向你展示符合你标准的不同车型。汽车需要的运输能力超过400升?所有不满足此条件的汽车都不是解决方案。
Prolog执行深度优先搜索,这意味着它会找到它找到的第一个答案,然后检查是否有其他方法来回答它。如果没有结果,答案是否定的。如果至少有一个解决方案,答案是肯定的,您可以获得所有问题的答案。这样,您只能获得满足您设定的整个目标链的结果。