"Ignored or could not reach conclusion" in Dafny - dafny

I was confused about whether some added lemmas can help Dafny verify a desired property, mainly because the hint "ignored or could not reach conclusion" was ambiguous. For example, in the following proof:
forall x | x in s ensures x.1.Valid() {
// assertion 1
// assertion 2
// assertion 3
// assertion 4
// assertion 5
}
Dafny reports errors on assertions 1-4, but for assertion 5 Dafny says "ignored or could not reach conclusion". When I commented out assertions 3, now Dafny reports error on assertion 5 as well. However, assertion 3 is absolutely not related to assertion 5, because assertion 5 has something to do with heap objects, while assertion 3 only has to do with a sequence of type seq(<int, int>).
I find it difficult to add lemmas if I have no idea whether an added lemma will successfully help prove the subsequent assertions. Why does Dafny choose to ignore assertion 5 when assertion 3 is not commented out? Can I force Dafny not to "ignore" some assertion?

Related

Print values of constraint at each iteration during optimization

How can we do this from Pydrake? Print values of constraint at each iteration during optimization
EDIT 1:
I tried:
def update(n):
print(n)
prog.AddVisualizationCallback(update, n)
in accordance with the example here at the bottom: https://github.com/RobotLocomotion/drake/blob/master/tutorials/debug_mathematical_program.ipynb
But it spat out this error:
prog.AddVisualizationCallback(update, n)
TypeError: AddVisualizationCallback(): incompatible function arguments. The following argument types are supported:
1. (self: pydrake.solvers.mathematicalprogram.MathematicalProgram, arg0: Callable[[numpy.ndarray[numpy.float64[m, 1]]], None], arg1: numpy.ndarray[object[m, 1]]) -> pydrake.solvers.mathematicalprogram.Binding[VisualizationCallback]
Here are a few possibilities:
You can use AddVisualizationCallback to make effectively an empty generic constraint that gets called on each iteration.
You might also want to increase the solver verbosity level (see the “debugging mathematical programs” tutorial) so that the solver itself prints some progress info.
Depending on what sort of constraint you’re thinking about, you could potentially just implement the constraint itself as a python method (with a print statement inside) instead of whatever you’re doing to add it right now.

Dafny as a SAT-QBF solver is not giving right results

I am trying to get the habit to use Dafny as a friendly SAT-QBF solver for some simple formulae, since doing it in, for instance, Z3 is too uncomfortable.
The context for this is that I have implemented Cooper's algorithm for quantifier elimination and, when all the variables are bounded, it can be used as a decision procedure: therefore, I want to know which is the result that I should get before executing it.
However, I encountered a problem in Dafny.
Let us raise, for instance, this formula (written in Dafny):
assert forall x_1: int :: exists y_1: int :: forall x_2: int :: exists y_2 : int
:: (y_2<y_1) && (x_2<y_2) && (x_1<x_2);
In my Cooper, it returns False, while Dafny returns assertion violation (along with the typical triggerswarnings), which I interpret as False too. Okay, so no problem with this.
But if I raise:
assert exists x_1: int :: exists y_1: int :: exists x_2: int :: exists y_2 : int
:: (y_2<y_1) && (x_2<y_2) && (x_1<x_2);
In my Cooper, it returns True, while Dafny also returns assertion violation. I have done a manual Cooper execution (pencil and paper) and I think the True is right one.
Any idea of what is going on?
PS: I have not tried it in Z3, yet, because I am doing first other attempts with other theories.
EDIT
Trigger warnings can be avoided using a simple trick to instantiate the quantified variables: creating an uninterpreted function.
method Main() {
assert exists x_1 : int {:trigger P(x_1)} :: exists y_1: int {:trigger P(y_1)}
:: exists x_2: int {:trigger P(x_2)} :: exists y_2 : int {:trigger P(y_2)}
:: (y_2<y_1) && (x_2<y_2) && (x_1<x_2);
}
predicate P(a: int)
{
true
}
You cannot do this with Dafny. While Dafny supports quantifiers, booleans, arithmetic, and many other things (recursive functions, sets, sequences, objects and references, multi-dimensional arrays, induction, inductive and coinductive datatypes, bitvectors, greatest and least fixpoints of monotonic functions, etc.), it is not suitable for SAT-QBF (or QBF + artihmetic) benchmarks.
Dafny's errors, including the assertion violation, tell you that the verifier was not able to do the proof. It may be that the property still holds, but you'll need to supply more of the proof yourself. In other words, you should interpret the assertion violation as a "don't know" answer. Stated differently, you cannot decide (only semi-decide) formulas with Dafny.
Dafny uses quantifiers in the SMT solvers via matching patterns, aka triggers. When a quantifier has no good triggers, which is what Dafny's "no trigger" warning is telling you, you may see bad performance, unstable verifications, and so-called butterfly effects (where a small and seemingly unrelated part of the program causes a change in the automatic construction of other proofs). Triggers are driven by uninterpreted function symbols, which your example doesn't have at all.
If you want a readable syntax, you may be able to do what you're trying through Boogie. I have not tried that, but you could try putting Boogie in its monomorphic mode and then supplying prover options to ask for the SAT-QBF or something similar (see Boogie's /help). Otherwise, if you're interested in deciding these problems, then going directly to SMT solver is the way to go.

Assertion fails after modifying another array in Dafny

I ran into a weird problem in Dafny. I tried to extract it as much as possible here: https://rise4fun.com/Dafny/F7sK
The thing is, after the modification of truthAssignment, stack.valid fails even if stack.valid doesn't know about truthAssignment.
assert stack.valid();
truthAssignment[variable] := 1;
assert stack.valid(); // assertion violation
The reason Dafny fails to verify the assertion assert stack.valid(); is the last conjunct in the body of valid():
(forall c :: c in contents ==>
exists i,j :: 0 <= i < stack.Length
&& 0 <= j < |stack[i]|
&& stack[i][j] == c)
It has the form forall ... exists ..., and proving such a condition to be invariant is difficult for the verifier. Once you have figured out that this is the part of valid() that the verifier cannot prove (which you can do by, for example, manually inlining the definition of valid() in place of your assertion), then the solution is to give the verifier some assistance.
When the verifier--or a human, for that matter--tries to prove something for the form forall c :: P(c), then it makes up an arbitrary c and then tries to prove the "P(c)" for it. (Logicians call this rule "universal introduction".) Easy. Then, to prove something of the form exists i,j :: Q(i,j), the verifier looks for a witness to the "Q(i,j)". (This is known as "existential introduction".) Here, the verifier is not particularly creative and often needs help. Sometimes, you have to figure out some i and j yourself and then assert Q(i,j). Other times, it suffices to just mention some component of the needed Q(i,j) and the verifier will then figure out the rest. Exactly what to do can be a trial-and-error process.
What makes James's remedy above work is the fact that it mentions stack.stack[..] after the update truthAssignment[variable] := 1;. This tickles the verifier in a way that lets it see the light. Just writing the trivially proved assertion:
assert 0 <= |stack.stack[..]|; // mentioning stack.stack[..] helps the verifier in the next line
after the update also works in this case.
Rustan
The following verifies for me:
assert stack.valid();
ghost var old_stack := stack.stack[..];
truthAssignment[variable] := 1;
assert stack.stack[..] == old_stack;
assert stack.valid();
I don't really understand why this works, but it falls under the general category of "extentional equality for sequences is hard for Dafny".

Do the assertions in the luassert library have a `level` parameter similar to the builtin `error` function?

I am currently writing a test suite using busted/luassert and since I have put some assertions in a separate function I am getting inaccurate stack traces. For example, consider the following test suite (a_spec.lua):
local function my_custom_assertion(x) -- 1
assert.is_true(x > 0) -- 2 <-
end -- 3
-- 4
describe("My test suite", function() -- 5
it("they are positive", function() -- 6
my_custom_assertion(-10) -- 7 <-
my_custom_assertion(-20) -- 8 <-
end) -- 9
end) -- 10
When I run it, my test case fails but the stack trace points to line 2 so I can't tell which of the two assertions was the one that failed.
$busted spec/a_spec.lua
◼
0 successes / 1 failure / 0 errors / 0 pending : 0.002242 seconds
Failure → spec/a_spec.lua # 6
My test suite they are positive
spec/a_spec.lua:2: Expected objects to be the same.
Passed in:
(boolean) false
Expected:
(boolean) true
Is there a way I could have it point to line 7 or 8 instead? One way this would be possible is if luassert's assert.is_true function had a level parameter similar to the builtin error function.
Looking at luassert's source code it seems that it does care about the stack level but I haven't been able to figure out if this feature is internal or if it is exposed to the user somehow.
Instead of creating a custom assertion by creating a function that calls assert.xyzz(), create a function that returns true or false and register it with assert:register.
See the second example in the README.
Turns out that there is a way to solve my actual problem of finding out which of the assertions was the one that fired without needing to change how I write my tests. By invoking busted with the -v (--verbose) option it prints a full stack trace when an assertion fails instead of just providing a single line number.
$ busted -v spec/a_spec.lua
0 successes / 1 failure / 0 errors / 0 pending : 0.003241 seconds
Failure → spec/a_spec.lua # 6
My test suite they are positive
spec/a_spec.lua:2: Expected objects to be the same.
Passed in:
(boolean) false
Expected:
(boolean) true
stack traceback:
spec/a_spec.lua:2: in upvalue 'my_custom_assertion'
spec/a_spec.lua:7: in function <spec/a_spec.lua:6>
That mention of line number 7 lets me know what assertion was the one that failed.

Finding if Integer is Even or Odd

I am learning Erlang and one of the problems as per Joe's book states
The function even(X) should return true if X is an even integer and
otherwise false. odd(X) should return true if X is an odd integer.
The way I solve this is
-module(math_functions).
%% API
-export([even/1, odd/1]).
even(Integer) -> (Integer >= 0) and (Integer rem 2 =:= 0).
odd(Integer) -> (Integer >= 1) and (Integer rem 2 =/= 0).
and run this as
Eshell V6.2 (abort with ^G)
1> math_functions:odd(13).
true
2> math_functions:odd(-13).
false
3> math_functions:odd(1).
true
4> math_functions:even(1).
false
5> math_functions:even(2).
true
6> math_functions:even(-2).
false
7>
The question I have is if there are better ways to do this
Thanks
You could use guards to limit yourself to integers greater than or equal to zero, and then simply check the least-significant bit as suggested in the comment to your question. You can also define odd/1 in terms of even/1:
even(X) when X >= 0 -> (X band 1) == 0.
odd(X) when X > 0 -> not even(X).
The guards are part of the function-head, so if you call even(-1) it will fail to match in exactly the same way as if you called even(1, 2) (i.e. with the wrong number of arguments).
Answer to Daydreamer comment about Steve answer.
When you write a function, a frequent usage in erlang is to code only the "success" cases and let crash the unsuccessful cases (I'll come back later to explain why it is important).
Another criteria, valid for any language, is to avoid surprise when someone use or read your code.
In one of your comment you say that the odd and even functions you want to write are limited to positive or null integers (I won't discuss this choice, and at least the odd and even functions are limited to integers). This means that you have to ask yourself a first question: what is the behavior of my function if it is called with a bad parameter.
First choice: let it crash this the Steve proposition: the function works only with the correct arguments. I always prefer this solution. The only exception is if I do not master the input parameters, for example if they come directly from a file, a user interface ... Then I prefer the third choice.
Second choice: return a result this is your choice: you return false. From a logic point of view, for odd and even function, returning false is valid: is something is not true, it is false :o). I don't like this solution for 2 reasons. The first one is that it is not something you can generalize easily to something else than boolean answer. The second and more important to me, is that it may surprise the user. When the function odd(N) return false, it is reasonable to think that N is even, while in this case odd(-2) and even(-2) will both return false.
third choice: return a tagged result this is something you see very often in erlang: a function return either {ok,Value} or {Error,Term}. doing this you let the choice to the calling function to manage or not a bad arguments errors. the Error variable allows you to have explicit error messages, useful for debug and also user interface. In your example the code becomes:
even(X) when is_integer(X), X >= 0 -> {ok,(X band 1) == 0};
even(X) -> {illegal_param,X}.
odd(X) when is_integer(X), X >= 0 -> {ok,(X band 1) == 1};
odd(X) -> {illegal_param,X}.
When programming, it is important to detect error as soon as possible, in erlang it is even more important. If one process does not detect (and the simplest detection is crash) and error and propagate some invalid information through messages, it may be very difficult to find the root cause of a problem, ignoring which process (maybe died) issued this message. Coding only the success cases is an easy way to detect problems as soon as possible.
Find the no if even
%functions that manipulate functions are called higher-order %functions, and the data type that represents a function in Erlang is %called a fun. here in below example you see FUNCTIONS THAT HAVE %FUNCTIONS AS THEIR ARGUMENTS
% K is an example list
1> K=[4,5,6,8,10].
[4,5,6,8,10]
% Use lisst:filter to perform no/2 and filter if rem=0
2> lists:filter(fun(J)->(J rem 2)=:=0 end, K).
[4,6,8,10]
Another way:
% Function to check even
22> Checkeven=fun(U)->(U rem 2)=:=0 end.
#Fun<erl_eval.7.126501267>
23> Checkeven(5).
false
% Define a test list
25> K=[1,2,3,4,5].
[1,2,3,4,5]
% Use lists filter to apply Checkeven func to all elements of k
26> lists:filter(Checkeven,K).
[2,4]
%Using List comprehension
42> K.
[1,2,3,4,5]
% For all elements of K check remainder of elem/2 is zero
43> [(S rem 2=:=0) || S<-K].
[false,true,false,true,false]

Resources