解决Prolog中的相互递归约束

时间:2016-07-22 20:11:38

标签: recursion prolog constraint-programming

我试图用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).

4 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

可以使用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

答案 2 :(得分:2)

我认为你想要的是你有鸟类,你有哺乳动物。如果它是一只鸟或哺乳动物,你还在进一步试图确定一种动物是一种动物。

当前代码过度指定,并具有循环逻辑。

遍历代码......

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

这表示 Xanimal ,如果 XmammalX为{ {1}} 的。到目前为止,非常好。

bird的描述为:

bird

这些事实表明bird('parrot'). bird('pigeon'). parrotbirdpigeon。但接下来是这条规则:

bird

其中说 bird(X) :- (X='parrot';X='pigeon'),animal(X). X ,如果 birdXparrot,AND如果pigeonX 。前两个事实已经确定animalparrot是鸟类。为什么这个规则是必要的?它进一步增加了pigeonX的条件,而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).

这个逻辑使用事实来定义什么是鸟类或哺乳动物,然后提供一个规则,说明如果一个生物被认为是鸟类或哺乳动物,那么它就是动物。

答案 3 :(得分:2)

解决此类问题的一个方法是简单地启用Prolog系统的标签机制。

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

:- use_module(library(tabling)).

:- table animal/1.

然后我得到例如:

?- animal(X).
false.

?- male(X).
false.

?- bird(X).
false.

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