有没有办法做尺寸比较?

时间:2018-12-06 14:51:03

标签: prolog

我最近发现了Prolog语言,并一直在进行基础练习。我目前正在建立有关mammalsbirdsreptiles等动物类的数据库,我想通过在动物内部进行大小比较来扩展数据库,但不确定如何做。

这是我的数据库。

warm_blooded(bat).
warm_blooded(penguin).

cold_blooded(crocodile).

has_fur(bat).

has_feathers(penguin).

has_scales(crocodile).

gives_birth_live(bat).

lays_eggs(penguin).
lays_eggs(crocodile).

produces_milk(bat).

has_lungs(crocodile).
has_lungs(bat).
has_lungs(penguin).


%% if the being belongs to the mammalai class ,mammalia being the scientific word for mammal
mammalia(X) :-  
    warm_blooded(X),
    produces_milk(X), 
    (
        has_fur(X)
    ;
        gives_birth_live(X)
    ),
    format('~w ~s mammal ~n', [X, "is a"]).

 %% if the being belongs to the aves class aves being the scientific word for bird
 aves(X) :- 
    warm_blooded(X), 
    has_feathers(X), 
    lays_eggs(X), 
    has_lungs(X),
    format('~w ~s bird ~n', [X, "is a"]).

 %% if the being belongs to the reptillia class(reptillia being the scientific word for reptile

 reptillia(X) :- 
    cold_blooded(X), 
    lays_eggs(X), 
    has_scales(X), 
    has_lungs(X),
    format('~w ~s reptile ~n', [X, "is a"]).

我尝试在参数中添加大小,但一直收到编译错误。我想要一个输出,用户可以确定彼此比较时哪个动物更大。

1 个答案:

答案 0 :(得分:2)

一种简单有效的方法是将大小事实与每只动物相关联。

size(bat,1).
size(penguin,2).
size(crocodile,3).

然后添加一个带有两个子句的谓词,以选择两个动物中较大的一个。

larger(A,B,A) :-
    size(A,S1),
    size(B,S2),
    S1 > S2.

larger(A,B,B) :-
    size(A,S1),
    size(B,S2),
    S2 >= S1.

示例:

?- larger(penguin,crocodile,X).
X = crocodile.

?- larger(penguin,bat,X).
X = penguin ;
false.

?- larger(bat,bat,X).
X = bat.

请注意,对于第二个动物较小的示例,它将尝试第一个子句并成功,但是随后有一个选择点,因此尝试第二个子句并失败。这是纯解决方案。

如果您想通过切割来避免选择点不纯净,则可以执行以下操作

larger_2(A,B,A) :-
    size(A,S1),
    size(B,S2),
    S1 > S2,
    !.

larger_2(A,B,B) :-
    size(A,S1),
    size(B,S2),
    S2 >= S1,
    !.

示例:

?- larger_2(penguin,crocodile,X).
X = crocodile.

?- larger_2(penguin,bat,X).
X = penguin.

?- larger_2(bat,bat,X).
X = bat.

丹尼尔·里昂斯(Daniel Lyons)指出的另一种方法是使用->/2

larger_3(A,B,Larger) :-
    size(A,SA),
    size(B,SB),
    (
        SA > SB
    ->
        Larger = A
    ;
        Larger = B
    ).

此变体不仅仅是->/2的一个运算符,而是->/2;2的组合。

这也不会留下选择点,并且是不纯正的,因为它也使用剪切(!)。使用listing/1,我们可以在Prolog中看到实现。

?- listing('->'/2).
:- meta_predicate 0->0.

system:A->B :-
        call((   A
             ->  B
             )).

true.

?- listing(;/2).
:- meta_predicate 0;0.

system:A:B;A:C :- !,
        call(A:(B;C)).
system:A:B;C:D :-
        call(A:(B;C:D)).

true.

请注意削减!

SWI-Prolog documentation中指出了两个操作员如何协同工作。

The combination ;/2 and ->/2 acts as if defined as:

If -> Then; _Else :- If, !, Then.
If -> _Then; Else :- !, Else.
If -> Then :- If, !, Then.

关于->/2;/2一起使用的另一点要注意的是,许多Prolog程序员之间的语法布局是结合使用()和偏移运算符{{1 }}和->/2,以使;2脱颖而出。

;

当将( % condition -> % true ; % false ) 用作OR运算符并且不偏移;时,在对源代码进行快速扫描时通常会被忽略,因为它被视为逗号; ,

还要注意

之后没有;.
,

SA > SB

Larger = A

但是最后需要一个运算符,

Larger = B