Ada GNAT 证明 1 不是 >= 0

如何解决Ada GNAT 证明 1 不是 >= 0

我试图证明,我在数组中查找第二大值的算法可以正常工作。这是我的代码:

function FindMax2 (V : Vector) return Integer is
    Max : Natural := 0;
    SecondMax : Natural := 0;
begin
    for I in V'Range loop

        pragma Assert
            (Max >= 0 and
            SecondMax >= 0 and
            V(I) > 0);

        if V(I) > Max then
            SecondMax := Max;
            Max := V(I);
        elsif V(I) /= Max and V(I) > SecondMax then
            SecondMax := V(I);
        end if;

        pragma Loop_Invariant
                    (Max > SecondMax and
                    V(I) > 0 and
                    (for all J in V'First .. I => V(J) <= Max));
    end loop;
    return SecondMax;
end FindMax2;

这是我的前置和后置条件:

package Max2 with SPARK_Mode is

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

    function FindMax2 (V : Vector) return Integer
    with
        Pre => V'First < Integer'Last and V'Length > 0,Post => FindMax2'Result >= 0 and
        (FindMax2'Result = 0 or (for some I in V'Range => FindMax2'Result = V(I))) and
        (if FindMax2'Result /= 0 then (for some I in V'Range => V(I) > FindMax2'Result)) and
        (if FindMax2'Result = 0 then (for all I in V'Range => (for all J in V'Range => V(I) = V(J)))
        else
            (for all I in V'Range => (if V(I) > FindMax2'Result then (for all J in V'Range => V(J) <= V(I)))));
end Max2;

我现在被 GNATprove 的这条消息困住了:

max2.ads:8:17: medium: postcondition might fail (e.g. when FindMax2'Result = 1 and V = (others => 1) and V'First = 0 and V'Last = 0)

如果我没记错,它是指结果大于或等于 0 的第一个条件,那么为什么它把 1 作为反例呢?有什么办法可以证明这一点吗?

解决方法

我设法解决了我的问题。我对错误消息的理解是错误的,gnatprove 指的是整个后置条件语句。如果有人对解决方案感兴趣,我在循环不变式中添加了一些条件

pragma Loop_Invariant
            (Max > SecondMax and
            V(I) > 0 and
            (for all J in V'First .. I => V(J) <= Max) and

            (Max = 0 or (for some J in V'First .. I => Max = V(J))) and
            (SecondMax = 0 or (for some J in V'First .. I => SecondMax = V(J))) and

            (if SecondMax = 0 then (for all J in V'First .. I => (for all K in V'First .. I => V(J) = V(K)))
            else (for all J in V'First .. I => (if V(J) > SecondMax then (for all K in V'First .. I => V(K) <= V(J))))));
,

请注意,实际答案是由 OP 自己 here 提供的。学分应该去那里。这只是我对这个好结果的评论的补充。

ma​​x2.ads

package Max2 with SPARK_Mode is

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


   function All_Same (V : Vector) return Boolean is
     (for all I in V'Range => (for all J in V'Range => V(I) = V(J)))
     with Ghost;

   function Elem_Of (V : Vector; X : Integer) return Boolean is
      (for some I in V'Range => V (I) = X)
       with Ghost; 

   function Is_Largest (V : Vector; X : Integer) return Boolean is
     (Elem_Of (V,X) and (for all I in V'Range => V (I) <= X))
       with Ghost;

   function Is_Second_Largest (V : Vector; X : Integer) return Boolean is
     (Elem_Of (V,X) and not Is_Largest (V,X) and
          (for all I in V'Range => V(I) <= X or else Is_Largest (V,V (I))))
       with Ghost;

   pragma Annotate (GNATprove,Inline_For_Proof,All_Same);
   pragma Annotate (GNATprove,Elem_Of);
   pragma Annotate (GNATprove,Is_Largest);
   pragma Annotate (GNATprove,Is_Second_Largest);


   procedure FindMax2 (V : Vector; Found : out Boolean; Value : out Natural)
     with Post => (if Found then Is_Second_Largest (V,Value) else All_Same (V));

end Max2;

ma​​x2.adb

package body Max2 with SPARK_Mode is
   
   --------------
   -- FindMax2 --
   --------------
   
   procedure FindMax2 
     (V     : in     Vector;
      Found :    out Boolean; 
      Value :    out Natural) 
   is
      L1 : Natural := 0;
      L2 : Natural := 0;
   begin      
      
      if V'Length > 1 then      
         for I in V'Range loop

            if L1 < V(I) then
               L2 := L1;
               L1 := V(I);
            elsif L2 < V(I) and V(I) < L1 then
               L2 := V(I);
            end if;

            pragma Loop_Invariant
              (L2 < L1);
           
            pragma Loop_Invariant
              (L1 = 0 or Elem_Of (V (V'First .. I),L1));
            pragma Loop_Invariant
              (L2 = 0 or Elem_Of (V (V'First .. I),L2));
            
            pragma Loop_Invariant
              (Is_Largest (V (V'First .. I),L1));
                    
            pragma Loop_Invariant
              (if L2 = 0 
               then All_Same (V (V'First .. I))
               else Is_Second_Largest (V (V'First .. I),L2));
         
         end loop;
      end if;
      
      Found := (L2 > 0);
      Value := L2;
      
   end FindMax2;

end Max2;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res