在 Prolog 中计算函子内部的函子

Evaluating functors inside a functor in Prolog

我正在阅读 John Stobo 的 Prolog solving with Prolog 一书。我已经学习了第 1 章(根据事实编程)和第 2 章(根据规则编程)现在我在第 3 章:R规则中的递归 我正在练习第 3.1 节中给出的程序。我已经对程序进行了一些阐述(没有改变主要结构)并添加了我自己的仿函数(或函数或规则?)命名为 is_rank_lower/2 但它没有按预期工作。

当我输入(或询问 Prolog)时

is_rank_lower(ryan, jondoe).

输出是

错误。

预期输出:true。

因为ryan是二等兵,jondoe是下士,二等兵的军衔低于下士。

解释在代码中。

问题 #1:如何使我自己的仿函数 is_lower_rank 按预期工作?

问题 #2:这个问题可能与本书有关,因为当我按原样写下程序时,它会稍微出错,这可能是我自己的原因仿函数也会错误地运行。只是猜测。

当我输入:

lower_rank(二等兵,下士)。

Prolog returns 和 true 并等待它,我必须在 true 后面放一个点然后单击 enter 然后才 return ?-提示。

预期输出为:

return 与 true. 然后 return 到 ?- 提示

作者好像在说这个问题。在第 57 页,他写道“如果目标失败,lower_rank 将不会终止”我已经应用了所有指令,但仿函数仍然不起作用。如何让它发挥作用?

我的序言版本swi-prolog 7.2.0

% John Stobo, problem solving with Prolog, March.1989

% FACTS:
next_degree(private, corporal). 
next_degree(corporal, sergeant).
next_degree(sergeant, lieutenant).
next_degree(lieutenant, captain).
next_degree(captain, major).
next_degree(major, "lieutenant colonel").
next_degree("lieutenant colonel", colonel).
next_degree(colonel, "brigadier general").
next_degree("brigadier general", "major general").
next_degree("major general","lieutenant general").
next_degree("lieutenant general", general).

soldier(ryan, private).
soldier(jondoe, corporal).
sooldier(smartson, captain).

% RULES:
lower_rank(R1, R2) :-
    next_degree(R1, R2).
 
lower_rank(R1, R2) :- % this works but if  
    next_degree(R1, R3), % the result is "true"
    lower_rank(R3, R2). % it doesn't end properly
% only if  the user types a dot, it ends properly

is_rank_lower(A1,A2) :-
    lower_rank(soldier(A1,X), soldier(A2,X)).
% doesn't work because the functors are inserted as
% 'soldier(ryan, _G1471), soldier(jondoe, _G1471))
% not as private, corporal, i.e. they are not evaluated

next_degree/2 似乎是一种奇怪的方法 - 书中建议它是明智的,还是作为不该做的例子?

https://swi-prolog.discourse.group/t/useful-prolog-references/1089

有不错的书

这个有效:

% First argument is an atom, hence single quotes in swi-prolog
rank_order(private, 1).
rank_order(corporal, 2).
rank_order(sergeant, 3).
rank_order(lieutenant, 4).
rank_order(captain, 5).
rank_order(major, 6).
rank_order('lieutenant colonel', 7).
rank_order(colonel, 8).
rank_order('brigadier general', 9).
rank_order('major general', 10).
rank_order('lieutenant general', 11).

soldier(ryan, private).
soldier(jondoe, corporal).
% Not mis-spelled as "sooldier"
soldier(smartson, captain).

rank_lower(RankLower, RankUpper) :-
    rank_order(RankLower, RankLowerOrder),
    rank_order(RankUpper, RankUpperOrder),
    RankLowerOrder < RankUpperOrder.

soldier_rank_lower(SoldierLower, SoldierUpper) :-
    soldier(SoldierLower, RankLower),
    soldier(SoldierUpper, RankUpper),
    rank_lower(RankLower, RankUpper).

结果 swi-prolog:

?- rank_lower(private, corporal).
true.

?- soldier_rank_lower(ryan, jondoe).
true.

?- soldier_rank_lower(L, U).
L = ryan,
U = jondoe ;
L = ryan,
U = smartson ;
L = jondoe,
U = smartson ;
false.

第二次尝试:

rank_next(private, corporal).
rank_next(corporal, sergeant).
rank_next(sergeant, lieutenant).
rank_next(lieutenant, captain).
rank_next(captain, major).
rank_next(major, 'lieutenant colonel').
rank_next('lieutenant colonel', colonel).
rank_next(colonel, 'brigadier general').
rank_next('brigadier general', 'major general').
rank_next('major general', 'lieutenant general').
rank_next('lieutenant general', general).

soldier(ryan, private).
soldier(jondoe, corporal).
soldier(smartson, captain).

rank_lower(RankLower, RankUpper) :-
    rank_next(RankLower, RankLower1),
    % Increase lower to eventually meet with upper
    (   RankLower1 = RankUpper ;
        rank_lower(RankLower1, RankUpper)
    ).

soldier_rank_lower(SoldierLower, SoldierUpper) :-
    soldier(SoldierLower, RankLower),
    soldier(SoldierUpper, RankUpper),
    % Won't have multiple answers
    once(rank_lower(RankLower, RankUpper)).

这使得以下内容具有确定性:

?- soldier_rank_lower(ryan, jondoe).
true.

...同时保持rank_lower/2的一般性,即:

?- findall(L-U, rank_lower(L, U), Pairs), length(Pairs, Len).
Pairs = [private-corporal,private-sergeant,private-lieutenant, ...
Len = 66.