Datatypes and order of constructors - dafny

Is there a difference between the following definitions?
datatype Nat = S(Nat) | Z
And
datatype Nat = Z | S(Nat)
I would expect no, but interestingly enough, the following code compiles fine with the first definition, but not with the second.
function natToDay(n : Nat) : Day
decreases n
{
match n {
case Z => Monday
case S(Z) => Tuesday
case S(S(Z)) => Wednesday
case S(S(S(Z))) => Thursday
case S(S(S(S(Z)))) => Friday
case S(S(S(S(S(Z))))) => Saturday
case S(S(S(S(S(S(Z)))))) => Sunday
case S(S(S(S(S(S(S(k))))))) => natToDay(k)
}
}
lemma {:induction n} proof(n : Nat)
ensures natToDay(n) == Sunday ==> natToDay(n) == Sunday
ensures natToDay(n) == Saturday ==> natToDay(S(n)) == Sunday
ensures natToDay(n) == Friday ==> natToDay(S(S(n))) == Sunday
ensures natToDay(n) == Thursday ==> natToDay(S(S(S(n)))) == Sunday
ensures natToDay(n) == Wednesday ==> natToDay(S(S(S(S(n))))) == Sunday
ensures natToDay(n) == Tuesday ==> natToDay(S(S(S(S(S(n)))))) == Sunday
ensures natToDay(n) == Monday ==> natToDay(S(S(S(S(S(S(n))))))) == Sunday
{}
The first datatype definition produces:
Dafny program verifier finished with 2 verified, 0 errors
Wrote textual form of target program to test.cs
The second one produces:
/Users/boro/Desktop/dafny/test.dfy(27,0): Error: A postcondition might not hold on this return path.
/Users/boro/Desktop/dafny/test.dfy(21,54): Related location: This is the postcondition that might not hold.
Execution trace:
...

There's not supposed to be any difference between the two. Please report this problem on https://github.com/dafny-lang/dafny/issues.

Related

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.

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

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);
}

How to parse a string of integers only in some range with Parsec?

I'm trying to learn Parsec by parsing a date string of format "YYYYMMDD", for example "20161030". And my solution is:
date :: Parser (String, String, String)
date = do
year <- replicateM 4 digit
month <- replicateM 2 digit
day <- replicateM 2 digit
return (year, month, day)
But the problem is that "20161356" is also a valid date for my code.
How can I validate the "MM" is between 1 and 12; and "DD" is between 1 and 31?
You could add a guard as suggested by Thomas M. DuBuisson:
date :: Parser (String, String, String)
date = do
year <- replicateM 4 digit
month <- replicateM 2 digit
day <- replicateM 2 digit
guard $ read month > 0 && read month <= 12 && read day > 0 && read day <= 31
return (year, month, day)
However, this results in a bad error message:
λ> parse date "" "20161356"
Left (line 1, column 9):unknown parse error
We can fix this by combining guard with <?> to provide a better error message:
date :: Parser (String, String, String)
date = do
year <- replicateM 4 digit
month <- replicateM 2 digit
guard (read month > 0 && read month <= 12) <?> "valid month (1–12)"
day <- replicateM 2 digit
guard (read day > 0 && read day <= 31) <?> "valid day (1–31)"
return (year, month, day)
With this approach, you get a more useful error message:
λ> parse date "" "20161356"
Left (line 1, column 7):
expecting valid month (1–12)
As a side note, I think it is valuable to validate (or at least sanity check) the date in a parser—it ensures that the date validation composes with the rest of your parser and error-handling code. You can't forget to check the date later in your code and the error is localized correctly, which is very useful if you're parsing documents with lots of dates.

cond style statements in erlang

Coming from a Lisp background, Erlang's case statement seems a bit baffling to me. I'm currently working on the Sieve of Eratosthenes problem, trying to generate a list of the prime factors of a number N. However I can't seem to migrate what seems like a simple cond statement in Lisp to the equivalent in Erlang.
So far I have constructed an if statement that resembles how I would go about things in Lisp:
prime_factors(N) -> pf_helper(N, [], 2).
pf_helper(M, PL, D) ->
if
prime_p(M) == true -> [ M | PL ];
(prime_p(D) == true) and (M rem D == 0) -> pl_helper(M div D, [ D | PL ], D+1);
(prime_p(D) == true) and (M rem D /= 0) -> pl_helper(M, PL, D+1);
prime_p(D) == false -> pl_helper(M, PL, D+1)
end.
I am aware that this will not compile since I can only have BIF calls in my guards. The problem is that I cannot conceptualize how this would run as a case statement, since case handles a conditional expression on one argument. In the case that I represent the three pf_helper arguments in a tuple:
pf_helper(M,PL,D) -> pf_helper({M, PL, D}).
what would the patterns be inside the case statements that correspond to the conditional expressions
prime_p(M) == true
(prime_p(D) == true) and (M rem D == 0)
(prime_p(D) == true) and (M rem D /= 0)
prime_p(D) == false
?
Use some guards:
case {prime_p(M), prime_p(D)} of
{true, _} -> [M|PL];
{false, true} when (M rem D == 0) -> ...;
{false, true} when (M rem D /= 0) -> ...;
{false, false} -> ...
end
I think Anthony Ramine was working on implementing cond at one point.

Parsing on dates with F#

Are there some 'date parser' library that does for dates what FParsec does to strings ?
That is, you either specify rules and it will match against them to recognize the supplied patterns.
Conversely, are there any libraries to generate dates based on some parsing rules ?
The idea would be to supply user with a 'real time' completion to guide him to a valid future fparsec matching.
(does this problem of generative parsing has a name in the secluded parsing circles ?)
You can define a simple domain specific language (DSL) to express these kinds of rules. The type corresponding to your "parser" is actually just a function that takes a date and returns boolean:
type DateClassifier = DC of (DateTime -> bool)
You can easily define some simple functions:
// Succeeds when the date is wednesday
let wednesday = DC (fun dt -> dt.DayOfWeek = DayOfWeek.Wednesday)
// Succeeds if the date is after specified limit
let after limit = DC (fun dt -> dt > limit)
// Succeeds if the day is the specified value
let day d = DC (fun dt -> dt.Day = d)
// Takes two date classifiers and succeeds if either of them succeeds
let (<|>) (DC f) (DC g) = (fun dt -> f dt || g dt)
// Takes two date classifiers and succeeds if both of them succeed
let (<&>) (DC f) (DC g) = (fun dt -> f dt && g dt)
To specify your condition - "the next wednesday after the 5th of the month" - you'll need a helper that generates function that succeeds on any day following 5th, which can be done like this (this is a bit inefficient, but it is composition using existing primitives, which is nice):
let afterDay d =
[ for n in d + 1 .. 31 -> day n ] |> Seq.reduce (<|>)
Your specification (or "parser") that only succeeds for the day you described is then:
after DateTime.Now (wednesday <&> afterDay 5)

Resources