sort / 2,keysort / 2 vs. samsort / 3,predsort / 3

时间:2015-07-22 20:18:02

标签: sorting prolog iso-prolog

ISO-Prolog提供sort/2keysort/2,它依赖于通常称为"标准术语顺序"的术语顺序(7.2)。 对具有不同顺序的列表进行排序的常用方法是将该列表的每个元素El以某种方式映射到对XKey-El对列表,然后对该列表进行排序,最后将密钥投射出去。例如,考虑keysort/2See the note for an implementation)如何表达sort/2

在许多情况下,这种方法比使用通用实现特定排序谓词快得多,后者依赖于用户定义的顺序作为SWI predsort(C_3, List, SortedList) 或SICStus' samsort(O_2, List, SortedList)

我的问题归结为:

  

是否存在使用predsort/3进行排序的情况。 samsort/3不能被某些映射取代sort/2 - 并且正在投射? 1

为了清楚起见,更好地坚持有限的基础术语。因为,无限的地面术语不具有完整的词典顺序,因为它需要作为有限情况的扩展;而且,目前尚不清楚变量与两个不同变量的实例相关的比较将如何得出ISO / IEC 13211-1:1995中的7.2.1:

  

7.2.1变量

     

如果XY是不相同的变量,则为   X term_precedes Y应依赖于实现   除了在创建排序列表期间(7.1.6.5,
  8.10.3.1 j)排序应保持不变。

因此不清楚predsort/3是否仍然符合条件 创建排序列表。很清楚的是,在 sort/2keysort/2期间,排序保持不变

1感谢@WillNess,此预测至少应包括reverse/2 - 或任何线性转换。这也意味着可以实现具有重复和独特结果的结果(类似于keysort/2的实现方式)。

3 个答案:

答案 0 :(得分:5)

首先,你可以"否定" Prolog原子。我们称之为atom_neg/2(这是一个愚蠢的名字,但无论如何它确实有些愚蠢):

atom_neg(A, NK) :-
    atom_codes(A, Cs),
    maplist(negate, Cs, NCs),
    append(NCs, [0], NK).

negate(X, N) :- N is -X.

我并不是说这样做很实际,但显然,这是可能的。

总排序是一个弱排序,一个关键函数 f 在集合 T 上,同时在密码域上有一个总排序 r f 定义弱排序 wr(x,y)< ==> r(f(x),f(y))

(该上下文中函数的Codomain是函数返回的值的域。)

我可能完全错了,但是关系的存在需要一个密钥的存在:你可以用另一个关系来定义一个关系,但最终你必须比较一些可以孤立存在的东西:密钥。

这里的要点是键不需要与我们想要排序的东西在同一个域中,并且为<的对象定义弱排序(关系) strong>相同域名。 Prolog在这里做了一些奇怪的事情:它为所有可能的术语定义了一个标准的术语 。 Prolog也没有&#34;类型&#34;或&#34;域&#34;的正确概念。我的直觉告诉我,排序不属于同一个域的东西根本不是很有用,但Prolog显然不同意。

您无法为两种情况定义关键功能:

  1. 比较谓词保持自己的状态;
  2. 你有&#34;不透明&#34;提供比较功能但不提供键功能的对象(例如,在C中定义)。
  3. 无论哪种方式,predsort都很有用:没有人比Will Ness更喜欢atom_neg/2解决方案。然而,它目前有一个严重的效率:它不允许稳定的排序。 SWI-Prolog已经can be used in this way,只需要将当前行为添加到predsort/3的规范和文档中。

答案 1 :(得分:4)

@ poris的

编辑the answer显示了如何“否定”原子以进行比较,因此在这种情况下它会使我的控制论无效。而问题中的新规定完全无效。

在复杂排序标准的情况下,必须安排多个子键。如果需要保留重复项,则在为sort/2构造的术语中,在排序子项之后,应将增量索引作为原始术语的前缀。

虽然构造的子键的复杂性和数量可能会失控。成像排序首先按X,然后按Y,在某些区域按升序或降序排列,首先按按Y,在其他区域按X秒排序。

然后,在标准的术语顺序中,仅用线性数量的键构造和对数线性(可能是轻的)比较来替换对数线性(可能是计算上很重)的比较的优势可以消失。

琐事,predsort/3例如反向的原子列表,带有自定义比较谓词

comp(<,A,B):- B @< A.

等,sort/2无法在"standard order of terms"中起作用(引用SWI文档)。有了数字,我们可以翻转标志,但不能用名字。

也许您想要将reverse添加到允许的操作中。

允许sort/4,我看不到任何不起作用的内容。由于它是稳定的,因此可以通过二次通过(首先是次要通道,然后通过主要标准)来适应次要标准。

答案 2 :(得分:2)

我想我可能会对你的问题有一个正确的答案。

如果您有部分订购,您仍然可以尝试使用predsort/3进行排序,并且您可能会得到比仅仅说&#34更好的结果;总排序不存在。&#34;

这是一个例子:说你有一支由两支队伍组成的比赛。每场比赛都只给出一支球队,并且在一支球队达到一定数量的分数之前进行比赛。

现在,你组织一个锦标赛,它有一个小组赛阶段,由4个小组组成,这是一个循环赛。只有两支顶级球队才能脱颖而出。

对于每场比赛,球队得分为own_points - other_teams_points。换句话说,如果你玩到7,最终得分是:

A队 - 5:7 - B队

他们A队得分-2,B队得2分。

在小组赛阶段结束时,您可以通过以下方式订购球队:

  1. 总分
  2. 如果总得分相同,那么赢得直接战斗的团队会被命令更高。
  3. 最值得注意的是,使用这种得分方案,如果A队击败B队,B队击败C队,C队击败A队和#34队,则无法解决三方平局 ;稳定&#34;在这种情况下,排序毫无意义。

    但是,使用predsort/3,您可以尝试找到两个顶级团队,在大多数情况下,您将获得明确的答案。如上所述解决三向抽签通常使用抛硬币来解决。