解决 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)).
这表示 X
是 animal
if X
是 mammal
或 X
是 bird
。到目前为止,还不错。
bird
的描述如下:
bird('parrot').
bird('pigeon').
这些事实表明 parrot
是 bird
,pigeon
是 bird
。但是还有这个规则:
bird(X) :- (X='parrot';X='pigeon'),animal(X).
也就是说 X
是 bird
if X
是 parrot
或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).
此逻辑使用事实定义了哪些生物是鸟类或哺乳动物,然后提供了一条规则,说明如果已知某个生物是鸟类或哺乳动物,那么它就是动物。
此类问题的一个解决方案是简单地启用您的 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
我正在尝试使用 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)).
这表示 X
是 animal
if X
是 mammal
或 X
是 bird
。到目前为止,还不错。
bird
的描述如下:
bird('parrot').
bird('pigeon').
这些事实表明 parrot
是 bird
,pigeon
是 bird
。但是还有这个规则:
bird(X) :- (X='parrot';X='pigeon'),animal(X).
也就是说 X
是 bird
if X
是 parrot
或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).
此逻辑使用事实定义了哪些生物是鸟类或哺乳动物,然后提供了一条规则,说明如果已知某个生物是鸟类或哺乳动物,那么它就是动物。
此类问题的一个解决方案是简单地启用您的 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