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.
Related
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.
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.
I've come across a programming question at reddit (Take a look at the link for the question)
This was one the solutions in Python:
s="112213"
k=2
result=0
for i in range(len(s)):
num_seen = 0
window = {}
for ind in range(i, len(s)):
if not s[ind] in window:
num_seen += 1
window[s[ind]] = 1
else:
window[s[ind]] += 1
if window[s[ind]] == k:
num_seen -= 1
if num_seen == 0:
result +=1
elif window[s[ind]] > k:
break
print(result)
I've tried to port this solution into Raku and here is my code:
my #s=<1 1 2 2 1 3>;
my $k=2;
my $res=0;
for ^#s {
my $seen = 0;
my %window;
for #s[$_..*] {
if $^a == %window.keys.none {
$seen++;
%window{$^a} = 1;}
else {
%window{$^a} += 1;}
if %window{$^a} == $k {
$seen--;
if $seen == 0 {
$res++;} }
elsif %window{$^a} > $k {
last;}}}
say $res;
It gives this error:
Use of an uninitialized value of type Any in a numeric context in a block at ... line 13
How to fix it?
I don't feel that's a MRE. There are too many issues with it for me to get in to. What I did instead is start from the original Python and translated that. I'll add some comments:
my \s="112213" .comb; # .comb to simulate Python string[n] indexing.
my \k=2;
my $result=0; # result is mutated so give it a sigil
for ^s -> \i { # don't use $^foo vars with for loops
my $num_seen = 0;
my \window = {}
for i..s-1 -> \ind {
if s[ind] == window.keys.none { # usefully indent code!
$num_seen += 1;
window{s[ind]} = 1
} else {
window{s[ind]} += 1
}
if window{s[ind]} == k {
$num_seen -= 1;
if $num_seen == 0 {
$result +=1
}
} elsif window{s[ind]} > k {
last
}
}
}
print($result)
displays 4.
I'm not saying that's a good solution in Raku. It's just a relatively mechanical translation. Hopefully it's helpful.
As usual, the answer by #raiph is correct. I just want to do the minimal changes to your program that get it right. In this case, it's simply adding indices to both loops to make stuff clearer. You were using the context variable $_ in the first, and $^a in the second (inner), and it was getting unnecesarily confusing.
my #s=<1 1 2 2 1 3>;
my $k=2;
my $res=0;
for ^#s -> $i {
my $seen = 0;
my %window;
for #s[$i..*] -> $c {
if $c == %window.keys.none {
$seen++;
%window{$c} = 1;
} else {
%window{$c} += 1;
}
if %window{$c} == $k {
$seen--;
if $seen == 0 {
$res++;
}
} elsif %window{$c} > $k {
last;
}
}
}
say $res;
As you see , besides trying to indent everything a bit more properly, the only additional thing is to add -> $i and -> $c so that loops are indexed, and then use them where you were using implicit variables.
I have been having this problem for a few hours. I don't know what it is, but I am having a hard time thinking clearly at the moment. This method displays a set of images. The first part of the method is just setting the gridbag constraints, whereas the next part in the if statement is creating jlabels and adding them to an arraylist of jlabels. The exception is being thrown when I try and add mouselisteners to the jlabels after they have been added to the arraylist (this is on line 112, and i have commented this on the code).
public void displayComplexStimulus(BufferedImage[] complexStimulus){
for(int i = 0; i < numberOfElements; i++){
if (i == 0 || i == 1 || i == 2){
c.gridx = i;
c.gridy = 0;
}
else if(i == 3 || i == 4 || i == 5){
c.gridx = i - 3;
c.gridy = 1;
}
else {
c.gridx = i - 6;
c.gridy = 2;
}
if(counter == 1){
if (phase1Trial.getPositionOfCorrectImage()!= i){
phase1IncorrectLabels.add(new JLabel(new ImageIcon(complexStimulus[i])));
phase1IncorrectLabels.get(i).addMouseListener(this); //line 112
add(phase1IncorrectLabels.get(i),c);
}
else if(phase1Trial.getPositionOfCorrectImage() == i){
correctLabel = new JLabel(new ImageIcon(complexStimulus[i]));
add(correctLabel, c);
correctLabel.addMouseListener(this);
}
}
}
}
If i==phase1Trial.getPositionOfCorrectImage() you're not adding an element to phase1IncorrectLabels. So in the next iteration after adding one element to the array it's at position i-1 and not i. You should replace your get(i) by get(phase1IncorrectLabels.size() - 1).
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;
}
}