Loop Invariants: Part 1 7 January 2019 OSU CSE 1 Reasoning About - - PowerPoint PPT Presentation

loop invariants part 1
SMART_READER_LITE
LIVE PREVIEW

Loop Invariants: Part 1 7 January 2019 OSU CSE 1 Reasoning About - - PowerPoint PPT Presentation

Loop Invariants: Part 1 7 January 2019 OSU CSE 1 Reasoning About Method Calls What a method call does is described by its contract Precondition: a property that is true before the call is made Postcondition: a property that is true


slide-1
SLIDE 1

Loop Invariants: Part 1

7 January 2019 OSU CSE 1

slide-2
SLIDE 2

Reasoning About Method Calls

  • What a method call does is described by

its contract

– Precondition: a property that is true before the call is made – Postcondition: a property that is true after the call returns

7 January 2019 OSU CSE 2

slide-3
SLIDE 3

Reasoning About Loops

  • What a while loop does is described by

its loop invariant

– Invariant: a property that is true every time the code reaches a certain point—in the case of a loop invariant, the loop condition test

7 January 2019 OSU CSE 3

slide-4
SLIDE 4

Reasoning About Loops

  • What a while loop does is described by

its loop invariant

– Invariant: a property that is true every time the code reaches a certain point—in the case of a loop invariant, the loop condition test

7 January 2019 OSU CSE 4

Why is a loop treated differently than a method call? Simply put, experience shows this is a good way to think about loops.

slide-5
SLIDE 5

Reasoning About Loops

  • What a while loop does is described by

its loop invariant

– Invariant: a property that is true every time the code reaches a certain point—in the case of a loop invariant, the loop condition test

7 January 2019 OSU CSE 5

Just while loops? Yes; the same idea can be applied to for loops, but some modifications are required.

slide-6
SLIDE 6

Reasoning About Loops

  • What a while loop does is described by

its loop invariant

– Invariant: a property that is true every time the code reaches a certain point—in the case of a loop invariant, the loop condition test

7 January 2019 OSU CSE 6

Since a loop invariant is true every time through the loop, it says what does not change; hence it really says what the loop does not do.

slide-7
SLIDE 7

while Statement Control Flow

test false true loop-body

while (test) { loop-body }

7 January 2019 OSU CSE 7

slide-8
SLIDE 8

while Statement Control Flow

test false true loop-body

while (test) { loop-body }

7 January 2019 OSU CSE 8

The loop invariant is a property that is true both here, just before the loop begins...

slide-9
SLIDE 9

while Statement Control Flow

test false true loop-body

while (test) { loop-body }

7 January 2019 OSU CSE 9

... and here, just after every execution of the loop body.

slide-10
SLIDE 10

Example #1

void append(Queue<T> q)

  • Concatenates (“appends”) q to the end of

this.

  • Updates: this
  • Clears: q
  • Ensures:

this = #this * #q

7 January 2019 OSU CSE 10

slide-11
SLIDE 11

Example #1: Method Body

while (q.length() > 0) { T x = q.dequeue(); this.enqueue(x); }

7 January 2019 OSU CSE 11

slide-12
SLIDE 12

Example #1: Method Body

while (q.length() > 0) { T x = q.dequeue(); this.enqueue(x); }

7 January 2019 OSU CSE 12

What is true every time we test the loop condition? Lots of things... such as?

slide-13
SLIDE 13

7 January 2019 OSU CSE 13

this = < 1, 2, 3 > q = < 4, 5, 6 > while (q.length() > 0) { T x = q.dequeue(); this.enqueue(x); }

slide-14
SLIDE 14

7 January 2019 OSU CSE 14

this = < 1, 2, 3 > q = < 4, 5, 6 > while (q.length() > 0) { T x = q.dequeue(); this.enqueue(x); }

What is true the first time we test the loop condition? Lots of things... such as?

slide-15
SLIDE 15

7 January 2019 OSU CSE 15

this = < 1, 2, 3 > q = < 4, 5, 6 > while (q.length() > 0) { this = < 1, 2, 3 > q = < 4, 5, 6 > T x = q.dequeue(); this = < 1, 2, 3 > q = < 5, 6 > x = 4 this.enqueue(x); this = < 1, 2, 3, 4 > q = < 5, 6 > x = 4 }

slide-16
SLIDE 16

7 January 2019 OSU CSE 16

this = < 1, 2, 3 > q = < 4, 5, 6 > while (q.length() > 0) { this = < 1, 2, 3 > q = < 4, 5, 6 > T x = q.dequeue(); this = < 1, 2, 3 > q = < 5, 6 > x = 4 this.enqueue(x); this = < 1, 2, 3, 4 > q = < 5, 6 > x = 4 }

What is true the first and second times we test the loop condition? Fewer things... such as?

slide-17
SLIDE 17

7 January 2019 OSU CSE 17

this = < 1, 2, 3 > q = < 4, 5, 6 > while (q.length() > 0) { this = < 1, 2, 3 > q = < 4, 5, 6 > T x = q.dequeue(); this = < 1, 2, 3 > q = < 5, 6 > x = 4 this.enqueue(x); this = < 1, 2, 3, 4 > q = < 5, 6 > x = 4 }

The value of x is not involved in the loop invariant because there is no x when we first hit the loop!

slide-18
SLIDE 18

7 January 2019 OSU CSE 18

this = < 1, 2, 3 > q = < 4, 5, 6 > while (q.length() > 0) { this = < 1, 2, 3, 4 > q = < 5, 6 > T x = q.dequeue(); this = < 1, 2, 3, 4 > q = < 6 > x = 5 this.enqueue(x); this = < 1, 2, 3, 4, 5 > q = < 6 > x = 5 }

slide-19
SLIDE 19

7 January 2019 OSU CSE 19

this = < 1, 2, 3 > q = < 4, 5, 6 > while (q.length() > 0) { this = < 1, 2, 3, 4 > q = < 5, 6 > T x = q.dequeue(); this = < 1, 2, 3, 4 > q = < 6 > x = 5 this.enqueue(x); this = < 1, 2, 3, 4, 5 > q = < 6 > x = 5 }

What is true the first, second, and third times we test the loop condition? Fewer things still... such as?

slide-20
SLIDE 20

7 January 2019 OSU CSE 20

this = < 1, 2, 3 > q = < 4, 5, 6 > while (q.length() > 0) { this = < 1, 2, 3, 4, 5 > q = < 6 > T x = q.dequeue(); this = < 1, 2, 3, 4, 5 > q = < > x = 6 this.enqueue(x); this = < 1, 2, 3, 4, 5, 6 > q = < > x = 6 }

slide-21
SLIDE 21

7 January 2019 OSU CSE 21

this = < 1, 2, 3 > q = < 4, 5, 6 > while (q.length() > 0) { this = < 1, 2, 3, 4, 5 > q = < 6 > T x = q.dequeue(); this = < 1, 2, 3, 4, 5 > q = < > x = 6 this.enqueue(x); this = < 1, 2, 3, 4, 5, 6 > q = < > x = 6 }

What is true the first, second, third, and fourth times we test the loop condition? Fewer things still... such as?

slide-22
SLIDE 22

7 January 2019 OSU CSE 22

this = < 1, 2, 3 > q = < 4, 5, 6 > while (q.length() > 0) { this = < 1, 2, 3, 4, 5 > q = < 6 > T x = q.dequeue(); this = < 1, 2, 3, 4, 5 > q = < > x = 6 this.enqueue(x); this = < 1, 2, 3, 4, 5, 6 > q = < > x = 6 }

Whatever is true the last time we test the loop condition is also true here, after the loop finally terminates.

slide-23
SLIDE 23

Some Things That Do Not Change

  • “The lengths of the strings are non-

negative” does not change

– |this| >= 0 and |q| >= 0 does not change – True, but this literally goes without saying; the length of any string is always non-negative – It is no more useful than saying, e.g., “17 < 42 does not change”, because it is a mathematical fact, not something about this loop in particular

7 January 2019 OSU CSE 23

slide-24
SLIDE 24

Some Things That Do Not Change

  • “The sum of the lengths of the strings”

does not change

– |this| + |q| does not change – True, and a useful observation about this particular loop; but one can say more

7 January 2019 OSU CSE 24

slide-25
SLIDE 25

Some Things That Do Not Change

  • “The concatentation of the strings” does

not change

– this * q does not change – True, and a stronger useful observation about this loop because it implies the previous

  • bservation about the sum of the lengths
  • In other words, if this * q does not change, then

|this| + |q| also does not change; but not vice versa

7 January 2019 OSU CSE 25

slide-26
SLIDE 26

How To Express an Invariant

  • How do we say “the concatenation of the

strings does not change”?

– We need to talk about both:

  • The current values of the variables
  • The original values of the variables, just before

the loop condition was first tested (variable names prefixed with #)

this * q = #this * #q

7 January 2019 OSU CSE 26

slide-27
SLIDE 27

Example #1: Method Body

/** * @updates this, q * @maintains * this * q = #this * #q */ while (q.length() > 0) { T x = q.dequeue(); this.enqueue(x); }

7 January 2019 OSU CSE 27

slide-28
SLIDE 28

Example #1: Method Body

/** * @updates this, q * @maintains * this * q = #this * #q */ while (q.length() > 0) { T x = q.dequeue(); this.enqueue(x); }

7 January 2019 OSU CSE 28

This Javadoc tag introduces the list of variables whose values might change in some iteration.

slide-29
SLIDE 29

Example #1: Method Body

/** * @updates this, q * @maintains * this * q = #this * #q */ while (q.length() > 0) { T x = q.dequeue(); this.enqueue(x); }

7 January 2019 OSU CSE 29

Any variable in scope that is not listed as an updates- mode variable is, by default, a restores-mode variable, meaning the loop body does not change its value.

slide-30
SLIDE 30

Example #1: Method Body

/** * @updates this, q * @maintains * this * q = #this * #q */ while (q.length() > 0) { T x = q.dequeue(); this.enqueue(x); }

7 January 2019 OSU CSE 30

This Javadoc tag introduces the claim that the following loop “maintains” the property, i.e., it is a loop invariant.

slide-31
SLIDE 31

Example #1: Method Body

/** * @updates this, q * @maintains * this * q = #this * #q */ while (q.length() > 0) { T x = q.dequeue(); this.enqueue(x); }

7 January 2019 OSU CSE 31

slide-32
SLIDE 32

Using a Loop Invariant

  • If you have a strong enough loop invariant,

you can trace over a loop in a single step, and predict the values of the variables when it terminates—without tracing through the loop body even once

7 January 2019 OSU CSE 32

slide-33
SLIDE 33

Example #1: Method Body

/** * @updates this, q * @maintains * this * q = #this * #q */ while (q.length() > 0) { ... }

7 January 2019 OSU CSE 33

Pretend you cannot see the loop body. Can you still trace

  • ver this loop?
slide-34
SLIDE 34

7 January 2019 OSU CSE 34

this = < 1, 2, 3 > q = < 4, 5, 6 > /** * @maintains * this * q = #this * #q */ while (q.length() > 0) { ... } this = q =

When execution reaches this point, we know two things...

slide-35
SLIDE 35

7 January 2019 OSU CSE 35

this = < 1, 2, 3 > q = < 4, 5, 6 > /** * @maintains * this * q = #this * #q */ while (q.length() > 0) { ... } this = q =

We know (1) the loop invariant is true, so: this * q = #this * #q

slide-36
SLIDE 36

7 January 2019 OSU CSE 36

this = < 1, 2, 3 > q = < 4, 5, 6 > /** * @maintains * this * q = #this * #q */ while (q.length() > 0) { ... } this = q =

We also know (2) the loop condition is false, so: |q| <= 0

slide-37
SLIDE 37

7 January 2019 OSU CSE 37

this = < 1, 2, 3 > q = < 4, 5, 6 > /** * @maintains * this * q = #this * #q */ while (q.length() > 0) { ... } this = < 1, 2, 3, 4, 5, 6 > q = < >

Combining (1) and (2), the

  • nly values the variables

can possibly have at this point are these.

slide-38
SLIDE 38

Justification for (1)

  • The loop invariant is true just after the loop

terminates—if the code that tests the loop condition does not change the value of any variable appearing in the loop invariant

7 January 2019 OSU CSE 38

slide-39
SLIDE 39

The Loop Invariant Picture

test false true loop-body

while (test) { loop-body }

7 January 2019 OSU CSE 39

If the loop invariant is true at the two red points, and “test” updates nothing... ...then the loop invariant is true at the two green points.

slide-40
SLIDE 40

Justification for (1)

  • Best practice: Code that tests the loop

condition should not update any variables appearing in the loop invariant

– Easy way to achieve this: the test should not update any variables at all

7 January 2019 OSU CSE 40

slide-41
SLIDE 41

Justification for (2)

  • The loop does not terminate until and

unless the loop condition is false

– However, a loop might never terminate; so you need to show that it does – This is similar to how you show a recursive method terminates

7 January 2019 OSU CSE 41

slide-42
SLIDE 42

Loop Termination

  • To show that a loop terminates, it is

sufficient to provide a progress metric (a.k.a. termination function, a.k.a. variant function)

– An integer-valued function of the variables in scope (where the loop appears in the code) – Always non-negative – Always decreases when the loop body is executed once

7 January 2019 OSU CSE 42

slide-43
SLIDE 43

Example #1: Method Body

/** * @updates this, q * @maintains * this * q = #this * #q * @decreases * |q| */ while (q.length() > 0) { T x = q.dequeue(); this.enqueue(x); }

7 January 2019 OSU CSE 43

slide-44
SLIDE 44

Example #1: Method Body

/** * @updates this, q * @maintains * this * q = #this * #q * @decreases * |q| */ while (q.length() > 0) { T x = q.dequeue(); this.enqueue(x); }

7 January 2019 OSU CSE 44

This Javadoc annotation claims the loop that follows “decreases” the stated progress metric.

slide-45
SLIDE 45

Conclusion

  • Even if you do not choose to write down a

loop invariant or progress metric, if you think about loops in these terms it can help you avoid errors and bad practices in loop code

– Off-by-one errors – Wrong/missing code in the loop body – Declarations of variables outside the loop that are only used inside the loop body

7 January 2019 OSU CSE 45