如何在嵌入双循环的函数上证明Ada/SPARK前提条件

如何在嵌入双循环的函数上证明Ada/SPARK前提条件,ada,doubly-linked-list,proofs,spark-2014,Ada,Doubly Linked List,Proofs,Spark 2014,我试图证明“prepend”的前提条件在下面程序的执行过程中成立。前提是: 长度(容器)正); 照明光源: 照明源包装清单(最大照明源); 端规格; 正文: 带规格;使用说明书; 与Ada.容器一起使用;使用Ada容器; 带SPARK_模式的主程序 是 开始 照明源包装清晰(照明源); 对于Y,在1。。500圈 pragma Loop_不变量(Y选择限制(我们将外循环和内循环上的限制分开,以明确): 包双循环 带火花点火模式 是 外极限:常数:=500; 内极限:常数:=500; 末端双U形环

我试图证明“prepend”的前提条件在下面程序的执行过程中成立。前提是:

长度(容器)
我试图证明这一点的代码以pragmas的形式出现在下面。我可以证明这个前提条件适用于单循环,但不适用于双循环。我找不到任何双循环的例子,尽管我找到了非常复杂的循环不变量的例子

规格:

使用Ada.Containers.Formal双链接列表;使用Ada容器;
SPARK_模式的封装规格为
最大照度源:常数计数类型:=250001;
包装照明_光源_包装是新的
Ada.Containers.Formal\u双链接\u列表
(元素类型=>正);
照明光源:
照明源包装清单(最大照明源);
端规格;
正文:

带规格;使用说明书;
与Ada.容器一起使用;使用Ada容器;
带SPARK_模式的主程序
是
开始
照明源包装清晰(照明源);
对于Y,在1。。500圈
pragma Loop_不变量(Y选择限制(我们将外循环和内循环上的限制分开,以明确):

包双循环
带火花点火模式
是
外极限:常数:=500;
内极限:常数:=500;
末端双U形环;
我们将通用包实例化为库级包:

pragma火花_模式;
使用Ada.Containers.Formal_双链接_列表;
包双_Loop.Lists是
新的Ada.Containers.Formal双链接列表(元素类型=>正数);
主程序的说明:

程序双_循环。以SPARK_模式运行;
然后是主程序的主体:

与Ada.Containers;
具有双循环列表;
使用SPARK_模式运行程序Double_Loop
使用所有类型Ada.Containers.Count_type;
数据:Lists.List(容量=>外部限制*内部限制);
开始
列表。清除(数据);
外部:
对于Ada.Containers.Count类型范围1.外部限制循环中的Y
内部:
对于Ada.Containers.Count_类型范围1.内部限制循环中的X
Lists.Prepend(容器=>Data,
新项目=>17);
pragma循环不变量
(长度(数据)=(Y-1)*内极限+X);
端环内;
pragma Loop_不变量(Lists.Length(Data)=Y*内部_限制);
端环外;
结束双_循环运行;

请注意,我是如何关注循环不变量列表长度的演变的

循环不变量的挑战是,它们必须从进入循环到循环不变量,从循环不变量到循环不变量,经过一次循环迭代再回到循环不变量都是可证明的。你能通过使用当前循环不变量?谢谢,这是一个很好的方法来可视化证明循环不变量所需的内容。我不能证明我上面的循环不变量,我想这是因为它们是错误的,X*Y不是当前迭代的计数。我希望第一次迭代是可证明的,但在第一次迭代之后是不可证明的,但事实恰恰相反。我在我的Bitbucket存储库中发布了我的答案,其中有SPARK 2014示例: