3

我对 Prolog 很陌生,我被分配了这个任务。

我的代码如下:

relatives(cindy,tanya).
relatives(tanya,alan).
relatives(alan,mike).
relatives(kerry,jay).
relatives(jay,alan).

isRelated(X,Y):-
    relatives(X,Y).
isRelated(X,Y):-
    relatives(X,Z),
    isRelated(Z,Y).

很简单。这表明如果:

?- isRelated(cindy,mike).

Prolog 将返回 true。现在,我被困在如何让它返回 true 如果:

?- isRelated(mike,cindy).

我一直在想出一些想法,比如如果 isRelated(Z,Y) 返回 false,然后切换 X 和 Y,然后再次运行 isRelated。但我不确定 Prolog 是否允许这样的想法。任何提示或建议将不胜感激。谢谢!

更新:* ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * **

所以我补充说:

isRelated(X,Y):-
    relatives(X,Y);
    relatives(Y,X).

这将满足“直接”关系,但很简单,我发现它不满足间接关系。

我真的想做一些类似的事情,如果初始查询:

isRelated(mike,cindy)

失败,然后尝试通过切换X和Y来查看是否相反:

isRelated(cindy,mike)

那肯定会返回true。我只是不知道如何在 Prolog 的语法上做到这一点。

4

3 回答 3

1

进一步提示评论中的人,因为我还不能发表评论:根据你原来的规则和事实, isRelated(cindy,tanya)是真的,但isRelated(tanya,cindy)不是,所以你需要isRelated(X,Y)对称;有什么简单的补充isRelated可以做到这一点?

此外,您可以尝试绘制关系图relatives(X,Y),并为所有基本事实使用从 X 到 Y 的箭头,看看这是否有助于您考虑 Prolog 解释器将如何尝试满足查询。

于 2012-02-23T06:48:53.337 回答
1

你快到了,你只是想,我想,把太多的东西塞进一个谓词里。

用英语写出问题陈述并以此为基础:

两个人 X 和 Y 之间存在关系

  • 如果 X 和 Y 直接相关,或者
  • 如果 X 的任何直系亲属 P 与 Y 有关。

然后它变得容易。我会这样处理它:

首先,你有一组关于亲戚的事实。

related( cindy, tanya ).
...
related( james, alan ).

然后,描述直接关系的谓词是这些事实的术语:

directly_related( X , Y ) :- % a direct relationship exists 
  related(X,Y)               %   if X is related to Y
  .                          % ... OR ...
directly_related( X , Y ) :- % a direct relationship exists
  related(Y,X)               %   if Y is related to X
  .                          %

最后,一个描述任何关系的谓词:

is_related(X,Y) :-        % a relationship exists between X and Y
  directly_related(X,Y)   %   if a direct relationship exists between them
  .                       % ... OR ...
is_related(X,Y) :-        % a relationship exists between X and Y
  directly_related(X,P) , %   if a direct relationship exists between X and some other person P
  is_related(P,Y)         %   and [recursively] a relationship exists between P and Y.
  .                       %

解决方案实际上比这更复杂:

  1. 关于关系的事实描述了一个或多个图表。有关图表的更多信息,请访问 http://web.cecs.pdx.edu/~sheard/course/Cs163/Doc/Graphs.html。您正在做的是在图中找到从节点 X 到节点 Y 的路径。

  2. 如果关于关系的事实所描述的图在 X 和 Y 之间有一条或多条路径,则上述解决方案可以(并且将)成功多次(在回溯中),每一条这样的路径一次。解决方案需要是确定性的。通常,在确定两个人有亲属关系后,我们就完成了:仅仅因为我有两个堂兄弟并不意味着我与我的姑姑有两次亲属关系。

  3. 如果关系图包含循环(几乎可以肯定),使得存在“循环”路径:A → B → C → A …,则解决方案容易受到无限递归的影响。这意味着解决方案需要检测和处理周期。那怎么可能实现?

于 2012-02-23T18:58:00.407 回答
1

因此,要回答您的最后一个问题,您不会像在 C 中调用的那样在 Prolog 中切换and的值。逻辑变量持有的值不能显式更改,只能回溯。但是你可以很容易地使用你会使用的地方,反之亦然:XYswap(x,y)YX

somePred(X,Y):- is_it(X,Y).
somePred(X,Y):- is_it(Y,X).

这将somePred谓词定义为逻辑析取,即"OR"。它也可以明确地写出来,比如

somePred(X,Y):- is_it(X,Y) ; is_it(Y,X).

注意那里的分号。谓词之间的逗号,OTOH 定义了一个连词,一个“AND”(复合词中的逗号仅用于分隔该词的“参数”)。

于 2012-02-23T07:26:44.923 回答