1

假设我有一个谓词,有时会给我多个输出。像这样 -

foo(Number, Out) :- Number < 10, Out = less_than_ten.
foo(Number, Out) :- Number > 0, Out = more_than_zero.

我如何才能获得在另一个谓词中给出的所有值Outfoo记住它有时会给出一个,有时会给出多个(例如在列表中)?

编辑-不太确定我得到的答案回答了我的问题,所以我会更具体。采用上述谓词,我可以运行查询foo(5, Out).这满足两个规则,所以如果我在 SWI-prolog 中运行它,我会得到这个 -

?- foo(5, Out).
Out = less_than_ten

然后我可以输入一个分号让序言回溯并寻找其他解决方案 -

?- foo(5, Out).
Out = less_than_ten ;
Out = more_than_zero.

因此,如果我在另一个谓词中执行此谓词,在给定 Number = 5 的情况下,如何获得 Out 的所有有效值?

4

2 回答 2

3

如果您只考虑整数,您可以选择使用 CLP(FD)。那么你的谓词 foo 可能看起来像这样:

:- use_module(library(clpfd)).

foo(Nums) :-
   Nums ins 1..9.     % the numbers in the list Nums are 0 < X < 10

您可以使用此谓词来测试数字列表是否在您想要的范围内:

   ?- foo([1,2,3,4,5]).
yes
   ?- foo([0,1,2,3,4,5]).
no
   ?- foo([1,2,3,4,5,10]).
no

如果您想使用它来生成该范围内的整数列表,您必须确保这Nums是一个列表以避免实例化错误。您可以通过在查询中添加目标长度/2 来做到这一点:

   ?- length(Nums,_), foo(Nums).
Nums = [] ? ;          % <- no number
Nums = [_A],           % <- one number
_A in 1..9 ? ;
Nums = [_A,_B],        % <- two numbers
_A in 1..9,
_B in 1..9 ? ;
Nums = [_A,_B,_C],     % <- three numbers
_A in 1..9,
_B in 1..9,
_C in 1..9 ?
.
.
.

这些答案包含剩余目标(有关详细信息,请参阅CLP(FD) 文档)。如果要查看实际数字,则必须添加一个目标来标记列表:

   ?- length(Nums,_), foo(Nums), label(Nums).
Nums = [] ? ;
Nums = [1] ? ;
Nums = [2] ? ;
Nums = [3] ? ;
.
.
.
Nums = [1,1] ? ;
Nums = [1,2] ? ;
Nums = [1,3] ? ;
.
.
.
Nums = [9,9] ? ;
Nums = [1,1,1] ? ;
Nums = [1,1,2] ? ;
.
.
.
于 2018-11-29T07:03:39.950 回答
0

刚刚找到回答这个问题的谓词。Prolog 有一个内置的 predicate ,它将谓词的参数与参数bagof(Template, Goal, Bag)统一起来(不确定这是正确的 prolog 术语!)。因此,在问题的示例中,使用,这将统一解决方案列表with 。在 SWI-prolog 中运行查询:TemplateGoalBagbagof(Out, foo(5, Out), Outputs).OutOutputs

4 ?- bagof(Out, foo(5, Out), Outputs).
Outputs = [less_than_ten, more_than_zero].

关于找到目标所有解决方案的不同方法的有用指南。

于 2018-11-29T13:40:50.790 回答