【问题标题】:GNATprove: "postcondition might fail" in simple functionGNATprove:简单函数中的“后置条件可能失败”
【发布时间】:2015-10-22 20:25:58
【问题描述】:

我想写一个简单的函数,在给定的整数数组中找到最大的数。这是规格:

package Maximum with SPARK_Mode is

   type Vector is array(Integer range <>) of Integer;

   function Maximum (A : in Vector) return Integer
     with
       SPARK_Mode,
       Pre => A'Length > 0,
         Post =>
         (for all i in A'Range => A(i) <= Maximum'Result)
         and then
           (for some i in A'Range => A(i) = Maximum'Result);

end Maximum;

这是函数的主体:

package body Maximum with SPARK_Mode is

   function Maximum (A : in Vector) return Integer
   is
   Max : Integer := A (A'First);
   begin
      if (A'Length = 1) then
         return Max;
      end if;

      for I in A'First + 1 .. A'Last loop
         pragma Loop_Invariant
           (for all Index in A'First .. I - 1 => Max >= A(Index));

         if A (I) > Max then
            Max := A (I);
         end if;
      end loop;

      return Max;
   end Maximum;

end Maximum;

当我尝试用 SPARK 证明这个函数时,它说后置条件可能会失败。我现在试图理解这一点 5 个小时,但我不知道为什么会这样说。这真的很烦人,这个功能必须工作。你知道为什么 SPARK 的行为如此奇怪吗?这个函数不满足其后置条件的数据示例是什么?它总是返回一个直接取自给定数组的值,并且总是最大值。

【问题讨论】:

  • 请注意 gnatprove 说“可能”。这并不意味着它有一个反例。只表示不能证明后置条件成立。

标签: ada gnat formal-verification spark-ada spark-2014


【解决方案1】:

你的错误是使循环不变量,它比后置条件弱:

规格:

package Maximum
  with SPARK_Mode
is

   type Vector is array (Integer range <>) of Integer;

   function Maximum (A : in Vector) return Integer
     with
       Pre  => A'Length > 0,
       Post => (for all i in A'Range => A(i) <= Maximum'Result)
               and
               (for some i in A'Range => A(i) = Maximum'Result);

end Maximum;

实施:

package body Maximum with SPARK_Mode is

   function Maximum (A : in Vector) return Integer
   is
   Max : Integer := A (A'First);
   begin
      if (A'Length = 1) then
         return Max;
      end if;

      for K in A'First + 1 .. A'Last loop
         pragma Loop_Invariant
           ((for all  I in A'First .. K - 1 => A (I) <= Max)
            and
            (for some I in A'First .. K - 1 => A (I) = Max));

         if A (K) > Max then
            Max := A (K);
         end if;
      end loop;

      return Max;
   end Maximum;

end Maximum;

项目文件:

project Maximum is
   for Main use ("maximum");
end Maximum;

【讨论】:

  • 是的,是的,谢谢!无论如何,在我提出这个问题后几个小时我就想通了,但我很高兴看到有人真的给出了一个很好的答案(我在发布这个问题 3 小时后获得了 5 次浏览)。顺便说一下,这些 SPARK 的信息非常具有误导性。
  • 我通常只在收到新问题的每日摘要时才查看问题,因此在 24 小时前得到我的回复很快。
猜你喜欢
  • 1970-01-01
  • 2020-10-31
  • 1970-01-01
  • 2023-01-25
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多