CSE 331: Software Design and Implementation, Autumn 2026
Your job is to deliver code that you know works.
{{ P }} code {{ Q }}P leads to a state satisfying Q.x0 for the old value{{ P }} x = e; {{ P[x ↦ x0] and x = e[x ↦ x0] }}{{ Q[x ↦ e] }} x = e; {{ Q }}{{ P }}
{{ A }}
code
{{ B }}
{{ Q }}{{ P }} code {{ Q }} is valid. Break it down:{{ A }} code {{ B }} is valid,{{ P }}
if (b) {
{{ P and b }}
first
{{ A }}
} else {
{{ P and not b }}
second
{{ B }}
}
{{ A or B }}
{{ Q }}or.Q.abs (on the slide):9/**
10 * Gives the absolute value of a number.
11 *
12 * @param n the number
13 * @requires -2147483647 <= n
14 * @return n if 0 <= n, and -n if n < 0
15 */16int abs(int n) {
{{ n = n0 }}
17 if (n < 0) {
{{ n = n0 and n < 0 }}
18 n = -n;
{{ n0 < 0 and n = -n0 }}
19 }
{{ (n0 < 0 and n = -n0) or
(0 <= n0 and n = n0) }}
20 return n;
21}n0 < 0 and n = -n0-n0, which equals n.0 <= n0 and n = n0n0, which equals n.abs satisfies its specification6/**
7 * Adds up the elements of an array.
8 *
9 * @param a the array
10 * @return a[0] + ... + a[a.length - 1],
11 * the sum of the elements
12 */
13long sum(int[] a) {13long sum(int[] a) {
14 long s = 0;
15 int i = 0;
16 while (i < a.length) {
17 s = s + a[i];
18 i = i + 1;
19 }
20 return s;
21}0 < a.length and i = 1 and s = a[0]0 < a.length and 1 < a.length and i = 2 and s = a[0] + a[1]sum on {3, 4, 5}: one row each time line 16 checks its condition
| check | i | s | i < a.length | s = a[0] + ... + a[i - 1] |
|---|---|---|---|---|
| 1 | 0 | 0 | 0 < 3: true | true: 0 is the sum of no terms |
| 2 | 1 | 3 | 1 < 3: true | true: 3 = 3 |
| 3 | 2 | 7 | 2 < 3: true | true: 7 = 3 + 4 |
| 4 | 3 | 12 | 3 < 3: false | true: 12 = 3 + 4 + 5 |
0 <= i and i <= a.lengthi starts at 0; only line 18 changes it, by adding 1i < a.length: after it, i <= a.lengths = a[0] + ... + a[i - 1]i and s are 0: the sum of no termsa[i] to s: the first i + 1 elementsi: again the first i elementsDefinition: loop invariant
A loop invariant of while (b) { body } is an assertion that
holds each time the loop checks condition b.
Before the first iteration, between iterations, and after the last.
13long sum(int[] a) {
14 long s = 0;
15 int i = 0;
{{ Inv: 0 <= i and i <= a.length and
s = a[0] + ... + a[i - 1] }}
16 while (i < a.length) {
17 s = s + a[i];
18 i = i + 1;
19 }
20 return s;
21}Inv: puts I at the condition check, not before the loop{{ P }}
{{ Inv: I }}
while (b) {
{{ I and b }}
body
{{ I }}
}
{{ I and not b }}
{{ Q }}b is the loop's condition.
I is a claim the programmer supplies.
The triple {{ P }} while ... {{ Q }}
is valid if three checks pass:
(1) P implies I.
(2) The triple {{ I and b }} body {{ I }}
is valid.
(3) I and not b implies Q.
I and bb is false, so I and not b after the loopsum: Wednesday's rules check itlong s = 0;
int i = 0;
while (i < a.length) {
s = s + a[i];
i = i + 1;
}
return s;13long sum(int[] a) {
{{ true }}
14 long s = 0;
{{ s = 0 }}
15 int i = 0;
{{ s = 0 and i = 0 }}
{{ Inv: 0 <= i and i <= a.length and
s = a[0] + ... + a[i - 1] }} {{ Inv: 0 <= i and i <= a.length and
s = a[0] + ... + a[i - 1] }}
16 while (i < a.length) {
{{ 0 <= i and i <= a.length and
s = a[0] + ... + a[i - 1] and i < a.length }}
17 s = s + a[i];
{{ 0 <= i and i < a.length and s = a[0] + ... + a[i] }}
18 i = i + 1;
{{ 1 <= i and i <= a.length and
s = a[0] + ... + a[i - 1] }}
19 }
{{ 0 <= i and i <= a.length and
s = a[0] + ... + a[i - 1] and not (i < a.length) }}
{{ s = a[0] + ... + a[a.length - 1] }}
20 return s;
21}0 <= i since i = 0
i <= a.length since i = 0 and 0 <= a.length
a[0] + ... + a[i - 1] = 0 since i = 0: the sum of no terms
= s since s = 0s = 0 and i = 0, has to imply I{{ I and i < a.length }} s = s + a[i]; i = i + 1; {{ I }}s0, the old ss = s0 + a[i] the forward rule
= a[0] + ... + a[i - 1] + a[i] since s0 = a[0] + ... + a[i - 1]
= a[0] + ... + a[i]i <= a.length dropped:0 <= i and i < a.length and s = a[0] + ... + a[i]i is i - 1i - 1 for i in each fact of the claim between the lines0 <= i - 1 from 0 <= i
1 <= i adding 1 to both sides
i - 1 < a.length from i < a.length
i <= a.length since i and a.length are integers
s = a[0] + ... + a[i - 1] from s = a[0] + ... + a[i]1 <= i implies 0 <= ia.length <= i since not (i < a.length)
i = a.length since i <= a.length
s = a[0] + ... + a[i - 1] from I
= a[0] + ... + a[a.length - 1] since i = a.lengthi = a.length used i <= a.lengtha.length <= i, not i = a.lengthsum is validi = i + 1; s = s + a[i];?14long s = 0;
15int i = 0;
16while (i < a.length) {
17 s = s + a[i];17 i = i + 1;
18 i = i + 1;18 s = s + a[i];
19}
20return s;{{ Inv: 0 <= i and i <= a.length and
s = a[0] + ... + a[i - 1] }}sum: a.length - i, the elements not yet addeda.length and i are intsi <= a.lengthia.length passes: sum satisfies its specificationtrue for Itruetrue and not true has to imply Qfalse: the checks would prove the postcondition falsesum has been given to uss = a[0] + ... + a[a.length - 1]i is the count of elements added so fari for a.length in Q: the main fact of Is = a[0] + ... + a[i - 1]i = a.length, so the main fact turns back into Qi starts and where it stops:0 <= i: line 15 starts i at 0i <= a.length: a pass runs only when i < a.lengthi <= a.lengths = a[0] + ... + a[i - 1]0 <= i and i <= a.lengthsumTo.13long sumTo(int n) {
14 long s = 0;
15 int i = 0;
16 while (i < n) {
17 i = i + 1;
18 s = s + i;
19 }
20 return s;
21}i <= a.length from sum's I0 < a.length to sum's Isum is right, so both times the claim is what has to changeSum in prosesum is the second loop of Sumsum, that sentence is now one claim, the invariantint wraps: so a bound on the inputs, or a longYour job is to deliver code that you know works.