Algorithm 如何从SWI Prolog中某个查询产生最大结果的列表中找到输入?

Algorithm 如何从SWI Prolog中某个查询产生最大结果的列表中找到输入?,algorithm,prolog,idioms,logic-programming,Algorithm,Prolog,Idioms,Logic Programming,我现在刚刚开始学习Prolog,所以我不熟悉做大多数事情的正常方式 基本上,我有一个规则,它从输入中给出一个值: ScoreFromInput(Input, Score) :- ... 我有一个输入列表,只是数字。我很难找到能得到最高分数的输入 这就是我现在拥有的,但我认为它会无限重复: bestInput(BestInput) :- %#Bind the list of valid inputs legalInputs(ValidInputs), %# -1000 i

我现在刚刚开始学习Prolog,所以我不熟悉做大多数事情的正常方式

基本上,我有一个规则,它从输入中给出一个值:

ScoreFromInput(Input, Score) :- ...
我有一个输入列表,只是数字。我很难找到能得到最高分数的输入

这就是我现在拥有的,但我认为它会无限重复:

bestInput(BestInput) :-
    %#Bind the list of valid inputs
    legalInputs(ValidInputs),
    %# -1000 is a dummy score, it should get replaced on the first call to bestInputHelper
    bestInputHelper(ValidInputs,-1000,BestInput).

%#I think this rule should work if the first input in the list is not the best one
bestInputHelper([Input|RestOfInputs],BestScore,BestInput):-
    bestInputHelper(RestOfInputs,RestBestScore,BestInput),
    ScoreFromInput(Input,BestScore),
    RestBestScore > BestScore.

%#And this one if it is the best input
bestInputHelper([Input|RestOfInputs],BestScore,Input):-
    bestInputHelper(RestOfInputs,RestBestScore,_RestBestInput),
    ScoreFromInput(Input,BestScore),
    RestBestScore =< BestScore.
bestInput(最佳输入):-
%#绑定有效输入的列表
合法投入(有效投入),
%#-1000是一个虚拟分数,在第一次调用BestinpUserper时应将其替换
最佳输入权限(有效输入,-1000,最佳输入)。
%#如果列表中的第一个输入不是最好的,我认为这个规则应该有效
bestInputHelper([Input | RestOfInputs]、BestScore、BestInput):-
最佳输入者(RestOfInputs、RestBestScore、BestInput),
ScoreFromInput(输入,最佳分数),
RestBestScore>BestScore。
%#如果这是最好的输入
bestInputHelper([Input | RestOfInputs],BestScore,Input):-
最佳输入者(RestOfInputs,RestBestScore,_RestBestInput),
ScoreFromInput(输入,最佳分数),
RestBestScore=

到目前为止,这就是我所拥有的,但我认为有一种更直接的方法。感谢您的帮助!谢谢

一种简单的表述方式是,如果没有更好的输入,则输入是最好的:

best_input(Best) :-
    legal_inputs(Inputs),
    member(Best, Inputs),
    input_score(Best, Score),
    \+ ( member(Better, Inputs), input_score(Better, S), S > Score).
要查看您自己的代码有什么问题,请尝试例如SWI Prolog的图形跟踪器:

?- gtrace, best_input(Best).

请使用可读的名称而不是不可读的名称。

尽管Chris对Prolog不太熟悉,但他概述的方法可能比mat的方法更有效地找到得分最高的输入。与进行二次比较不同,Chris的方法可以线性扫描可能的输入

此处maxScoreOfList/3将返回有效输入列表的最佳项Z和最佳分数B作为第三个参数。谓词将在空列表上失败

maxScoreOfList(Z,B,[H|T]) :-
    scoreFromInput(H,S),
    maxScoreOfListAux(Z,B,H,S,T).
需要一个“helper”函数,如下所示,它说明了添加一些额外参数的“技巧”,以便在到达输入列表的末尾时,输出Z和B可以绑定到“到目前为止”找到的最佳项和分数:


Prolog命名的一点是以小写字母(大写或下划线开始变量名)开始谓词。所以我把答案中的ScoreFromInput改为ScoreFromInput。@hardmath:啊,是的,谢谢你指出这一点。在我的实际程序中,就是这样。我只是在这里切换到“输入”和“评分”,这样对不熟悉我的程序的人来说,他们的目的是明确的,我想我错过了。啊,有趣的做事方式!谢谢你的替代方法。幸运的是,我的程序处理的输入足够小,可以使用二次算法(最多24个),但我可以肯定地看到,这对于较大的输入更有用。此外,我认为这是实现我的代码的正确方法。谢谢
maxScoreOfListAux(Z,B,Z,B,[ ]).
maxScoreOfListAux(Z,B,X,S,[H|T]) :-
    scoreFromInput(H,Q),
    (   S >= Q
     -> ( Y = X, R = S )
     ;  ( Y = H, R = Q )
    ),
    maxScoreOfListAux(Z,B,Y,R,T).