0

我是使用 swi Prolog 的新手,现在我正在尝试使用 Prolog http://www.allstarpuzzles.com/logic/00335.html解决这个逻辑难题

但是当我尝试运行该程序时,该程序似乎停止响应并且 Prolog 冻结。看来我在确定每支球队的得分时遇到了问题。这是我的 Prolog 代码:

team(dirtydozen).
team(plough).
team(barflyers).
team(threestooges).
team(friends).

pub(maid).
pub(old).
pub(clown).
pub(king).
pub(queen).

score(75).
score(74).
score(73).
score(72).
score(71).
score(70).
score(69).
score(68).
score(67).
score(66).
score(65).
score(64).
score(63).
score(62).
score(61).
score(60).


solve :-
  score(Score1),score(Score2),score(Score3),score(Score4),score(Score5),
  pub(Pub1),pub(Pub2),pub(Pub3),pub(Pub4),pub(Pub5),

  Hasil = [[dirtydozen,Pub1,Score1],
       [plough,Pub2,Score2],
       [barflyers,Pub3,Score3],
       [threestooges,Pub4,Score4],
       [friends,Pub5,Score5]],
 Score1 is Score2 + 6,
 Score1 is Score3 + 9,
 \+ member([threestooges,maid,_],Hasil),

 member([friends,_,A],Hasil),
 member([_,old,B],Hasil),
 member([_,clown,C],Hasil),
 member([_,king,D],Hasil),
 (A-B) is 2*(C-D),
 member([_,queen,E],Hasil),
 member([threestooges,_,F],Hasil),
 F >= E+3.
4

1 回答 1

1

几乎是对的。只有四个问题。;-) 首先,这是一个几乎可以工作的版本:

team(dirtydozen).
team(plough).
team(barflyers).
team(threestooges).
team(friends).

pub(maid).
pub(old).
pub(clown).
pub(king).
pub(queen).

score(75).
score(74).
score(73).
score(72).
score(71).
score(70).
score(69).
score(68).
score(67).
score(66).
score(65).
score(64).
score(63).
score(62).
score(61).
score(60).

solve(Hasil) :-
    Hasil = [[dirtydozen,Pub1,Score1],
         [plough,Pub2,Score2],
         [barflyers,Pub3,Score3],
         [threestooges,Pub4,Score4],
         [friends,Pub5,Score5]],
    member([friends,_,A],Hasil),
    member([_,old,B],Hasil),
    member([_,clown,C],Hasil),
    member([_,king,D],Hasil),
    member([_,queen,E],Hasil),
    member([threestooges,_,F],Hasil),
    \+ member([threestooges,maid,_],Hasil),
    score(Score2),
    Score1 is Score2 + 6,
    score(Score3),
    Score1 is Score3 + 9,
    score(Score1),
    score(Score4),
    score(Score5),
    AB is A-B,
    AB is 2*(C-D),
    F >= E+3,
    pub(Pub1),
    pub(Pub2),
    pub(Pub3),
    pub(Pub4),
    pub(Pub5).

几乎,因为它提供了解决方案,而且速度很快,并且根据您的规范它们是正确的。但是,有很多,那是因为您没有指定所有酒吧/团队/分数必须彼此不同,例如

[[dirtydozen,old,75],[plough,clown,69],[barflyers,queen,66],
 [threestooges,king,75], [friends,old,63]]

是一个解决方案,即使“旧”和“75”在其中两次。如果您使用的是 SWI,all_different则从 clp_fd 包中添加调用或手动执行:

A \= B, A \= C, ... B \= C etc.

现在,关于冻结:这只是因为您的子句排序不理想。先看看scores 和pubs。在solve谓词的前两行中,这两者的所有可能排列都分配给Score[N]andPub[N]变量。尝试计算有多少可能的分配!只有这样,您的程序才会继续检查相关分配是否符合规则。

通过重新排序您的条件,我从一开始就排除了大量的作业。以这些行为例:

score(Score1), score(Score2), Score1 is Score2 + 2,...

这可以像这样评估:

Score1 = 75, Score2 = 75, 75 is 75+2? 
Score1 = 74, Score2 = 75, 74 is 75+2? 
Score1 = 73, Score2 = 75, 73 is 75+2? 
Score1 = 72, Score2 = 75, 72 is 75+2? 
...

总而言之,必须检查 Score1 和 Score2 的多达 225 个组合,以查看它们是否是正确的分配。

现在让我们考虑重新排序的版本:

score(Score2), Score1 is Score2 + 2, score(Score1),...

评估现在沿着这些路线进行:

Score2 = 75, Score1 = 77, score(77)?
Score2 = 74, Score1 = 76, score(76)?
Score2 = 73, Score1 = 75, score(75)?

我们只剩下 15 个有效的作业。所以规则是:尝试将这些变量相互固定,以免树过度展开。修复移动目标!

仅有的两个其他小问题:1)(A-B) is 2*(C-D)不起作用,因为它指出,评估的结果2*(C-D)必须不是整数,而是形式的术语(A-B)。引入一个中间变量来解析。2)你没有让solvereturn 任何有用的东西,所以它只说true. 不知道这是不是你想要的。;-)

于 2013-04-04T15:00:01.170 回答