解决 Prolog 中的相互递归约束

Solving mutually recursive constraints in Prolog

我正在尝试使用 SWI-Prolog 解决一些相互递归的约束。这些约束相对简单,但是查询这些谓词中的任何一个都会导致无限递归:

%If X is an animal, then X is a bird or a mammal, and vice-versa.
animal(X) :- 
    (mammal(X);bird(X)),
    (male(X);female(X)).

male(X) :- animal(X).
female(X) :- animal(X).

bird(X) :- (X='parrot';X='pigeon'),animal(X).

mammal(X) :- (X='cat';X='dog'),animal(X).

是否可以在不使它们成为非递归的情况下在 Prolog 中解决这些约束?

我用几个基本案例写了一个类似的程序,但是查询 mammal(X),bird(X) 仍然导致无限递归而不是返回 false:

%If X is an animal, then X is a bird or a mammal, and vice-versa.
animal(X) :- 
    (mammal(X);bird(X)).

bird('parrot').
bird('pigeon').
bird(X) :- (X='parrot';X='pigeon'),animal(X).

mammal('cat').
mammal('dog').
mammal(X) :- (X='cat';X='dog'),animal(X).

解决递归约束需要一个或多个基本情况;你还没有提供任何。问题不在于 Prolog;它与问题定义。

我认为你想表达的意思是你有鸟类和哺乳动物。如果一个生物是鸟类或哺乳动物,那么你进一步试图确定它是动物。

目前代码过度规范,存在循环逻辑。

遍历代码...

animal(X) :- 
    (mammal(X); bird(X)).

这表示 Xanimal if XmammalXbird。到目前为止,还不错。

bird 的描述如下:

bird('parrot').
bird('pigeon').

这些事实表明 parrotbirdpigeonbird。但是还有这个规则:

bird(X) :- (X='parrot';X='pigeon'),animal(X).

也就是说 Xbird if Xparrotpigeon,如果 Xanimal。前面的两个事实已经确定 parrotpigeon 是鸟。为什么这个规则是必要的?并且它进一步添加了 X 是一个 animal 的条件,这又是根据 birdmammal 定义的,因此是循环的。

mammal 定义也是如此。它具有哺乳动物所需的事实:

mammal('cat').
mammal('dog').

然后用循环逻辑多指定

mammal(X) :- (X='cat';X='dog'), animal(X).

你需要的本质很简单:

bird('parrot').
bird('pigeon').

mammal('cat').
mammal('dog').

animal(X) :- 
    mammal(X); bird(X).

此逻辑使用事实定义了哪些生物是鸟类或哺乳动物,然后提供了一条规则,说明如果已知某个生物是鸟类或哺乳动物,那么它就是动物。

此类问题的一个解决方案是简单地启用您的 Prolog 系统的 制表 机制。

例如,在 SWI-Prolog(最新开发版本)中,如果我只是在程序的开头添加以下指令:

:- use_module(library(tabling)).

:- table animal/1.

然后我得到例如:

?- animal(X).
false.

?- male(X).
false.

?- bird(X).
false.

所以,在这些情况下,我们仍然没有找到任何解决方案,但至少我们得到了答案。

可以使用constraint handling rules找到相互递归约束的解决方案。

这是一组相互递归的约束:

%If X is an animal, then X is a bird or a mammal, and vice-versa.
:- use_module(library(chr)).

:- chr_constraint mammal/2,bird/2,animal/1,male/1,female/1,species/2.

animal(X) <=> 
    (mammal(X,Species);bird(X,Species)),
    (male(X);female(X)).

male(X),female(X) ==> false.

bird(X,Species) <=> member(Species,[parrot,pigeon,crow]),species(X,Species).
bird(X,Species) ==> animal(X).

mammal(X,Species) <=> member(Species,[cat,dog,bull]),species(X,Species).
mammal(X,Species) ==> animal(X).

species(X,bull) ==> male(X).

...这是该程序的查询输出:

?- male(X),mammal(X,Species).
male(_G67406)
species(_G67406,cat)
Species = cat