Dafny prove lemmas in a high-order polymorphic function - theorem-proving

I have been working on an algorithm (Dafny cannot prove function-method equivalence, with High-Order-Polymorphic Recursive vs Linear Iterative) to count the number of subsequences of a sequence that hold a property P. For instance, how many subsequences hold that 'the number of positives on its left part are more that on its right part'.
But this was just to offer some context.
The important function is this CountAux function below. Given a proposition P (like, x is positive), a sequ sequence of sequences, an index i to move through the sequences, and an upper bound j:
function CountAux<T>(P: T -> bool, sequ: seq<T>, i: int, j:int): int
requires 0 <= i <= j <= |sequ|
decreases j - i //necessary to prove termination
ensures CountAux(P,sequ,i,j)>=0;
{
if i == j then 0
else (if P(sequ[i]) then 1 else 0) + CountAux(P, sequ, i+1,j)
}
To finish with it, now, it turns out I need a couple of lemmas (which I strongly believe they are true). But I have no idea how to do prove, could anyone help or provide the proofs? Do not seem difficult, but I am not used to prove in Dafny (sure they can be done using structural induction).
These are the lemmas I would like to prove:
lemma countLemma1<T>(P: T -> bool, sequ: seq<T>,i:int,j:int,k:int)
requires 0<=i<=k<=j<=|sequ|
ensures CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j)
//i.e. [i,k) [k,j)
{
if sequ == [] {
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
else{
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
}
lemma countLemma2<T>(P: T -> bool, sequ: seq<T>,i:int,j:int,k:int,l:int)
requires 0<=i<=j<=|sequ| && 0<=k<=l<=j-i
ensures CountAux(P,sequ[i..j],k,l)==CountAux(P,sequ,i+k,i+l)
//that is, counting the subsequence is the same as counting the original sequence with certain displacements
{
if sequ == [] {
assert CountAux(P,sequ[i..j],k,l)==CountAux(P,sequ,i+k,i+l);
}
else{
assert CountAux(P,sequ[i..j],k,l)==CountAux(P,sequ,i+k,i+l);
}
}
EDIT:
I have been trying but it seems I am misunderstanding structural induction. I identified three basic cases. Out of them, I see that if i==0, then the induction should hold (it fails), and therefore if i>0 I try to reach the i==0 using induction:
lemma countID<T>(P: T -> bool, sequ: seq<T>,i:int,j:int,k:int)//[i,k) [k,j)
requires 0<=i<=k<=j<=|sequ|
ensures CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j)
{
if sequ == [] || (j==0) || (k==0) {
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
else {
if (i==0) {
countID(P,sequ[1..],i,j-1,k-1);
assert CountAux(P,sequ[1..],i,j-1)
==CountAux(P,sequ[1..],i,k-1)+CountAux(P,sequ[1..],k-1,j-1);
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
else{
//countID(P,sequ[i..],0,j-i,k-i);
//assert CountAux(P,sequ[i..],0,j-i)
// ==CountAux(P,sequ[i..],0,k-i)+CountAux(P,sequ[i..],k-i,j-i);
countID(P,sequ[1..],i-1,j-1,k-1);
assert CountAux(P,sequ[1..],i-1,j-1)
==CountAux(P,sequ[1..],i-1,k-1)+CountAux(P,sequ[1..],k-1,j-1);
}
//assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
}

You can prove your lemma in recursive manner.
You can refer https://www.rise4fun.com/Dafny/tutorialcontent/Lemmas#h25 for detailed explanation. It also has an example which happens to be very similar to your problem.
lemma countLemma1<T>(P: T -> bool, sequ: seq<T>,i:int,j:int,k:int)
requires 0<=i<=k<=j<=|sequ|
ensures CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j)
decreases j - i
//i.e. [i,k) [k,j)
{
if i == j {
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
else{
if i == k {
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
else {
countLemma1(P, sequ, i+1, j, k);
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
}
}
lemma countLemma2<T>(P: T -> bool, sequ: seq<T>,i:int,j:int,k:int,l:int)
requires 0<=i<=j<=|sequ| && 0<=k<=l<=j-i
ensures CountAux(P,sequ[i..j],k,l)==CountAux(P,sequ,i+k,i+l)
decreases j - i
//that is, counting the subsequence is the same as counting the original sequence with certain displacements
{
if i == j {
assert CountAux(P,sequ[i..j],k,l) == CountAux(P,sequ,i+k,i+l);
}
else{
if k == l {
assert CountAux(P,sequ[i..j],k,l) == CountAux(P,sequ,i+k,i+l);
}
else {
countLemma1(P, sequ[i..j], k, l, l-1);
assert CountAux(P,sequ[i..j],k,l) == CountAux(P,sequ[i..j],k,l-1) + CountAux(P,sequ[i..j],l-1,l);
countLemma1(P, sequ, i+k, i+l, i+l-1);
assert CountAux(P,sequ,i+k,i+l) == CountAux(P,sequ,i+k,i+l-1) + CountAux(P,sequ,i+l-1,i+l);
countLemma2(P, sequ, i, j-1, k ,l-1);
assert CountAux(P,sequ[i..(j-1)],k,l-1) == CountAux(P,sequ,i+k,i+l-1);
lastIndexDoesntMatter(P, sequ, i,j,k,l);
assert CountAux(P,sequ[i..j],k,l-1) == CountAux(P,sequ[i..(j-1)],k,l-1); // this part is what requires two additional lemmas
assert CountAux(P,sequ[i..j],l-1,l) == CountAux(P,sequ,i+l-1,i+l);
assert CountAux(P,sequ[i..j],k,l) == CountAux(P,sequ,i+k,i+l);
}
}
}
lemma lastIndexDoesntMatter<T>(P: T -> bool, sequ: seq<T>,i:int,j:int,k:int,l:int)
requires i != j
requires k != l
requires 0<=i<=j<=|sequ| && 0<=k<=l<=j-i
ensures CountAux(P,sequ[i..j],k,l-1) == CountAux(P,sequ[i..(j-1)],k,l-1)
{
assert l-1 < j;
if j == i + 1 {
}
else {
unusedLastIndex(P, sequ[i..j], k, l-1);
assert sequ[i..(j-1)] == sequ[i..j][0..(|sequ[i..j]|-1)];
assert CountAux(P,sequ[i..j],k,l-1) == CountAux(P,sequ[i..(j-1)],k,l-1);
}
}
lemma unusedLastIndex<T>(P: T -> bool, sequ: seq<T>, i: int, j:int)
requires 1 < |sequ|
requires 0 <= i <= j < |sequ|
ensures CountAux(P,sequ,i,j) == CountAux(P,sequ[0..(|sequ|-1)],i,j)
decreases j-i
{
if i == j{
}
else {
unusedLastIndex(P, sequ, i+1, j);
}
}

Related

What is the correct use of select statement in Go?

Good Day everyone
I have been learning the fundaments of go and how to use its channel-based concurrency paradigm.
However, while playing with some code I wrote focusing on the select statement I found a strange behavior:
func main() {
even := make(chan int)
odd := make(chan int)
quit := make(chan bool)
//send
go send(even, odd, quit)
//receive
receive(even, odd, quit)
fmt.Println("Exiting")
}
func send(e, o chan<- int, q chan<- bool) {
for i := 0; i < 100; i++ {
if i%2 == 0 {
e <- i
} else {
o <- i
}
}
close(e)
close(o)
q <- true
close(q)
}
func receive(e, o <-chan int, q <-chan bool) {
for cont, i := true, 0; cont; i++ {
fmt.Println("value of i", i, cont)
select {
case v := <-e:
fmt.Println("From even channel:", v)
case v := <-o:
fmt.Println("from odd channel:", v)
case v := <-q:
fmt.Println("Got exit message", v)
// return // have also tried this instead
cont = false
}
}
}
when I run this simple program sometimes the i accumulator ends up with more than a 100 being printed to the console, and instead of finishing up with a "from odd channel: 99", the for loop continues on outputting one or more zeroes from even/odd channels randomly, as if the quit channel's message was being somewhat being delayed onto its case and instead the odd/even channels were sending more integers thus quitting the for loop not exactly after the odd/even channels have been closed.
value of i 97 true
from odd channel: 97
value of i 98 true
From even channel: 98
value of i 99 true
from odd channel: 99
value of i 100 true
From even channel: 0
value of i 101 true
From even channel: 0
value of i 102 true
from odd channel: 0
value of i 103 true
From even channel: 0
value of i 104 true
Got exit message true
Exiting
I have tried to search for the correct use of the case statement but I havenĀ“t been able to find the problem with my code.
It seems like the same behavior can be reproduced on the go playground: my code
thanks for your attention put on my question.
The program is printing 0 because receive on a closed channel returns the zero value. Here's one way to accomplish your goal.
First, eliminate the q channel. Closing the o and e channels is sufficient to indicate that the sender is done.
func send(e, o chan<- int, q chan<- bool) {
for i := 0; i < 100; i++ {
if i%2 == 0 {
e <- i
} else {
o <- i
}
}
close(e)
close(o)
}
When receiving values, use the two value receive to detect when the zero value is returned because the channel is closed. Set the channel to nil when the channel is closed. Receive on a nil channel does not yield a value. Loop until both channels are nil.
func receive(e, o <-chan int, q <-chan bool) {
for e != nil && o != nil {
select {
case v, ok := <-e:
if !ok {
e = nil
continue
}
fmt.Println("From even channel:", v)
case v, ok := <-o:
if !ok {
o = nil
continue
}
fmt.Println("From odd channel:", v)
}
}
}
playground example

swift 3 variable used before begin initialized

I have an issue with my n variable. I cannot use n in for loop. Why? n was initialized before for loop. Please, help.
import Foundation
var n: Int
var t: Int
while(true){
var tt = readLine()
t = Int(tt!)!
if (t==0){
break
}
else if ( t < 0){
n = t*(-1)
}
else if(t > 0){
n = t
}
var arr : [[String]] = []
for i in 0..<n*2{
for y in 0..<n*2{
arr[i][y] = "."
}
}
}
A variable may be declared and not immediately initialized, as long as initialization is guaranteed before first use
The error is more subtle than at first glance. You may actually declare a property without initializing it, as long as all program flows leading to its first use ascertain initialization of it.
The issue is with the if, else if and else if block:
var n: Int // declaration
// ...
if (t == 0) {
break
}
else if (t < 0) {
n = t*(-1)
}
else if (t > 0){
n = t
}
// first use
for i in 0..<n*2 { /* ... */ }
Swift cannot not infer that this block is in fact exhaustive, and believes that there is a possibility that none of the above if statements holds, which, in the eyes of the compiler, would lead to the following program state:
program flow has not been broken (break)
and n has not been instantiated
As humans, however, we know that the if - else if - else if block above is indeed exhaustive, and can help the compiler out by simply changing the last if else statement to a simple else statement.
if (t == 0) {
break
}
else if (t < 0) {
n = t*(-1)
}
// if none of the above, t > 0
else {
n = t
}
On another note, the nested array access of non-existing array elements, arr[i][y] = "." will lead to a runtime exception, but this is another issue. In its current form, it looks as if the intent with the nested loops could be replaced with a nested array instantiation:
var arr = [[String]](repeating: [String](repeating: ".", count: 2*n), count: 2*n)
or,
var arr = (0..<2*n).map { _ in [String](repeating: ".", count: 2*n) }
The variable n is only declared, not initialized.
To initialize the variables:
var n: Int = 0
var t: Int = 0

Swift on array.sort - Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions

I am downgrading Swift code from Xcode 8.3.1 to Xcode 7.3.1.
The Swift compiler of Xcode 7.3.1 raises
Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions
while pointing on line zeroParameterAndPaths.sort {. The code was ok in Xcode 8.3.1.
What's wrong and how to fix it?
class NewConnectingSegmentZeroParameterAndPath {
let step : Int; // 0 = main, 1 = first outline, 2 = second outline
let parameter : CGFloat;
init(step: Int, parameter: CGFloat) {
self.step = step;
self.parameter = parameter;
}
}
var zeroParameterAndPaths : [NewConnectingSegmentZeroParameterAndPath] = [];
// ... some zeroParameterAndPaths .appendContentsOf calls
zeroParameterAndPaths.sort {
return $0.parameter < $1.parameter
|| ($0.parameter == $1.parameter
&& ($0.step == 1 || ($0.step == 0 && $1.step == 2))
)
};
You have two choices. One is simply to do what the error message suggests, i.e. pulling the complex bool apart into separate pieces:
zeroParameterAndPaths.sort {
let bless = ($0.parameter < $1.parameter)
let beq = ($0.parameter == $1.parameter)
let band = ($0.step == 0 && $1.step == 2)
let bor = ($0.step == 1 || band)
let beqandbor = (beq && bor)
return (bless || beqandbor)
};
The other is to provide an explicit in line giving the param types and result type:
zeroParameterAndPaths.sort {
(a:NewConnectingSegmentZeroParameterAndPath, b:NewConnectingSegmentZeroParameterAndPath) -> Bool in
return a.parameter < b.parameter
|| (a.parameter == b.parameter
&& (a.step == 1 || (a.step == 0 && b.step == 2))
)
};
You could also make your class a little bit more helpful and make it implement the condition. The compiler is much less likely to get confused in a function body than in a closure:
class NewConnectingSegmentZeroParameterAndPath {
let step : Int; // 0 = main, 1 = first outline, 2 = second outline
let parameter : CGFloat;
init(step: Int, parameter: CGFloat) {
self.step = step;
self.parameter = parameter;
}
func orderedBefore(_ other: NewConnectingSegmentZeroParameterAndPath) -> Bool
{
return parameter < other.parameter
|| parameter == other.parameter
&& (step == 1 || step == 0 && other.step == 2)
}
}
var zeroParameterAndPaths : [NewConnectingSegmentZeroParameterAndPath] = [];
// ... some zeroParameterAndPaths .appendContentsOf calls
zeroParameterAndPaths.sort { $0.orderedBefore($1) }
Apart from the issue of the type inference engine not being able to quickly resolve such complex bool expressions, such expressions are really hard to follow. I suggest you break it down into something simpler, like so:
zeroParameterAndPaths.sort {
if $0.parameter != $1.parameter { return $0.parameter < $1.parameter ]
if $0.step == 1 { return true }
if $0.step == 0 && $1.step == 2 { return true }
return false
};
There's my attempt at it. I'm not even sure if it's correct, the original expression is pretty hard to follow.

Are "&&" and "," the same in Swift?

As the title says, I just came across a case where if && (AND) and , give the same result in Swift. I tested the code below:
let a = 5
let b = 6
if a<6, b>0 {
print("should be true")
}
if a<6, b<0 {
print("should be false")
}
if a>6, b>0 {
print("should be false")
}
if a>6, b<0 {
print("should be false")
}
It only logs:
should be true
So, the behavior of , is just like &&, am I correct?
They can be used in similar situations but that does not mean they are exactly the same.
Consider:
if (a && b) || c
you cannot write
if (a, b) || c
even a && b || c is different from a, b || c.
if a, b is something like
if a {
if b {
...
}
}
Both expressions have to be evaluated to true but they are still two separate expressions. We shouldn't imagine && there.
Why do we need the , operator?
The operator is needed to combine optional binding with boolean conditions, e.g.
if let a = a, a.isValid() {
becuase && wouldn't help us in such situations.
They're different in that a comma will take the lowest precedence possible. i.e everything else will be executed before the commas are checked.
// (true || false) && false
if true || false, false {
print("I will never be executed")
}
// true || (false && false)
if true || false && false {
print("I am always executed")
}

A concise way to not execute a loop now that C-Style for loops are going to be removed from Swift 3?

Imagine we have this code which works perfectly for n >= 0.
func fibonacci(n: Int) -> Int {
var memo = [0,1]
for var i = 2; i <= n; i++ {
memo.append(memo[i-1] + memo[i-2])
}
return memo[n]
}
If I remove the C-style for loop due to upcoming changes to Swift 3.0, I get something like this:
func fibonacci(n: Int) -> Int {
var memo = [0,1]
for i in 2...n {
memo.append(memo[i-1] + memo[i-2])
}
return memo[n]
}
While this works fine for n >= 2, it fails for the numbers 0 and 1 with this error message:
fatal error: Can't form Range with end < start
What's the most concise way to fix this code so it works properly for 0 and 1?
(Note: It's okay, and even desirable, for negative numbers to crash the app.)
Note: I realize I could add a guard statement:
guard n >= 2 else { return memo[n] }
... but I'm hoping there is a better way to fix just the faulty part of the code (2...n).
For example, if there was a concise way to create a range that returns zero elements if end < start, that would be a more ideal solution.
To do this in a way that works for n < 2, you can use the stride method.
let startIndex = 2
let endIndex = n
for i in stride(from: startIndex, through: endIndex, by: 1) {
memo.append(memo[i-1] + memo[i-2])
}
You can easily create a valid range with the max() function:
for i in 2 ..< max(2, n+1) {
memo.append(memo[i-1] + memo[i-2])
}
This evaluates to an empty range 2 ..< 2 if n < 2.
It is important to use the ..< operator which excludes the upper bound because 2 ... 1 is not a valid range.
But in this function I would simply treat the special cases first
func fibonacci(n: Int) -> Int {
// Let it crash if n < 0:
precondition(n >= 0, "n must not be negative")
// Handle n = 0, 1:
if n <= 1 {
return n
}
// Handle n >= 2:
var memo = [0,1]
for i in 2 ... n {
memo.append(memo[i-1] + memo[i-2])
}
return memo[n]
}
(Note that your memo array is set to the initial value [0, 1]
for each function call, so the values are not really "memoized".
Without memoization you don't need an array, it would suffice to keep the last two numbers to compute the next.)
As it turns out, the variable i will always be equal to the count of the memoizing array, so you can just use that as your loop condition:
func fibonacci(n: Int) -> Int {
var memo = [0,1]
while n >= memo.count {
memo.append(memo[memo.count-1] + memo[memo.count-2])
}
return memo[n]
}
Alternatively, you could express the loop as a recursive function:
func fibonacci(n: Int) -> Int {
var memo = [0,1]
func rec(i: Int) -> Int {
if i >= memo.count { memo.append(rec(i-2) + rec(i-1)) }
return memo[i]
}
return rec(n)
}
Really, though, if is the best solution here. Ranges don't allow the end to be smaller than the beginning by design. The extra line for:
func fibonacci(n: Int) -> Int {
if n < 2 { return n }
var memo = [0,1]
for i in 2...n {
memo.append(memo[i-1] + memo[i-2])
}
return memo[n]
}
Is readable and understandable. (To my eye, the code above is better than the for ;; version)
#Marc's answer is great: https://stackoverflow.com/a/34324032/1032900
But the stride syntax is too long for frequent usage, so I made it a little more pleasant for the common i++ usages...
extension Strideable {
#warn_unused_result
public func stride(to end: Self) -> StrideTo<Self> {
return stride(to: end, by: 1)
}
}
extension Strideable {
#warn_unused_result
public func stride(thru end: Self) -> StrideThrough<Self> {
return stride(through: end, by: 1)
}
}
So use like this:
for i in startPos.stride(to: endPos) {
print("pos at: \(i)")
}