gpt4 book ai didi

prolog - 使用 Prolog 在帧中实现推理的代码问题

转载 作者:行者123 更新时间:2023-12-01 03:18:42 24 4
gpt4 key购买 nike

这是从 Ivan Bratko 的书“Prolog Programming for人工智能 - 第 3 版 - 第 377 页”中获取的代码示例。它非常适合查询 ?-value(kiwi, active_at, night) .通过给出结果为 true .

但它也给出了 true 的结果用于查询 ?- value(kiwi, active_at, daylight).应该是 false .

我应该如何修改它,或者我错过了什么?

%--------Define frames
bird(a_kind_of, animal).
bird(active_at, daylight).

albatross(a_kind_of, bird).
albatross(colour, black).
albatross(size, 10).

kiwi(a_kind_of, bird).
kiwi(active_at, night).
kiwi(colour, brown).
kiwi(size, 24).

albert(instance_of, albatross).
albert(size, 10).

%--------Inference in Frames
value(Frame, Slot, Value):-
Query =.. [Frame, Slot, Value],
call(Query), !. %Value is directly retrieved
value(Frame, Slot, Value):-
parent(Frame, ParentName),
value(ParentName, Slot, Value). % More general rule

parent(Frame, ParentName):-
(Query =.. [Frame, a_kind_of, ParentName];
Query =.. [Frame, instance_of, ParentName]),
call(Query).

最佳答案

首先让我们来看看有问题的查询。您的第一个查询...

?- value(kiwi, active_at, night).
true.

... 成功执行 value/3 的第一条规则。如果您手动尝试目标,您可以看到这一点。查询...
?- Query =.. [kiwi, active_at, night].

... 成功并统一变量 Querykiwi(active_at, night) :
?- Query =.. [kiwi, active_at, night].
Query = kiwi(active_at, night).

下一个目标调用 Query ...
?- call(kiwi(active_at, night)).
true.

... 并且成功,因为你有一个事实 kiwi(active_at, night). .下一个目标 !防止 Prolog 回溯和搜索进一步的解决方案,因此查询 ?- value(kiwi, active_at, night).确定性地成功(您不必在第一个解决方案后按 ;)。现在让我们看看您的第二个查询...
?- value(kiwi, active_at, daylight).
true ;
false.

……那也成功了。 value/3 的第一条规则统一了 Querykiwi(active_at, daylight)并随后调用它:
?- call(kiwi(active_at, daylight)).
false.

此调用失败,因为您没有合适的事实。请注意,此时规则无法成功,因此 Prolog 不会为最后一个目标而烦恼,而是继续执行 value/3 的第二个规则。这里是第一个进球
?- parent(kiwi,ParentName).
ParentName = bird ;
false.

... 成功并正在统一 ParentNamebird由于析取的第一个参数......
?- Query =.. [kiwi, a_kind_of, ParentName].
Query = kiwi(a_kind_of, ParentName).

...以及随后在 parent/2 中的 call/1:
?- call(kiwi(a_kind_of, ParentName)).
ParentName = bird.

现在 value/3 的第二个规则的第二个目标调用自身,再次从第一个规则开始:
?- value(bird, active_at, daylight).
true.

这成功了,因此查询...
?- value(kiwi, active_at, daylight).
true

……也成功了。请注意,Prolog 在回答 true 后正在等待输入如果你按 ;它正在寻找进一步的解决方案:
?- value(kiwi, active_at, daylight).
true ;

虽然目标 value(bird, active_at, daylight)由于 value/3 的第一条规则的削减,确定性地成功,调用谓词的第一个目标 ( parent(kiwi,ParentName))(value/3 的第二条规则)留下了一个选择点打开(参见上面的查询)和现在 Prolog正在回溯以寻找其他解决方案。但是没有那么 Prolog 的答案:
?- value(kiwi, active_at, daylight).
true ;
false.

然而,如果你问猕猴桃什么时候活跃,Prolog 会回答:
?- value(kiwi, active_at, X).
X = night.

原因 daylight不是派生的,这里又是删减。在 X = night 的 value/3 的第一条规则成功后它阻止 Prolog 搜索其他解决方案。从逻辑的角度来看,这种行为是完全错误的:要么猕猴桃在白天和黑夜都活跃,那么最后一个查询应该产生两种解决方案,或者它们是夜间事件,然后查询 ?- value(kiwi, active_at, daylight).应该失败。我不想推测谓词 value/3 的预期行为,因此我将引用 Wikipedia entry on kiwi取而代之的是:猕猴桃很害羞,通常在夜间事件。它们大多是夜间习性,可能是食肉动物(包括人类)侵入栖息地的结果。在新西兰已经清除了引入的捕食者的地区,例如保护区,经常可以在白天看到猕猴桃。

如果您想同时拥有这两种解决方案,我建议添加一些事实 iscallable/1(不过不要将其称为 callable/1,因为已经有一个具有该名称的内置函数)涵盖您的事实,请将其添加到 value/3和 parent/2 并像这样删除剪切:
iscallable(bird).                                 % <- new fact
iscallable(albatross). % <- new fact
iscallable(kiwi). % <- new fact
iscallable(albert). % <- new fact

value(Frame, Slot, Value):-
iscallable(Frame), % <- new goal iscallable/1
Query =.. [Frame, Slot, Value],
call(Query). % <- removed cut here
value(Frame, Slot, Value):-
parent(Frame, ParentName),
value(ParentName, Slot, Value).

parent(Frame, ParentName):-
iscallable(Frame), % <- new goal iscallable/1
(Query =.. [Frame, a_kind_of, ParentName];
Query =.. [Frame, instance_of, ParentName]),
call(Query).

通过这些更改,您将始终获得两种解决方案:
?- value(kiwi, active_at,X).
X = night ;
X = daylight ;
false.

?- value(kiwi, active_at,night).
true ;
false.

?- value(kiwi, active_at,daylight).
true ;
false.

要了解为什么在 value/3 的规则 1 中需要类似 iscallable/1 的内容,请将其删除并考虑以下查询:
?- value(kiwi, active_at, X).
X = night ;
X = daylight ;
ERROR: value/3: Undefined procedure: animal/2
Exception: (9) animal(active_at, _G4462) ? creep
Exception: (8) value(animal, active_at, _G4462) ? creep

谓词值/3 试图调用不存在的谓词animal/2。要了解为什么在 parent/2 中需要类似 iscallable/1 的内容,请将其删除并考虑以下查询:
?- value(kiwi, active_at,X).
X = night ;
X = daylight ;
ERROR: parent/2: Undefined procedure: animal/2
Exception: (10) animal(a_kind_of, _G4558) ? creep

另一方面,如果您只选择夜间解决方案,您可以定义一个事实 nocturnalbird/2 来描述夜间事件并相应地更改事实 kiwi/2:
nocturnalbird(active_at, night).  % <- new fact

%kiwi(a_kind_of, bird). % <- remove fact
kiwi(a_kind_of, nocturnalbird). % <- new fact
%kiwi(active_at, night). % <- remove fact
kiwi(colour, brown).
kiwi(size, 24).

这会产生所需的结果:
?- value(kiwi, active_at,X).
X = night ;
false.

?- value(kiwi, active_at,night).
true ;
false.

?- value(kiwi, active_at,daylight).
false.

如果您计划扩展此示例以包括夜行鸟类的动物属性,则需要添加事实 nocturnalbird(a_kind_of, animal).以及在 value/3 和 parent/2 中包含 iscallable/1 像上面一样。

编辑:

事实上,正如@false 在评论中指出的那样,这里根本不需要 =../2 。您可以简单地使用 call/N 代替:
value(Frame, Slot, Value):-
iscallable(Frame),
call(Frame, Slot, Value). % <- here
value(Frame, Slot, Value):-
parent(Frame, ParentName),
value(ParentName, Slot, Value).

parent(Frame, ParentName):-
iscallable(Frame),
(call(Frame, a_kind_of, ParentName); % <- here
call(Frame, instance_of, ParentName)). % <- here

关于prolog - 使用 Prolog 在帧中实现推理的代码问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47468734/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com