Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/api/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在prolog中创建互斥或_Prolog - Fatal编程技术网

在prolog中创建互斥或

在prolog中创建互斥或,prolog,Prolog,假设你有一群下棋的人。你想确定是否存在一个从未输给任何人(不败)的玩家。假设事实是以赢的形式给出的(詹姆斯、汤姆)。韩元(詹姆斯,彼得),韩元(克雷格,汤姆)。迷路了(彼得、汤姆)。那么根据条件,一个玩家X从未输过 undefeated(X) :- \+ won(_, X), \+ lost(X, _). 所以不败(詹姆斯)是真的,不败(克雷格)是真的,但不败(汤姆)和不败(彼得)是假的。现在调用Undefeed(X)时出现了问题,因为这将简单地返回no。为了解决这个问题,我们需要一个在开始时

假设你有一群下棋的人。你想确定是否存在一个从未输给任何人(不败)的玩家。假设事实是以赢的形式给出的(詹姆斯、汤姆)。韩元(詹姆斯,彼得),韩元(克雷格,汤姆)。迷路了(彼得、汤姆)。那么根据条件,一个玩家X从未输过

undefeated(X) :- \+ won(_, X), \+ lost(X, _).
所以不败(詹姆斯)是真的,不败(克雷格)是真的,但不败(汤姆)和不败(彼得)是假的。现在调用Undefeed(X)时出现了问题,因为这将简单地返回no。为了解决这个问题,我们需要一个在开始时始终为true的语句,因此我们为分别玩白色和黑色棋子的玩家添加事实whiteplayer()和blackplayer()

whiteplayer(james).
whiteplayer(craig).
whiteplayer(tom).
whiteplayer(peter).
blackplayer(james).
blackplayer(peter).
blackplayer(tom).
并将“不败”更改为:

undefeated(X) :- (whiteplayer(X); blackplayer(X)), \+ won(_, X), \+ lost(X, _).

但现在我们遇到了一个新问题。查询不败(X)给出了解决方案james,craig,james,这是因为james同时玩白色和黑色棋子,但craig只玩白色棋子。所以问题是,对于白人玩家(詹姆斯)和黑人玩家(詹姆斯)来说,不败(詹姆斯)仍在继续,我怎样才能使它在回溯时只对其中一个进行呢?

如果你知道至少有一个人从
X
中获胜,那么
X
就不是不败的。只需尝试查找至少一个
Z
,这样
Z
就可以从
X
中获胜。如果发生这种情况,则意味着prolog会找到一个匹配项,它将尝试返回true,而您只需将该值反转为false并剪切所有其他分支

同样的道理也适用于那些没有专长的人。在这种情况下,prolog找不到匹配项并返回false,而不反转其值

这是你的代码,如果我理解你的提问者的权利顺便说一句,它总是很好地使用吉他比赛,看看发生了什么

won(james,tom). 
won(james,peter).
won(craig,tom). 
lost(peter,tom).



undefeated(X):-
  \+ won(_Z,X),!.

如果您的事实和规则允许变量的特定实例化以多种方式成功,那么您将获得重复,除非您使用切割(通常也会消除有效的解决方案,这是不可取的),或者您可以使用消除重复的
集合(或“手动”)收集冗余的子分辨率

所以你可以这样做:

validplayer(X) :- whiteplayer(X) ; blackplayer(X).

undefeated(Player) :-
    setof(P, validplayer(P), Players),
    member(Player, Players),
    \+ won(_, Player), \+ lost(Player, _).
理想情况下,如果您可以定义
validplayer/1
,使其对任何给定的播放器成功一次,并且不会被剪切,则效果会更好。但你目前对事实的定义并不支持这一点


我还建议您不应该同时需要
won/2
lost/2
事实,因为
won(X,Y)
等同于
lost(Y,X)
。最好坚持其中一种。希望您的数据库不会同时拥有
won(john,paul)
lost(paul,john)
,或者上述解决方案仍然会产生重复项,您需要在
undefeeds/1
上执行
setof/3
setof(U,undefeeded(U),listofundefeedplayers)

为什么数据库中既有
won/2
又有
lost/2
事实?它们是多余的,这会导致一些混乱。
won(X,Y)
是否等同于
lost(Y,X)
?@lower是的,它们是等价的,不幸的是,我一直在处理这两个问题。
undefeed(X)
查询只会导致没有解决方案。如果你添加丢失的事实,这将失败(james,tom)。而且如果你加上丢失的事实(詹姆斯,汤姆),它也不会返回不败(X)@LuaiGhunim的所有解。然后詹姆斯在一场比赛中输给了汤姆,因此他不再是不败的。如果你仔细阅读格雷格的问题,他正在寻找答案,以返回所有答案。如果一个谓词无法找到有效的解决方案,或者没有提供所有可用的解决方案,那么它就是有缺陷的。OP说他们必须同时处理
won/2
lost/2
。(与!!…;)相比,
丢失/2
有多好:)