【问题标题】:prolog find minimum value queryprolog查找最小值查询
【发布时间】:2013-04-27 07:49:19
【问题描述】:

如果我有以下格式的事实:

person(name,age).

如何编写查询以找到最年轻的人?

我曾尝试使用递归,但一直陷入无限循环。到目前为止,从我所做的所有阅读中,我发现我需要使用 !切割运算符。任何帮助将不胜感激。

【问题讨论】:

    标签: prolog minimum


    【解决方案1】:

    您绝对不需要使用 cut 运算符。我很难想象那个解决方案会是什么样子。

    最简单的做法是进行这种查询:

    youngest(person(Name,Age)) :-
      person(Name, Age),
      \+ (person(Name2,Age2), Name2 \= Name, Age2 < Age).
    

    遗憾的是,这不是很有效,因为它可能必须为每个人搜索一次数据库,导致 O(N^2) 性能。但应该清楚它为什么起作用。

    更快的解决方案是使用setof/3

    youngest(person(Name, Age)) :-
      setof(Age-Name, person(Name,Age), [Age-Name|_]).
    

    我们依赖于 setof/3 将对列表进行排序这一事实,这将导致最年轻的人被移动到结果列表的开头以使其正常工作。它的性能更好,但读起来不是很清楚。

    有一个标准库可用于解决 SWI 的此类问题,但我不确定您是否在使用 SWI,而且我自己也没有使用过,但您可以研究一下。它叫做aggregate

    另一种方法是直接使用findall/3 实现数据库,然后使用专门为此编写的谓词直接找到最小值。这样的解决方案可能看起来像这样:

    youngest(Person) :-
      findall(person(Name,Age), person(Name,Age), [P1|Rest]),
      youngest(P1, Rest, Person).
    
    youngest(Person, [], Person).
    youngest(person(Name, Age), [person(N2,A2)|Rest], Person) :-
      Age < A2 -> youngest(person(Name, Age), Rest, Person)
                ; youngest(person(N2, A2),    Rest, Person).
    

    但是,这似乎需要做很多工作,尽管它可能会为您提供最佳性能(应该是线性时间)。

    【讨论】:

    • 这句话似乎无效:
    • youngest(person(Name,Age)) :- person(Name, Age), \+ (person(Name2,Age2), Name2 \= Name, Age2
    • “有效”是什么意思?它肯定是。你用的是什么Prolog?你记得在加载规则之前输入[user].吗?
    • 错误:未定义的过程:(\+)/3 错误:但是,有以下定义:错误:(\+)/1 我正在使用 SWI
    • 您需要在\+ 之后有一个空格,或者在它之后的内容周围放置另一组括号。你用的是什么 Prolog?
    【解决方案2】:

    只是添加到 Daniel (+1) 的(非常完整的)答案中:library(aggregate) 可以进行此类搜索 - 以及更多:

    youngest(Person) :-
        aggregate(min(Age,Pers), person(Pers,Age), min(_, Person)).
    

    我认为值得研究,因为 Prolog 与数据库的类比,以及该语言中缺少聚合运算符。

    【讨论】:

      猜你喜欢
      • 2017-09-19
      • 1970-01-01
      • 2011-06-05
      • 1970-01-01
      • 2022-10-26
      • 2013-11-16
      • 2018-03-11
      • 2012-12-03
      • 1970-01-01
      相关资源
      最近更新 更多