根据偏好事实对键值对列表进行排序?

时间:2016-05-11 07:48:01

标签: sorting prolog predicate swi-prolog

我有这个列表(从文件中读取): [A-3,A-2,A-1,B-3,B-2,B-1,C-3,C-2,C-1,END_OF_FILE]

我还有以下谓词:

% ipo(A,B) -> A is preferred over B
ipo(end_of_file, _).
ipo(c-3,a-3).
ipo(c-3,b-3).
ipo(c-3,b-2).
ipo(a-2,c-3).
ipo(a-2,b-2).

% gr(A,B) -> A is better than B | for example a-2 is better than a-3
% for same key, the lower value is better
% also A is better than B if A is preferred over B

gr(X-I, X-J):- I<J.
gr(A, B):- ipo(A,B).

psort(>, E1, E2):- gr(E1, E2).
psort(<, E1, E2):- \+ gr(E1, E2).

rank(In, Out):-
    predsort(psort, In, Out).

谓词排名(In,Out)使用psort作为predsort的谓词来对我的列表进行排序以进行首选。除了它没有。

输入:rank([a-3,a-2,a-1,b-3,b-2,b-1,c-3,c-2,c-1,end_of_file],排序)

实际输出:排序= [a-3,a-2,a-1,b-3,b-2,b-1,c-3,c-2,c-1,end_of_file]。< / p>

预期输出:排序= [a-3,b-3,b-2,b-1,c-3,a-2,a-1,c-2,c-1,end_of_file]。< / p>

输出不必是唯一的。对手头的任务很重要的是要考虑偏好事实。

  1. 在prolog中这样做是否可行?
  2. 我做错了什么?
  3. 什么是解决任务的有效替代方案(如DAG,Topological-Sort,......)?
  4. 修改

    使用CapelliC的有用建议,我设法将我的计划推进到以下目的:

    ipo(c-3,a-3).
    ipo(c-3,b-3).
    ipo(c-3,b-2).
    ipo(b-1,c-3).
    ipo(a-2,c-3).
    ipo(a-2,b-2).
    
    gr(X-I, X-J):- !, I<J.
    gr(A, B):- ipo(A,B).
    
    psort(>, E1, E2):- gr(E1, E2).
    psort(<, _E1, _E2).
    
    rank(In, Out):-
        predsort(psort, In, Out).
    

    以下测试运行仍显示错误输出。那是&#39; b-2&#39;绝不应该在&#39; b-3&#39;的左边。因为根据gr(2),b-2优于b-3。

    ?- combinations(L), append(L1, [_], L), rank(L1, Sorted).
    L = [a-3, a-2, a-1, b-3, b-2, b-1, c-3, c-2, c-1, end_of_file],
    L1 = [a-3, a-2, a-1, b-3, b-2, b-1, c-3, c-2, c-1],
    Sorted = [a-3, b-2, c-3, a-2, a-1, b-3, b-1, c-2, c-1] .
    

1 个答案:

答案 0 :(得分:2)

关于效率:我已将您的代码更改为

gr(X-I, X-J):- !, I<J.
gr(A, B):- ipo(A,B).

psort(>, E1, E2):- gr(E1, E2).
psort(<, _E1, _E2).

(切割意味着没有必要检查ipo / 2关系,当看到相同的第一对元素时)

结果似乎合适:

?- rank([c-3,a-2,a-3,a-1], Sorted).
Sorted = [a-3, c-3, a-2, a-1].

当然,它从 lower higher 首选项排序。完成后只需将其反转,或者在psort / 3中交换运算符:

psort(<, E1, E2):- gr(E1, E2).
psort(>, _E1, _E2).

?- rank([c-3,a-2,a-3,a-1], Sorted).
Sorted = [a-1, a-2, c-3, a-3].

我会从输入列表中排除end_of_file,而ipo / 2也会清除规范。如果无法纠正输入“例程”,则可以执行

?- append(L, [_], [c-3,a-2,a-3,a-1,end_of_file]).
L = [c-3, a-2, a-3, a-1]

最后,ipo / 2似乎不完整(不是c-3优于a-1?我猜是这样......)。一个可能的简单解决方案可能是未定义数字字段:

ipo(c-_, a-_).
...