【问题标题】:Sum from backtrackable predicates or facts可回溯谓词或事实的总和
【发布时间】:2014-12-15 19:02:19
【问题描述】:

我正在尝试将不同的值加在一起,假设我有这个:

%fact(Type, Name, Weight).
fact(fruit, apple, 10).
fact(fruit, pear, 20).
fact(vegetable, tomato, 15).

现在,我遇到的问题是,如果我想将所有水果的重量相加。到目前为止我做了什么:

printWeight(Type):-
    fact(Type,_,R),
    (Type = 'fruit'
    -> true
    ; false
    ),
    *Here I want to add the weight of all the fruits, in case Type = fruit*

有人知道如何解决这个问题吗?

【问题讨论】:

  • 我假设在你的第一个代码片段中,你的意思是写% fact(Type, Name, Weight).I.e。第一行是描述fact/3 谓词的comment
  • 是的,我就是这个意思。

标签: prolog


【解决方案1】:

您可以轻松地使用findall/3 获取所有权重,然后使用sumlist 或其他一些简单的函数对所有权重求和:

findall(W, fact(Type, _, W), L),
sumlist(L, Weight).

Weight 将保存权重的总和。用法示例:

?- Type = fruit, findall(W, fact(Type, _, W), L), sumlist(L, Weight).
Type = fruit,
L = [10, 20],
Weight = 30.

【讨论】:

    【解决方案2】:

    有关内置谓词 bagof/3 和或多或少的标准库谓词,请参阅您的 prolog 实现文档,该谓词对列表中的数字求和(在 SWI-Prolog 中,可用作 sumlist/2):

    ?- bagof(W, Name^fact(fruit, Name, W), Ws), sumlist(Ws, Sum).
    Ws = [10, 20],
    Sum = 30.
    
    ?- bagof(W, Name^fact(meat, Name, W), Ws), sumlist(Ws, Sum).
    false.
    

    第二个查询失败,因为您的数据库中没有肉制品。你可以保持原样(因为也许你想知道是否没有某种类型的产品),或者使用findall/3

    ?- findall(W, fact(meat, _, W), Ws), sumlist(Ws, Sum).
    Ws = [],
    Sum = 0.
    

    如果你使用SWI-Prolog,还有library(aggregate)

    ?- aggregate(sum(W), Name^fact(fruit, Name, W), W_sum).
    W_sum = 30.
    

    您可以将aggregate_all/3 用于上述findall/3 的行为:

    ?- aggregate(sum(W), Name^fact(meat, Name, W), W_sum).
    false.
    
    ?- aggregate_all(sum(W), Name^fact(meat, Name, W), W_sum).
    W_sum = 0.
    

    如果您不想使用sumlist/2(或不允许使用),这就是添加两个数字(整数或浮点数)的方式:

    Sum is A + B
    

    所以你必须弄清楚如何“折叠”一个列表。

    编辑:

    所以,要创建一个谓词 type_totalweight/2,例如使用findall/3

    type_totalweight(Type, Weight) :-
        findall(W, fact(Type, _, W), Ws),
        sumlist(Ws, Weight).
    

    【讨论】:

    • 当目标参数没有解决方案时,bagof/3(和setof/3)失败而不是返回一个空列表,您可以通过(也)展示和解释使用的替代方法来改进您的答案findall/3。还提到 sumlist/2 通常是一个库谓词,根据 Prolog 系统,它可能可用也可能不可用是个好主意。
    • @PauloMoura 这是一个“我希望我的谓词意味着什么”的问题,我猜。但无论如何,这是一个非常有效的评论。
    • 谢谢。 findall/3 对于初学者来说通常也很容易,因为它不需要他们理解bagof/3(和setof/3)中使用的存在量化变量的概念。
    • @PauloMoura 根据我的经验判断,findall/3 对于初学者来说更容易掌握是正确的。它在认知负荷方面排在bagof/3setof/3 之前,如果我理解正确的话,年龄?
    • @Boris 我最古老的手册是“DECsystem-10 PROLOG USER'S MANUAL”,日期为 1982 年 11 月 10 日。它描述了 bagof/3setof/3,但没有提到 findall/3 .
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多