如何使用多个答案处理一个谓词?

时间:2014-03-21 19:45:57

标签: prolog

假设我有一个谓词,看看是否有人有一个妹妹。

然后在我看来有两种可能性:

1)有人使用姐妹(X,Y),因此用户想要所有与姐妹一起的人的名单。 2)有人使用姐妹(人,Y),所以用户想要看到那个人的所有姐妹。

然后结果也可以是三种可能性之一:

1)找到一个答案。 2)找到多个答案。 2)没有找到任何东西。

现在我可以在Prolog(伪代码)中执行此操作

如果X和Y没有被替换并找到多个答案,则打印出“所有姐妹对” 其他    如果X和Y没有被替换并且找到一个答案那么打印这个“对的唯一姐妹是”   否则,如果X被替换并找到多个答案,则打印“Person1的姐妹们”

所以,如果那么这将是一个非常大的。 有没有更清洁的方法来解决这个问题?

鲁洛夫

编辑1:

我想到了这个方式:

display_sisters(X,Y) :-
      var(X), 
      var(Y), 
      setof (x-y,sisters_of(X,Y),Sisters), 
      <<check if Sisters is non-empty>>>
       write "The sisters are" , 
        <<print answers>>

display_sisters(X,Y) :-
      var(X), 
      var(Y), 
      setof (x-y,sisters_of(X,Y),Sisters), 
      <<check if Sisters is empty>>>
       write "There are no sisters" , 

2 个答案:

答案 0 :(得分:0)

不,如果没有答案或重复,你忘记说要打印什么。

您的要求非常具体,代码将会被细节混乱。 有些Prolog可用portray / 1,但你应该把它应用到列表......

通用的东西可能是(使用setof / 3来避免重复)

print_answers(Query, One, More, None) :-
    Query =.. [Functor, A1, A2],
    ( nonvar(One) ; One = 'The only ~s of ~w is ~w' ),
    ( nonvar(More) ; More = 'All the ~ss pairs are ~w' ),
    ( nonvar(None) ; None = 'None ~s found' ),
    (   setof(A1-A2, Query, Answers)
    ->  (   Answers = [_]
        ->  format(One, [Functor, A1, A2])
        ;   format(More, [Functor, Answers])
        )
    ;   format(None, [Functor])
    ).

产生

sister(a,b).
sister(a,c).

?- print_answers(sister(a,X),_,_,_).
All the sisters pairs are [a-b,a-c]

?- print_answers(sister(a,b),_,_,_).
The only sister of a is b

但是imho不值得努力...

答案 1 :(得分:0)

如果我正确理解了这个问题,您需要根据条件寻找非常具体的语言并显示结果。 @ CapelliC的答案是使用format和Prolog&#34; if-then-else&#34;将结果压缩成最简洁的谓词的方法。图案。

这是一个稍微冗长的解决方案,不使用format,而是使用&#34; if-then-else&#34;模式稍后解释。也许这会让你朝着正确的方向迈出一步,但是在你有机会研究之后,重新考虑@ CapelliC的解决方案,以获得更一般的治疗(可以用于各种兄弟预测) Prolog format如何运作。 (format与C中的printf非常相似,但格式符号不同。)

% Display all sister pairs
%
display_sisters(X, Y) :-
    var(X), var(Y),
    setof(X-Y, sisters_of(X, Y), Sisters),
    length(Sisters, Number),
    (   Number =:= 0
    ->  write('No one has a sister')
    ;   (   Number =:= 1
        ->  write('The only person with sister is: '),
            write(Sisters)
        ;   write('All the persons with sisters are: '),
            write(Sisters)
        )
    ), nl.

% Display sisters of a given person
%
display_sisters(X, Y) :-
    nonvar(X), var(Y),
    setof(Y, sisters_of(X, Y), Sisters),
    length(Sisters, Number),
    (   Number =:= 0
    ->  write('Person '), write(X), write(' has no sister')
    ;   (   Number =:= 1
        ->  write('The only sister '), write(X), write(' has is '),
            write(Sisters)
        ;   write('All of '), write(X), write('''s sisters are: '),
            write(Sisters)
        )
    ), nl.

这大量使用&#34; if-then-else&#34;在Prolog中构建。它可能在没有它的情况下完成,但它会变得更加冗长,有点麻烦。 &#34; if-then-else&#34;有助于浓缩逻辑。

构造:

P1 -> P2.

将查询P1,如果成功,则查询P2。否则,它将失败。结合Prolog中的OR(;),你可以做一个&#34; if-then-else&#34;:

P1 -> P2 ; P3.

如果P1成功,则Prolog将转到P2查询。否则,P1 -> P2会失败并且会P3(因为OR,;)。由于运算符优先级,如果此构造中或周围有多个语句,则需要括号。 ,的优先级高于;;高于->。所以更精细的模式看起来像:

P1,
P2,
(  P3    % Start of the if-then-else : P3 is the condition
-> P4,   % P4, P5 are both in the true leg due to precedence of ','
   P5
;  P6,   % P6, P7 are both the false leg due to precedence of ','
   P7
),...    % End of the if-then-else

在为答案显示的代码中,还有另一个if-then-else作为&#34; false&#34;腿,所以它只是拥有它自己的分组:

...
(  P1       % The condition
-> P2       % 'true' branch is P2
;  (  P3    % 'false' branch is another if-then-else pattern
   -> P4
   ;  P5,
      P6
   )
)

如果您想要在Prolog中做更多精心设计的事情,那么您将需要“点击”#34;学习其他一些内置功能(&#34; if-then-else&#34;,=../2format等等。如果你通过@CapelliC的答案学习和工作,你将会更多地了解Prolog。