counting


Dafny and counting of occurences


I've been looking at the use of lemmas in Dafny but am finding it hard to understand and obviously the below example doesn't verify, quite possibly because Dafny doesn't see the induction or something like a lemma to prove some property of count? Basically, I don't know how or what I need to define to help convince Dafny that counting is inductive and a thing etc. Some of the ensures and invariants specifications are not necessary, but that's not the point. btw, this was easier in Spec#.
function count(items: seq<int>, item: int): nat
decreases |items|
{
if |items| == 0 then 0 else
(if items[|items| - 1] == item then 1 else 0)
+ count( items[..(|items| - 1)], item )
}
method occurences(items: array<int>, item: int) returns (r: nat)
requires items != null
ensures r <= items.Length
// some number of occurences of item
ensures r > 0 ==> exists k: nat :: k < items.Length
&& items[k] == item
// no occurences of item
ensures r == 0 ==> forall k: nat :: k < items.Length
==> items[k] != item
ensures r == count( items[..], item )
{
var i: nat := 0;
var num: nat := 0;
while i < items.Length
// i is increasing and there could be elements that match
invariant num <= i <= items.Length
invariant num > 0 ==> exists k: nat :: k < i
&& items[k] == item
invariant num == 0 ==> forall k: nat :: k < i
==> items[k] != item
invariant num == old(num) + 1 || num == old(num)
invariant num == count( items[..i], item )
{
if items[i] == item
{ num := num + 1; }
i := i + 1;
}
return num;
}
I would use a definition of count based around a multiset, then everything works:
function count(items: seq<int>, item: int): nat
decreases |items|
{
multiset(items)[item]
}
method occurences(items: array<int>, item: int) returns (r: nat)
requires items != null
ensures r <= items.Length
// some number of occurences of item
ensures r > 0 ==> exists k: nat :: k < items.Length
&& items[k] == item
// no occurences of item
ensures r == 0 ==> forall k: nat :: k < items.Length
==> items[k] != item
ensures r == count(items[..], item)
{
var i: nat := 0;
var num: nat := 0;
while i < items.Length
// i is increasing and there could be elements that match
invariant num <= i <= items.Length
invariant num > 0 ==> exists k: nat :: k < i
&& items[k] == item
invariant num == 0 ==> forall k: nat :: k < i
==> items[k] != item
invariant num == old(num) + 1 || num == old(num)
invariant num == count(items[..i], item)
{
if items[i] == item
{ num := num + 1; }
i := i + 1;
}
assert items[..i] == items[..];
r := num;
}
I would also like to suggest two alternative approaches, and another solution to your original design.
Without changing the implementation, I personally would probably write the specification like this:
function count(items: seq<int>, item: int): nat
decreases |items|
{
multiset(items)[item]
}
method occurences(items: array<int>, item: int) returns (num: nat)
requires items != null
ensures num <= items.Length
ensures num == 0 <==> item !in items[..]
ensures num == count(items[..], item)
{
num := 0;
var i: nat := 0;
while i < items.Length
invariant num <= i <= items.Length
invariant num == 0 <==> item !in items[..i]
invariant num == count(items[..i], item)
{
if items[i] == item
{ num := num + 1; }
i := i + 1;
}
assert items[..i] == items[..];
}
If I were to decide on the implementation too then I would write it like this:
method occurences(items: array<int>, item: int) returns (num: nat)
requires items != null
ensures num == multiset(items[..])[item]
{
num := multiset(items[..])[item];
}
There is a way to get the original to verify by adding an extra assertion. NB. I think that "old" doesn't do what you think it does in a loop invariant.
function count(items: seq<int>, item: int): nat
decreases |items|
{
if |items| == 0 then 0 else
(if items[|items|-1] == item then 1 else 0)
+ count(items[..|items|-1], item )
}
method occurences(items: array<int>, item: int) returns (r: nat)
requires items != null
ensures r <= items.Length
// some number of occurences of item
ensures r > 0 ==> exists k: nat :: k < items.Length
&& items[k] == item
// no occurences of item
ensures r == 0 ==> forall k: nat :: k < items.Length
==> items[k] != item
ensures r == count( items[..], item )
{
var i: nat := 0;
var num:nat := 0;
while i < items.Length
invariant num <= i <= items.Length
invariant num > 0 ==> exists k: nat :: k < i
&& items[k] == item
invariant num == 0 ==> forall k: nat :: k < i
==> items[k] != item
invariant num == count(items[..i], item)
{
assert items[..i+1] == items[..i] + [items[i]];
if items[i] == item
{ num := num + 1; }
i := i + 1;
}
assert items[..i] == items[..];
r := num;
}

Related Links

How to answer queries of type l,r,k which finds number of elements in an array in range l to r which occurs atleast k times?
Dafny and counting of occurences
Counting the number of capital letters in each row in [R]
python: count values of dictionary
How to apply hyperloglog to a timeseries stream
Counting the number of occurrences of C in each line and outputting this number plus the total number of characters in that line
Digit Counting Issue in C++ Program
Binary Strings of the form *111*

Categories

HOME
google-chrome
typelite
windows-8.1
enums
nsview
braintree
risk-management
initialization
slider
liferay-7
qooxdoo
clone
sentry
angular-meteor
jpa-criteria
erd
sslhandshakeexception
freertos
jodatime
sonata
xbox360
twisted
closures
spam
coreldraw
stackexchange.redis
device
cell
animated-gif
ratio
react-dnd
jstree
python-appium
ruby-daemons
sparkle
bitbake
dotcms
source-insight
xcrun
quickcheck
mongoengine
cloveretl
image-optimization
textmate2
oauth2
imgur
swfupload
dagger
dbcc
sonicmq
lightning-workbench
aurelia-fetch-client
google-news
palindrome
ptvs
case-when
predicates
swiperefreshlayout
http4s
yui3
deviare
bigdecimal
nsdata
dojo-build
adp
ajaxmin
polymerfire
gwt-syncproxy
openmrs
diawi
miniconda
astropy
featuretoggle
ngcordova
wicked-gem
fat32
juttle
nidaqmx
rails-api
jack
ivalueconverter
proxy-server
coalesce
arel
jsplitpane
smartfox
cgrectmake
live-wallpaper
telerik-ajax
django-apps
boost-foreach
data-dump
nsrangeexception
azure-acs
cewolf
channelfactory
resharper-5.1
outlook-2007-addin
asdoc
resharper-5.0
yahoo-maps
ppc
bucket
projectpier
suggestbox
watchpoint

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App