2

我正在尝试在 Prolog 中解决以下问题,并且我认为我的编码是正确的,但是我的查询只是返回 false。关于改变什么的任何建议?问题如下:

“Bagel Alley 是当地的百吉饼店,在早上上下班途中总是热闹非凡,因为人们在上班路上停下来买咖啡和百吉饼。每天早上在现场新鲜制作,百吉饼非常受欢迎,而且事实上,这家店的咖啡也很棒,简直是锦上添花!在 Bagel Alley 工作的人都很开朗友好,而且能干,所以尽管顾客数量众多,但等待的时间从不漫长或不愉快。乔和他的四个同事今天早上过来看看大家都在说什么,惊喜地发现这家店名不虚传。确定每个同事的名字,什么样的百吉饼配上馅料,味道和大小每个点的咖啡(小、中或大)。”

  1. 布拉德拿到了他的百吉饼,不是小麦,上面什么都没有。沃尔特点了一杯咖啡。

  2. 得到中型咖啡的两个同事一个得到了榛子味,另一个得到了他的百吉饼加花生酱。

  3. 得到洋葱百吉饼但没有加黄油的人还得到了法国香草咖啡,但不是小尺寸。

  4. 五个同事是乔,一个是大杯咖啡,一个是杏仁味咖啡,一个是小麦百吉饼,还有一个是在百吉饼上放鸡蛋和培根。

  5. 里克没有点蓝莓百吉饼,但他点了哥伦比亚咖啡。Amaretto 咖啡是和切达面包圈一起点的,但不是 Walt 点的。

  6. 奶油芝士没有配蓝莓百吉饼,但配了一大杯咖啡。芝麻百吉饼配黄油,但卡洛斯没有点。

我写的Prolog代码在这里:

bagels(Sol):-
   Sol = [[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_]],
   member([brad,X,plain,_,_], Sol), X \== wheat,
   member([walt,_,_,small,_], Sol),
   member([_,_,_,medium1,hazelnut], Sol),
   member([_,_,peanut_butter,medium2,_], Sol),
   member([_,onion,Y,Z,french_vanilla], Sol), Y \== butter, Z \== small,
   member([joe,Ja,Jb,Jc,Jd], Sol),Ja\==wheat,Jb\==egg_bacon,Jc\==large,Jd==amaretto,
   member([La,Lb,Lc,large,Ld], Sol), La\==joe,Lb\==wheat,Lc\==egg_bacon,Ld\==amaretto,
   member([Aa,Ab,Ac,Ad,amaretto], Sol), Aa\==joe,Ab\==wheat,Ac\==egg_bacon,Ad\==large,
   member([Wa,wheat,Wb,Wc,Wd], Sol), Wa\==joe,Wb\==egg_bacon,Wc\==large,Wd\==amaretto,
   member([Ea,Eb,egg_bacon,Ec,Ed], Sol), Ea\==joe,Eb\==wheat,Ec\==large,Ed\==amaretto,
   member([rick,R,_,_,columbian], Sol),R\==blueberry,
   member([A,cheddar,_,_,amaretto], Sol), A\==walt,
   member([_,B,cream_cheese,large,_], Sol), B\==blueberry,
   member([C,sesame,butter,_,_], Sol), C \== carlos,
   member([_,_,_,other,_], Sol),
   member([_,_,_,_,other], Sol).

我相信运行查询“百吉饼(X)”。应该给我解决问题的方法,但它返回错误。我错过了什么吗?提前谢谢了!

4

2 回答 2

3

首先,问题陈述似乎需要一些审查 - 特别是第 4 点。

你这里有一个逻辑难题。因此,您确实需要坚持 Prolog 的逻辑部分。但是,在您的代码中,我看到(\==)/2并且(==)/2两者都没有完全意识到他们假装代表的逻辑关系。相反,请分别使用dif/2(=)/2

但即使更换了这些,情况也好不到哪里去,你的程序仍然失败。但是,通过纯粹的定义,您就有机会定位问题。你的问题是bagels(Sols)失败了。因此,目前的定义过于专业,过于狭隘。因此,我将尝试通过删除您的一些要求来概括它。为此,我会*在前面补充一些你的目标。我将对它们进行概括,以使生成的程序仍然失败。

剩下的是一个概括,告诉你你必须在哪里修改你的程序。否则,错误将持续存在。

编辑:我强调了对我来说特别奇怪的东西:两个喝杏仁的男人。

:- op(950, fy, *)。
*_。

百吉饼(溶胶):-
   溶胶 = [[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_] ,[_,_,_,_,_]],
   成员([布拉德,X,平原,_,_],索尔),
      差异(X,小麦),
   成员([沃尔特,_,_,小,_],索尔),
   成员([_,_,_,medium1,hazelnut], Sol),
   *成员([_,_,peanut_butter,medium2,_], Sol) ,
   成员([_,洋葱,Y,Z,french_vanilla],索尔),
      *差异(Y,黄油),
      差异(Z,小),
   成员([乔,Ja,Jb,Jc,Jd],索尔),
      * dif(Ja,wheat) , * dif(Jb,egg_bacon) ,
      差异(Jc,大),
      Jd=杏仁,
   * member([La,Lb,Lc,large,Ld], Sol) ,
      * dif(La,joe) , * dif(Lb,wheat) , * dif(Lc,egg_bacon) , * dif(Ld,amaretto) ,
    member([Aa,Ab,Ac,Ad,amaretto], Sol) ,
       dif (啊,乔),
      * dif(Ab,wheat) , * dif(Ac,egg_bacon) , * dif(Ad,large) ,
   成员([Wa,小麦,Wb,Wc,Wd],Sol),
      * dif(Wa, joe) , * dif(Wb, egg_bacon) ,
      差异(Wc,大),
      差异(Wd,杏仁),
   成员([Ea,Eb,egg_bacon,Ec,Ed],Sol),
      *差异(Ea,乔),
      差异(Eb,小麦),
      *差异(Ec,大),
      差异(埃德,杏仁),
   成员([rick,R,_,_,哥伦比亚],索尔),
      *差异(R,蓝莓),
   *成员([A,切达干酪,_,_,amaretto], Sol) ,
      *差异(A,沃尔特),
   成员([_,B,cream_cheese,大,_],溶胶),
      *差异(B,蓝莓),
   * member([C,sesame,butter,_,_], Sol) ,
      *差异(C,卡洛斯),
   *成员([_,_,_,other,_], Sol) ,
   *成员([_,_,_,_,other], 索尔)

不过,您可能会不高兴:为什么还剩下这么多代码?这样做的原因是您忘记在开始时陈述一些一般性观察。特别是他们想要一个不同的浇头。有了这些信息,程序片段就会缩小到仅突出显示的行。但是,必须从以下目标开始使用library(lambda).

bagels(Sol):-
   Sol = [[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_]],
    maplist(Sol+\P^member([P|_], Sol),
          [brad,walt,joe,rick,carlos]),
    maplist(Sol+\D^member([_,_,_,_,D], Sol),
          [amaretto,french_vanilla,hazelnut,columbian,other]),
    ...
于 2016-04-15T16:39:22.037 回答
1

我试图提高可读性,使用 DCG 传递状态(在此页面中查找“隐式传递状态” ),因此此代码段与您的解决方案非常不同。

您可以看到负面知识以两种不同的方式表达出来:在涉及人员的地方,我们可以直接使用\=,因为名称总是被实例化,但对于其他值,例如kind(brad, K),我使用{dif(K, wheat)},因为 K 可能还没有被实例化。

state(S), [state(T)] --> [state(T)], {member(S, T)}.

kind(P, K)  --> state([P, K, _, _, _]).
topping(P, T)   --> state([P, _, T, _, _]).
flavor(P, F)    --> state([P, _, _, F, _]).
size(P, S)  --> state([P, _, _, _, S]).


hint1 -->
  kind(brad, K), {dif(K, wheat)}, topping(brad, plain), size(walt, small).
hint2 -->
  size(P1, medium), size(P2, medium), {P1 \= P2},
  flavor(P1, hazelnut), topping(P2, peanut_butter).
hint3 -->
  kind(P, onion), flavor(P, french_vanilla), size(P, S), {dif(S, small)}.
hint4 -->
  size(P1, large), flavor(P2, amaretto), kind(P3, wheat), topping(P4, egg_bacon),
  {forall(select(X, [joe,P1,P2,P3,P4], Ps), maplist(\=(X), Ps))}.
hint5 -->
  kind(rick, K), {dif(K, blueberry)}, flavor(rick, columbian),
  kind(P, cheddar), flavor(P, amaretto), {P \= walt}.
hint6 -->
  topping(P1, cream_cheese), kind(P2, blueberry), {P1 \= P2}, size(P1, large),
  kind(P, sesame), topping(P, butter), {P \= carlos}.

bagels(Sol):- Sol =
    [[brad,_,_,_,_],
     [walt,_,_,_,_],
     [joe,_,_,_,_],
     [rick,_,_,_,_],
     [carlos,_,_,_,_]],
  phrase((hint1, hint2, hint3, hint4, hint5, hint6), [state(Sol)], _).

唉,我得到了太多的解决方案......也许我的提示翻译中有一个错误,或者 all_different 也应该应用于所有属性,就像提示 n.4 所做的那样

?- aggregate(count,S^bagels(S),N).
N = 7.
于 2016-04-16T18:45:08.127 回答