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
extjs
eclipse-plugin
exchange-server
qc
braintree
out-of-memory
ios-simulator
mirc
openflow
linker
phpmqtt
tweepy
static-analysis
sharepoint-online
fullcalendar-scheduler
squirrel-sql
squid
corona
fresco
closures
playframework-2.0
jitsi
android-permissions
bsd
candlestick-chart
perfino
react-dnd
jpa-2.1
background-color
bonita
dnsmasq
tightvnc
objectmapper
riotjs
fotorama
overwrite
shapeless
directfb
java-stream
subclassing
twilio-php
aurelia-http-client
tidal-scheduler
assemblies
flowchart
python-jira
slideshow
permission-denied
linq-to-excel
aws-kinesis-firehose
photoswipe
md5-file
cordova-ios
nslayoutconstraint
palindrome
swiperefreshlayout
emf-compare
allegro
portal
thread-exceptions
xmlbeans
android-syncadapter
codecharge
processor
swiffy
mnesia
preferenceactivity
pack
outlook.com
self
featuretoggle
blockquote
roxygen2
explain
gflags
shell-extensions
python-c-extension
subview
adhoc-polymorphism
cout
relationships
mobile-country-code
ecos
libgcc
xcode6.3.1
rpg
nachos
radius-protocol
boolean-algebra
particle-swarm
sql-view
jquery-transit
ax
objective-c-runtime
session-0-isolation
nsmutablestring
border-box
jzmq
uploading
kolite
sigar
drawimage
delphi-prism
server-variables
office-automation
database-deadlocks
ccl
tessellation
main-method
ntruencrypt
index.dat
community-server

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