我们能否使用循环不变量来证明算法的正确性,在第一次迭代之后而不是之前证明它是正确的?

2024-01-24

CLRS 说

我们必须展示有关循环不变量的三件事:

  • 初始化:在循环的第一次迭代之前这是正确的。
  • 维护:如果在循环迭代之前为 true,则在下一次迭代之前它仍然为 true。
  • 终止:当循环终止时,不变量为我们提供了一个有用的属性,有助于表明算法是正确的。

我的问题是我可以编辑这些步骤并将其改为:

  • 初始化:在循环的第一次迭代之后这是正确的。
  • 维护:如果在循环迭代后为 true,则在下一次迭代后仍为 true。
  • 终止:当循环终止时,不变量为我们提供了一个有用的属性,有助于表明算法是正确的。

说明:基本上我们使用数学归纳原理来证明正确性。使用“初始化”,我们证明该属性在第一次迭代后成立。使用“维护”,我们可以表明该属性适用于所有迭代,因为“初始化”和“维护”一起创建了一条链。因此该属性在最后一次迭代后也保持不变。

例子:

RANDOMIZE-IN-PLACE(A) 
1 n ← length[A] 
2 for i ← to n
3 do swap A[i] ↔ A[RANDOM(i, n)]

对于这个算法,教科书上已经给出了使用标准程序的证明(由于太长,我没有将其包含在此处)。

我的建议:

  • Loop Invariant: Just after the ith iteration of the for loop of lines 2-3, for each possible (i)-permutation, the subarray A[1 .. i] contains this (i)-permutation with probability (n - i)!/n!.
  • Initialization: After 1st iteration A[1] contains this permutation with probability (n-1)!/n!=1/n which is true.
  • Maintenance: Let it be true after (i-1)th iteration. After (i)th iteration, A[1...i] contains this permutation with probability [(n-i+1)!/n!]*[1/(n-i+1)]=(n-i)!/n! which is what we want.
  • 终止:终止时,i = n,并且子数组 A[1 .. n] 是给定的 n 排列,概率为 (n - n)!/n! = 1/n!.因此,RANDOMIZE-IN-PLACE 产生均匀的随机排列。

我的解释逻辑合理吗?

任何帮助将不胜感激。谢谢。


除了您必须执行额外的步骤(覆盖根本不运行的循环)这一事实之外,您当然还可以在第一次迭代之后证明不变量为真,而不是在第一次迭代之前证明它为真。

但我怀疑这通常是否有意义

  • 首先,正如已经说过的,您已经有一个特殊情况(如果根本不执行循环会发生什么),这可能会导致一个类似于初始化的证明,您首先想跳过它
  • 其次,第一次迭代后不变式为真的证明很可能与维护证明非常相似,因此您可能会编写两个非常相似的证明,只是为了跳过初始化,这很可能是一个相当大的过程。简单的证明。

Analogy

尽管这没有直接关系,但这个问题听起来很像尝试优化以下(伪)代码:

int product(int[] values)
    product = 1
    for i = 0 to values.size - 1
        product *= values[i]
    return product

To this:

int product(int[] values)
    product = values[0] // to make the code quicker, start with the first item already
    for i = 1 to values.size - 1 // start the loop at the second item
        product *= values[i]
    return product

只是,你现在必须包括额外的检查,是否values数组为空(我在上面的代码中没有)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我们能否使用循环不变量来证明算法的正确性,在第一次迭代之后而不是之前证明它是正确的? 的相关文章

  • iOS心率检测算法

    我正在尝试在我正在开发的应用程序中实现心跳记录功能 首选方法是使用 iPhone 的摄像头 在灯亮的情况下 让用户将手指放在镜头上 然后检测视频源中与用户心脏相对应的波动 我通过以下堆栈溢出问题找到了一个非常好的起点here https s
  • 如何计算python 2D散点占用面积

    我使用 matplotlib 绘制了这两个 2000 个点的序列 从图片上看 前2000点占用的面积比后2000点要小 但如果我想定量计算2000个点的第一序列和第二序列占用了多少面积 该怎么办 我真的很感谢任何帮助 建议或意见 非常感谢
  • 算法 - 如何有效删除列表中的重复元素?

    有一个list L 它包含以下元素任意类型each 如何有效删除此类列表中的所有重复元素 必须保留订单 只需要一个算法 因此不允许导入任何外部库 相关问题 在Python中 从列表中删除重复项以使所有元素都是唯一的最快算法是什么在维持秩序的
  • 找到不(必要)与二进制矩阵中的图像边界对齐的最大矩形

    我在用这个解决方案 https stackoverflow com questions 2478447 find largest rectangle containing only zeros in an nn binary matrix在
  • 对矩阵进行舍入,保留行和列总计

    想要 以保留行和列总计的方式对矩阵进行舍入的 伪 代码 问题从向量开始 X and Y of 非负整数 with Sum X Sum Y 想要圆X Y Sum X 同时保留行和列总计 这是婚姻问题的一种 Xa需要进行一定次数的握手 拨打该号
  • 快速排序应用程序中这些交换代码行的目的是什么?

    我试图理解快速排序的实现或应用程序以找到第 k 个最小元素 这是我试图理解的代码 public int quicksort int a int start int end int k if start lt end int pivot pa
  • 如何设计一种算法来计算倒数式数学数字难题

    我一直想这样做 但每次我开始思考这个问题时 它的指数性质都会让我大吃一惊 我希望能够理解的问题解决器和代码是针对倒计时数学问题的 给定一组数字 X1 到 X5 计算如何使用数学运算将它们组合起来生成 Y 您可以应用乘法 除法 加法和减法 那
  • 如何在单向链表(一次遍历中)中从尾部获取第 n 个节点?

    所以我在一次考试中得到了这个问题 如何从单链表的尾部获取第 n 个节点 每个节点都有一个值和一个下一个 指向下一个值的指针 我们得到这个 getNodeFromTail Node head int x 所以我的做法是通过遍历一次来求出列表的
  • 运行时间为 O(n) 且就地排序的排序算法

    有没有运行时间为O n 并且还分类到位 在某些情况下 最好的情况是 O n 但这可能是因为项目集合已经排序 你正在看 O nlogn 一些较好的平均值 话虽如此 排序算法的 Wiki 还是相当不错的 有一个表格比较了流行的算法 说明了它们的
  • 当平方和为N时,如何找到四个变量的所有可能值?

    A 2 B 2 C 2 D 2 N给定一个整数N 打印出整数值的所有可能组合ABCD求解方程 我猜我们可以比暴力做得更好 天真的暴力会是这样的 n 3200724 lim sqrt n 1 for a 0 a lt lim a for b
  • 处理流星中的长服务器端计算

    我正在使用 jimp https www npmjs com package jimp https www npmjs com package jimp 在meteor JS中生成图像服务器端 换句话说 我正在使用递归算法 计算 图像的像素
  • 填充体积算法

    我有一个具有一定尺寸长度 宽度 高度的盒子 我有不同长度 宽度 高度的物品 是否有现有的算法可以确定放入盒子中的最佳物品 这称为装箱 切割库存 背包问题 并且是 NP 难问题 一般来说 您只能通过使用启发式方法获得近似解 请参见示例 htt
  • 序列和与 GCD

    大约一个月前 我在编程挑战中遇到了这个问题 但社论尚未发布 所以我在这里问 有一个大小为 N 的数组 A 求 A 的 K 个长度子序列的总和 GCD Example 如果 A 1 2 3 且 K 2 1 2 3 总和 1 GCD 3 1 3
  • 素数生成器算法

    我一直在尝试解决素数生成算法的SPOJ问题 这是问题 彼得想为他的密码系统生成一些素数 帮助 他 你的任务是生成两个给定之间的所有素数 数字 Input 输入以单行中测试用例的数量 t 开始 t Output 对于每个测试用例 打印所有素数
  • 自动跟踪算法

    我正在尝试写一个simple跟踪例程来跟踪电影中的某些点 本质上我有一系列 100 帧长的电影 在黑暗背景上显示一些亮点 我每帧有大约 100 150 个点 它们在电影的过程中移动 我想跟踪它们 所以我正在寻找一些有效的 但可能不会过度实施
  • Python Pandas:沿一列比较两个数据帧,并返回另一个数据帧中两个数据帧的行内容

    我正在处理两个 csv 文件并作为数据框 df1 和 df2 导入 df1 有 50000 行 df2 有 150000 行 我想将 df2 的 时间 与 df1 求时间差并返回所有列的值 对应相似的行 保存在df3中 时间同步 例如 35
  • 是否有一种算法可以在线性时间内计算数组反转?

    我知道有多少倒转 en wikipedia org wiki Inversion 28discrete mathematics 29 in an n 元素数组可以在 O n log n 操作使用增强型归并排序 http www geeksf
  • 为什么这个算法的Big-O复杂度是O(n^2)?

    我知道这个算法的大O复杂度是O n 2 但我不明白为什么 int sum 0 int i 1 j n n while i lt j sum 即使我们设定了j n n一开始 我们在每次迭代期间递增 i 并递减 j 因此最终的迭代次数不应该比n
  • 如何光栅化旋转矩形(通过 setpixel 在 2d 中)

    我有四个 2d 顶点 A B C D 的旋转矩形 我需要在像素缓冲区中 有效地 光栅化 绘制它 使用 setpixel x y 颜色 怎么做 我正在尝试使用一些代码 例如 convertilg a b c d do up down left
  • 总和不小于 key 的数组的最小子集

    给定一个数组 假设为非负整数 我们需要找到最小长度子集 使得元素之和不小于 K K 是作为输入提供的另一个整数 是否有可能找到时间复杂度为 O n n 的大 oh 的解决方案 我目前的想法是这样的 我们可以在 O n log n 中对数组进

随机推荐