# Recursion

In this section, we will see how to prove the correctness of programs that use recursive functions. We will see that verifying a recursive function is exactly the same as verifying a non-recursive function:

- We must prove a function’s preconditions before calling it (including before making a recursive call)
- After calling a function, we can list the function’s postconditions as premises (including after making a recursive call)
- The function can list its preconditions as premises
- The function must prove its postconditions just before it ends

## Writing a recursive mult function

We know we can multiply two numbers, `x`

and `y`

, using the `*`

operator – `x * y`

. But what if we wanted to find the same result using only addition, not multiplication? Multiplication can be thought of as repeated addition – `x * y`

is really `x + x + ... + x`

, where we add together `y`

total `x`

’s.

We *could* do this repeated addition with a loop (and we will when we introduce loops in section 9.3), but we will use recursion instead. When we write a recursive function, we try to think of two things:

- The
*base case*: the simplest version of the problem that we could immediately solve with no more work. - The
*recursive case*: bigger versions of the problem, where we solve a piece of the problem and then recursively solve a smaller piece

In the case of the multiplication `x * y`

, we have:

- Base case: if
`y`

is 0, we have no work to do. Adding togther 0`x`

’s is just 0. - Recursive case: if
`y`

is bigger than 0, we do ONE addition (`x + ...`

) and recursively add the remaining`y - 1`

numbers. (This will become our recursive call.)

With those cases in mind, we can write a recursive `mult`

functio:

```
import org.sireum.logika._
def mult(x: Z, y: Z): Z = {
var ans: Z = 0
if (y > 0) {
var addRest: Z = mult(x, y-1)
ans = x + addRest
} else {
//do nothing
}
return ans
}
```

Note that we separated the recursive call (`def addRest: Z = mult(x, y-1)`

) from adding on the next piece (`ans = x + addRest`

). In Logika, all function calls must go on a separate line by themselves – we can’t combine them with other operations. Also, we included a dummy “else” branch to make the verification simpler.

## Walking through mult

Suppose we call `mult`

as follows:

`var times: Z = mult(4, 2)`

We can trace the recursive calls:

```
times = mult(4, 2)
(x = 4, y = 2)
addRest = mult(4, 1) => mult(4, 1)
ans = 4 + addRest (x = 4, y = 1)
returns ans addRest = mult(4, 0) => mult(4, 0)
ans = 4 + addRest (x = 4, y = 0)
returns ans ans = 0
returns 0
```

We start with `mult(4, 2)`

, and then immediately make the recursive call `mult(4, 1)`

, which immediately makes the recursive call `mult(4, 0)`

. That function instance hits the base case and returns 0. We now return back up the chain of function calls – the 0 gets returned back to the `mult(4, 1)`

instance, which adds 4 and then returns 4:

```
=> mult(4, 1)
(x = 4, y = 1)
addRest = mult(4, 0) = 0
ans = 4 + addRest = 4
returns ans (4)
```

This 4 returns back to the `mult(4, 2)`

instance, which adds another 4 and returns 8:

```
mult(4, 2)
(x = 4, y = 2)
addRest = mult(4, 1) = 4
ans = 4 + addRest = 8
returns ans (8)
```

We have now backed our way up the chain – the 8 is returned back from the original function call, and `times`

is set to 8.

## mult function contract

Looking at our `mult`

function, we see that the base case is when `y`

is 0 and the recursive case is when `y > 0`

. Clearly, the function is not intended to work for negative values of `y`

. This will be our precondition – that `y`

must be greater than or equal to 0.

Our postcondition should describe what `mult`

is returning in terms of its parameters. In this case, we know that `mult`

is performing a multiplication of `x`

and `y`

using repeated addition. So, our function should ensure that it returns `x*y`

(that `result == x*y`

). Here is the function with the function contract:

```
import org.sireum.logika._
def mult(x: Z, y: Z): Z = {
//we still need to add the verification logic blocks
l"""{
requires y >= 0
ensures result == x*y
}"""
var ans: Z = 0
if (y > 0) {
var addRest: Z = mult(x, y-1)
ans = x + addRest
} else {
//do nothing
}
return ans
}
```

## Verification in mult

Now that we have our function contract for `mult`

, we must add logic blocks with two things in mind:

- Proving the precondition before a recursive call
- Proving the postcondition before we return from the function

Our recursive call looks like:

`var addRest: Z = mult(x, y-1)`

Since our precondition is `y >= 0`

, we see that we must prove that what we are passing as the second parameter (`y-1`

, in the case of the recursive call) is greater than or equal to 0. This tells us that before our recursive call, we must have shown exactly: `y-1 >= 0`

. We can finish proving the precondition as follows:

```
import org.sireum.logika._
def mult(x: Z, y: Z): Z = {
//we still need to prove the postcondition
l"""{
requires y >= 0
ensures result == x*y
}"""
var ans: Z = 0
if (y > 0) {
l"""{
1. y > 0 premise //IF condition is true
2. y-1 >= 0 algebra 1 //Proves the precondition for the recursive call
}"""
var addRest: Z = mult(x, y-1)
ans = x + addRest
} else {
//do nothing
}
return ans
}
```

All that remains is to prove the `mult`

postcondition – that we are returning `x*y`

. Since we are returning the variable `ans`

, then we must prove the claim `ans == x*y`

just before our return statement. In order to help with this process, we will need to take advantage of the postcondition after our recursive call. The function promises to return the first parameter times the second parameter, so when we do `addRest: Z = mult(x, y-1)`

, we know that `addRest == x*(y-1)`

(the first parameter, `x`

, times the second parameter, `y-1`

). Here is the completed verification

```
import org.sireum.logika._
def mult(x: Z, y: Z): Z = {
//verification complete!
l"""{
requires y >= 0
ensures result == x*y
}"""
var ans: Z = 0
if (y > 0) {
l"""{
1. y > 0 premise //IF condition is true
2. y-1 >= 0 algebra 1 //Proves the precondition for the recursive call
}"""
var addRest: Z = mult(x, y-1)
l"""{
1. addRest == x*(y-1) premise //Postcondition from the recursive call
2. addRest == x*y - x algebra 1
}"""
ans = x + addRest
l"""{
1. addRest == x*y - x premise //Pulled from previous block
2. ans == x + addRest premise //From the "ans = x + addRest" assignment statement
3. ans == x + x*y - x algebra 1 2
4. ans == x*y algebra 3 //Showed the postcondition for the IF branch
}"""
} else {
//do nothing in code - but we still do verification
//need to show that postcondition will be correct even if we take this branch
l"""{
1. ¬(y > 0) premise //if condition is false
2. y >= 0 premise //precondition
3. y == 0 algebra 1 2
4. ans == 0 premise //ans is unchanged
5. ans == x*y algebra 3 4 //Showed the postcondition for the ELSE branch
}"""
}
//Tie together what we learned in both branches
l"""{
1. ans == x*y premise //shows the postcondition
}"""
return ans
}
```

## Verification of calling code

Verifying the test code that calls a recursive function works exactly the same way as it does for any other function:

- We must prove the precondition before calling the function
- We can list the postcondition as a premise after calling the function

Suppose we want to test `mult`

as follows:

```
val times: Z = mult(4, 2)
assert(times == 8)
```

We could complete the verification by proving the precondition and then using the postcondition to help us prove the claim in the assert:

```
l"""{
1. 2 >= 0 algebra //proves the precondition
}"""
val times: Z = mult(4, 2)
l"""{
1. times == 4*2 premise //mult postcondition
2. times == 8 algebra 1 //needed for the assert
}"""
assert(times == 8)
```

Note that since our second parameter is `2`

, that we must demonstrate exactly `2 >= 0`

to satisfy `mult`

’s precondition. Furthermore, since `mult`

promises to return the first parameter times the second parameter, and since we are storing the result of the function call in the `times`

variable, then we can claim `times == 4*2`

as a premise.