Prolog,返回最大值的排列

时间:2018-05-21 14:01:19

标签: prolog return max permutation

我制作了一个谓词时间表(A,B,C),用于回溯列表A,B,C中的可能排列和回溯

| ?- schedule(A,B,C).

A = [im204,im212,im217]
B = [im209,im214,im218]
C = [im210,im216] ? ;

A = [im204,im212,im218]
B = [im209,im214,im217]
C = [im210,im216] ? ;

A = [im204,im212,im216]
B = [im209,im214,im218]
C = [im210,im217] ? 

我还有谓词schedule_score(A,B,C,S),它从A,B,C到S列表返回得分(不记得得分的含义)。

| ?-  score_schedule([im204,im209,im212],[im210,im214,im216],[im217,im218],S).

S = 578

在我的新谓语中

all_schedule_scores(A,B,C,S):-
   schedule(A,B,C),
   score_schedule(A,B,C,S).

它返回可能的排列和分数

| ?- all_schedule_scores(A,B,C,S).

A = [im204,im212,im217]
B = [im209,im214,im218]
C = [im210,im216]
S = 342 ? ;

A = [im204,im212,im218]
B = [im209,im214,im217]
C = [im210,im216]
S = 371 ? ;

A = [im204,im212,im216]
B = [im209,im214,im218]
C = [im210,im217]
S = 294 ? 

我想知道是否有一种方法我只能返回最高分数的排列(或者不返回任何分数不是最大的排列)。

2 个答案:

答案 0 :(得分:2)

目前尚不清楚您正在使用的Prolog实施方式。这是一个使用setof/3(将结果从低到高排序)的解决方案:

max_scored(MaxA, MaxB, MaxC, MaxS) :-
    setof((S,A,B,C), all_scheduled_scores(A,B,C,S), AllScoresLowToHigh), 
    reverse(AllScoresLowToHigh, [(MaxS,MaxA,MaxB,MaxC)|_]).

排序使用自然排序,因此如果(S1,A1,B1,C1)大于(S2,A2,B2,C2),则S1被视为大于S2

此解决方案只找到一个最大结果。如果您有多个相同的最大值,我会将其作为练习留给您。您只需要选择具有相同分数的reverse/2的第二个参数的第一个元素。

答案 1 :(得分:0)

如果您的Prolog支持它,您可以使用库(aggregate):

max_scored_schedule(ScA,ScB,ScC,Score) :-
    aggregate(max(S,[A,B,C]), (schedule(A,B,C),score_schedule(A,B,C,S)), max(Score,[ScA,ScB,ScC])).

使用您提供的硬编码数据进行测试:

?- max_scored_schedule(A,B,C,S).
A = [im204, im209, im212],
B = [im210, im214, im216],
C = [im217, im218],
S = 578.

正如您所看到的,只需要正确排序参数......

修改

库(solutionsequences)允许类似SQL的查询,它可以解决您的问题

?- order_by([desc(S)], group_by(S, (A,B,C), (schedule(A,B,C),score_schedule(A,B,C,S)), G)).

但是@lurker的直截了当的答案是整洁的(+1),并且不要求你将另一个库移植到你的Prolog