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

标签 sorting prolog predicate swi-prolog

我有这个列表(从文件中读取): [a-3,a-2,a-1,b-3,b-2,b-1,c-3,c-2,c-1,文件结束]

我还有以下谓词:

% 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).

谓词rank(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],已排序) .

实际输出:Sorted = [a-3, a-2, a-1, b-3, b-2, b-1, c-3, c-2, c-1, end_of_file].

预期输出:已排序 = [a-3, b-3, b-2, b-1, c-3, a-2, a-1, c-2, c-1, end_of_file].

输出不必是唯一的。对于当前的任务来说,重要的是考虑偏好事实。

  1. 在序言中这样做可行吗?
  2. 我做错了什么?
  3. 解决任务的有效替代方案是什么(例如 DAG、拓扑排序……)?

编辑

利用 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).

下面的测试运行,仍然显示错误的输出。也就是说,“b-2”永远不应该位于“b-3”的左侧,因为根据 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] .

最佳答案

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

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].

当然,它是从较低较高偏好排序的。完成后只需反转它,或者交换 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-_).
...

关于根据偏好事实对键值对列表进行排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37156243/

相关文章:

JavaScript 按字母顺序排序不对所有值进行排序

Prolog 错误捕获

prolog - 获取 Prolog 类型的所有元素

java - Java 中链接谓词的首选方式是什么?

c++ - 谓词和仿函数有什么区别?

sorting - 我应该对排序功能进行哪些测试?

python - 字典在 python 3 中不可订购?

ios - 对自定义对象数组内的数字进行排序

jquery - Prolog 中的 CORS 不起作用

list - Lisp - 如何检查列表是否为点对?