我试图用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).
答案 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)).
这表示 X
为animal
,如果 X
为mammal
或X
为{ {1}} 的。到目前为止,非常好。
bird
的描述为:
bird
这些事实表明bird('parrot').
bird('pigeon').
是parrot
而bird
是pigeon
。但接下来是这条规则:
bird
其中说 bird(X) :- (X='parrot';X='pigeon'),animal(X).
是X
,如果 bird
是X
或parrot
,AND如果pigeon
是X
。前两个事实已经确定animal
和parrot
是鸟类。为什么这个规则是必要的?它进一步增加了pigeon
是X
的条件,而animal
又是bird
和mammal
的定义,因此是循环的。
类似于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.
所以,在这些情况下,我们仍然找不到任何解决方案,但至少我们得到答案。