A Dafny solution to the Sum and Max verification benchmark. I added some additional specification to verify that the result max
is really the maximum and the sum
is really the sum.
method SumMax(a: array<int>) returns (sum:int, max:int) requires a != null; requires a.Length >= 0; requires forall i :: 0 <= i < a.Length ==> a[i] >= 0; ensures sum <= a.Length*max; ensures forall i :: 0 <= i < a.Length ==> a[i] <= max; ensures a.Length == 0 || (exists i :: 0 <= i < a.Length && a[i] == max); ensures sum == Sum(a); { max := 0; sum := 0; var idx:int := 0; while idx<a.Length invariant idx <= a.Length; invariant forall i :: 0 <= i < idx ==> a[i] <= max; invariant (idx==0 && max==0) || exists i :: 0 <= i < idx && a[i] == max; invariant sum <= idx*max; invariant sum == Sum'(a, 0, idx); { if (max < a[idx]) { max := a[idx]; } sum := sum + a[idx]; idx := idx + 1; } } function Sum(a: array<int>) : int reads a; requires a != null; { Sum'(a, 0, a.Length) } function Sum'(a: array<int>, i:int, j:int) : int reads a; requires a != null; requires 0 <= i <= j <= a.Length; { if j == i then 0 else Sum'(a, i, j-1) + a[j-1] } lemma SumOfIntervalOneIsElement(a: array<int>, i:int) requires a != null; requires 0 <= i < a.Length; ensures a.Length > 0; ensures Sum'(a, i, i+1) == a[i]; { } lemma SumOfIntervalIsSumOfSubIntervals (a: array<int>, i:int, j:int, k:int) requires a != null; requires 0 <= i <= j <= k <= a.Length; ensures Sum'(a, i, j) + Sum'(a, j, k) == Sum'(a, i, k); { } |