/*@ @*/ /*@ In the following we consider arrays of maximum length N whose elements are natural numbers of maximum size M: @*/ //@ val N = /*@@*/4/*@@*/; // choose small values val M = /*@@*/1/*@@*/; type int = ℕ[N]; type elem = ℕ[M]; type array = Array[N,elem]; /*@ Specify a procedure "merge(a,na,b,nb)" that takes two arrays a and b of size na and nb, respectively, where na+nb is less than equal N and both a and b are sorted in ascending order. The procedure returns an array c of size na+nb which represents the "merged" version of a and b: c is also sorted in ascending order and contains all elements of a and b. In detail, define the precondition pre(a,na,b,nb) and postcondition post(a,na,b,nb,c) of the procedure (it is recommended, to define an auxiliary predicate sorted(a,n) that states that array a is sorted in the first n positions): @*/ //@ pred sorted(a:array, n:int) ⇔ ∀i:int with 0 ≤ i ∧ i+1 < n. a[i] ≤ a[i+1] ; pred pre(a:array, na:int, b:array, nb:int) ⇔ na+nb < N ∧ sorted(a,na) ∧ sorted(b,nb) ; pred post(a:array, na:int, b:array, nb:int, c:array) ⇔ sorted(c,na+nb) ∧ (∃p:Array[N,ℕ[N]]. (∀i:int, j:int with i < j ∧ j < na+nb. p[i] ≠ p[j]) ∧ (∀i:int with i < na+nb. let j=p[i] in j < na+nb ∧ if j < na then c[i]=a[j] else c[i]=b[j-na])) ; //@ //@ fun result(a:array, na:int, b:array, nb:int):array requires pre(a,na,b,nb); = choose c:array with post(a,na,b,nb,c); theorem satisfiable(a:array, na:int, b:array, nb:int) requires pre(a,na,b,nb); ⇔ ∃c:array. post(a,na,b,nb,c); theorem nottrivial() ⇔ ∃a:array, na:int, b:array, nb:int with pre(a,na,b,nb). ∃c:array. ¬post(a,na,b,nb,c); theorem unique(a:array, na:int, b:array, nb:int) requires pre(a,na,b,nb); ⇔ ∀c1:array with post(a,na,b,nb,c1). ∀c2:array with post(a,na,b,nb,c2). ∀i:int with 0 ≤ i ∧ i < na+nb. c1[i] = c2[i]; //@First investigate your specification: /*@ @*/ //@Now further validate your specification: /*@ @*/ //@ /*@ @*/ /*@ Now check whether post() define the first na+nb elements of the result array uniquely (the remaining elements are not of interest): @*/ /*@ @*/ proc merge(a:array, na:int, b:array, nb:int): array { var c:array = Array[N,elem](0); var ia:int ≔ 0; var ib:int ≔ 0; for var i:int = 0; i Finally check whether your specification specifies merge(a,na,b,nb) adequately: @*/ /*@ @*/ //@ /*@ @*/