Dafny How could I write a predicate to prove a string is sorted by 'b' => 'a' => 'd'? - dafny

Could somebody please help me out in writing a Dafny predicate that checks if a string is sorted in the order 'b' -> 'a' -> 'd'
i.e:
"bbbaaaaad" == true
"abd" == false
"bad" == true
The predicate should have the following form:
predicate sortedbad(s:string)
{
[???]
}
Thanks

Here is one way to do it.
predicate bad_compare(c1:char, c2:char) {
c1 == 'b' || (c1 == 'a' && c2 != 'b') || c2 == 'd'
}
predicate sortedbad(s:string)
{
forall i, j | 0 <= i <= j < |s| :: bad_compare(s[i], s[j])
}
lemma Test()
{
assert sortedbad("bbbbaaaadddd");
var s := "bbbbbbda";
assert !bad_compare(s[6], s[7]);
assert !sortedbad(s);
}

Related

Multiset proof verification in dafny

I'm trying to prove a little lemma for a larger proof, the lemma definition is below:
lemma LoopLemma(a: seq<int>, b: seq<int>, c: seq<int>, k:int, i:int, j:int)
requires 0 <= i < |a| && 0<= j < |b| && 0 <= k < |c| && i +j ==k && |a| + |b| == |c|
requires Sorted(c[..k]) && Sorted(b) && Sorted(a)
requires multiset(c[..k]) == multiset(a[..i]+b[..j])
ensures Sorted(c[..k]+[b[j]]) && Sorted(c[..k]+[a[i]])
{
assert multiset(c[..k]) == multiset(a[..i]+b[..j]);
var q:=a[..i]+b[..j];
var c1 := c[..k];
assert Sorted(c1);
assert multiset(c1) == multiset(q);
assert |q| == i + j;
assert |c1| == k == i + j;
calc {
multiset(c1) == multiset(q);
==
forall l :: l in multiset(c1) ==> l in multiset(q);
== {assert forall l :: l in multiset(q) ==> exists r :: 0 <= r <|q| && l == q[r]; assert forall l :: l in multiset(c1) ==> exists r :: 0 <= r <|c1| && l == c1[r];}
forall l :: 0<=l <|c1| ==> exists r :: 0 <= r < |q| && q[r] == c1[l];
}
}
I get "the calculation step between the previous line and this line might not hold" for the last step, and I don't understand why.
All I'm saying there is that if the multisets of two sequences are equal, for any entry in the first sequence exists an entry in the second sequence with the same value.
I tried some simpler examples (where I define the sequences explicitly) and it worked. Maybe I don't understand something about multisets?
Any suggestions will help.
Additional hint that needed here is every element in sequence is in multiset i.e forall i :: 0 <= i < |c[..k]| ==> c[..k][i] in multiset(c[..k]) (hint in forward direction of reasoning). Following snippet verifies.
predicate Sorted(a: seq<int>)
{
if |a| <= 1 then true else (a[0] <= a[1]) && Sorted(a[1..])
}
lemma LoopLemma(a: seq<int>, b: seq<int>, c: seq<int>, k: int, i: int, j: int)
requires 0 <= i < |a| && 0 <= j < |b| && 0 <= k < |c| && i + j == k && |a| + |b| == |c|
requires Sorted(c[..k]) && Sorted(a) && Sorted(b)
requires multiset(c[..k]) == multiset(a[..i] + b[..j])
{
var s := a[..i] + b[..j];
calc {
multiset(c[..k]) == multiset(s);
forall e :: e in multiset(c[..k]) ==> e in multiset(s);
{
assert forall e :: e in multiset(c[..k]) ==>
exists r :: 0 <= r < |s| && s[r] == e;
// assert forall e :: e in multiset(c[..k]) ==>
// exists r :: 0 <= r < |c[..k]| && c[..k][r] == e;
assert forall i :: 0 <= i < |c[..k]| ==> c[..k][i] in multiset(c[..k]);
}
forall i :: 0 <= i < |c[..k]| ==> exists r :: 0 <= r < |s| && s[r] == c[..k][i];
}
}

How let-such-that expressions could be done in Dafny 3.1.0?

Expressions let-such-that that worked in previous releases of Dafny do not work in Dafny 3.1.0. For example, the following code (also in https://rise4fun.com/Dafny/ABZpf) raise the error: "to be compilable, the value of a let-such-that expression must be uniquely determined".
datatype NNF_Formula = F
| T
| V(prop:string)
| NegV(prop:string)
| EX(f:NNF_Formula)
| AX(f:NNF_Formula)
| EG(f:NNF_Formula)
| AG(f:NNF_Formula)
| ER(f1:NNF_Formula,f2:NNF_Formula)
| AR(f1:NNF_Formula,f2:NNF_Formula)
| EF(f:NNF_Formula)
| AF(f:NNF_Formula)
| EU(f1:NNF_Formula,f2:NNF_Formula)
| AU(f1:NNF_Formula,f2:NNF_Formula)
| EUsel(f1:NNF_Formula,f2:NNF_Formula)
| AUsel(f1:NNF_Formula,f2:NNF_Formula)
| Or(f1:NNF_Formula,f2:NNF_Formula)
| And(f1:NNF_Formula,f2:NNF_Formula)
function method family(alpha: NNF_Formula): nat {
match alpha
case F => 0
case T => 1
case V(_) => 2
case NegV(_) => 3
case AX(_) => 4
case EX(_) => 5
case AG(_) => 6
case EG(_) => 7
case AR(_, _) => 8
case ER(_, _) => 9
case AF(_) => 10
case EF(_) => 11
case AU(_, _) => 12
case EU(_, _) => 13
case AUsel(_, _) => 14
case EUsel(_, _) => 15
case Or(_, _) => 16
case And(_, _) => 17
}
// ORDER IN NNF FORMULAS
predicate method leq_string(s1:string,s2:string) {
s1 == "" || (s2 != "" && s1[0] <= s2[0] && ( s1[0] == s2[0] ==> leq_string(s1[1..],s2[1..])))
}
lemma antisym_leq_string_Lemma (s1:string, s2:string)
requires leq_string(s1,s2) && leq_string(s2,s1)
ensures s1 == s2
{
if s1 != "" && s2 != "" { antisym_leq_string_Lemma(s1[1..],s2[1..]); }
}
predicate method leq_NNF_Formula (alpha:NNF_Formula, beta:NNF_Formula)
{
if family(alpha) < family(beta) then true
else if family(alpha) > family(beta) then false
else if family(alpha) <= 1 then true
else if 2 <= family(alpha) <= 3 then leq_string(alpha.prop,beta.prop)
else if 4 <= family(alpha) <= 7 || 10 <= family(alpha) <= 11 then leq_NNF_Formula(alpha.f,beta.f)
else leq_NNF_Formula(alpha.f1,beta.f1) && (alpha.f1 == beta.f1 ==> leq_NNF_Formula(alpha.f2,beta.f2))
}
lemma minimum_formula_Lemma (s:set<NNF_Formula>)
requires s != {}
ensures exists phi :: phi in s && forall psi :: psi in s-{phi} ==> (leq_NNF_Formula(phi,psi) && psi != phi)
function method pick_minimum_formula(s: set<NNF_Formula>): NNF_Formula
requires s != {}
{
minimum_formula_Lemma(s);
var phi :| phi in s && forall psi :: psi in s-{phi} ==> (leq_NNF_Formula(phi,psi) && psi != phi);
phi
}
For clarity, I have omitted the proof of the lemma, but it can be proved. I have also complicated a bit the ensures of the lemma for ensured uniqueness. In previous releases of Dafny also this works:
ensures exists phi :: phi in s && forall psi :: psi in s ==> leq_NNF_Formula(phi,psi).
I need some way of iteration on sets of NNF_Formula, is there a different way to do this on Dafny 3.1.0?
This error could certainly serve to be clearer.
This scenario is only disallowed for function methods. However, you could write it in an ordinary method and it would be fine.
method pick_minimum_formula(s: set<NNF_Formula>) returns (nnf: NNF_Formula)
requires s != {}
{
minimum_formula_Lemma(s);
var phi :| phi in s && forall psi :: psi in s-{phi} ==> (leq_NNF_Formula(phi,psi) && psi != phi);
nnf := phi;
}
You could also write it as a function, and it would be fine.
However, a function method does require that any let-such-that expression be unique. The reason is that a compiled let-such-that expression might be non-deterministic; on the other hand, any function must to be deterministic. But a function method must be a method whose output matches the result of the function! This cannot be guaranteed if the method would be nondeterministic.

How can I implement this Automaton in Java?

I want to implement this deterministic finite automaton in Java and I want the program the program to recognize the language of the automaton.
Automaton
I already got this code, but I donĀ“t no how to make the switch the best way :
int estado = 0;
char c = 0;
//else ir para erro
switch(aOpcao) {
case 1:
if(c == '/')
estado = 1;
break;
case 2:
if(c == '!')
estado = 7;
if(c == '#')
estado = 6;
break;
case 3:
if(c == 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c == 'f'
|| c == 'g' || c == 'h' || c == 'i' || c == 'j' || c == 'k' ||
c == 'l' || c == 'm' || c == 'n' || c == 'o' || c == 'p' || c == 'q'
|| c == 'r' || c == 's' || c == 't' || c == 'u' || c == 'v' || c == 'w'
|| c == 'x' || c == 'y' || c == 'z' )
estado = 8;
if(c == '!')
estado = 7;
if(c == ',')
estado = 14;
if(c == 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c == 'f'
|| c == 'g' || c == 'h' || c == 'i' || c == 'j' || c == 'k' ||
c == 'l' || c == 'm' || c == 'n' || c == 'o' || c == 'p' || c == 'q'
|| c == 'r' || c == 's' || c == 't' || c == 'u' || c == 'v' || c == 'w'
|| c == 'x' || c == 'y' || c == 'z' )
estado = 13;
break;
if you are looking for a better way to check if c is alphabet or not for those two long if statement.
then one simple way in java is to change it to
if( (c >= 'a' && c <= 'z') )
if you are talking about how to completely translate the above code into java. You have read java switch() statement and java documentation by yourself. Your question seems like a homework problem.

Given several axioms and a property, how do I structure a proof of the property?

Given the following axioms:
A>=0
forall n :: n>=0 && n<N1 ==> n < A
N1 >= A
We want to prove that N1==A using Dafny.
I have tried following Dafny program:
function N1(n: int,A: int):bool
requires A>=0 && n>=0
{
if n==0 && A<=n
then true else
if n>0
&& A<=n
&& forall k::
(if 0<=k && k<n
then A>k else true)
then true
else false
}
lemma Theorem(n: int,A: int)
requires A>=0 && n>=0 && N1(n,A)
ensures n==A;
{ }
But Dafny fails to prove that. Is there a way to N1==A from the given axioms?
Dafny can prove it just fine, but it needs a bit more help:
predicate P(n:int, N1:int)
{
n >= 0 && n < N1
}
lemma Lem(A:int, N1:int)
requires A>=0
requires forall n :: P(n, N1) ==> n < A
requires N1 >= A
ensures N1 == A
{
if(N1 > A)
{
assert A >= 0 && A < N1;
assert P(A, N1);
assert A < A;
assert false;
}
assert N1 <= A;
}
The proof proceeds by contradiction, and is quite standard. The only Dafny specific bit of the proof is that we have to give a name to the property that n >= 0 && n < N1. We give the property the name P by introducing it as a predicate. The requirement to introduce P comes from the interaction of Dafny with some details of how quantifier instantiation (trigger matching) works in the underlying SMT solver (Z3).
You may alternatively prefer to write the lemma this way:
lemma Lem(A:int, N1:int)
requires A>=0
requires forall n :: P(n, N1) ==> n < A
requires N1 >= A
ensures N1 == A
{
calc ==>
{
N1 > A;
{assert P(A, N1);}
A < A;
false;
}
assert N1 <= A;
}

Dafny predicate neither true nor false

How can a Dafny predicate be neither true nor false?
This:
predicate sorted(s: seq<int>)
{
forall j, k :: 0 <= j < k < |s| ==> s[j] <= s[k]
}
lemma SortedTest()
{
assert sorted([1, 3, 2]);
assert !sorted([1, 3, 2]);
}
Produces double assertion violations:
Dafny program verifier version 1.9.7.30401, Copyright (c) 2003-2016, Microsoft.
Sort.dfy(8,10): Error: assertion violation
Sort.dfy(3,2): Related location
Sort.dfy(3,43): Related location
Execution trace:
(0,0): anon0
Sort.dfy(9,9): Error: assertion violation
Execution trace:
(0,0): anon0
Dafny program verifier finished with 2 verified, 2 errors
Dafny is not saying that the assertions are false, it is saying that it can't prove that they hold. If you give it a bit more help then it will prove the one that is true:
predicate sorted(s: seq<int>)
{
forall j, k :: 0 <= j < k < |s| ==> s[j] <= s[k]
}
lemma SortedTest()
{
var a := [1, 3, 2];
assert a[0] == 1 && a[1] == 3 && a[2] == 2;
assert sorted(a);
assert !sorted(a);
}

Resources