我正在try 通过用Python语言编写的真实示例来理解编程中的不变量.我对在哪里放置assert条语句来判断不变量感到困惑.

我的研究显示了在哪里判断不变量的不同模式.例如:

before the loop starts
before each iteration of the loop
after the loop terminates

VS

... // the Loop Invariant must be true here
while ( TEST CONDITION ) {
// top of the loop
...
// bottom of the loop
// the Loop Invariant must be true here
}
// Termination + Loop Invariant = Goal

下面我给出了一本数学书中一个不变例子的代码.有两个版本,一个使用函数,另一个不使用函数.我希望这不会有什么不同,但我想要彻底.

我的问题是:

  • 为了与不变量保持一致,我至少需要多少个断言状态来确保程序的正确性?
  • 在我的示例中,哪些断言语句是多余的?
  • 如果上述问题有多个答案,哪一个将被认为是最佳实践?

理想情况下,我希望看到重写我的代码,包括最好的实践和对我在工作中迄今可能忽略的任何问题的关注.

非常感谢您提供的任何意见.

下面是练习:

E2. Suppose the positive integer n is odd. First Al writes the numbers 1, 2,..., 2n on the blackboard. Then he picks any two numbers a, b, erases them, and writes, instead, |a − b|. Prove that an odd number will remain at the end.

Solution. Suppose S is the sum of all the numbers still on the blackboard. Initially this sum is S = 1+2+···+2n = n(2n+1), an odd number. Each step reduces S by 2 min(a, b), which is an even number. So the parity of S is an invariant. During the whole reduction process we have S ≡ 1 mod 2. Initially the parity is odd. So, it will also be odd at the end.

import random

def invariant_example(n):
    xs = [x for x in range(1, 2*n+1)]
    print(xs)
    assert sum(xs) % 2 == 1
    while len(xs) >= 2:
        assert sum(xs) % 2 == 1
        a, b = random.sample(xs, 2)
        print(f"a: {a}, b: {b}, xs: {xs}")
        xs.remove(a)
        xs.remove(b)
        xs.append(abs(a - b))
        assert sum(xs) % 2 == 1
    assert sum(xs) % 2 == 1
    return xs
    
print(invariant_example(5))

n = 5
xs = [x for x in range(1, 2*n+1)]
print(xs)
assert sum(xs) % 2 == 1
while len(xs) >= 2:
    assert sum(xs) % 2 == 1
    a, b = random.sample(xs, 2)
    print(f"a: {a}, b: {b}, xs: {xs}")
    xs.remove(a)
    xs.remove(b)
    xs.append(abs(a - b))
    assert sum(xs) % 2 == 1
assert sum(xs) % 2 == 1
print(xs)

推荐答案

您拥有的唯一technically个冗余的assert语句是循环中的任一语句.也就是说,really并不是两个都需要.

例如:

如果两者都有,则While循环中的第一个assert将在第二个之后立即执行(因为代码将返回到循环的顶部).两次调用之间不会更改任何值,因此第一个assert语句的结果将始终与第二个assert语句的结果相同.

最佳实践可能是将assert放在循环的顶部,以防止在违反循环不变量时执行循环内的代码.

编辑:正如Kelly Bundy所指出的,最后的断言语句还应该包括循环退出条件.我忘了在上面提到这一点.

Python相关问答推荐

如何使用数组的最小条目拆分数组

如何创建一个缓冲区周围的一行与manim?

将JSON对象转换为Dataframe

使用Python从URL下载Excel文件

Python列表不会在条件while循环中正确随机化'

try 检索blob名称列表时出现错误填充错误""

在不同的帧B中判断帧A中的子字符串,每个帧的大小不同

Gekko中基于时间的间隔约束

Flask运行时无法在Python中打印到控制台

当单元测试失败时,是否有一个惯例会抛出许多类似的错误消息?

使用类型提示进行类型转换

如何设置nan值为numpy数组多条件

以极轴表示的行数表达式?

具有不匹配列的2D到3D广播

生产者/消费者-Queue.get by list

PANDA:如何将多选列转换为索引/列

使用pyopencl、ArrayFire或另一个Python OpenCL库制作基于欧几里得距离的掩模

日志(log)轴上的自定义刻度出现意外的次要刻度标记行为

达到最大的Python Webhost资源

有没有更python的方法来复制python中列表的第n个元素?例如,使用列表理解