Both of these problems are from the same paper and use basically the same proof, so we’ll do them together.

**The Problems**: Inequivalence of Programs With Arrays (PO11 in the appendix) and Inequivalence and Programs with Assignments (PO12 in the appendix)

**The Description (for Inequivalence of Programs With Assignments): **

Given two programs P and Q that access a common set of variables, S. Each statement in the program is of the form “x_{0} <- if x_{1} = x_{2} then x_{3} else x_{4}“, where each x_{i} is a variable from S. Will the two programs always give different output for all initial variable configurations?

**The Description (for Inequivalence of Programs With Assignments):**

Same idea, but the possible statements in the program are:

- Select an element B of an array α: A <- α.B
- Update an element B of an array α: α.B <- A
- “Operate” on an operation Φ: A <- Φ B
_{1}B_{2}..B_{k.}Φ comes from a given finite set of operations and is expected to take a certain number of arguments (k) that we know ahead of time.

**Example: ** The “outputs” of these programs are the final values of the variables. They denote a “final” value by representing a program as a Directed Acyclic Graph, and the leaf nodes (of outdegree 0) are the variables with final values. We will specify what variables we care about as output variables

So for example, we might have the one-line program:

k <- if i=j then 2 else 3

Compared to the one-line program:

k <- if i=j then 3 else 2

If k is our output variable, then for all values of i and j both programs will produce different outputs. If we change our second program to:

k<- if i=j then 2 else 2

…then if we assign i and j the same values, both programs will give the same output.

**Reduction (for Inequivalence of Programs With Assignments): **Downey and Sethi use 3SAT. If we start with a formula with variables y_{1}..y_{n} we will create a program with variables {T,F, A_{1}..A_{n}, B_{1}..B_{n,}). Then we just write a program that checks if all clauses are true. “D” will be our output variable and will be updated for each clause. We start it as true initially:

`D <- if T = T then T else T // D is true so far`

Then we check the first clause. A variable “C” will be used for each clause. It starts out false and will be set to true once the clause is satisfied:

`C <- if F = F then F else F // C is false so far`

Then for each literal x_{1}..x_{3} we check if it has been made true. We use A_{i} if the literal is positive in the clause and B_{i} if the literal is negative in the clause. So suppose our clause was (y_{1}, ~y_{2}, y_{4}), we’d have the lines:

`// does the first literal make the clause true?`

`C <- if A`

_{1} = T then T else C

`// does the second literal make the clause true?`

`C <- if B`

_{2} = T then T else C

`// does the third literal make the clause true?`

`C <- if A`

_{4}= T then T else C

C now is true if and only if the clause is satisfied, so let’s update D:

`// D becomes false if we don't satisfy that clause`

`D <- if C = T then D else F`

We then repeat that process for each clause. At the end, we add rules saying that a variable and its negation can’t both have the same value:

`D <- if A`

_{1} = B_{1} then F else D

..repeated for each variable.

The final output of this program is D, which will be true if our inputs legally satisfied the formula, and false otherwise.

Our second program just outputs the constant “F”. The programs will produce different outputs if and only if there is a way for the first program to produce a T, which happens when D is true, which happens when all clauses are true, which happens when the formula is satisfiable.

**Reduction (Inequivalence of Programs With Arrays):** The same program works, we just need to replace our assignment if operations. We do this by placing all of the elements of what we are comparing into an array, and replacing the statement “E <- if A=B then C else D” with:

`α.A <- D`

`α.B <- C`

`E <- α.A`

..if A and B are the same, then we will fill that spot in the array with D then C, and get a C out. Otherwise, the two assignments go to different locations, and E is set to what is in the array at position A, which is the value D. Since we can go back to the previous reduction and replace all of its statements with 3 statements under the new rules, the reduction works in the same way.

**Difficulty: **6. This isn’t a hard reduction to do, I think the hardest thing is to get students to think in terms 0f the restrictions these programs require. There are no loops or anything (that would make this problem undecidable, at least in general), and representing variables as positions in an array is something we might be used to doing if all variables are integers, but since variables here are things like “B_{2}” some work might need to be done to convince students that the mapping to integers for all variables is reasonable. It’s not a thing we do as much with modern high-level languages as we might have done in the 1970s when the underlying machine was much more exposed.