严格证明以下C ++代码的属性?

时间:2018-01-08 13:45:44

标签: c++ static-analysis coq proof-of-correctness

采用以下C ++ 14代码段:

unsigned int f(unsigned int a, unsigned int b){
    if(a>b)return a;
    return b;
}

声明: 函数f返回其参数的最大值。

现在,声明显然是"显然"是的,但我未能就 ISO / IEC 14882:2014(E)规范严格证明这一点。

首先:我不能以正式的方式陈述财产。

正式版可以是: 对于每个语句 s ,当抽象机器(在规范中定义)处于状态 P s 看起来像&#34 F( expr_a expr_b )"和' f'在 s 中解析为有问题的函数, s(P).return = max(expr_a(P).return,expr_b(P).return)

此处对于状态 P 和表达式 s s(P)是评估 s后机器的状态

问题:该陈述的正确形式化版本是什么?如何使用上述规范强加的属性来证明声明?对于每个演绎步骤,请参考标准中适用的片段,允许所述步骤(片段的数量足够)。

编辑:可能在Coq中正式化

3 个答案:

答案 0 :(得分:4)

请为我近似老化的数学知识道歉。

自然数(BN)的闭合子集的最大值可以定义如下:

Max:(BN,BN) -> BN
(x ∊ BN)(a ∊ BN)(b ∊ BN)(x = Max(a,b)) => ( x=a & a>b | x=b )

符号具有共同的数学意义。

虽然你的功能可以改写如下,但联合国是unsigned int的整体:

f:(UN,UN) -> UN
(x ∊ UN)(a ∊ UN)(b ∊ UN)(x = f(a,b)) => ( x=a && a>b || x=b )

其中symbol =是operator==(unsigned int,unsigned int)等等......

因此,问题是减少知道标准是否指定由unsigned integer与C ++算术运算符和比较运算符形成的数学结构同构到物质结构(类) ,类别)由一个封闭的N子集与共同的arithemtic操作和关系形成。我认为答案是肯定的,用普通英语表达:

C ++ 14标准,[expr.rel]/5(关系运算符)

  

如果两个操作数(转换后)都是算术或枚举类型,则每个运算符如果指定的关系为真,则应生成true,如果为假,则为false

C ++ 14标准,[basic.fundamental]/4(基本类型)

  

无符号整数应遵守算术模2n的定律,其中n是特定整数大小的值表示中的位数。

然后您还可以通过分析{{3中的文本 - 来证明({truefalse},&&||)也与布尔算术同构}}  和[expr.log.and]

我认为你不应该进一步表明存在这种同构,因为进一步意味着展示公理。

答案 1 :(得分:2)

在我看来,最简单的解决方案是向后证明这一点。如果f的第一个参数是最大参数,则证明返回了第一个参数(相当简单 - 根据定义,最大参数a大于b)。如果第二个参数是最大参数,则证明返回第二个参数。如果两者相等,则表明没有唯一的最大元素,因此第二个参数仍然是 a 最大参数。

最后,证明这三个选项都是详尽无遗的。如果传递了唯一的最大参数,则必须将其作为第一个或第二个参数传递,因为f是二进制的。

答案 2 :(得分:1)

我不确定你想要什么。查看以前的版本N3337,我们可以很容易地看到几乎所有内容都已指定:

  • a和b以调用值(功能5.2.2 - 4)
  • 开头
  • 调用函数执行函数体的复合语句(Obvious,但where?)
  • 这些陈述通常按顺序执行(陈述6)
  • 如果条件为真,则if语句执行第一个子语句(If语句6.4.1)
  • 关系实际上按预期工作(关系运算符5.9 - 5)
  • return语句将值返回给函数的调用者(返回语句6.6.3)

但是,您尝试以f(expr_a,expr_b)开头;并且评估f的论据可能需要更多;特别是因为它们没有排序 - 可能是任何函数调用。