automatedprogramverificationandtesting 15414/15614fall2016...
TRANSCRIPT
Automated Program Verification and Testing15414/15614 Fall 2016Lecture 15:Midterm Review & Total Correctness
Matt [email protected]
October 25, 2016
Matt Fredrikson Deductive Verification 1 / 42
Today’s Lecture
▶ Go over the midterm
▶ Review path conditions & related verification conditions
▶ VCs for total correctness
Matt Fredrikson Deductive Verification 2 / 42
Problem 1
The formula is valid
P Q R F1 : P ∧Q F2 : ¬F1 ¬R F3 : ¬R → Q F4 : R → F3 F5 : F2 → F4
0 0 0 0 1 1 0 1 10 0 1 0 1 0 1 1 10 1 0 0 1 1 1 1 10 1 1 0 1 0 1 1 11 0 0 0 1 1 0 1 11 0 1 0 1 0 1 1 11 1 0 1 0 1 1 1 11 1 1 1 0 0 1 1 1
If you assumed different associativity of →, we didn’t take points off
Matt Fredrikson Deductive Verification 3 / 42
Problem 2
The formula can be expressed as ¬(¬F1 ∧ ¬F2)
So, we want to disprove I ̸|= F1 ∨ F2 ↔ ¬(¬F1 ∧ ¬F2)
Recalling the rule for ↔, there are two cases to considerI ̸|= F ↔ G
I |= F ∧ ¬G | I |= ¬F ∧G
Matt Fredrikson Deductive Verification 4 / 42
Problem 2, First Case
Step Reason1. I ̸|= F1 ∨ F2 ↔ ¬(¬F1 ∧ ¬F2) assumption
2a. I |= (F1 ∨ F2) ∧ ¬¬(¬F1 ∧ ¬F2) 1 and ↔ , case a3a. I |= F1 ∨ F2 2a and ∧4a. I |= ¬¬(¬F1 ∧ ¬F2) 2a and ∧5a. I ̸|= ¬(¬F1 ∧ ¬F2) 4a and ¬6a. I |= ¬F1 ∧ ¬F2 5a and ¬7a. I |= ¬F1 6a and ∧8a. I |= ¬F1 6a and ∧9a. I ̸|= F1 7a and ¬10a. I ̸|= F2 8a and ¬
11aa. I |= F1 3a, case a12aa. ⊥ 11aa and 9a11ab. I |= F2 3a, case b12ab. ⊥ 11ab and 10a
Matt Fredrikson Deductive Verification 5 / 42
Problem 2, Second Case
Step Reason1. I ̸|= F1 ∨ F2 ↔ ¬(¬F1 ∧ ¬F2) assumption2b. I |= ¬(F1 ∨ F2) ∧ ¬(¬F1 ∧ ¬F2) 1 and ↔ , case b3b. I |= ¬(F1 ∨ F2) 2b and ∧4b. I |= ¬(¬F1 ∧ ¬F2) 2b and ∧5b. I ̸|= F1 ∨ F2 3b and ¬6b. I ̸|= ¬F1 ∧ ¬F2 4b and ¬7b. I ̸|= F1 5b and ∨8b. I ̸|= F2 5b and ∨
8ba. I ̸|= ¬F1 6b and ∧ , case a9ba. I |= F1 8ba and ¬10ba. ⊥ 7b and 9ba8bb. I ̸|= ¬F2 6b and ∧ , case b9bb. I |= F2 8bb and ¬10bb. ⊥ 8b and 9bb
Matt Fredrikson Deductive Verification 6 / 42
Problem 3
(¬P ∨Q ∨R) ∧ (¬Q ∨R) ∧ (¬Q ∨ ¬R) ∧ (P ∨ ¬Q ∨ ¬R)
Step State Reason1. ∅ init.2. Q◦ decide Q3. Q◦, R propagate ¬Q ∨R4. Q confl. ,¬Q ∨ ¬R; backtrack5. Q, P ◦ decide P6. Q, P,R propagate ¬P ∨Q ∨R7. sat
Matt Fredrikson Deductive Verification 7 / 42
Problem 4
(∀j.a[j] = b⟨i ◁ v⟩[j]) ∧ a[i] ̸= v
This formula is in the fragment, because it is equivalent to:(∀j.true → a[j] = b⟨i ◁ v⟩[j]) ∧ a[i] ̸= v
Recall, we said that extensionality was in the fragment:∀i.a[i] = b[i]
Both formulas have a trivial index guard
Matt Fredrikson Deductive Verification 8 / 42
Problem 4
We showed an algorithm for removing quantifiers in lecture 81. F1: Put F in negation normal form2. F2: Remove all write terms from F1
3. F3: Remove existential quantifiers from F2
4. Select a sufficient set of index terms I5. F4: Transform ∀ into conjunction using I
This gives us a quantifier-free TEUF formula
No points off if you skipped step 2 on the exam
Matt Fredrikson Deductive Verification 9 / 42
Problem 4
First, we remove the write operation by applying:
F [a⟨i ◁ v⟩]F [a′] ∧ a′[i] = v ∧ (∀j.j ̸= i → a[j] = a′[j])
For fresh a′
This leaves us with:(∀j.a[j] = b′[j]) ∧ a[i] ̸= v ∧ b′[i] = v ∧ (∀j.i ̸= j → b′[j] = b[j])
We then need to find the index set
I ={λ}
∪ {t | · [t] ∈ F and t is not ∀-quantified }∪ {t | t is an evar in an index guard of F }
So, I = {λ, i}
Matt Fredrikson Deductive Verification 10 / 42
Problem 4
Now the important step: remove ∀
H[∀i.F [i] → G[i]]
H[∧
i∈I(F [i] → G[i])]
This gives us: ∧j∈{λ,i}
a[j] = b′[j]
∧a[i] ̸= v∧b′[i] = v∧
∧j∈{λ,i}
i ̸= j → b′[j] = b[j]
∧λ ̸= i
We remove the “big” conjunction:
a[i] = b′[i] ∧ a[λ] = b′[λ] ∧ a[i] ̸= v ∧ b′[i] = v ∧ i ̸= i → b′[i] = b[i]
∧ i ̸= λ → b′[λ] = b[λ] ∧ λ ̸= i
And finally, simplify to:a[i] = b′[i] ∧ a[λ] = b′[λ] ∧ a[i] ̸= v ∧ b′[i] = v ∧ b′[λ] = b[λ] ∧ λ ̸= i
Matt Fredrikson Deductive Verification 11 / 42
Problem 5
The following formula is valid if and only if the translation is correct:(v1 = f(x1, y1)∧v2 = f(x2, y2)∧z = g(v1, v2)) → z = g(f(x1, y1), f(x2, y2))
Our formula is of the form ϕ1 → ϕ2
We know that if ϕ1 ∧ ϕ2 is sat, then so is ϕ1 → ϕ2
So we find a satisfying interpretation for:(v1 = f(x1, y1)∧v2 = f(x2, y2)∧z = g(v1, v2))∧z = g(f(x1, y1), f(x2, y2))
Matt Fredrikson Deductive Verification 12 / 42
Problem 5
Computing the congruence closure:
{{v1}, {v2}, {x1}, {x2}, {y1}, {y2}, {z}, {f(x1, y1)}, {f(x2, y2)}, {g(v1, v2)}, {g(f(x1, y1), f(x1, y1))}}
{{v1, f(x1, y1)}, {v2}, {x1}, {x2}, {y1}, {y2}, {z}, {f(x2, y2)}, {g(v1, v2)}, {g(f(x1, y1), f(x1, y1))}}
{{v1, f(x1, y1)}, {v2, f(x2, y2)}, {x1}, {x2}, {y1}, {y2}, {z}, {g(v1, v2)}, {g(f(x1, y1), f(x1, y1))}}
{{v1, f(x1, y1)}, {v2, f(x2, y2)}, {x1}, {x2}, {y1}, {y2}, {z, g(v1, v2)}, {g(f(x1, y1), f(x1, y1))}}
{{v1, f(x1, y1)}, {v2, f(x2, y2)}, {x1}, {x2}, {y1}, {y2}, {z, g(v1, v2), g(f(x1, y1), f(x1, y1))}}
Matt Fredrikson Deductive Verification 13 / 42
Problem 6
We discussed the following definition for program equivalence:
∀σ, σ′.⟨c1, σ⟩ ⇓ σ′ ⇔ ⟨c2, σ⟩ ⇓ σ′
For part 2, we need to prove both directions:∀σ, σ′.⟨c1, σ⟩ ⇓ σ′ ⇒ ⟨c2, σ⟩ ⇓ σ′
∀σ, σ′.⟨c1, σ⟩ ⇓ σ′ ⇐ ⟨c2, σ⟩ ⇓ σ′
Matt Fredrikson Deductive Verification 14 / 42
Problem 6, ⇒
The last rule applied in the derivation was either WhileTrue orWhileFalse
If it was WhileFalse, then there must have been T1 that led to:
WhileFalse
T1
⟨b, σ⟩ ⇓b false⟨while b do c, σ⟩ ⇓ σ
So in this case, σ = σ′. Then we also know that:
WhileFalse
T1
⟨b, σ⟩ ⇓b false⟨while b do (while b do c), σ⟩ ⇓ σ
Matt Fredrikson Deductive Verification 15 / 42
Problem 6, ⇒
If b evaluates to true (so WhileTrue applies), we know that:
WhileTrue
T1
⟨b, σ⟩ ⇓b trueT2
⟨c, σ⟩ ⇓ σ′′T3
⟨while b do c, σ′′⟩ ⇓ σ′
⟨while b do c, σ⟩ ⇓ σ′
We also know that ⟨b, σ′⟩ ⇓b false. So:
WhileTrue
T1
⟨b, σ⟩ ⇓b trueT1 T2 T3
⟨while b do c, σ⟩ ⇓ σ′⟨b, σ′⟩ ⇓b false
⟨while b do (· · · ), σ′⟩ ⇓ σ′
⟨while b do (while b do c), σ⟩ ⇓ σ′
Matt Fredrikson Deductive Verification 16 / 42
Problem 6, ⇐
The other direction is similar.
In the case of WhileFalse,T1
⟨b, σ⟩ ⇓b false⟨while b do (while b do c), σ⟩ ⇓ σ
T1
⟨b, σ⟩ ⇓b false⟨while b do c, σ⟩ ⇓ σ
In the case of WhileTrue,T1
⟨b, σ⟩ ⇓b trueT2
⟨while b do c, σ⟩ ⇓ σ′⟨b, σ′⟩ ⇓b false
⟨while b do c, σ′⟩ ⇓ σ′
⟨while b do (while b do c), σ⟩ ⇓ σ′
Leaving us to conclude that,T2
⟨while b do c, σ⟩ ⇓ σ′
Matt Fredrikson Deductive Verification 17 / 42
Problem 7
The postcondition we’re after is:(∀i.0 ≤ i < n → a[i] ≤ m) ∧ (∃i.0 ≤ i < n ∧m = a[i])
The loop invariant needed to prove this is:(∀i.0 ≤ i < k → a[i] ≤ m) ∧ (∃i.0 ≤ i ≤ k ∧m = a[i])
Technically, you also need k ≤ n and i < n in the invariant if arrayshave bounds
Matt Fredrikson Deductive Verification 18 / 42
Problem 8
The loop invariant needed for this problem is: I : x = y + a
This leaves us with two additional verification conditions:I ∧ ¬(a ̸= 0) → x = y
I ∧ a ̸= 0 → wlp(y := y + 1; a := a− 1, x = y + a)
Clearly, (x = y + a ∧ a = 0) → x = y
Then:wlp(c3; c4, x = y + a) = wlp(y := y + 1,wlp(a := a− 1, x = y + 1))
= wlp(y := y + 1, x = y + a− 1)= (x = y + 1 + a− 1)= (x = y + a)
And we know that (x = y + a ∧ a ̸= 0) → x = y + a
Matt Fredrikson Deductive Verification 19 / 42
Problem 8
Then:wlp(while a ̸= 0 do y := y + 1; a := a− 1, x = y) = (x = y + a)
We need to show that0 ≤ x ⇒ wlp(a := x; y := 0, x = y + a)
Computing the weakest precondition:wlp(a := x; y := 0, x = y + a) = wlp(a := x,wlp(y := 0, x = y + a))
= wlp(a := x, x = 0 + a)= (x = 0 + x)⇔ (x = x)
So x = x is equivalent to true, and 0 ≤ x → true.
Matt Fredrikson Deductive Verification 20 / 42
Proving Partial Correctness (Review)
Now, a program is partially correct if for each procedure P :1. Whenever P ’s preconditions are satisfied on entry2. P ’s postconditions are satisfied on exit
We’ll extend the approach we’ve talked about so far1. Reduce the annotated program to a set of verification conditions2. If all VCs are valid, then the program is correct
Our approach will be different:▶ Use annotations to decompose the program into simpler parts▶ Generate VC for each part in isolation, assuming each
annotation holds▶ Make sure that correctness of the whole follows from
correctness of each part
Matt Fredrikson Deductive Verification 21 / 42
Basic Paths (Review)
A basicpath is a sequence of instructions that:▶ Begins at procedure precondition or loop invariant▶ Ends at a loop invariant, assertion, or procedure postcondition▶ Doesn’t cross loops: invariants only at beginning or end of path
Basic paths correspond to straight-line segments of code
Think of a Hoare triple over a sequence command:{P} c1; c2; ...; cn {Q}
P,Q are pre-/postconditions, loop invariants, or assertion guards
Matt Fredrikson Deductive Verification 22 / 42
assume statement (Review)
{l ≤ i ∧ ∀j.l ≤ j < i → a[j] ̸= e}while(i ≤ u);if(a[i] = e);rv := 1;{(rv = 1) ↔ (∃i.l ≤ i ≤ u ∧ a[i] = e)}
{l ≤ i ∧ ∀j.l ≤ j < i → a[j] ̸= e}assume i ≤ u;assume a[i] = e;rv := 1; {(rv = 1) ↔ (∃i.l ≤ i ≤ u ∧ a[i] = e)}
Guarded statements introduce assumptions about environment
We write these in basic paths using an assume statement
assume b means:1. Rest of path executed only if b is true in current environment2. When reasoning about rest of path, we can assume b holds
Matt Fredrikson Deductive Verification 23 / 42
Basic Paths: Example
proc LinearSearch(a : array, l, u, e)pre 0 ≤ l ∧ u < |a|post (rv = 1) ↔ (∃i.l ≤ i ≤ u ∧ a[i] = e)
{i := l;while(i ≤ u){l ≤ i ∧ ∀j.l ≤ j < i → a[j] ̸= e}
{if(a[i] = e) return 1;i := i + 1;
}return 0;
}
Matt Fredrikson Deductive Verification 24 / 42
Procedure Calls (Review)
Given a procedure f with prototypeproc f(x1, . . . , xn)pre P [x1, . . . , xn]post Q[x1, . . . , xn, rv]
When f is called in context w := f(e1, . . . , en);
Augment the calling context with an assertion:{P [e1, . . . , en]};w := f(e1/x1, . . . , en/xn);
In paths that pass through the call,1. Create fresh variable v to hold the return value2. Replace call with an assumption of the postcondition:
assume G[e1/x1, . . . , en/xn, v/rv]
Matt Fredrikson Deductive Verification 25 / 42
Example: Linear Search (1)
Recall the first basic path:{0 ≤ l ∧ u < |a|}i := l{l ≤ i ∧ ∀j.l ≤ j < i → a[j] ̸= e}
The VC for this is:0 ≤ l ∧ u < |a| → wlp(i := l, l ≤ i ∧ ∀j.l ≤ j < i → a[j] ̸= e)
We have that:wlp(i := l, l ≤ i ∧ ∀j.l ≤ j < i → a[j] ̸= e)
⇔ l ≤ l ∧ ∀j.l ≤ j < l → a[j] ̸= e⇔ true ∧ ∀j.false → a[j] ̸= e⇔ true
Our final condition is valid:0 ≤ l ∧ u < |a| ⇒ true
Matt Fredrikson Deductive Verification 26 / 42
Example: Linear Search (2)Recall the second basic path:
{P : l ≤ i ∧ ∀j.l ≤ j < i → a[j] ̸= e}c1 : assume i ≤ u;c2 : assume a[i] = e;c3 : rv := 1;{Q : (rv = 1) ↔ ∃j.l ≤ j ≤ u ∧ a[j] = e}
The VC for this is:P → wlp(c1; c2; c3, Q) ⇔ P → wlp(c1,wlp(c2,wlp(c3, Q)))
We have that:wlp(rv := 1, (rv = 1) ↔ ∃j.l ≤ j ≤ u ∧ a[j] = e)
⇔ (1 = 1) ↔ ∃j.l ≤ j ≤ u ∧ a[j] = e⇔ ∃j.l ≤ j ≤ u ∧ a[j] = e
Our final condition is:0 ≤ l ∧ u < |a| ⇒ true
Matt Fredrikson Deductive Verification 27 / 42
Example: Linear Search (3)Recall the second basic path:
{P : l ≤ i ∧ ∀j.l ≤ j < i → a[j] ̸= e}c1 : assume i ≤ u;c2 : assume a[i] = e;c3 : rv := 1;{Q : (rv = 1) ↔ ∃j.l ≤ j ≤ u ∧ a[j] = e}
The VC for this is:P → wlp(c1; c2; c3, Q) ⇔ P → wlp(c1,wlp(c2,wlp(c3, Q)))
Moving on,wlp(c1,wlp(assume a[i] = e, ∃j.l ≤ j ≤ u ∧ a[j] = e))
⇔ wlp(c1, a[i] = e → ∃j.l ≤ j ≤ u ∧ a[j] = e)⇔ wlp(assume i ≤ u, a[i] = e → ∃j.l ≤ j ≤ u ∧ a[j] = e)⇔ i ≤ u → (a[i] = e → ∃j.l ≤ j ≤ u ∧ a[j] = e)
Our final condition is:0 ≤ l ∧ u < |a| ⇒ true
Matt Fredrikson Deductive Verification 28 / 42
Example: Linear Search (4)
Our final condition is:(l ≤ i ≤ u ∧ ∀j.l ≤ j < i → a[j] ̸= e) → (a[i] = e → ∃j.l ≤ j ≤ u ∧ a[j] = e)
⇔ (l ≤ i ≤ u ∧ a[i] = e ∧ ∀j.l ≤ j < i → a[j] ̸= e) → ∃j.l ≤ j ≤ u ∧ a[j] = e
Notice that:l ≤ i ≤ u ∧ a[i] = e → ∃j.l ≤ j ≤ u ∧ a[j] = e
is valid
So, the condition is valid, and the corresponding triple is as well
Matt Fredrikson Deductive Verification 29 / 42
Total Correctness
Partial correctness doesn’t require termination
Totalcorrectness is a stronger statement, written:
[P ] c [Q]
The meaning of [P ] c [Q] is:
▶ If we begin executing c in an environmentsatisfying P ,▶ then c terminates,▶ and its final environment will satisfy Q
Total correctness introduces another obligation for verification
Matt Fredrikson Deductive Verification 30 / 42
Proving Total Correctness
Obviously, we’ll need to prove that the program eventually terminates
Intuitively, we’ll do the following:
1. Find a set S with some ordering and smallest element
2. Find a function δ that maps program states to S
3. Prove that δ always decreases as the program executes
δ is called a rankingfunction
Idea: If program diverges, δ would decrease infinitely
Matt Fredrikson Deductive Verification 31 / 42
Well-Founded Relations
Let ≺ be a binary predicate over some set S, and ≻ be its “inverse”
Well-Founded Relation≺ is a well-foundedrelation iff there is no infinite sequence
s1, s2, s3, . . . in S
where each element is lessthan its predecessor:s1 ≻ s2 ≻ s3 ≻ · · ·
In other words, eachdecreasingsequencein S isfinite.
Matt Fredrikson Deductive Verification 32 / 42
Aside: Well-Founded Induction
Well-founded induction generalizes “normal” induction over numbers
Can use any binary predicate ≺ that’s well-founded in our theory▶ InductiveHypothesis: For every n, n′ where n′ ≺ n, assume
F [n′] is T -valid▶ Prove that F [n] is T -valid
This is summarized by the axiom schema:(∀n.(∀n′.n′ ≺ n → F [n′]) → F [n]) → ∀x.F [x]
Structural induction is an instance: ≺ is the “subprogram” relation
Matt Fredrikson Deductive Verification 33 / 42
Example: Well-Founded Relation
< defined over the natural numbers
0 is the least element; any decreasing sequence of N is finite:
Think of inductively-defined sets
Axioms are the least elements:succ(succ(· · · 0 · · · )) ≻ succ(· · · 0 · · · ) ≻ · · · ≻ 0
< over the rationals is not well-founded
No least element:1 >
1
2>
1
3>
1
4> · · · > 1
n>
1
n + 1> · · ·
Matt Fredrikson Deductive Verification 34 / 42
Lexicographic Well-Founded Relations
Given sets S1, . . . , Sn and relations ≺1, . . . ,≺m, let S = S1 × · · · × Sn
Define the relation ≺:
(s1, . . . , sn) ≺ (t1, . . . , tn) ⇔m∨i=1
si ≺i ti ∧i−1∧j=1
sj = tj
So, (s1, . . . , sn) ≺ (t1, . . . , tn) iff:
▶ At some position i, si ≺i ti
▶ and for all preceding positions j, sj = tj
If ≺1, . . . ,≺i are well-founded, then so is ≺
Matt Fredrikson Deductive Verification 35 / 42
Well-Founded Relations and Ranking Functions
We use well-foundedness to prove termination
Basic strategy:
1. Choose S and well-founded ≺.Usually f(some var) or a tuple with lexicographic relation <n
2. Find a suitable ranking functionδ : program states 7→ S
3. Show that δ decreases according to ≺ on every basic path
Program must terminate, as no infinite-decending sequences in ≺
Matt Fredrikson Deductive Verification 36 / 42
Annotating Ranking Functions
We annotate ranking functions in code with ↓
Needed in function prototype, head of loops
For example:▶ ↓ i, as long as i’s domain has a well-founded ordering▶ ↓ u− l + 1, assuming u, l are naturals▶ ↓ (i + 1, j − 1), same assumption as above
Basic paths now have ranking functions at beginning and end▶ Usually accompanied by assertion at the beginning▶ By themselves at the end, to prove the path decreases
Matt Fredrikson Deductive Verification 37 / 42
Verification Conditions
{P}↓ δ(x)c1;...cn;↓ δ(x)
We produce the verification condition:P → wlp(c1; · · · ; cn, δ(x) ≺ δ(x′))[x/x′]
▶ The value of δ(x) at the end is less than at the beginning▶ Don’t want wlp to modify value of x at the beginning▶ Rename it to x′, then subst. x back in after computing wlp
Matt Fredrikson Deductive Verification 38 / 42
Example: Termination Verification Condition
{i ≥ 1}↓ ii := i− 1;↓ i
Let’s compute the VC:
i ≥ 1 → wlp(i := i− 1, i < i′)[i/i′]
becomes i ≥ 1 → (i− 1 < i′)[i/i′]
becomes i ≥ 1 → i− 1 < i
This is valid, as expected
Matt Fredrikson Deductive Verification 39 / 42
Slightly Larger Example
{P : i + 1 ≥ 0 ∧ i− j ≥ 0}↓ (i + 1, i− j)
c1 : assume j ≥ ic2 : i := i− 1;
↓ (i + 1, i + 1)
Our verification condition is:P → wlp(c1; c2, (i + 1, i + 1) <2 (i′ + 1, i′ − j′))[i/i′, j/j′]
Computing the wlp:wlp(c1; c2, (i + 1, i + 1) <2 (i′ + 1, i′ − j′))
↪→ wlp(c1,wlp(i := i− 1, (i + 1, i + 1) <2 (i′ + 1, i′ − j′)))↪→ wlp(assume j ≥ i, (i− 1 + 1, i− 1 + 1) <2 (i′ + 1, i′ − j′)))↪→ j ≥ i → (i, i) <2 (i′ + 1, i′ − j′)
Matt Fredrikson Deductive Verification 40 / 42
Slightly Larger Example
{P : i + 1 ≥ 0 ∧ i− j ≥ 0}↓ (i + 1, i− j)
c1 : assume j ≥ ic2 : i := i− 1;
↓ (i + 1, i + 1)
Our verification condition is now:
P → (j ≥ i → (i, i) <2 (i′ + 1, i′ − j′))[i/i′, j/j′]↪→ P → (j ≥ i → (i, i) <2 (i + 1, i− j))↪→ i + 1 ≥ 0 ∧ i− j ≥ 0 → (j ≥ i → (i, i) <2 (i + 1, i− j))↪→ i + 1 ≥ 0 ∧ i− j ≥ 0 ∧ j ≥ i → (i, i) <2 (i + 1, i− j)↪→ i > 0 ∧ i = j → (i, i) <2 (i + 1, i− j)
Again, valid as expected
Matt Fredrikson Deductive Verification 41 / 42
Next Lecture
Strategies for developing inductive annotations
How to effectively prove correctness for larger programs
Matt Fredrikson Deductive Verification 42 / 42