I am new to dafny and am trying to get this simple piece of code to work. I want to count the occurrences of a char in a string. I am receiving an assertion violation on line 4. I know my function is finding the right amount of characters, but clearly there are some holes in this assertion. I'm trying to get the basics down before I start using pre and post conditions and what not, and this should be possible without them. The function simply checks the last character in the string and returns a 1 or 0, along with calling the function again which cuts off the tail of the string until it is empty.
method Main() {
var s:string := "hello world";
print tally(s, 'l');
assert tally(s,'l') == 3;
}
function method tally(s: string, letter: char): nat
{
if |s| == 0 then 0
else if s[|s|-1] == letter then 1+tally(s[..|s|-1], letter)
else 0 + tally(s[..|s|-1], letter)
}
http://rise4fun.com/Dafny/2lvt
Here is the link to my code.
It would be natural to think that the Dafny static verifier can
evaluate any code, like the expression in your assert statement. The
verifier does try to evaluate expressions like these where the
arguments are given as constants (like your "hello world", 'l',
and 3). However, the static verifier wants to avoid recursing
forever (or even recursing for too long), so it doesn't always fully
go through these expressions. In your case, there are also limits to
what the verifier is able to do with the sequence operations. So, in
short, although the verifier tries to be helpful, it does not always
get to the bottom of the recursions.
There are two ways you can work around these limits to get the
verifier to accept your assertion.
The most reliable way to debug the situation is to start with smaller
inputs and build up to the longer inputs you're using. This is quite
tedious, however, and it makes you appreciate when Dafny is able to do
these things automatically. The following (which verifies)
illustrates what you would do:
var s := "hello world";
assert tally("he",'l') == 0;
assert tally("hel",'l') == 1;
assert "hell"[..3] == "hel";
assert tally("hell",'l') == 2;
assert "hello"[..4] == "hell";
assert tally("hello",'l') == 2;
assert "hello "[..5] == "hello";
assert tally("hello ",'l') == 2;
assert "hello w"[..6] == "hello ";
assert tally("hello w",'l') == 2;
assert "hello wo"[..7] == "hello w";
assert tally("hello wo",'l') == 2;
assert "hello wor"[..8] == "hello wo";
assert tally("hello wor",'l') == 2;
assert "hello worl"[..9] == "hello wor";
assert tally("hello worl",'l') == 3;
assert s[..10] == "hello worl";
assert tally(s,'l') == 3;
In fact, the thing that the Dafny verifier does not expand (too many
times) for you are the "take" operations (that is, the expressions of
the form s[..E]). The following intermediate assertions will also
verify themselves and will help to verify the final assertion. These
intermediate assertions show what the verifier doesn't think to do
automatically for you.
var s := "hello world";
assert "he"[..1] == "h";
assert "hel"[..2] == "he";
assert "hell"[..3] == "hel";
assert "hello"[..4] == "hell";
assert "hello "[..5] == "hello";
assert "hello w"[..6] == "hello ";
assert "hello wo"[..7] == "hello w";
assert "hello wor"[..8] == "hello wo";
assert "hello worl"[..9] == "hello wor";
assert s[..10] == "hello worl";
assert tally(s,'l') == 3;
You might wonder, "how in the world would I come up with this?". The
most systematic way would be to start like in my first example above.
Then, you could try pruning the many assertions there to see what it
is the verifier needs.
(I'm now thinking that perhaps the Dafny verifier could be enhanced to
do these operations, too. It may cause performance problems
elsewhere. I shall take a look.)
The other way to work around the verifier's limits is to define
function tally in a different way, in particular avoiding the "take"
operations, which the verifier does not want to expand a lot. It is
not clear what to change to make the verifier happy in these
situations, or if that's even possible at all, so this workaround may
not be the best. Nevertheless, I tried the following definition of
tally and it makes your assertion go through:
function method tally'(s: string, letter: char): nat
{
tally_from(s, letter, 0)
}
function method tally_from(s: string, letter: char, start: nat): nat
requires start <= |s|
decreases |s| - start
{
if start == |s| then 0
else (if s[start] == letter then 1 else 0) + tally_from(s, letter, start+1)
}
Note that these definitions do not use any "take" operations. Here,
the verifier is happy to expand all the recursive calls until the
final answer is found.
Rustan
Related
I stuck with a project. It's an encryption-decryption program. But to complicate the things it uses command-line arguments instead of user input. I solved the user input part. But this part is really hard for me. Here is the objective:
Objectives
The program must parse three arguments: -mode, -key, and -data. The first argument should determine the program's mode (enc for encryption, dec for decryption). The second argument is an integer key to modify the message, and the third is a text or ciphertext to encrypt/decrypt.
Arguments are guaranteed to be passed to the program. If, for some reason, they turn out to be wrong:
If there is no -mode, the program should work in the enc mode;
If there is no -key, the program should consider that it is 0;
If there is no -data, the program should assume that data is an empty string.
Keep in mind that the order of the arguments might be different. For example, -mode enc maybe at the end, at the beginning, or in the middle of the array.
Examples
Example 1: encryption; the arguments are: -mode enc -key 5 -data "Welcome to hyperskill!"
\jqhtrj%yt%m~ujwxpnqq&
java -jar programName.jar -mode enc -key 5 -data "Welcome to hyperskill!"
This way the program inputs \jqhtrj%yt%m~ujwxpnqq&
But how to achieve the same input if the program starts with for example
java -jar programName.jar -data "Welcome to hyperskill!" -mode enc -key 5 ?? The encoding-decoding part is done in the previous stage.
Thanks in advance!
Assuming that the command line arguments will always come in the format of -nameOfArgument and then immediately followed by the argument itself, here is a simple way. For more complicated command line options, I would recommend using a parser library like kotlinx-cli.
Because of the assumption, you will always find an even number of elements in the arguments array passed to main. You can make this array chunked into lists of 2 elements each, and then associate the two elements into a Map.
fun main(args: Array<String>) {
val argsMap = args.toList().chunked(2).associate { it[0] to it[1] }
}
After that, argsMap["-mode"] gets you the mode, argsMap["-key"] gets you the key. These could also be null, which means that that argument is not passed.
Firstly thanks to Sweeper for the assistance! Maybe not the finest solution, but here is my code:
fun main(args: Array<String>) {
val argsMap = args.toList().chunked(2).associate { it[0] to it[1] }
if (argsMap["-mode"] == "enc" || argsMap["-mode"] == "") {
for (char in argsMap["-data"] ?: "") {
print(char + (argsMap["-key"]?.toInt() ?: "".toInt()))
}
} else if (argsMap["-mode"] == "dec") {
for (char in argsMap["-data"] ?: "") {
print(char - (argsMap["-key"]?.toInt() ?: "".toInt()))
}
} else if (argsMap["-key"] == "") {
print(argsMap["-data"])
} else if (argsMap["-data"] == "") {
print("")
}
}
Hi I have simplified the problem to a method that simply copies the elements of one array to another array. My problem is that the final assert verifies yet the initial assert fails to verify even though I have a guard to ensure that initial assert only applies after the first time the loop is entered. Hence I think the final assert should imply the initial assert.
Any help much appreciated.
method simpImp(a:array<int>) returns (r:array<int>)
{
print "a ",a[..],"\n";
r := new int[a.Length];
var i:nat := 0;
while (i< a.Length)
decreases a.Length - i
invariant a.Length >= i
{
if (i> 0) { print " bool ",r[i-1] == a[i-1],"\n";}
else {print "*i ",i,"\n";}
//if (i> 0) { assert r[i-1] == a[i-1]; } //Fail
//assert (i>0) ==> r[i-1] == a[i-1]; //Fail
r[i] := a[i];
i:= i +1;
assert r[i-1] == a[i-1];
}
}
method Main() {
var a:array<int> := new int[5];
a[0],a[1],a[2],a[3],a[4] := 10,2,30,4,3;
var iny:= simpImp(a);
print "r ",iny[..],"\n";
}
The issue is that you need to add something to your loop invariant to "remember" any facts you need to carry between iterations. Dafny analyzes the loop body in isolation, assuming only the loop invariants at the beginning of the body. So unless you add the fact to the loop invariant, it will be "forgotten" by Dafny.
In your simplified example, adding
invariant i > 0 ==> r[i-1] == a[i-1]
to the loop causes the program to verify.
You can read more about loop invariants in the second half of this answer. Note that that discussion is phrased in terms of establishing that loop invariants are preserved, but the reasoning is mostly identical to trying to establish that an assertion inside the loop body is valid. Please feel free to ask further questions!
Is there in GoogleTest something like:
ASSERT_EQ_ONE_OF_TWO(TestValue, Value1, Value2)
which tests if TestValue == Value1 || TestValue == Value2?
This variant:
ASSERT_TRUE(TestValue == Value1 || TestValue == Value2)
is OK, but it does not show in log which value TestValue has if it fails.
Is there in GoogleTest something like
I think No.
is OK, but it does not show in log which value TestValue has if it
fails.
You can add addition log information like this:
TEST (ExampleTest, DummyTest)
{
// Arrange.
const int allowedOne = 7;
const int allowedTwo = 42;
int real = 0;
// Act.
real = 5;
// Assert.
EXPECT_TRUE (real == allowedOne || real == allowedTwo)
<< "Where real value: " << real
<< " not equal neither: " << allowedOne
<< " nor: " << allowedTwo << ".";
}
This code will be produce the following log when fails:
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from ExampleTest
[ RUN ] ExampleTest.DummyTest
/home/gluttton/ExampleTest.cpp:13: Failure
Value of: real == allowedOne || real == allowedTwo
Actual: false
Expected: true
Where real value: 5 not equal neither: 7 nor: 42.
[ FAILED ] ExampleTest.DummyTest (0 ms)
[----------] 1 test from ExampleTest (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] ExampleTest.DummyTest
You can use EXPECT_THAT() in combination with a container and the Contains() matcher to achieve this:
EXPECT_THAT((std::array{ Value1, Value2 }), Contains(TestValue));
Note that the braces after array are needed for list initialization and the parentheses around array are needed, because macros (such as EXPECT_THAT()) do not understand braces and would otherwise interpret the two arguments as three arguments.
This will give an output similar to this (created with GTest 1.10)
error: Value of: (std::array{ Value1, Value2 })
Expected: contains at least one element that is equal to 42
Actual: { 12, 21 }
Pro:
Prints all values
one-liner
works out of the box
Con:
Finding the value of TestValue in the output is not easy
Syntax is not straight forward
Modern compiler features are needed
C++11 is needed due to std::array and list initialization (still not available everywhere)
C++17 is needed due to CTAD, use std::initializer_list<T>{ ... } on C++11/14. Alternatively a free function can be used to deduce size and type of the array.
I haven't found anything "baked in" to do what you are asking, but a predicate assertion should be able to handle the type of assertion you are asking for. Additionally, GoogleTest will automatically print out the arguments and their values when the assertion does fail.
The assertion you would use in your case is
ASSERT_PRED3(<insert predicate>, TestValue, Value1, Value2)
The predicate is a function or functor that returns bool, where false fails the assertion. For your predicate, you could use a function like the following:
bool OrEqual(int testValue, int option1, int option2)
{
if (testValue == option1 ||
testValue == option2)
{
return true;
}
else
{
return false;
}
}
Of course, this is a simple example. Since you can provide any function or functor that takes the provided arguments, there is plenty that you can do with predicate assertions.
Here is the documentation: https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#predicate-assertions-for-better-error-messages
You can use the following:
ASSERT_THAT(TestValue, AnyOf(Value1, Value2));
or if you need floating point matching with doubles:
ASSERT_THAT(TestValue, AnyOf(DoubleEq(Value1), DoubleEq(Value2)));
I'm a newbie to this site, so if I mess up any question-asking etiquette here I apologize in advance... Thanks!
This is extremely simplified example code, but I think it shows what I'm talking about: I have a C++ method that makes a call into another method to test a value...
char m_array[MAX]; // class member, MAX is a #define
foo(unsigned int n)
{
if (validNumber(n)) //test n
{
// do stuff
m_array[n-1] = 0;
}
}
where: validNumber(unsigned int val) { return ((val > 0) && (val <= MAX)); }
The irritation I'm having is that PC Lint's Value Tracking seems to ignore the validNumber() call and gives a warning 661 possible access of out-of-bounds pointer (1 beyond end of data) by operator '['
However if I do it like this, Lint is happy:
if ((n > 0) && (n <= MAX)) //test n
...
So, does Lint's Value Tracking just not work if the test is a method call?
Thanks again,
HF
I'd guess that validNumber is defined after foo, but in any case, PC Lint normally makes one pass over the code, and in such cases it doesn't see validNumber as a check for the boundaries for n.
You could try the option -passes(2) or even 3, and see what Lint makes out of it. I think (but didn't try) that Lint would then correctly note that the value for n is within the correct bounds.
I've responded to threads here (or at least commented) with answers containing code like this, but I'm wondering if it's good or bad form to write a series of if branches with one (or more) of the branches doing nothing in them, generally to eliminate checking for null in every branch.
An example (C# code):
if (str == null) { /* Do nothing */ }
else if (str == "SomeSpecialValue")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
instead of:
if (str != null && str == "SomeSpecialValue")
{
// ...
}
else if (str != null && str.Length > 1)
{
// ...
}
And, of course, this is just an example, as I tend to use these with larger and more complex classes. And in most of these cases, a null value would indicate to do nothing.
For me, this reduces the complication of my code and makes sense when I see it. So, is this good or bad form (a code smell, even)?
I prefer doing it like this-
if (str != null)
{
if (str == "[NULL]")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
}
I think you can always "reword" an if with an empty body into it's negation with a body, and that it looks better and makes more sense.
I would normally put a return or something like that in the first if:
void Foo()
{
if (str == null) { return; }
if (str == "SomeSpecialValue")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
}
If you can't do this, because the function does something else after the if/else, I'd say it's time to refactor, and split the if/else part out into a separate function, from which you can return early.
It is indeed good to avoid the following, because it needlessly re-checks one of the conditions (the fact that the compiler will optimize this away is beside the point--it potentially makes more work for folks trying to read your code):
if (str != null && str == "SomeSpecialValue")
{
// ...
}
else if (str != null && str.Length > 1)
{
// ...
}
But it's also rather bizarre to do what you suggested, below:
if (str == null) { /* Do nothing */ }
else if (str == "SomeSpecialValue")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
I say this is bizarre because it obfuscates your intent and defies the reader's expectations. If you check for a condition, people expect you to do something if it is satisfied--but you're not. This is because your intent is not to actually process the null condition, but rather to avoid a null pointer when you check the two conditions you're actually interested in. In effect, rather than having two conceptual states to handle, with a sanity provision (non-null input), it reads instead like you have three conceptual states to handle. The fact that, computationally, you could say there are three such states is beside the point--it's less clear.
The usual case approach in this sort of situation is as Oren A suggested--check for the null, and then check the other conditions within the result block:
if (str != null)
{
if (str == "SomeSpecialValue")
{
// ...
}
else if (str.Length > 1)
{
// ...
}
}
This is little more than a matter of readability-enhancing style, as opposed to an issue of code smell.
EDIT: However, if you're set on the do-nothing condition, I do very much like that you included a "do nothing" comment. Otherwise, folks might think you simply forgot to complete the code.
In this particular case I will return early and it makes code easier to read
if (string.IsNullOrEmpty(str)) { return; }
I like to put an explicit return statement.
Yes it is a code smell.
One indication is that you thought to ask this question.
Another indication is that the code looks incomplete- as if something should belong there. It may be readable sure, but it feels off.
When reading that code, an outsider has to stop for a second and use brainpower to determine if the code is valid/complete/correct/as intended/adjective.
user359996 hit the nail on the head:
I say this is bizarre because it obfuscates your intent and defies the reader's expectations.
Your first example is perfectly readable to me -- doesn't smell at all.
It all depends on context. If putting an empty if statement makes the code more readable, then go for that.
It's readable, whether it is good or bad depends upon what you are trying to achieve - generally long nested "goes-on-forever" type if statements are bad. Don't forget about static string methods baked into the framework: string.IsNullOrEmpty() and string.IsNullOrWhiteSpace().
Your if (str == null) { /* Do nothing */ } line is unusual, but does have one positive point: it is letting other developers know up front that you are deliberately doing nothing for that case, with your long if/else if structure your intentions could become unclear if you changed it to
if (str != null)
{
/* carry on with the rest of the tests */
}