相关疑难解决方法(0)

坚定性:定义及其与逻辑纯度和终止的关系

到目前为止,我一直坚持 Prolog程序意味着:

如果对于一个查询Q,有一个subterm S,使得存在一个术语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.

这个问题的一个很好的解决方案是依靠 …

prolog non-termination logical-purity steadfastness

12
推荐指数
1
解决办法
296
查看次数

min_member/2的反直觉行为

min_member(-Min ,+ List)

如果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 min clpfd

10
推荐指数
3
解决办法
303
查看次数

编程中的削减是否有害?

嘿伙计们我这学期正在学习人工智能课程,我们正在学习Prolog.我们的讲师告诉我们尽量避免在我们的任务中使用削减,但是,对于我似乎无法避免使用它们的几个问题.我只是好奇为什么削减被认为是罪(讲师的话)?我知道这是一种捷径,但我已经习惯了解它们如何影响我的节目.

谢谢.

prolog prolog-cut

9
推荐指数
2
解决办法
423
查看次数

使用手动列表迭代与通过失败递归的优缺点是什么

我一直反对这一点,我无法确定攻击它的方法.以下是处理一些季节事实的两种方法.

我想弄清楚的是,是否使用方法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 prolog-dif prolog-toplevel

8
推荐指数
2
解决办法
2032
查看次数

Prolog - 参数未实例化

我试图了解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 clpfd

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

实现一个 Prolog 谓词,说明一个元素是否属于一个列表。非数字列表的问题

我正在为大学考试学习 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)

prolog prolog-dif

5
推荐指数
2
解决办法
7352
查看次数

Prolog递归跳过相同的结果

我的代码运行但问题是它不止一次显示相同的结果.这是我的代码:

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)

但是我没能将它应用到我的代码中.请帮忙.

recursion prolog prolog-setof

4
推荐指数
1
解决办法
878
查看次数