How to resolve a contradiction using Hoare-Logic in LinearSearch - linear-search

I'm trying to proof the following LinearSearch using the Hoare-Logic, but I get a contradiction proofing (1) => (2). I belive that my invariant should be different.
Currently I'm using {s ≥ 0 & s < i → f[s] ≠ value} as invariant. That means all elements from 0 to i-1 have already been compared with the searched value, therefor all elements from f[0] to f[i-1] are unequal to the searched value.
I started applying the rules from the bottom of the algorithm to the top.
The contradiction arises when I try to proof the (1) implicieses (2). Because it applies in (1) that {f[i] = value} and for all s < i it applies that f[s] ≠ value. That is correct so far.
But in (2) it applies for all s <i+1 that f[s] ≠ value and consequently f[i] ≠ value.
The caontradiction is: to proof that
(1) → (2)
I have to proof that
f[i] = value → f[i] ≠ value
and that is not true.
Thats why I think I need to change my invariant. But I don't no how?
public boolean LinearSearch (int value, int[] f) {
//Precondition = {f.length() > 0}
int i = 0;
boolean found = false;
//{s ≥ 0 & s < i → f[s] ≠ value}
while (i < f.length()-1 || !found) {
//{(s ≥ 0 & s < i → f[s] ≠ value) & (i < f.length()-1 || found = false)}
if (value == f[i]) {
(1) //{(s ≥ 0 & s < i → f[s] ≠ value) & (i < f.length()-1 || found = false) & (value = f[i])}
(2) //{(s ≥ 0 & s < i+1 → f[s] ≠ value)}
↕
//{(s ≥ 0 & s < i+1 → f[s] ≠ value) & true = true}
found = true;
//{(s ≥ 0 & s < i+1 → f[s] ≠ value) & found = found}
}
//{(s ≥ 0 & s < i+1 → f[s] ≠ value) & found = found}
↕
//{s ≥ 0 & s < i+1 → f[s] ≠ value}
i = i + 1;
//{s ≥ 0 & s < i → f[s] ≠ value}
}//end while
//{(s ≥ 0 & s < i → f[s] ≠ value) & !(i < f.length()-1 || found = false)}
↓
//Postcondition = {i = f.length()-1 | f[i] = value}
return found;
}//end LinearSearch

Thank you #aioobe for your answer.
I tried
{s ≥ 0 & s < i-1 → f[s] ≠ value}
and got the following proof. I think it works. If you see mistakes please tell me. Maybe it helps anyone else who needs to use the Hoare-Logic.
public boolean LinearSearch (int value, int[] f) {
//Precondition = {f.length() > 0}
↓
//{true & true}
↕
//{true & false = false}
↕
//{false → f[s] ≠ value & false = false}
↕
//{s ≥ 0 & s < 0-1 → f[s] ≠ value & false = false}
int i = 0;
//{s ≥ 0 & s < i-1 → f[s] ≠ value & false = false}
boolean found = false;
//{s ≥ 0 & s < i-1 → f[s] ≠ value & found = found}
↕
//{s ≥ 0 & s < i-1 → f[s] ≠ value}
while (i < f.length() & !found) {
//{(s ≥ 0 & s < i-1 → f[s] ≠ value) & (i < f.length() & found = false)}
if (value == f[i]) {
//{(s ≥ 0 & s < i-1 → f[s] ≠ value) & (i < f.length() & found = false) & (value = f[i])}
↓
//{(s ≥ 0 & s < i → f[s] ≠ value)}
↕
//{(s ≥ 0 & s < i-1+1 → f[s] ≠ value) & true = true}
found = true;
//{(s ≥ 0 & s < i-1+1 → f[s] ≠ value) & found = found}
}
//{(s ≥ 0 & s < i-1+1 → f[s] ≠ value) & found = found}
↕
//{s ≥ 0 & s < i-1+1 → f[s] ≠ value}
i = i + 1;
//{s ≥ 0 & s < i-1 → f[s] ≠ value}
}//end while
//{(s ≥ 0 & s < i-1 → f[s] ≠ value) & !(i < f.length() & found = false)}
↓
//Postcondition = {i = f.length() | found = true}
return found;
}//end LinearSearch

Related

Get If (condition), then (assign value), else (assign other value) statement in Linear Programming

I'm looking for a linear programming equation that satisfied the conditions;
Given that all variables here are binary variables
if A+B = 2; then C = 1; else C = 0
Also,
if A+B+D = 3; then E = 1; else E = 0
How would one phrase this and satisfy these conditions as well as linearity conditions?
I've tried
A + B - 2 <= M(1-y) and 1 - C <= My
for the first constraint but it doesn't seem to work
For the first equation, you can use:
C + 1 >= A + B
2C <= A + B
If there is a natural sense (max/min) for C in the problem, one of those is sufficient.
Similarly for the second:
E + 2 >= A + B + D
3E <= A + B + D

Pascal Triangle Find position x, y with Haskell function

I want to get 2 integers from an input like pascal 2 1. This input should be 2, because the list starts with x and y = 0. Also pos must be <= row and i don't want to use guards. My code looks like this:
pascal :: Int -> Int -> Int
pascal row pos
if row == 0 || pos == 0 then "1"
else if row > pos then error "Invalid input."
else (pascal (row-1) (pos-1)) + (pascal (row-1) (pos))
Error code:
Unexpected if expression in function application:
if row == 0 || pos == 0 then
"1"
else
if row > pos then
error "Invalid input."
else
(pascal (row - 1) (pos - 1)) + (pascal (row - 1) (pos))
You could write it with parentheses
Or perhaps you meant to enable BlockArguments?
pascal :: Int -> Int -> Int
pascal row pos =
if row == 0 || pos == 0 then 1
else if row > pos then error "Invalid input."
else (pascal (row-1) (pos-1)) + (pascal (row-1) (pos))
To get rid of that error you just need to add an =, which you probably just forgot. But this is really bad style in Haskell. This code begs for guards.

Asserting about the return value of a method involving sequences

I'm a beginner with Dafny, and I'm wondering why the assertion just before the print in the Main method is violated. I'm trying to find the rightmost index where an item should be inserted in order to preserve the order in the sequence, which in this specific case is 4.
https://rise4fun.com/Dafny/4lR2
method BinarySearchInsertionHint(a: seq<int>, key: int) returns (r: int)
requires forall i,j :: 0 <= i < j < |a| ==> a[i] <= a[j]
ensures 0 <= r <= |a|
ensures forall i :: 0 <= i < r ==> a[i] <= key
ensures r < |a| ==> forall i :: r <= i < |a| ==> key < a[i]
{
var lo, hi := 0, |a|;
while lo < hi
decreases hi - lo
invariant 0 <= lo <= hi <= |a|
invariant forall i :: 0 <= i < lo ==> a[i] <= key
invariant forall i :: hi <= i < |a| ==> key < a[i]
{
var mid := (lo + hi) / 2;
assert(lo <= mid < hi);
if a[mid] <= key {
lo := mid + 1;
} else if key < a[mid] {
hi := mid;
}
}
assert(lo == hi);
r := lo;
}
method Main() {
var a := [0, 1, 1, 1, 2];
var hint := BinarySearchInsertionHint(a, 1);
assert hint == 4; // assertion violation
print hint;
}
This can indeed be confusing! There are a few things going on here.
First, remember that Dafny reasons about each method separately, using only the specifications of other methods. So in Main, the only thing Dafny will know about BinarySearchInsertionHint is its postconditions. Now it turns out that hint == 4 actually does follow from the postconditions, but it's a little nontrivial to convince Dafny of this.
This brings us to the Second Thing going on here, which is quantifier triggers. The postconditons of BinarySearchInsertionHint use universal quantifiers (forall), which Dafny reasons about using syntactic heuristics for instantiation. Both of the quantifiers in this example are triggered on a[i], which means that they will not be used at value v unless a[v] is "in scope" for the verifier.
You can get the assertion to pass by mentioning a[3] and a[4], which is enough for Dafny to figure out from the postconditions that hint must be 4. Like this:
method Main() {
var a := [0, 1, 1, 1, 2];
var hint := BinarySearchInsertionHint(a, 1);
assert a[3] == 1; // these assertions just "mention" a[3] and a[4]
assert a[4] == 2;
assert hint == 4; // assertion now passes
print hint;
}
You can read more about Dafny's modular verification, incompleteness, and quantifier triggers in the Dafny FAQ.

Finding string that matches specific requirements

There is a function that should return true:
func accessible(agent string) bool {
a := strings.Split(agent, " ")
if len(a) != 3 { return false }
b := a[0]
c := a[1]
d := a[2]
x := strings.EqualFold(b, c)
y := b != strings.ToLower(c)
z := strings.Index(d, b+c) == 1 && len(d) == 5
return x && y && z
}
However I can't figure out which string input will match these requirements. Am I missing something?
PS: This is task #3 from gocode.io
agent must be 3 "words", 3 parts separated by spaces:
a := strings.Split(agent, " ")
if len(a) != 3 { return false }
1st and 2nd words must match case insensitive:
x := strings.EqualFold(b, c)
But not case sensitive:
y := b != strings.ToLower(c)
And 3rd word must contain the first 2 concatenated:
z := strings.Index(d, b+c) == 1 && len(d) == 5
Starting at index 1 (prepend with any character) and must contain 5 chars (5 bytes) (postpend to have 5 chars/bytes).
Example:
fmt.Println(accessible("A a _Aa__"))
Prints:
true

Parse Error on input 'appendString' Haskell

Hey guys so this is a strange little error I'm getting and I'm not understand why it's giving it to me.
It says Parse Error in input 'appendString' yet I see nothing wrong with it...
I call it from an if,then else statement as follows:
createShow currentIndex (Grid {delta = d, middle = (x,y), points = g}) dir counter =
if currentIndex ==0 || dir == 2
then (appendString d (x,y) g currentIndex) ++ (createShow currentIndex+1 (Grid {delta = d, middle = (x,y), points = g}) 2 (counter+1))
else if counter == (2*d+1)
then (appendString d (x,y) g currentIndex) ++ (appendX x)
else if dir == 1
then (appendString d (x,y) g currentIndex) ++ (createShow currentIndex-1 (Grid {delta = d, middle = (x,y), points = g}) 1 (counter+1))
where createShow returns a string and so does appendString
appendString gives the error in the constructor:
appendString d (x,y) g currentIndex =
(if currentIndex == y
then "y "
else
" " ) ++ (show currentIndex) ++(rowFunction g x d 0 (x+d) 1)++ "\n"
do you see where I could have gone wrong with it?
Edit: Added entire area
Haskell if's are not like other if's in say Java or python. The biggest difference is that they are expressions unlike java or python where they are statements.
They are much closer to the condition ? res1 : res2 from C.
The correct way to write nested if's is like this:
if condition
then foo
else if condition2
then bar
else ...
You'll notice that this is horribly ugly.
That's why haskell has guards:
foo args | condition = foo
| condition2= bar
| otherwise = meh
Here we declare a function foo and if condition is true then we execute foo otherwise we proceed to condition2 and otherwise is always true. For you
createShow currentIndex (Grid {delta = d, middle = (x,y), points = g}) dir counter
| currentIndex == 0 || dir == 2 = appendString d ....
| counter == (2 * d + 1) = appendString d ....
| dir == 1 = appendString d ....
which looks much more readable.
Here's a refactoring::
createShow currentIndex grid#(Grid {delta = d, middle = (x,y), points = g}) dir counter =
prefix ++ show currentIndex ++ row ++ "\n" ++ nextLine
where
prefix = if currentIndex == y then "y " else " "
row = rowFunction g x d 0 (x+d) 1
nextLine | currentIndex == 0 || dir == 2 = createShow (currentIndex+1) grid 2 (counter+1)
nextLine | counter == (2*d+1) = appendX x
nextLine | dir == 1 = createShow (currentIndex-1) grid 1 (counter+1)
appendX x = ...
Things to notice:
Using a where clause often lets you avoid repeating parameters
The common call to appendString has been factored out, and moved to the top, and then in-lined, since it is only called once.
Use of guards in nextLine to handle a cascaded if more clearly.
The guards and form of nextLine make it clear it isn't a total function. What happens when it falls off the end?
The use of grid# to name a pattern. This way you don't need to "reconstruct" the Grid value when making the recursive calls.
One can go further. Noticing that Grid {...} and dir never change throughout the function suggests factoring those out:
createShow currentIndex (Grid {delta = d, middle = (x,y), points = g}) dir counter =
line currentIndex counter
where
line currentIndex counter =
prefix ++ show currentIndex ++ row ++ "\n" ++ nextLine currentIndex counter
prefix = if currentIndex == y then "y " else " "
row = rowFunction g x d 0 (x+d) 1
nextLine currentIndex counter
| currentIndex == 0 || dir == 2 = line (currentIndex+1) (counter+1)
| counter == (2*d+1) = appendX x
| dir == 1 = line (currentIndex-1) (counter+1)
appendX x = ...
Here, line plays the part of "carrying" around the only values that differ as the function recurses. It would be a common idiom to place those arguments at the end of what createShow takes, and thus even factor them out:
createShow :: Grid -> Int -> Int -> Int -> String
createShow (Grid {delta = d, middle = (x,y), points = g}) dir = line
where
line currentIndex counter =
prefix ++ show currentIndex ++ row ++ "\n" ++ nextLine currentIndex counter
prefix = if currentIndex == y then "y " else " "
row = rowFunction g x d 0 (x+d) 1
nextLine currentIndex counter
| currentIndex == 0 || dir == 2 = line (currentIndex+1) (counter+1)
| counter == (2*d+1) = appendX x
| dir == 1 = line (currentIndex-1) (counter+1)
appendX x = ...

Resources