到目前为止,我一直坚持 Prolog程序意味着:
如果对于一个查询
Q,有一个subtermS,使得存在一个术语T,使?- S=T, Q.成功虽然?- Q, S=T.失败,然后通过调用一个谓词Q是不踏实.
直觉上,我因此坚定地表示我们不能使用实例化来"欺骗"谓词来提供解决方案,否则这些解决方案不仅不会被给予,而是被拒绝.注意非终止程序的区别!
特别是,至少在我看来,逻辑纯度总是意味着坚定不移.
例子.为了更好地理解坚定性的概念,考虑这个属性的几乎经典的反例,在将高级学生引入Prolog的操作方面时经常引用,使用两个整数之间关系的错误定义及其最大值:
integer_integer_maximum(X, Y, Y) :-
Y >= X,
!.
integer_integer_maximum(X, _, X).
这个中的一个明显错误 - 我们应该说" 摇摆不定 " - 定义当然是以下查询错误地成功:
?- M = 0, integer_integer_maximum(0, 1, M). M = 0. % wrong!
而交换目标产生了正确的答案:
?- integer_integer_maximum(0, 1, M), M = 0. false.
这个问题的一个很好的解决方案是依靠 …
如果Min是标准术语中最小的成员,则为True.如果List为空,则失败.
?- min_member(3, [1,2,X]).
X = 3.
Run Code Online (Sandbox Code Playgroud)
解释当然是变量在标准的术语顺序中位于所有其他术语之前,并且使用统一.但是,报告的解决方案感觉有些不对劲.
怎么可以说是合理的?我该如何解释这个解决方案?
编辑:
防止min_member/2成功使用此解决方案的一种方法是更改标准库(SWI-Prolog)实现,如下所示:
xmin_member(Min, [H|T]) :-
xmin_member_(T, H, Min).
xmin_member_([], Min0, Min) :-
( var(Min0), nonvar(Min)
-> fail
; Min = Min0
).
xmin_member_([H|T], Min0, Min) :-
( H @>= Min0
-> xmin_member_(T, Min0, Min)
; xmin_member_(T, H, Min)
).
Run Code Online (Sandbox Code Playgroud)
失败而不是抛出实例化错误(@mat在他的回答中建议,如果我理解正确的话)的理由是,这是一个明确的问题:
" [1,2,X]当X是自由变量时,3是最小成员吗?"
对此的答案是(至少对我来说)一个明确的"不",而不是"我无法说出来".
这与以下行为属于同一类sort/2:
?- sort([A,B,C], [3,1,2]).
A = 3,
B = 1,
C = 2.
Run Code Online (Sandbox Code Playgroud)
适用相同的技巧:
?- …Run Code Online (Sandbox Code Playgroud) 嘿伙计们我这学期正在学习人工智能课程,我们正在学习Prolog.我们的讲师告诉我们尽量避免在我们的任务中使用削减,但是,对于我似乎无法避免使用它们的几个问题.我只是好奇为什么削减被认为是罪(讲师的话)?我知道这是一种捷径,但我已经习惯了解它们如何影响我的节目.
谢谢.
我一直反对这一点,我无法确定攻击它的方法.以下是处理一些季节事实的两种方法.
我想弄清楚的是,是否使用方法1或方法2,以及每种方法的利弊是什么,特别是大量的事实.
methodone因为事实是可用的,所以似乎很浪费,为什么还要建立一个列表(特别是一个大的列表).如果列表足够大,这也必须有内存含义吗?它没有利用Prolog的自然回溯功能.
methodtwo利用回溯来为我做递归,我猜想会有更多的内存效率,但是通常这样做是不是很好的编程习惯呢?这可以说是更难以理解,可能还有其他副作用吗?
我可以看到的一个问题是每次fail调用时,我们都失去了将任何东西传递回调用谓词的能力,例如.如果是的话methodtwo(SeasonResults),因为我们故意不断地破坏谓词.所以methodtwo需要断言事实来存储状态.
大概(?)方法2会更快,因为它没有(大)列表处理吗?
我可以想象,如果我有一个清单,那么methodone将是要走的路......还是总是如此?在任何情况下都可以将列表声明为事实,methodone然后使用方法二处理它们?完全疯了吗?
但话说回来,我读到断言事实是一项非常"昂贵"的业务,所以列表处理可能是要走的路,即使是大型列表?
有什么想法吗?或者有时候使用一个而不是另一个更好,这取决于(什么)情况?例如.对于内存优化,使用方法2,包括断言事实,以及速度使用方法1?
season(spring).
season(summer).
season(autumn).
season(winter).
% Season handling
showseason(Season) :-
atom_length(Season, LenSeason),
write('Season Length is '), write(LenSeason), nl.
% -------------------------------------------------------------
% Method 1 - Findall facts/iterate through the list and process each
%--------------------------------------------------------------
% Iterate manually through a season list
lenseason([]).
lenseason([Season|MoreSeasons]) :-
showseason(Season),
lenseason(MoreSeasons).
% Findall to build a list then iterate until all done
methodone :-
findall(Season, season(Season), …Run Code Online (Sandbox Code Playgroud) 我试图了解Prolog的工作原理.我正在使用SWI-Prolog.这是一些代码:
forall(C1,C2) :- \+ (C1, \+ C2).
foo(N) :- N < 10.
bar(N) :- N > 5.
foobar(N) :- forall(foo(N),bar(N)).
Run Code Online (Sandbox Code Playgroud)
如果我执行以下操作,它会产生所需的输出:
?- foobar(5).
false.
Run Code Online (Sandbox Code Playgroud)
但是当我试图看到所有可能的值时,我得到一个错误:
?- foobar(N).
ERROR: </2: Arguments are not sufficiently instantiated
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?
我正在为大学考试学习 Prolog,但我在这个练习中遇到了问题:
not_member(X,L)如果元素X不属于列表,则实现为 TRUE的谓词L。
如果我的推理是正确的,我已经找到了解决方案:
% FACT (BASE CASE): It is TRUE that X is not in the list if the list is empty.
not_member(_,[]).
% RULE (GENERAL CASE): If the list is non-empty, I can divide it in its Head
% element and the sublist Tail. X does not belong to the list if it is different
% from the current Head element and if it does not belong to the sublist Tail.
not_member(X,[Head|Tail]) …Run Code Online (Sandbox Code Playgroud) 我的代码运行但问题是它不止一次显示相同的结果.这是我的代码:
disease(hiv,[sore_throat,headache,fever,rash]).
disease(pregnancy,[fatigue,vomiting,light_headedness,increased_waistline]).
disease(flu,[fatigue,fever,tiredness,nasal_discharge]).
diagnose([], []).
diagnose(Name, [H|T]) :-
disease(The_Disease, Symptoms),
member(H, Symptoms),
write(Name), write(' has/is '), writeln(The_Disease),
diagnose(Name, T).
member(X,[X|_]).
member(X,[_|T]):-
member(X,T).
Run Code Online (Sandbox Code Playgroud)
在prolog中执行时的结果:
?- diagnose(kevin,[sore_throat,fatigue,tiredness,rash]).
kevin has/is hiv
kevin has/is pregnancy
kevin has/is flu
kevin has/is hiv
kevin has/is flu
kevin has/is flu
kevin has/is hiv
false.
Run Code Online (Sandbox Code Playgroud)
我该如何避免同样的结果?我尝试使用我在这里找到的其他方法:
filter_doubles([], []).
filter_doubles([X|L], Result) :-
(memberchk(X,L) ->
filter_doubles(L, Result)
;
filter_doubles(L, Result0),
Result = [X|Result0]
).
Run Code Online (Sandbox Code Playgroud)
但是我没能将它应用到我的代码中.请帮忙.