Math 评定数组单调性的算法(即判断数组的“排序性”)

Math 评定数组单调性的算法(即判断数组的“排序性”),math,artificial-intelligence,genetic-algorithm,information-theory,Math,Artificial Intelligence,Genetic Algorithm,Information Theory,编辑:哇,很多很棒的回复。是的,我用它作为适应度函数来判断遗传算法执行的排序的质量。因此,评估成本很重要(即,它必须快速,最好是O(n)) 作为我正在玩弄的人工智能应用程序的一部分,我希望能够根据其单调性(也称为“排序性”)对候选整数数组进行评级。目前,我正在使用一种启发式方法来计算最长的排序运行,然后将其除以数组的长度: public double monotonicity(int[] array) { if (array.length == 0) return 1d; i

编辑:哇,很多很棒的回复。是的,我用它作为适应度函数来判断遗传算法执行的排序的质量。因此,评估成本很重要(即,它必须快速,最好是
O(n)


作为我正在玩弄的人工智能应用程序的一部分,我希望能够根据其单调性(也称为“排序性”)对候选整数数组进行评级。目前,我正在使用一种启发式方法来计算最长的排序运行,然后将其除以数组的长度:

public double monotonicity(int[] array) {
    if (array.length == 0) return 1d;

    int longestRun = longestSortedRun(array);
    return (double) longestRun / (double) array.length;
}

public int longestSortedRun(int[] array) {

    if (array.length == 0) return 0;

    int longestRun = 1;
    int currentRun = 1;

    for (int i = 1; i < array.length; i++) {
        if (array[i] >= array[i - 1]) {
            currentRun++;
        } else {
            currentRun = 1;
        }

        if (currentRun > longestRun) longestRun = currentRun;
    }

    return longestRun;
}

此数组被划分为三个已排序的子序列。我的算法只会给它40%的排序,但直觉上,它应该得到更高的分数。这类事情有标准算法吗?

这似乎是距离的一个很好的选择,距离是排序数组所需的交换次数。这应该与每个项在排序数组中的位置之间的距离成比例

这里有一个简单的ruby算法,可以求距离的平方和。这似乎是一个很好的分类度量——每次交换两个无序元素时,结果都会变小

ap = a.sort
sum = 0
a.each_index{|i| j = ap.index(a[i])-i 
  sum += (j*j)
}
dist = sum/(a.size*a.size)

像这样的

我认为要使用的函数的选择很大程度上取决于您打算使用它的目的。根据你的问题,我猜你是在用遗传系统来创建排序程序,这就是排名函数。如果是这样,那么执行速度至关重要。基于此,我打赌您的最长排序子序列算法会运行得很好。这听起来应该很好地定义适合度。

我建议看看排列的方向和反转距离。这些算法通常用于查找两个置换(标识和置换字符串)之间的距离。此距离度量应考虑更多的有序值簇以及反转(单调递减而不是递增子序列)。还有


这实际上完全取决于数字的含义,以及这个距离函数在您的上下文中是否有意义。

这在很大程度上取决于您打算使用度量的目的,但一种简单的方法是将数组输入到标准排序算法中,并测量有多少操作(交换和/或比较)需要对数组进行排序

这是我刚刚编的一个


对于每对相邻值,计算它们之间的数值差。如果第二个大于或等于第一个,则将其添加到已排序的总计中,否则添加到未排序的总计中。完成后,取两者的比率。

计算所有已排序子序列的长度,然后将其平方并相加。 如果你想校准你的最大相位,使用不同于2的功率


我不确定用长度对其进行规格化的最佳方法是什么,可能是将其除以长度的平方?

一些使用修饰符的实验Ratcliff&Obershelp

>>> from difflib import SequenceMatcher as sm
>>> a = [ 4, 5, 6, 0, 1, 2, 3, 7, 8, 9 ]
>>> c = [ 0, 1, 9, 2, 8, 3, 6, 4, 7, 5 ]
>>> b = [ 4, 5, 6, 0, 1, 2, 3, 7, 8, 9 ]
>>> b.sort()
>>> s = sm(None, a, b)
>>> s.ratio()
0.69999999999999996
>>> s2 = sm(None, c, b)
>>> s2.ratio()
0.29999999999999999

所以这是它需要做的。但不太确定如何证明这一点。

您可能正在寻找的是。这是两个数组之间气泡排序距离的一对一函数。要测试数组是否“几乎已排序”,请根据已排序数组计算其Kendall Tau。

我也有同样的问题(单调性评分),建议您尝试。最有效的算法运行在
O(n logn)
中,还不错


以问题为例,
{4,5,6,0,1,2,3,7,8,9}
的最长递增顺序是
{0,1,2,3,7,8,9}
(长度为7)。也许它比您的最长排序运行算法的评分(70%)更高。

用递增值与总步数来计算步数如何。这是
O(n)

即使这是在编程上下文中,您也可能希望在mathoverflow.com上问这个问题。。。他们可能更适合提供一个有用的答案。如果你能提供更多细节,告诉我们你的人工智能应用程序将根据“分类性”做出什么样的决定,这会有所帮助@Michael Bray:事实上是这样的。奇怪的是,mathoverflow.com解析为同一个IP,但它在这里不起作用。不要在mathoverflow上问这个问题,那个网站是用于研究生水平的论文工作的。@Bruno:谢谢你的更正。。。许多其他StackExchange网站都出现了问题,似乎与该软件最近的测试版有关。他们在工作,只是不太好。但这不是莱文施坦距离。levenshtein distance是编辑距离,是从一个序列到另一个序列的最小编辑操作数(插入、删除和替换)。一般方法很有趣,可以尝试找出排序数组需要多少“从序列交换2个间隔”操作。但我怀疑,实际上这很难计算。@Doc,再说一次,交换距离不是levenshtein距离。忘了严格的levenshtein不包括换位-D-L包括换位。@nlucaroni:是的,我知道,但你误解了我的评论-我的意思是,这是一种可能的方法,可以通过所需交换的数量来衡量分类度,就像“Levenshtein”测量插入、删除和替换的数量一样。这是否也是一个好办法?老实说,我不知道。通过将此视为煎饼问题,如果数组按降序排序,则只需一个“翻转”操作即可对其进行排序,因此它将被视为“几乎排序”。我怀疑这不是OP想要的。它几乎被分类了。此外,他只说单调。降序或升序,仍然显示排序的本质。我想说7654321比4237516排序更高。它解决了他的“聚集”问题。根据使用的算法,这很可能会产生非常不同的结果。当然,这是真的-
>>> from difflib import SequenceMatcher as sm
>>> a = [ 4, 5, 6, 0, 1, 2, 3, 7, 8, 9 ]
>>> c = [ 0, 1, 9, 2, 8, 3, 6, 4, 7, 5 ]
>>> b = [ 4, 5, 6, 0, 1, 2, 3, 7, 8, 9 ]
>>> b.sort()
>>> s = sm(None, a, b)
>>> s.ratio()
0.69999999999999996
>>> s2 = sm(None, c, b)
>>> s2.ratio()
0.29999999999999999