cmpsci 521/621 hw4 solutions

12
CMPSCI 521/621 HW4 Solutions Problem 1 a. Assumptions and notation: The loop control variables (i and j) get incremented at the last location of the loop (statements 8 and 9 respectively). Let |X| denote the size of a set X. Input: Let setA and setB be the symbolic names of the two input sets. Also, let the symbolic names of the elements of setA and setB be as follows: setA[0]=a, setA[1]=b; setB[0]=c, setB[1]=b. (We use setA[i] as a shorthand for setA.get(i).getIntValue()). Statements PV PC 0. intersection [] true 1. sizeA |setA| true 2. sizeB |setB| true 3. i 0 true 0 < |setA| 4. j 0 0 < |setA| 0 < |setB| 5. 0 < |setA| 0 < |setB| setA[0] = setB[0] 8. j 1 0 < |setA| 0 < |setB| setA[0] = setB[0] 4. 0 < |setA| 1 < |setB| setA[0] = setB[0] 5. 0 < |setA| 1 < |setB| setA[0] = setB[0] setA[0] = setB[1] 8. j 2 0 < |setA| 1 < |setB| setA[0] = setB[0] setA[0] = setB[1] 4. 0 < |setA| 2= |setB| setA[0] = setB[0] setA[0] = setB[1] 9. i 1 0 < |setA| 2= |setB| setA[0] = setB[0] setA[0] = setB[1] 3. 1 < |setA| 2= |setB| setA[0] = setB[0] setA[0] = setB[1] 4. j 0 1 < |setA| 2= |setB| setA[0] = setB[0] setA[0] = setB[1] 5. 1 < |setA| 2= |setB| setA[0] = setB[0] setA[0] = setB[1] setA[1] = setB[0] 8. j 1 1 < |setA| 2= |setB| setA[0] = setB[0] setA[0] = setB[1] setA[1] = setB[0] 4. 1 < |setA| 2= |setB| setA[0] = setB[0] setA[0] = setB[1] setA[1] = setB[0] 5. 1 < |setA| 2= |setB| setA[0] = setB[0] setA[0] = setB[1] setA[1] = setB[0] setA[1] = setB[1] 6. intersection[0] b 1 < |setA| 2= |setB| setA[0] = setB[0] setA[0] = setB[1] setA[1] = setB[0] setA[1] = setB[1] 7. j 2 1 < |setA| 2= |setB| setA[0] = setB[0] setA[0] = setB[1] setA[1] = setB[0] setA[1] = setB[1] 8. j 3 1 < |setA| 2= |setB| setA[0] = setB[0] setA[0] = setB[1] setA[1] = setB[0] setA[1] = setB[1] 4. 1 < |setA| 2= |setB| setA[0] = setB[0] setA[0] = setB[1] setA[1] = setB[0] setA[1] = setB[1]

Upload: others

Post on 02-Feb-2022

2 views

Category:

Documents


0 download

TRANSCRIPT

CMPSCI 521/621HW4 Solutions

Problem 1

a. Assumptions and notation: The loop control variables (i and j) get incremented at the last location ofthe loop (statements 8 and 9 respectively). Let |X| denote the size of a set X.

Input: Let setA and setB be the symbolic names of the two input sets. Also, let the symbolic names ofthe elements of setA and setB be as follows: setA[0]=a, setA[1]=b; setB[0]=c, setB[1]=b. (We use setA[i] asa shorthand for setA.get(i).getIntValue()).

Statements PV PC0. intersection ← [ ] true1. sizeA ← |setA| true2. sizeB ← |setB| true3. i ← 0 true ∧0 < |setA|4. j ← 0 0 < |setA| ∧0 < |setB|5. 0 < |setA| ∧0 < |setB| ∧ setA[0] #= setB[0]8. j ← 1 0 < |setA| ∧0 < |setB| ∧ setA[0] #= setB[0]4. 0 < |setA| ∧1 < |setB| ∧ setA[0] #= setB[0]5. 0 < |setA| ∧1 < |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]8. j ← 2 0 < |setA| ∧1 < |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]4. 0 < |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]9. i ← 1 0 < |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]3. 1 < |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]4. j ← 0 1 < |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]5. 1 < |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]

∧ setA[1] #= setB[0]8. j ← 1 1 < |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]

∧ setA[1] #= setB[0]4. 1 < |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]

∧ setA[1] #= setB[0]5. 1 < |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]

∧ setA[1] #= setB[0] ∧ setA[1] = setB[1]6. intersection[0] ← b 1 < |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]

∧ setA[1] #= setB[0] ∧ setA[1] = setB[1]7. j ← 2 1 < |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]

∧ setA[1] #= setB[0] ∧ setA[1] = setB[1]8. j ← 3 1 < |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]

∧ setA[1] #= setB[0] ∧ setA[1] = setB[1]4. 1 < |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]

∧ setA[1] #= setB[0] ∧ setA[1] = setB[1]

9. i ← 2 1 < |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]∧ setA[1] #= setB[0] ∧ setA[1] = setB[1]

3. 2 = |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]∧ setA[1] #= setB[0] ∧ setA[1] = setB[1]

10. 2 = |setA| ∧2 = |setB| ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1]∧ setA[1] #= setB[0] ∧ setA[1] = setB[1]

P = 0, 1, 2, 3, 4, 5, 8, 4, 5, 8, 4, 9, 3, 4, 5, 8, , 4, 5, 6, 7, 8, 4, 9, 3, 10D[P ] = {setA, setB| |setA| = 2 ∧ |setB| =2 ∧ setA[0] #= setB[0] ∧ setA[0] #= setB[1] ∧ setA[1] #= setB[0] ∧setA[1] = setB[1] }C[P ] = intersection[0] ← setA[1] (which in this case is the same as intersection[0] ← setB[1]).

b. Let setA and setB be the symbolic names of the two input sets. Also, let the symbolic names of theelements of setA be as follows: setA[0]=a, setA[1]=b. setB is empty. (We use setA[i] as a shorthand forsetA.get(i).getIntValue()).

Statements PV PC0. intersection ← [ ] true1. sizeA ← |setA| true2. sizeB ← |setB| true3. i ← 0 true ∧0 ≥ |setA| ∨ intersection.size() ≥ |setB|10. 0 ≥ |setA| ∧ intersection.size() ≥ |setB|

P = 0, 1, 2, 3, 10D[P ] = {setA, setB | 0 ≥ |setA| ∨ intersection.size() ≥ |setB| }. For this particular symbolic execution weknow that intersection.size()=0. Also the sizes of setA and setB are non-negative integers, thusD[P ] = {setA, setB | |setA| = 0 ∨ |setB| = 0 }C[P ] = intersection ← [ ].

The solutions for problems 2-6 are courtesy of Brandon McPhail.

Brandon McPhail

1.

2. For the method setIntersection:

(a). provide input and output assertions.

// preconditionsrequires setA != null;requires setB != null;requires setA.size() >= 0;requires setB.size() >= 0;// setA is a set:requires \forall( int k = 0; k < setA.size() - 1; k++;)

(\forall( int m = k+1; m < setA.size(); m++;)(setA.get(k).intValue() != setA.get(m).intValue()));

// setB is a set:requires \forall( int k = 0; k < setB.size() - 1; k++;)

(\forall (int m = k+1; m < setB.size(); m++;)(setB.get(k).intValue() != setB.get(m).intValue()));

// postconditions// result is a set:ensures \forall( int k = 0; k < \result.size() - 1; k++;)

(\forall (int m = k+1; m < \result.size(); m++;)(\result.get(k).intValue() != \result.get(m).intValue()));

// Everything in A that’s also in B is in resultensures \forall( int k = 0; k < setA.size(); k++;)

(setB.contains(setA.get(k)) ==> \result.contains(setA.get(k)));// Everything in result is in A and Bensures \forall( int k = 0; k < \result.size(); k++;)

(setA.contains(\result.get(k)) && setB.contains(\result.get(k)));

(b). provide the needed loop invariant(s) and indicate the location where each resides. Youmay want to provide the control flow graph and explicitly represent the code associatedwith the For Loops.

// loop invariant 1ensures i < sizeA;ensures intersection.size() < sizeB;ensures intersection.size() >= 0;// intersection is a setensures \forall( int k = 0; k < intersection.size() - 1; k++;)

(\forall (int m = k+1; m < intersection.size(); m++;)

Brandon McPhail

i < sizeA && intersection.size()

< sizeB

ArrayList<Integer> intersection = new ArrayList<Integer>();int sizeA = setA.size();int sizeB = setB.size();

int i = 0;

j < sizeB

int j = 0;

setA.get(i).intValue() == setB.set(j).intValue()

intersection.add(setA.get(i));j = sizeB;

j++;

i++;

return intersection;

Preconditions

Postconditions

loop invariant 2

invariant

loop invariant 1

Brandon McPhail

(intersection.get(k).intValue() != intersection.get(m).intValue()));// Everything in intersection is in A and Bensures \forall( int k = 0; k < intersection.size(); k++;)

(setA.contains(intersection.get(k)) && setB.contains(intersection.get(k)));// intersection includes all A[0...i] \cap Bensures \forall (int k = 0; k < i; k++;)

(setB.contains(setA.get(k)) ==> intersection.contains(setA.get(k)));// intersection excludes all A[i...sizeA]ensures \forall (int k = i; k < sizeA; k++;)

(\not intersection.contains(setA.get(k)));

// loop invariant 2ensures i < sizeA;ensures intersection.size() < sizeB;// intersection is a setensures \forall( int k = 0; k < intersection.size() - 1; k++;)

(\forall (int m = k+1; m < intersection.size(); m++;)(intersection.get(k).intValue() != intersection.get(m).intValue()));

// Everything in intersection is in A and Bensures \forall( int k = 0; k < intersection.size(); k++;)

(setA.contains(intersection.get(k)) && setB.contains(intersection.get(k)));// intersection includes all A[0...i] \cap Bensures \forall (int k = 0; k < i; k++;)

(setB.contains(setA.get(k)) ==> intersection.contains(setA.get(k)));// intersection excludes all A[i...sizeA]ensures \forall (int k = i; k < sizeA; k++;)

(\not intersection.contains(setA.get(k)));

// invariantensures i < sizeA;ensures intersection.size() <= sizeB;// intersection is a setensures \forall( int k = 0; k < intersection.size() - 1; k++;)

(\forall (int m = k+1; m < intersection.size(); m++;)(intersection.get(k).intValue() != intersection.get(m).intValue()));

// Everything in intersection is in A and Bensures \forall( int k = 0; k < intersection.size(); k++;)

(setA.contains(intersection.get(k)) && setB.contains(intersection.get(k)));// intersection includes all A[0..i] \cap Bensures \forall (int k = 0; k <= i; k++;)

(setB.contains(setA.get(k)) ==> intersection.contains(setA.get(k)));// intersection excludes all A[(i+1)...sizeA]ensures \forall (int k = i+1; k < sizeA; k++;)

Brandon McPhail

(\not intersection.contains(setA.get(k)));

3. Provide the verification conditions (lemmas) that would be needed to verify this method.We need to show 8 verification conditions:

1. preconditions → postconditions

2. preconditions → loop invariant 1

3. loop invariant 1 → invariant (infeasible)

4. loop invariant 1 → loop invariant 2

5. invariant → loop invariant 1

6. invariant → postconditions

7. loop invariant 2 → invariant (both cases)

8. loop invariant 2 → loop invariant 2 (only 1 case is feasible)

4. Verify that the invariant for the innermost loop back to the same invariant is true.See the next problem below (case 8):

5. Prove all the verification conditions needed to prove partial correctness.

1. preconditions → postconditions

Executing:

ArrayList<Integer> intersection = new ArrayList<Integer>();int sizeA = setA.size();int sizeB = setB.size();int i = 0;i < sizeA && intersection.size() < sizeB;

By execution, intersection.size() == 0, so

// result is a set:ensures \forall( int k = 0; k < \result.size() - 1; k++;)

(\forall (int m = k+1; m < \result.size(); m++;)(\result.get(k).intValue() != \result.get(m).intValue()));

// Everything in result is in A and Bensures \forall( int k = 0; k < \result.size(); k++;)

(setA.contains(\result.get(k)) && setB.contains(\result.get(k)));

Brandon McPhail

are vacuously true.

By execution i ≥ sizeA or intersection.size() ≥ sizeB, and i = 0. By precondition,sizeA ≥ 0, and sizeB ≥ 0. Suppose i ≥ sizeA. Then 0 ≤ sizeA ≤ i = 0 im-plies sizeA = i = 0. Otherwise, suppose intersection.size() ≥ sizeB. By execution,intersection.size() = 0, so 0 ≤ sizeB ≤ intersection.size() = 0 implies sizeB = 0.Either way, this

// Everything in A that’s also in B is in resultensures \forall( int k = 0; k < setA.size(); k++;)

(setB.contains(setA.get(k)) ==> \result.contains(setA.get(k)));

is vacuously true.

2. preconditions → loop invariant 1

We execute:

ArrayList<Integer> intersection = new ArrayList<Integer>();int sizeA = setA.size();int sizeB = setB.size();int i = 0;i < sizeA && intersection.size() < sizeB;

so by execution we have

ensures i < sizeA;ensures intersection.size() < sizeB;

Also by execution we have intersection.size() == 0, so

ensures intersection.size() >= 0;

and the following are all vacuously true:

// intersection is a setensures \forall( int k = 0; k < intersection.size() - 1; k++;)

(\forall (int m = k+1; m < intersection.size(); m++;)(intersection.get(k).intValue() != intersection.get(m).intValue()));

// Everything in intersection is in A and Bensures \forall( int k = 0; k < intersection.size(); k++;)

(setA.contains(intersection.get(k)) && setB.contains(intersection.get(k)));

Also, by execution, i = 0 and i < sizeA, so this assertion is vacuously true:

Brandon McPhail

// intersection includes all A[0...i] \cap Bensures \forall (int k = 0; k < i; k++;)

(setB.contains(setA.get(k)) ==> intersection.contains(setA.get(k)));

Finally, since intersection is empty, we have our final assertion:

// intersection excludes all A[i...sizeA]ensures \forall (int k = i; k < sizeA; k++;)

(\not intersection.contains(setA.get(k)));

3. loop invariant 1 → invariant

Executing

int j = 0;j < sizeB;

In order for j < sizeB to be false, by execution, sizeB must be negative. By loopinvariant 1, 0 ≤ intersection.size(), and intersection.size() < sizeB, so 0 < sizeB < 0is a contradiction. This is an infeasible path.

4. loop invariant 1 → loop invariant 2

We execute:

int j = 0;j < sizeB;

Since i and intersection remain unchanged, the following invariants persist:

// loop invariant 2ensures i < sizeA;ensures intersection.size() < sizeB;// intersection is a setensures \forall( int k = 0; k < intersection.size() - 1; k++;)

(\forall (int m = k+1; m < intersection.size(); m++;)(intersection.get(k).intValue() != intersection.get(m).intValue()));

// Everything in intersection is in A and Bensures \forall( int k = 0; k < intersection.size(); k++;)

(setA.contains(intersection.get(k)) && setB.contains(intersection.get(k)));// intersection includes all A[0...i] \cap Bensures \forall (int k = 0; k < i; k++;)

(setB.contains(setA.get(k)) ==> intersection.contains(setA.get(k)));// intersection excludes all A[i...sizeA]ensures \forall (int k = i; k < sizeA; k++;)

(\not intersection.contains(setA.get(k)));

Brandon McPhail

5. invariant → loop invariant 1

We execute

i++;i < sizeA && intersection.size() < sizeB;

so by execution, we have

ensures i < sizeA;ensures intersection.size() < sizeB;

Also, intersection remains unchanged, so we also maintain the following invariants:

ensures intersection.size() >= 0;// intersection is a setensures \forall( int k = 0; k < intersection.size() - 1; k++;)

(\forall (int m = k+1; m < intersection.size(); m++;)(intersection.get(k).intValue() != intersection.get(m).intValue()));

// Everything in intersection is in A and Bensures \forall( int k = 0; k < intersection.size(); k++;)

(setA.contains(intersection.get(k)) && setB.contains(intersection.get(k)));

Finally, since i is increased by one, from our old invariants

// intersection includes all A[0..i] \cap Bensures \forall (int k = 0; k <= i; k++;)

(setB.contains(setA.get(k)) ==> intersection.contains(setA.get(k)));// intersection excludes all A[(i+1)...sizeA]ensures \forall (int k = i+1; k < sizeA; k++;)

(\not intersection.contains(setA.get(k)));

we have

// intersection includes all A[0...i] \cap Bensures \forall (int k = 0; k < i; k++;)

(setB.contains(setA.get(k)) ==> intersection.contains(setA.get(k)));// intersection excludes all A[i...sizeA]ensures \forall (int k = i; k < sizeA; k++;)

(\not intersection.contains(setA.get(k)));

6. invariant → postconditions

We execute

Brandon McPhail

i++;i < sizeA && intersection.size() < sizeB;

By our invariant, we already have

// result is a set:ensures \forall( int k = 0; k < \result.size() - 1; k++;)

(\forall (int m = k+1; m < \result.size(); m++;)(\result.get(k).intValue() != \result.get(m).intValue()));

// Everything in result is in A and Bensures \forall( int k = 0; k < \result.size(); k++;)

(setA.contains(\result.get(k)) && setB.contains(\result.get(k)));

By execution, i < sizeA ∧ intersection.size() < sizeB is false. Suppose i >= sizeA.By our invariant, i < sizeA, so after executing i + +, we have i == sizeA. Substitutinginto our invariant, we have

// Everything in A that’s also in B is in resultensures \forall (int k = 0; k < sizeA; k++;)

(setB.contains(setA.get(k)) ==> intersection.contains(setA.get(k)));

Suppose instead that intersection.size() >= sizeB. By our invariant intersection.size() <=sizeB, so intersection.size() == sizeB. Substituting into our invariant, we have:

// Everything in result is in A and Bensures \forall( int k = 0; k < setB.size(); k++;)

(setA.contains(\result.get(k)) && setB.contains(\result.get(k)));

so everything in setB is also in the result and vice versa. So for any k such thatsetB.contains(setA.get(k)), we have that result.contains(setA.get(k)) such that

// Everything in A that’s also in B is in resultensures \forall (int k = 0; k < sizeA; k++;)

(setB.contains(setA.get(k)) ==> intersection.contains(setA.get(k)));

7. loop invariant 2 → invariant (both cases)

In either case, by our invariant we already have

ensures i < sizeA;

Case True: We execute

Brandon McPhail

setA.get(i).intValue() == setB.set(j).intValue();intersection.add(setA.get(i));j = sizeB;j++;j < sizeB;

By our invariant, intersection.size() < sizeB, so add one element still ensures thatensures intersection.size() <= sizeB;

We also have an invariant that intersection was previously a set, and thatensures \forall (int k = i; k < sizeA; k++;)

(\not intersection.contains(setA.get(i)));

so intersection did not already contain setA.get(i). So intersection is still a set andwe have:// intersection is a setensures \forall( int k = 0; k < intersection.size() - 1; k++;)

(\forall (int m = k+1; m < intersection.size(); m++;)(intersection.get(k).intValue() != intersection.get(m).intValue()));

Since setA.get(i) is in intersection, it follows that// Everything in intersection is in A and Bensures \forall( int k = 0; k < intersection.size(); k++;)

(setA.contains(intersection.get(k)) && setB.contains(intersection.get(k)));

By our invariant, intersection includes the intersection of the first i elements ofA with B, and excludes the remaining elements of A. By execution, now it alsoincludes the i + 1-st element, so we have// intersection includes all A[0..i] \cap Bensures \forall (int k = 0; k <= i; k++;)

(setB.contains(setA.get(k)) ==> intersection.contains(setA.get(k)));// intersection excludes all A[(i+1)...sizeA]ensures \forall (int k = i+1; k < sizeA; k++;)

(\not intersection.contains(setA.get(k)));

Case False: Since the intersection remains unchanged, we haveensures intersection.size() <= sizeB;// intersection is a setensures \forall( int k = 0; k < intersection.size() - 1; k++;)

(\forall (int m = k+1; m < intersection.size(); m++;)(intersection.get(k).intValue() != intersection.get(m).intValue()));

// Everything in intersection is in A and Bensures \forall( int k = 0; k < intersection.size(); k++;)

(setA.contains(intersection.get(k)) && setB.contains(intersection.get(k)));

Finally, since A[i] !∈ B, and we don’t include it in the intersection, we can updateour invariants to:// intersection includes all A[0..i] \cap B

Brandon McPhail

ensures \forall (int k = 0; k <= i; k++;)(setB.contains(setA.get(k)) ==> intersection.contains(setA.get(k)));

// intersection excludes all A[(i+1)...sizeA]ensures \forall (int k = i+1; k < sizeA; k++;)

(\not intersection.contains(setA.get(k)));

8. loop invariant 2 → loop invariant 2 (only 1 case is consistent)

Case True: We executesetA.get(i).intValue() == setB.get(j).intValue();intersection.add(setA.get(i));j = sizeB;j++;j < sizeB;

By execution, j < sizeB, but j = sizeB + 1, so this is an infeasible path.Case False: We execute

setA.get(i).intValue() == setB.get(j).intValue();j++;j < sizeB;

Since we have not updated i or intersection, all invariants continue to hold:// loop invariant 2ensures i < sizeA;ensures intersection.size() < sizeB;// intersection is a setensures \forall( int k = 0; k < intersection.size() - 1; k++;)

(\forall (int m = k+1; m < intersection.size(); m++;)(intersection.get(k).intValue() != intersection.get(m).intValue()));

// Everything in intersection is in A and Bensures \forall( int k = 0; k < intersection.size(); k++;)

(setA.contains(intersection.get(k)) && setB.contains(intersection.get(k)));// intersection includes all A[0...i] \cap Bensures \forall (int k = 0; k < i; k++;)

(setB.contains(setA.get(k)) ==> intersection.contains(setA.get(k)));// intersection excludes all A[i...sizeA]ensures \forall (int k = i; k < sizeA; k++;)

(\not intersection.contains(setA.get(k)));

6. Prove that the method setIntersection terminates.At every iteration of the inner loop, either j increases by 1, or j is set to sizeB+1, in which

case it exits the loop. Since sizeB is never modified, we always exit the inner loop.At every iteration of the outer loop, i increases by 1. Since sizeA never changes, we always

exit the outer loop (and we may exit early).Since we always exit the outer loop, the program terminates.