When are Dafny sequences equal? - sequence

Hi Having defined a function that builds a sequence from a set it is easy to verify that from equal sets the function must return equal sequences. But this is not what the results look liked
qr = [3, 1, 2] == qt = [1, 2, 3] ??
I am using VScode and running what it calls Dafny 0.18.0. There is either a bug in Dafny or a misunderstanding on my part.
Any corrections welcome.
predicate setIsSeq<T>(t : set<T>, q : seq<T>)
{ (|t| == |q|) ==>
(forall i :: (0 <= i < |q|) ==> (q[i] in t)) &&
(forall x :: x in t ==> (x in q))
}
function method fSetToSeq<T>(t : set<T>) : (r : seq<T>)
decreases t
ensures setIsSeq(t,r);
{
var inner := t;
if (|inner| == 0) then []
else (
var e :| e in inner;
var tx := inner - {e};
var qx := fSetToSeq(tx);
[e] + qx )
}
lemma {:induction s1, s2} whatIsSeq<T>(s1 : set<T>, s2 : set<T>)
ensures s1 == s2 ==> fSetToSeq(s1) == fSetToSeq(s2) {}
method Main() {
var st:set<nat> := {1,2,3};
var sr:set<nat> := {3,1,2};
assert st == sr;
var qr:seq<nat> := fSetToSeq(sr);
var qt:seq<nat> := fSetToSeq(st);
assert qr == qt;
print "qr = ", qr," == qt = ", qt," ?? \n";
var xr:seq<nat> := [1, 2, 3];
var yr:seq<nat> := [3, 1, 2];
print "yr = ", yr," != xr = ", xr," ?? \n";
assert yr != xr;
}

Yep, definitely a bug. This is the same bug as the one from this question. fSetToSeq should not be allowed to be compiled. Please report on github.

Related

Can not assert the value from Dafny method

This is the code for Bulls and Cows game, simply it just we have 2 array a[] and b[] with the same length, if a[i] == b[i] then Bulls += 1, if a[i] in b && a[i] != b[i] then Cows += 1.
I have written the Bulls and Cows function, but the method BullCows have some problem when calculate it, it make my assert fail.
`
function bullspec(s:seq<nat>, u:seq<nat>): nat
requires |s| > 0
requires |u| > 0
requires |s| == |u|
{
var index:=0;
if |s| == 1 then (
if s[0]==u[0]
then 1 else 0
) else (
if s[index] != u[index]
then bullspec(s[index+1..],u[index+1..])
else 1+bullspec(s[index+1..],u[index+1..])
)
}
function cowspec(s:seq<nat>, u:seq<nat>): nat
requires |s| > 0
requires |u| > 0
requires |s| <= |u|
{
var extra:= |u|-|s|;
var index:=0;
if |s| == 1 then (
if s[0] in u
then 1 else 0
) else(
if s[index] in u && s[index]!=u[extra]
then (1+ cowspec(s[index+1..],u))
else cowspec(s[index+1..],u)
)
}
method BullsCows (s:seq<nat>, u:seq<nat>) returns (b:nat, c:nat)
requires |s|>0 && |u|>0 &&|s|==|u|
// No duplicates in array
requires forall i, j | 0 <= i < |s| && 0 <= j < |s| && i != j :: s[i] != s[j]
requires forall i, j | 0 <= i < |u| && 0 <= j < |u| && i != j :: u[i] != u[j]
ensures forall k :: 0 <= k < |s| && s[k] !in u ==> b == c == 0
ensures forall k :: 0 <= k < |s| && s[k] in u ==> (c + b) > 0
{
var index := 0;
b := 0;
c := 0;
while(index<|s|)
invariant index <= |s|
invariant forall k :: 0 <= k < index && s[k] in u ==> (b + c) > 0
{
if s[index] in u {
if s[index] == u[index]{
b:=b+1;
} else {
c:=c+1;
}
}
index:=index + 1;
}
}
method NotMain()
{
var sys:seq<nat> := [4,2,9,3,1];
var usr:seq<nat> := [1,2,3,4,5];
assert bullspec(sys, usr) == 1; //True
assert cowspec(sys, usr) == 3; //True
var b:nat, c:nat := BullsCows(sys, usr);
assert b == 1; //Not true
assert c == 3; //Not true
}
`
The method NotMain said that assert b == 1; and assert c==3; are not true, this is Dafny language, please could someone help me with this logical, I'm banging my head.
I try put on many ensures in the BullsCows method but there's nothing happen
The problem is that the postcondition on BullsCows() is not strong enough to prove the final two assertions. In particular, there is no connection between the operation of BullsCows() and the specifications bullspec() and cowspec(). You need to connect these things together.
To illustrate I'm going to use a simpler example which is easier to follow. As for your example above, the final assertion fails in the following:
function sumspec(xs: seq<nat>, i: nat) : nat
requires i <= |xs| {
if |xs| == 0 || i == 0 then 0
else sumspec(xs,i-1) + xs[i-1]
}
method sum(s:seq<nat>) returns (r:nat) {
r := 0;
for i := 0 to |s| {
r := r + s[i];
}
return r;
}
method main() {
assert sumspec([1,2,3],3) == 6;
var r := sum([1,2,3]);
assert r == 6;
}
Whilst sumspec() is a valid specification for sum() we have not connected these two things. As such, Dafny assumes that sum() can return any value for r!
To connect the specification (sumspec) with its implementation (sum) we need a stronger postcondition:
method sum(s:seq<nat>) returns (r:nat)
ensures r == sumspec(s,|s|) {
r := 0;
for i := 0 to |s|
invariant r == sumspec(s,i) {
r := r + s[i];
}
return r;
}
Here, r == sumspec(s,|s|) connects the specification with the result of our implementation. We also added a loop invariant to help Dafny show this postcondition holds.

Calculate the numbers without separating them

I can't solve this problem, how to separate the numbers and do the required arithmetic
https://codeforces.com/group/MWSDmqGsZm/contest/219158/problem/O
This is my code , I don't know how true it is
fun main(args:Array<String>) {
val scanner = Scanner(System.`in`)
var s: String = read()!!
var c: Char? = null
var a: String = ""
var b: String = ""
var t: Boolean = true
for (i in 1..s.length) {
if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/') {
c = s[i]
t = false
}else{
if(t){
a+=s[i]
}else{
b+=s[i]
}
}
}
if(c=='+'){
println(a+b)
}else if (c=='-'){
println( "$a - $b" )
}else if (c=='*'){
println("$a * $b")
}else{
println("$a / $b")
}
Try this code:
fun main() {
val str = readLine()!!
val (index, operator) = str.findAnyOf(listOf("+", "-", "*", "/"))!!
val a = str.substring(0, index).toInt()
val b = str.substring(index + 1).toInt()
val result = when (operator) {
"+" -> a + b
"-" -> a - b
"*" -> a * b
"/" -> a / b
else -> -1
}
println(result)
}
findAnyOf documentation:
Finds the first occurrence of any of the specified [strings] in this char sequence.
Returns A pair of an index of the first occurrence of matched string from [strings] and the string matched or null if none of [strings] are found.
Rest of the logic is quite straightforward.

Multiset only verifying with one element array

I'm having a problem with verifying if the count of an element in a multiset is a specific number. Below are two programs, one working (verifying correctly) and one not.
Verifies correctly:
method Main() {
var a: array<int> := new int[1];
a[0] := 2;
assert a[0] == 2;
var ms: multiset<int> := multiset(a[..]);
print ms;
assert ms[2] == 1;
}
Doesn't verify correctly:
method Main() {
var a: array<int> := new int[2];
a[0] := 2;
a[1] := 3;
assert a[0] == 2;
assert a[1] == 3;
var ms: multiset<int> := multiset(a[..]);
print ms;
assert ms[2] == 1;
}
Although, using a sequence directly seems to work just fine:
method Main() {
var s := [2, 3];
var ms: multiset<int> := multiset(s);
print ms;
assert ms[2] == 1;
}
I'm not sure why this is happening. For the first program print ms; prints out multiset{2} and in the second program print ms; prints out multiset{2, 3} which both seem fine, but Dafny raises an assertion violation for the second one at assert ms[2] == 1;. It seems that this happens when the arrays length is > 1.
Am I misunderstanding how multisets work, or is there something else going wrong?
Solution 1
The second program verifies if you add assert a[..] == [2, 3]; some time after setting a[0] and a[1]. For example, the following works:
method Main() {
var a: array<int> := new int[2];
a[0] := 2;
a[1] := 3;
assert a[0] == 2;
assert a[1] == 3;
var ms: multiset<int> := multiset(a[..]);
assert a[..] == [2, 3];
print ms;
assert ms[2] == 1;
}
I don't know why that assert is necessary.
Solution 2
There's another solution which doesn't require asserting the concrete value of a[..]. One can define a function to_seq(a, i) which explicitly computes the value of a[i..] and then assert a[..] == to_seq(a, 0). In more detail:
function to_seq<T>(a: array<T>, i: int) : (res: seq<T>)
requires 0 <= i <= a.Length
ensures res == a[i..]
reads a
decreases a.Length-i
{
if i == a.Length
then []
else [a[i]] + to_seq(a, i + 1)
}
method Main() {
var a: array<int> := new int[2];
a[0] := 2;
a[1] := 3;
var ms: multiset<int> := multiset(a[..]);
assert a[..] == to_seq(a, 0);
assert ms[2] == 1;
}
I'm again not really sure why that assert helps.

Reverse int golang

How to change 12345 to 54321?
With a string, you can change the string to a rune, and reverse it, but you cannot do the same for an integer. I have searched and found no one talking about this. Examples
131415 >>> 514131
1357 >>> 7531
123a >>> ERROR
-EDIT-
I was thinking, why not create a slice and index that?
Then I realized that you can't index int
(http://play.golang.org/p/SUSg04tZsc)
MY NEW QUESTION IS
How do you index an int?
OR
How do you reverse a int?
Here is a solution that does not use indexing an int
package main
import (
"fmt"
)
func reverse_int(n int) int {
new_int := 0
for n > 0 {
remainder := n % 10
new_int *= 10
new_int += remainder
n /= 10
}
return new_int
}
func main() {
fmt.Println(reverse_int(123456))
fmt.Println(reverse_int(100))
fmt.Println(reverse_int(1001))
fmt.Println(reverse_int(131415))
fmt.Println(reverse_int(1357))
}
Result:
654321
1
1001
514131
7531
Go playground
I converted the integer to a string, reverse the string, and convert the result back to a string.
package main
import (
"fmt"
"strconv"
)
func main() {
fmt.Println(reverse_int(123456))
fmt.Println(reverse_int(100))
fmt.Println(reverse_int(1001))
fmt.Println(reverse_int(131415))
fmt.Println(reverse_int(1357))
}
func reverse_int(value int) int {
intString := strconv.Itoa(value)
newString := ""
for x := len(intString); x > 0; x-- {
newString += string(intString[x - 1])
}
newInt, err := strconv.Atoi(newString)
if(err != nil){
fmt.Println("Error converting string to int")
}
return newInt
}
Very similar to the first answer but this checks to make sure you don't go out of bounds on the type.
func reverse(x int) int {
rev := 0
for x != 0 {
pop := x % 10
x /= 10
if rev > math.MaxInt32/10 || (rev == math.MaxInt32 /10 && pop > 7) {
return 0
}
if rev < math.MinInt32/10 || (rev == math.MinInt32/10 && pop < -8) {
return 0
}
rev = rev * 10 + pop
}
return rev
}
Also flips negative numbers int
func Abs(x int) int {
if x < 0 {
return -x
}
return x
}
func reverse_int(n int) int {
newInt := 0
sign := 1
if n < 0 {
sign = -1
}
n = Abs(n)
for n > 0 {
remainder := n % 10
newInt = newInt*10 + remainder
n /= 10
}
return newInt * sign
}
func main() {
fmt.Println(reverse_int(-100))
fmt.Println(reverse_int(-1001))
fmt.Println(reverse_int(131415))
fmt.Println(reverse_int(1357))
}
Similar to Fokiruna's answer but also checks for a 32bit overflow
func reverse(x int) int {
result, sign := 0, 1
if(x < 0) {
sign = -1
x = -x
}
for x > 0 {
remainder := x % 10;
result = result * 10 + remainder
x = x/10
}
var checkInt int = int(int32(result))
if checkInt != result {
return 0
}
return result * sign
}

How to formulate a connection between pre-execution and post-execution state of a method?

I have the following zaMap (see full code here: http://rise4fun.com/Dafny/LCaM):
class zaMap {
var busybits :array<bool>;
var keys : array<int>;
var values : array<int>;
predicate wellformed ()
reads busybits, keys, values, this
{
busybits != null && keys != null && values != null &&
keys != values &&
busybits.Length == keys.Length &&
keys.Length == values.Length
}
// ... more predicates and methods follow
method put(k : int, v : int) returns (success : bool)
requires wellformed()
modifies busybits, keys, values
ensures !success ==> full()
ensures success ==> mapsto(k, v)
{
var i := findEmpty();
if (i < 0)
{
success := false;
return;
}
assert !busybits[i];
busybits[i] := true;
keys[i] := k;
values[i] := v;
success := true;
}
//...
Now I want to add more specifications to the put method. For example, I want to ensure, that if the return value is success == true, then a map was !full() before the function call, or equivalently if a map not full(), it is guaranteed to put there.
The problem is that, in the precondition "requires" I don't know yet what it will return, and in the postcondition "ensures" I don't have an original map anymore. What people do about that?
You can use the old keyword. Let's take a look at an example. The following method sets to zero all positions of an array containing the element x and leaving the rest as they are. Here's the code:
method setToZero(a: array<int>, x : int )
requires a != null;
modifies a;
ensures forall i :: 0 <= i < a.Length && old(a[i]) == x ==> a[i] == 0;
ensures forall i :: 0 <= i < a.Length && old(a[i]) != x ==> a[i] == old(a[i]);
{
var j := 0;
while (j < a.Length)
invariant 0 <= j <= a.Length;
invariant forall i :: 0 <= i < j && old(a[i]) == x ==> a[i] == 0;
invariant forall i :: 0 <= i < j && old(a[i]) != x ==> a[i] == old(a[i]);
invariant forall i :: j <= i < a.Length ==> a[i] == old(a[i]);
{
if (a[j] == x) {
a[j] := 0;
}
j := j + 1;
}
}