Questions tagged «correctness-proof»

要求或有关算法正确性证明的问题。

29
为什么写下数学证明比编写计算机代码更能抵御故障?
我注意到,我发现写下数学证明而不犯任何错误要比写下没有错误的计算机程序容易得多。 似乎这不仅仅是我的经验。大多数人在编程时总是会犯软件错误,而且他们让编译器始终告诉他们错误是什么。我从未听说过有人一口气编写大型计算机程序,但一无所错,并且完全相信它不会出错。(实际上,几乎没有任何程序是没有错误的,甚至包括许多高度调试的程序)。 然而,人们可以写整篇论文或数学证明书,而无需任何编译器向他们反馈自己犯错的反馈,有时甚至无法从他人那里得到反馈。 让我清楚一点。这并不是说人们不会在数学证明中犯错误,但是对于即使是有经验的数学家来说,错误通常也不是问题,并且可以在没有诸如编译器指向您的编译器的“外部oracle”帮助下解决。错误。 实际上,如果不是这种情况,那么在我看来数学几乎是不可能的。 因此,这引发了我一个问题:编写无故障的数学证明和编写无故障的计算机代码有什么不同,从而使前者比后者更易于处理? 可以说,事实是人们拥有编译器的“外部预言”,使他们指出自己的错误,这使程序员变得懒惰,从而阻止他们执行严格编写代码所必需的工作。这种观点意味着,如果他们没有编译器,他们将能够像数学家一样完美无缺。 您可能会发现这很有说服力,但是基于我的编程经验和写下数学证明,在我看来,这并不是真正的解释。两项工作似乎在根本上有所不同。 我最初的想法是,可能会有区别,对于数学家来说,正确的证明仅要求每个逻辑步骤都是正确的。如果每个步骤都正确,则整个证明都是正确的。另一方面,要使程序无缺陷,不仅每一行代码都必须正确,而且它与程序中每行其他代码的关系也必须正常工作。 换句话说,如果步骤中证明是正确的,那么在制作工序中的错误不会弄乱一步如初。但是,如果正确记录了一行代码,则在行犯错误将影响行的工作,因此,每当编写行,都必须考虑其与所有其他行的关系。我们可以使用封装以及所有类似的东西来限制这种情况,但是不能完全删除它。XXXÿYYX Y X XXXXXXXÿYYXXXXXX 这意味着检查数学证明中的错误的过程在证明步骤的数量上基本上是线性的,但是检查计算机代码中的错误的过程在代码行数上基本上是指数的。 你怎么看? 注意:该问题有大量答案,可探讨各种事实和观点。在回答之前,请阅读所有内容并仅在有新添加内容时回答。多余的答案或不支持事实的观点的答案可能会被删除。

13
如何愚弄“尝试一些测试用例”启发式算法:看起来正确但实际上不正确的算法
为了尝试测试某个问题的算法是否正确,通常的出发点是尝试在多个简单的测试案例上手动运行该算法-在一些示例问题实例(包括一些简单的“拐角案例”)上进行尝试”。这是一种很好的启发式方法:这是一种快速清除算法中许多错误尝试并了解为什么该算法无效的好方法。 但是,在学习算法时,有些学生很想停在这里:如果他们的算法在一些示例上都能正常工作,包括他们认为可以尝试的所有极端情况,那么他们得出的结论是算法必须正确。总是有一个学生问:“如果我可以在几个测试用例上尝试一下,为什么我需要证明我的算法正确?” 那么,如何欺骗“尝试一堆测试用例”启发式方法?我正在寻找一些很好的例子来表明这种启发式方法是不够的。换句话说,我正在寻找一个或多个算法的示例,这些示例从表面上看可能是正确的,并且在任何人都可能想出的所有小输入上输出正确答案,但是该算法实际上在哪里不起作用。也许该算法恰好在所有小输入上都能正常工作,仅对大输入失败,或者仅对具有异常模式的输入失败。 具体来说,我在寻找: 一种算法。该缺陷必须在算法级别上。我不是在寻找实现错误。(例如,该示例至少应与语言无关,并且该缺陷应与算法问题有关,而不是与软件工程或实现问题有关。) 有人可能会提出的一种算法。伪代码应该看起来至少看起来是正确的(例如,混淆或明显可疑的代码不是一个好例子)。如果这是某些学生在尝试解决作业或考试问题时真正想到的一种算法,则可加分。 通过概率较高的合理手动测试策略的算法。手动尝试一些小型测试用例的人应该不太可能发现该缺陷。例如,“手动模拟十二个小型测试用例的QuickCheck”应该不太可能揭示该算法不正确。 优选地,确定性算法。我已经看到许多学生认为“手动尝试一些测试用例”是检查确定性算法是否正确的合理方法,但是我怀疑大多数学生不会认为尝试几个测试用例是验证概率的好方法算法。对于概率算法,通常没有办法判断任何特定输出是否正确。而且您手头不足以对输出分布进行任何有用的统计检验。因此,我宁愿专注于确定性算法,因为它们更清楚地了解了学生的误解。 我想教导证明算法正确的重要性,并且希望使用一些这样的示例来帮助激发正确性的证明。我希望那些相对简单并且可以被大学生使用的例子;需要重型机械或大量数学/算法背景的示例不太有用。另外,我也不想使用“非自然”的算法;虽然构造一些怪异的人工算法来欺骗启发式方法可能很容易,但是如果看起来很不自然,或者构造了明显的后门只是为了欺骗这种启发式方法,那么它可能不会使学生信服。有什么好的例子吗?

2
如何证明贪心算法是正确的
我有一个贪心算法,我怀疑这可能是正确的,但我不确定。如何检查是否正确?证明贪婪算法正确的技术有哪些?有共同的模式或技术吗? 我希望这将成为一个参考问题,可以用来指导初学者。因此其范围比平常大。请小心给出一般的,有说服力的答案,至少由一个示例说明了这一点,但仍然涵盖了许多情况。谢谢!

1
如何证明随机播放算法的正确性?
我有两种方法可以按随机顺序生成项目列表,并想确定它们是否同样公平(公正)。 我使用的第一种方法是构造元素的整个列表,然后对其进行随机播放(例如Fisher-Yates随机播放)。第二种方法更多是一种迭代方法,该方法使列表在每次插入时都保持乱序。在伪代码中,插入函数为: insert( list, item ) list.append( item ) swap( list.random_item, list.last_item ) 我对展示这种特殊混洗的公平性感兴趣。使用此算法的优点是足够的,即使稍微不公平也可以。要决定,我需要一种评估其公平性的方法。 我的第一个想法是,我需要以这种方式计算可能的总排列与一组最终长度可能的总排列。但是,我对如何计算该算法产生的排列有些困惑。我也不能确定这是最好的还是最简单的方法。


5
缺乏正确性证明的算法示例
我们有Hoare逻辑。为什么仍然有可能算法是正确的,但是没有证据证明它是正确的?假设算法用C表示。然后我们可以逐步论证它正在执行应做的事情。 所以我的问题是: 给我一个正确的算法示例,但没有正确性证明。 编辑:我认为有一点背景可以帮助阐明我要去的地方。让我引用斯科特·亚伦森的话: 自1970年代以来,一直有人猜测P NP可能独立于数学的标准公理系统(例如Zermelo-Fraenkel集理论)(即,既不可证明也不可证明)。需要明确的是,这意味着≠≠\ne 尚不存在用于NP完全问题的多项式时间算法,但我们永远无法证明它(至少在我们通常的形式系统中无法证明),否则 确实存在用于NP完全问题的多项式时间算法,但是我们永远无法证明它有效,或者我们永远无法证明它在多项式时间内停止。 我指的是第二种可能性。由于Aaronson可以如此自信地将其列出为一种可能性,因此我认为必须存在类型2的现有示例。这就是为什么我要问这个问题。但是似乎没有一个快速明确的答案。

6
在一个间隔中找到两个数字的最大异或:我们能做得比二次更好吗?
lllrrrmax(i⊕j)max(i⊕j)\max{(i\oplus j)}l≤i,j≤rl≤i,j≤rl\le i,\,j\le r 天真的算法只检查所有可能的对。例如在红宝石中,我们有: def max_xor(l, r) max = 0 (l..r).each do |i| (i..r).each do |j| if (i ^ j > max) max = i ^ j end end end max end 我感觉到,我们可以做得比二次。是否有针对此问题的更好算法?

3
试图了解此Quicksort正确性证明
该证明是归纳证明,其内容如下: P(n)是“快速排序对长度为n的每个输入数组正确排序”的断言。 基本情况:每个长度为1的输入数组都已排序(P(1)成立) 归纳步骤:修复n => 2.修复一些长度为n的输入数组。 需要说明:如果对于所有k <n,P(k)成立,那么P(n)也成立 然后,他绘制围绕某个枢轴p划分的数组A。因此,他绘制了p,并将数组<p的部分称为第一部分,将> p的部分称为第二部分。部分1的长度= k1,部分2的长度为k2。通过“分区”子程序的正确性证明(之前已证明),枢轴p缠绕在正确的位置。 通过归纳假设:第1,第2部分通过递归调用正确排序。(使用P(K1),P(k2)) 所以:在递归调用之后,整个数组都将正确排序。 QED 我的困惑:我很难确切地看到这如何证明它的正确性。因此,我们假设P(k)确实适用于所有自然数k <n。 到目前为止,我看到的大多数归纳证明都类似:证明基本情况,并证明P(n)=> P(n + 1)。他们通常还涉及某种代数运算。这个证明似乎有很大的不同,我不理解如何将归纳概念应用到它。我可以合理地推断出Partition子例程的正确性是关键。因此,其正确性的理由如下:我们知道,每个递归调用都会围绕枢轴对数组进行分区。然后,该支点将处于其应有的位置。然后,每个子数组将进一步围绕枢轴进行划分,然后该枢轴将处于其正确位置。这样一直进行下去,直到得到长度为1的子数组,该数组被简单地排序了。 但是然后我们不假设P(k)满足所有k <n...。实际上我们正在展示它(因为Partition子例程将始终将一个元素置于其合法位置。)我们不是假设P (k)持有所有k

1
用于编辑距离计算的微优化:有效吗?
在Wikipedia上,给出了自下而上的用于编辑距离的动态编程方案的实现。它没有完全遵循定义。内部单元的计算如下: if s[i] = t[j] then d[i, j] := d[i-1, j-1] // no operation required else d[i, j] := minimum ( d[i-1, j] + 1, // a deletion d[i, j-1] + 1, // an insertion d[i-1, j-1] + 1 // a substitution ) } 如您所见,如果存在匹配项,该算法始终从左上角的邻居中选择值,从而节省了一些内存访问,ALU操作和比较。 但是,删除(或插入)可能会导致较小的值,因此该算法在局部上是不正确的,即,它违反了最佳标准。但是也许错误不会改变最终结果-可能会消除它。 这种微优化有效吗?为什么不呢?

2
在这种平方根边界查找算法中,如何获得循环不变性?
最初在math.SE上,但在那里没有答案。 考虑以下算法。 u := 0 v := n+1; while ( (u + 1) is not equal to v) do x := (u + v) / 2; if ( x * x <= n) u := x; else v := x; end_if end_while 其中u,v和n是整数,除法运算是整数除法。 解释算法计算的结果。 使用您对第一部分的回答作为算法的后置条件,建立循环不变式,并证明算法终止且正确。 在类中,后置条件被发现是和不变是0 ≤ ü 2 ≤ …

6
程序验证技术可以防止Heartbleed类型的错误发生吗?
关于Heartbleed错误,Bruce Schneier在4月15日的Crypto-Gram中写道:““灾难性”是正确的词。在1到10的范围内,这是11。几年前,我读到某个操作系统的内核已经通过现代程序验证系统进行了严格验证。因此,现在是否可以通过应用程序验证技术来防止出现Heartbleed风格的错误,还是这是不现实的,甚至基本上是不可能的?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.