如何引用“等效”算法

问题描述 投票:6回答:3

这是一个“软问题”,所以如果这不适合发布,请告诉我。

基本上我想知道如何谈论在某种意义上“等同”但在其他意义上“不同”的算法。

这是一个玩具的例子。假设我们得到一个长度为list的数字n列表。下面给出了两种简单的方法来列出列表中的数字。显然,这些方法在精确算术中完全相同,但在浮点运算中可能会给出不同的结果。

add_list_1(list,n):
    sum = 0
    for i=1,2,...,n:
        sum += list[i]
    return sum

add_list_2(list,n):
    sum = 0
    for i=n,...,2,1:
        sum += list[i]
    return sum

这是数值算法中常见的事情,Gram-Schmidt和Modified Gram Schmidt可能是最着名的例子。

算法的维基百科页面提到“高级描述”,“实现描述”和“正式描述”。

显然,实现和形式描述各不相同,但是诸如“添加列表”之类的高级描述对于两者都是相同的。

这些不同的算法,相同算法的不同实现,还是其他完全不同的东西?您如何描述高级别描述相同但在讨论它们时实现不同的算法?

algorithm math communication
3个回答
1
投票

以下定义可以在Info for the algorithm tag上找到。

算法是一组基于形式语言的有序指令,具有以下条件:

有限。指令的数量必须是有限的。

可执行文件。所有指令必须以某种语言相关的方式在有限的时间内执行。

特别考虑

基于正式语言的有序指令集

这告诉我们的是指令的顺序很重要。虽然两种不同算法的结果可能相同,但并不意味着算法是相同的。

你的Gram-Schmidt与Modified Gram-Schmidt的例子是一个有趣的例子。查看定义为here的每个算法的结构,这些确实是不同的算法,即使在高级描述中也是如此。步骤顺序不同。

您需要做的一个重要区别是在一组指令和输出集之间。 Here你可以找到三种最短路径算法的描述。基于输入的可能结果集是相同的,但它们是三种非常不同的算法。他们还有三种完全不同的高级描述。对于那些不关心这一点的人虽然这些“做同样的事情”(几乎伤害了我写这个)并且是equivalent

另一个重要的区别是算法之间步骤的相似性。让我们举个例子,用更正式的符号写出来:

procedure 1 (list, n):
    let sum = 0
    for i = 1 : n
        sum = sum + list[i]
    end for
    sum //using implicit return

procedure 2 (list, n):
    let sum = 0
    for i = n : 1
        sum = sum + list[i]
    end for
    sum //using implicit return

这两段代码具有相同的结果集,但指令看起来有所不同。在高层次上,这仍然不是真的。这取决于你如何正式化程序。循环是其中之一,如果我们将它们减少到索引,它们就会改变我们的程序。在这种特殊情况下(正如在评论中已经指出的那样),我们基本上可以用循环代替更正式的for each循环。

procedure 3 (list):
    let sum = 0
    for each element in list
        sum = sum + element
    end for
    sum

procedure 3现在做与procedure 1procedure 2相同的事情,他们的结果是相同的,但指示再次看起来不同。因此,程序是等效的算法,但在实现级别上却不一样。它们不一样,因为执行求和指令的顺序对于procedure 1procedure 2是不同的,并且在procedure 3中完全被忽略(这取决于你对for each的实现!)。

这就是高级描述的概念所在。正如您已经指出的那样,所有三种算法都是一样的。以下是您所指的Wikipedia article

1高​​级描述

“......用散文来描述算法,忽略了实现细节。在这个层面上,我们不需要提到机器如何管理它的磁带或磁头。”

2实施说明

“...散文用于定义图灵机使用其头部的方式以及将数据存储在其磁带上的方式。在此级别,我们不提供状态或转换功能的详细信息。”

3正式说明

最详细的“最低级别”给图灵机“状态表”。

牢记这一点你的问题实际上取决于它所提出的背景。高级别的所有三个程序都是相同的:

1. Let sum = 0
2. For every element in list add the element to sum
3. Return sum

我们不关心我们如何通过列表或我们如何总结,只是我们这样做。

在实施层面,我们已经看到了分歧。这些过程在“磁带”上的移动方式不同,但以相同的方式存储信息。当procedure 1从起始位置向磁带“右”移动时,procedure 2从“end”向磁带上“向左”移动(小心这一点,因为在TM中没有这样的东西,它必须以不同的状态定义,我们不在这个级别使用)。 procedure 3,它的定义不够好,无法做出这种区分。

在较低的层面上,我们需要非常精确。我没有达到TM状态表的水平,因此请接受这种相当非正式的程序描述。

procedure 1

1. Move right until you hit an unmarked integer or the "end" 
//In an actual TM this would not work, just for simplification I am using ints
    1.e. If you hit the end terminate //(i = n)
2. Record value //(sum += list[i]) (of course this is a lot longer in an actual TM)
3. Go back until you find the first marked number
4. Go to 1.

procedure 2将与1.3.指令相反,因此它们不一样。

但是在这些不同的层面上这些程序是否相同?根据Merriam Webster的说法,我会说他们处于各个层面。对于相同的输入**,它们的“值”或更好的“输出”是相同的**。沟通的问题是,这些算法,就像你在问题中已经说过的那样,返回相同的算法,使它们等效但不相同。

你指的是**浮点不准确意味着实现级别,两种算法已经不同。作为一个数学模型,我们不必担心浮点不准确,因为在数学中没有这样的东西(数学家生活在一个“完美的”世界)。

这些算法是相同高级描述的不同实现级别描述。因此,我会提到相同高级算法的不同实现,因为这个想法是相同的。

最后一个重要的区别是算法的进一步形式化,通过将其分配给一个集合来实现其复杂性(正如@jdehesa在评论中所指出的那样)。如果你只是使用大omicron,那么......你的集合将会变得庞大并使更多算法“等效”。这是因为合并排序和冒泡排序都是集合O(n^2)的成员,因为它们的时间复杂度(非常不经常,但n^2是两者的上限)。显然,冒泡排序不在O(n*log[2](n))中,但此描述并未指明。如果我们使用big theta那么bubble和merge sort就不再在同一个集合中了,上下文很重要。描述算法不仅仅是其步骤,还有一种方法可以用来区分算法。

总结一下:这取决于背景,特别是你在跟谁说话。如果要比较算法,请确保指定要执行此操作的级别。对于业余人士说“添加列表”将是足够好的,因为您的文档使用高级描述,在解释您的代码时解释您对上述高级别的实现,以及当您真正需要在将其放入之前将其形式化之前代码使用正式的描述。后期还将允许您到prove that your program executes correctly。当然,现在你不必再写下基础TM的所有状态了。在描述算法时,请以适当的形式进行设置。如果你有两个相同高级算法的不同实现,只需指出实现级别的差异(遍历的方向,求和的实现,返回值的格式等)。


0
投票

我想,你可以称之为模糊算法。虽然这个术语在文献中可能没有明确定义,但请考虑添加元素列表的示例。

它可以定义为 1.将总和初始化为零 2.添加列表中的元素以逐一求和。 3.归还总和

第二部分是模糊的,您可以按任何顺序添加它们,因为它没有在算法语句中定义,并且总和可能会在浮点数中更改为arithematic

我遇到的一个很好的例子:cornell lecture slide。那个凌乱的三明治例子是金色的。

您可以阅读Ambiguity一词所指的here wiki,它适用于各种环境,包括计算机科学算法。


0
投票

您可能指的是至少在表面上执行相同基础任务但具有不同数值稳定性水平(“稳健性”)的算法。这方面的两个例子可能是 -

“等效”算法还可以包括在计算机系统之间或者两者之间不确定或不一致的算法;例如,由于浮点数和/或浮点数学的实现差异,或者并行操作完成的顺序。对于关注可重复的“随机”数字生成的应用程序来说,这尤其成问题。

© www.soinside.com 2019 - 2024. All rights reserved.