Triggers, #instances in Z3 - triggers

My problem comes from a large Boogie file. I'll just explain the relevant parts here.
I declare a new type Msg for messages which have 7 fields tID, stype, bal, acc, mbal, mval, val. These fields are declared as functions in Boogie. Then I declared 72 Msg constants M1, ..., M72 and corresponding values of their fields. You can see the following example:
type Msg;
const unique M1: Msg;
function tID (Msg) returns (int);
function stype (Msg) returns (Str);
function bal (Msg) returns (int);
function acc (Msg) returns (Proc);
function mbal (Msg) returns (int);
function mval (Msg) returns (Val);
function val (Msg) returns (Val);
axiom (tID (M1) == 1);
axiom (stype (M1) == s1a);
axiom (bal (M1) == 1);
axiom (acc (M1) == ProcNull);
axiom (mbal (M1) == -2);
axiom (mval (M1) == ValNull);
axiom (val (M1) == ValNull);
where Proc, Str are some types and s1a, ProcNull, ValNull are some constants. Then I declare an axiom which says that two messages m1, m2 are equal if and only if every field of m1, m2. This axiom uses a trigger MsgComp(m1, m2).
function MsgComp(m1, m2: Msg): bool { true }
axiom (forall m1, m2: Msg :: {MsgComp(m1, m2)}
m1 == m2 <==>
(tID(m1) == tID(m2) && stype(m1) == stype(m2) &&
acc(m1) == acc(m2) && bal(m1) == bal(m2) &&
mbal(m1) == mbal(m2) && mval(m1) == mval(m2) &&
val(m1) == val(m2)));
Then, I declare a new variable m and assign arbitrary values to its fields such that m equals M1 or M2. I don't say explicitly m == M1 || m == M2but we can prove this assertion (line 786) with the above axiom.
assert (MsgComp(cMsg, M1) && MsgComp(cMsg, M2) && (cMsg == M1 || cMsg == M2));
However, if I want to check whether m is one of M1, ..., M72, Boogie shows that the corresponding assertion might not hold.
assert (MsgComp(cMsg, M1) && ... && MsgComp(cMsg, M72) && (cMsg == M1 || ... || cMsg == M72));
And I found that if I check that assertion with at most 32 constants, Boogie can verify it. Why can't Boogie or Z3 verify it with more constants?

On my machine, the check does not succeed even for the case of two constants.
I was able to get both checks to pass by changing them to the following form
assert MsgComp(cMsg, M1) && MsgComp(cMsg, M2) ==> (cMsg == M1 || cMsg == M2);
(Notice that the && in the middle has been changed to ==>.)
This also works for the assertion with the 72 values.
I don't know why this change matters. It looks like the conjuncts are ignored or simplified away before triggering happens.

Related

How to simplify and extend verified algorithm?

I implemented and verified a quicksort function based on the implementation here on page 22.
It verifies (hurray!) but I'm not too happy with the proof, quicksortSorted, that the quicksort function is sorted for a couple reasons that lead to the following questions.
For whatever reason it seems like the proof will not verify because of the two recursive calls needed by the lemma. I got around this by setting the quicksort function to opaque and using another helping lemma quicksortDef when I needed to assert something about its definition. I feel like making the function opaque shouldn't be required. Is there another way to call the recursive subcases that doesn't explode? (better inductive setup?)
Following from above I saw the {:fuel} attribute exists, can it be used to improve this situation?
Although I was able to verify the lemma that quicksort ensures the result is sorted. It would be nice if that fact was part of the ensure conditions of the quicksort function, but my attempts to add it there always seemed to trigger endless recursion. Is there a better way to define quicksort or to prove it which allows this?
When I tried to set filter and quicksort to be function methods I got an error about filters parameter being a ghost variable. Why is a generic predicate function parameter a ghost variable?
Finally the quicksortSorted lemma feels a bit over-complicated, any suggestion on how to simplify it?
Whole implementation on github:
function {:opaque} quicksort(xs: seq<int>): seq<int>
// ensures sortedRec(quicksort(xs))
ensures multiset(xs) == multiset(quicksort(xs))
ensures xs == [] ==> quicksort(xs) == []
ensures xs == [] ==> quicksort(xs) == []
decreases multiset(xs)
{
if xs == [] then [] else
assert xs == [xs[0]] + xs[1..];
filterPreservesMultiset(xs);
// var ln := y => y < xs[0];
// var gn := y => y >= xs[0];
var ln := lessThanFirst(xs);
var gn := greaterOrEqualFirst(xs);
filterMultiSetSlice(xs, xs[1..], ln);
filterMultiSetSlice(xs, xs[1..], gn);
quicksort(filter(xs[1..], ln)) + [xs[0]] + quicksort(filter(xs[1..], gn))
}
lemma quicksortDef(xs: seq<int>)
requires |xs| > 0
ensures quicksort(xs) == quicksort(filter(xs[1..], lessThanFirst(xs))) + [xs[0]] + quicksort(filter(xs[1..], greaterOrEqualFirst(xs)))
{
reveal quicksort();
}
lemma quicksortSorted(xs: seq<int>)
ensures sortedRec(quicksort(xs))
decreases multiset(xs)
{
if xs == [] {
assert quicksort(xs) == [];
assert sortedRec(quicksort(xs));
}else{
assert xs == [xs[0]] + xs[1..];
var ln := lessThanFirst(xs);
var gn := greaterOrEqualFirst(xs);
if xs[1..] == [] {
assert xs == [xs[0]];
assert sortedRec([xs[0]]);
}else{
// filterPreservesMultiset(xs[1..]);
filterMultiSetSlice(xs, xs[1..], ln);
filterMultiSetSlice(xs, xs[1..], gn);
var lessThan := filter(xs[1..], ln);
var greaterThan := filter(xs[1..], gn);
var sortedLt := quicksort(lessThan);
var sortedGt := quicksort(greaterThan);
// assert multiset(lessThan) == multiset(sortedLt);
assert multiset(greaterThan) == multiset(sortedGt);
assert forall y :: y in multiset(sortedGt) ==> y in multiset(greaterThan) && y in sortedGt && y in greaterThan;
assert listPartition(lessThan, [xs[0]]);
quicksortPreservesRelations(lessThan, [xs[0]]);
assert listPartition(sortedLt, [xs[0]]);
assert forall x :: x in sortedLt ==> forall y :: y in [xs[0]] ==> x < y ==> x < xs[0];
forall x | x in sortedLt + [xs[0]]
ensures forall y :: y in sortedGt ==> x <= y
{
forall y | y in sortedGt
ensures x <= y
{
assert y in greaterThan;
assert y >= xs[0];
if x in sortedLt {
assert forall z :: z in [xs[0]] ==> x < z ==> x < xs[0];
}else if x in [xs[0]] {
assert x == xs[0];
assert y >= xs[0];
}
}
}
quicksortSorted(lessThan);
quicksortSorted(greaterThan);
assert listPartition(sortedLt + [xs[0]], sortedGt);
// assert sortedRec(sortedLt);
// assert sortedRec(sortedGt);
sortedConcat(sortedLt, [xs[0]]);
assert sortedRec(sortedLt+[xs[0]]);
sortedConcat(sortedLt + [xs[0]], sortedGt);
assert sortedRec((sortedLt + [xs[0]]) + sortedGt);
quicksortDef(xs);
assert quicksort(xs) == sortedLt + [xs[0]] + sortedGt;
assert sortedRec(quicksort(xs));
}
}
}
predicate listPartition(xs: seq<int>, ys: seq<int>)
{
forall x :: x in xs ==> forall y :: y in ys ==> x <= y
}
predicate sortedRec(list: seq<int>) {
if list == [] then true else (forall y :: y in list[1..] ==> list[0] <= y) && sortedRec(list[1..])
}
lemma sortedConcat(xs: seq<int>, ys: seq<int>)
requires sortedRec(xs)
requires sortedRec(ys)
requires listPartition(xs,ys)
ensures sortedRec(xs + ys)
{
if xs == [] || ys == [] {
if xs == [] {
assert xs + ys == ys;
assert sortedRec(xs + ys);
} else if ys == [] {
assert xs + ys == xs;
assert sortedRec(xs+ys);
}
}else{
assert sortedRec([xs[0]]);
assert sortedRec([ys[0]]);
var sum := xs + ys;
assert xs == [xs[0]] + xs[1..];
assert ys == [ys[0]] + ys[1..];
assert xs[0] in xs;
assert forall y :: y in ys ==> xs[0] <= y;
assert forall xz :: xz in xs[1..] ==> xz in xs && forall y :: y in ys ==> xz <= y;
sortedConcat(xs[1..], ys);
assert xs+ys == [xs[0]] + (xs[1..]+ys);
assert sortedRec(xs + ys );
}
}

purescript writing implementation for Eq type class

I wrote this code in purescript
module TypeClasses where
import Prelude
import Data.Array
import Data.Number.Format(toString)
data Point = Point{x:: Number, y:: Number}
instance showPoint :: Show Point where
show (Point {x, y}) = (toString x) <> ", " <> (toString y)
instance eqPoint :: Eq Point where
eq p1 p2 = if (p1.x == p2.x && p1.y1 == p2.y2) then true else false
but I get error
Compiling TypeClasses
Error found:
in module TypeClasses
at src/TypeClasses.purs line 17, column 20 - line 17, column 22
Could not match type
{ x :: t0
| t1
}
with type
Point
while checking that type Point
is at least as general as type { x :: t0
| t1
}
while checking that expression p1
has type { x :: t0
| t1
}
while checking type of property accessor p1.x
in value declaration eqPoint
where t0 is an unknown type
t1 is an unknown type
See https://github.com/purescript/documentation/blob/master/errors/TypesDoNotUnify.md for more information,
or to contribute content related to this error.
A couple of issues with your code:
You have to deconstruct the Point parameters to access the "wrapped" record with your actual coordinates like this: eq (Point p1) (Point p2) (this will solve your type error)
.y1 and .y2 do not exist, I guess you mean .y
And as a hint: if something then true else false can be shortened to just something
So you will end up with this implementation of Eq for Point:
instance eqPoint :: Eq Point where
eq (Point p1) (Point p2) = p1.x == p2.x && p1.y == p2.y

Use of the forall construct in Stainless

I'm trying to proof in Stainless that if two lists have the same contents and one list is bounded by x then the other list is also bounded by x. For doing so, I'm told to use the construct:
forall(x => list.content.contains(x) ==> p(x))
The lemma would be written (in a verbose way) as:
def lowerBoundLemma(l1: List[BigInt],l2: List[BigInt],x:BigInt) : Boolean = {
require(l1.content == l2.content && forall(y => l1.content.contains(y) ==> y <= x))
forall(z => l2.content.contains(z) ==> z <= x) because{
forall(z => l2.content.contains(z) ==> z <= x) ==| l1.content == l2.content |
forall(z => l1.content.contains(z) ==> z <= x) ==| trivial |
forall(y => l1.content.contains(z) ==> y <= x)
}
}.holds
The problem is that I get the following errors:
exercise.scala:12:48: error: missing parameter type
require(l1.content == l2.content && forall(y => l1.content.contains(y) ==> y <= x))
Once I add the type to y I get this error (pointing to the left brace of the contains parentheses):
exercise.scala:12:81: error: ')' expected but '(' found.
require(l1.content == l2.content && forall(y : BigInt => l1.content.contains(y) ==> y <= x))
Any idea why this is happening?
I also tried the syntax l.forall(_ <= x) but I get errors when combining with constructs like because and ==| of the type: because is not a member of Boolean.
The issues you are facing are coming from the Scala compiler frontend to Stainless. In Scala, the syntax for a closure (with specified parameter type) is (x: Type) => body (note the extra parentheses!)
If you want to use because and ==|, you'll have to add import stainless.proof._ at the beginning of your source file.

Coffee Existential Operator different compliations [duplicate]

This question already has an answer here:
How does CoffeeScript's existential operator work?
(1 answer)
Closed 8 years ago.
Similar to this topic:
CoffeeScript Existential Operator and this
The coffeescript, I'm having a problem using the elvis operator:
foo = ->
y = foo()
console.log 'y is null' unless y?
console.log 'x is null' unless x?
Compiles to:
var foo, y;
foo = function() {};
y = foo();
if (y == null) {
console.log('y is null');
}
if (typeof x === "undefined" || x === null) {
console.log('x is null');
}
Output:
y is null
x is null
So the problem is that since y is assigned earlier that coffee takes the shortcut and assumes that y cannot be undefined. However, it is valid to return undefined from a function.
Is there a "safer" way to check that y is also not undefined?
UPDATED
Clarified Examples and Explanation:
From the comments, in the first if statement (y == null) is using double equal instead of ( x === null) triple equal, as in the second if statement. Clever.
? operator always checks if the value is neither null nor undefined.
y == null is absolutely correct way to check that the value of y is either null or undefined in JavaScript.
For example, the following CofeeScript code checks only for null values:
do_something() if y is null
which compiles to
if (y === null) do_something();
So, while y? (y == null in JS) checks for both null and undefined, y isnt null (y !== null in JS) checks only for null.
Check this answer for more detailed information.
See this answer for more info about equality checks in JavaScript.

Writing (A && C) || (B && C) conditional shorter

(E.G. In Perl) When either condition A or condition B have the same consequence
if (A){
# Consequence X
}elsif (B){
# Consequence X
}
we can write
if ( A || B ) {
# Consequence X
}
How about we have the following condition: Either when A and C are true, or B and C are true, consequence C follows.
This can be written very long:
if ( A && C){
# Consequence X
} elsif (B && C ){
# consequence X
}
My question is, is there any way to write this shorter?
Something like this:
if ( (A && C) || (B && C) )
is syntactically ok ???
Yes.
if ( A && C){
# Consequence X
} elsif (B && C ){
# consequence X
}
is the same as:
if ( (A && C) || (B && C) ){
#Consequence X
}
And this avoids evaluating C twice:
if ( (A || B) && C){
#Consequence X
}
BTW, this is more like a logical question, the logic here isn't limited to Perl.
Try the following:
if (C && (A || B)) {
}