-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
246 additions
and
8 deletions.
There are no files selected for viewing
7 changes: 5 additions & 2 deletions
7
.github/workflows/test-dafny.yml → .github/workflows/test-dafny-all.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,17 @@ | ||
name: Test All Dafny Files | ||
|
||
on: [push] | ||
on: | ||
push: | ||
branches: | ||
- main | ||
jobs: | ||
test: | ||
runs-on: ubuntu-20.04 | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Install Nix | ||
uses: cachix/install-nix-action@v20 | ||
- name: Test if all dafny files are named correctly | ||
- name: Test that all dafny files are named correctly | ||
run: nix run .#dafny-namecheck | ||
- name: Run Dafny on all files | ||
run: nix run .#dafny-check |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
name: Test New Dafny Files | ||
|
||
on: | ||
pull_request: | ||
branches: | ||
- main | ||
jobs: | ||
test-changed: | ||
runs-on: ubuntu-20.04 | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Install Nix | ||
uses: cachix/install-nix-action@v20 | ||
- name: Get changed files | ||
id: changed-files | ||
uses: tj-actions/changed-files@v45 | ||
- name: Test that all dafny files are named correctly | ||
run: nix run .#dafny-namecheck | ||
|
||
- name: Run Dafny on new files | ||
env: | ||
ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }} | ||
run: nix run .#dafny-check-new "${ALL_CHANGED_FILES}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
{ | ||
"tab_size": 2 | ||
"tab_size": 2, | ||
"format_on_save": "off" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
function sum(s: seq<real>) : real { | ||
if |s| == 0 then 0.0 else s[0] + sum(s[1..]) | ||
} | ||
|
||
lemma sum_prop(s: seq<real>) | ||
requires |s| > 0 | ||
ensures sum(s) == sum(s[..|s| - 1]) + s[ |s| - 1 ] | ||
{ | ||
if (|s| > 1) { | ||
assert (s[1..][..|s[1..]| - 1]) == s[1..|s| - 1]; | ||
} | ||
} | ||
|
||
function abs(x: real) : real | ||
ensures abs(x) >= 0.0 | ||
{ | ||
if x >= 0.0 then x else -x | ||
} | ||
|
||
function mean(s: seq<real>) : real | ||
requires |s| > 0 | ||
{ | ||
sum(s) / |s| as real | ||
} | ||
|
||
method mean_absolute_derivation(numbers: seq<real>) returns (derivation: real) | ||
requires |numbers| > 0 | ||
ensures var m := mean(numbers); | ||
derivation == mean(seq(|numbers|, i requires 0 <= i < |numbers| => abs(numbers[i] - m))) | ||
{ | ||
var s: real := 0.0; | ||
var i := 0; | ||
while i < |numbers| | ||
invariant 0 <= i <= |numbers| | ||
invariant s == sum(numbers[..i]) | ||
{ | ||
s := s + numbers[i]; | ||
assert sum(numbers[..i + 1]) == sum(numbers[..i]) + numbers[i] by { | ||
assert numbers[..i+1][..i] == numbers[..i]; | ||
sum_prop(numbers[..i + 1]); | ||
} | ||
i := i + 1; | ||
} | ||
|
||
var m := s / |numbers| as real; | ||
assert numbers[..|numbers|] == numbers; | ||
assert m == mean(numbers); | ||
|
||
var t: real := 0.0; | ||
i := 0; | ||
|
||
ghost var pref_seq := []; | ||
while i < |numbers| | ||
invariant 0 <= i <= |numbers| | ||
invariant |pref_seq| == i | ||
invariant pref_seq == seq(i, j requires 0 <= j < i => abs(numbers[j] - m)) | ||
invariant t == sum(pref_seq[..i]) | ||
{ | ||
ghost var pre_seq := pref_seq; | ||
assert pre_seq[..|pre_seq|] == pre_seq[..i] == pre_seq; | ||
|
||
pref_seq := pref_seq + [abs(numbers[i] - m)]; | ||
|
||
assert sum(pref_seq[..i + 1]) == sum(pref_seq[..i]) + pref_seq[i] by { | ||
assert pref_seq[..i+1][..i] == pref_seq[..i]; | ||
sum_prop(pref_seq[..i + 1]); | ||
} | ||
|
||
t := t + abs(numbers[i] - m); | ||
i := i + 1; | ||
} | ||
|
||
assert pref_seq[..|pref_seq|] == pref_seq; | ||
derivation := t / |numbers| as real; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
function contains_char(s: string, c: char): bool | ||
decreases |s| | ||
requires forall i :: 0 <= i < |s| ==> 'a' <= s[i] <= 'z' || 'A' <= s[i] <= 'Z' | ||
requires 'a' <= c <= 'z' | ||
{ | ||
if |s| == 0 then false else s[0] == c || contains_char(s[1..], c) | ||
} | ||
|
||
function upper_char(c: char) : (C: char) | ||
requires 'a' <= c <= 'z' | ||
ensures 'A' <= C <= 'Z' | ||
{ c - 'a' + 'A' } | ||
|
||
method count_distinct_characters(s: string) returns (count: int) | ||
requires forall i :: 0 <= i < |s| ==> 'a' <= s[i] <= 'z' || 'A' <= s[i] <= 'Z' | ||
ensures count == |set c | 'a' <= c <= 'z' && contains_char(s, c)| | ||
{ | ||
count := 0; | ||
ghost var contained: set<char> := {}; | ||
var i := 'a'; | ||
while i <= 'z' | ||
invariant 'a' <= i <= ('z' as int + 1) as char | ||
invariant count == |contained| | ||
invariant contained == set c | 'a' <= c < i && contains_char(s, c) | ||
{ | ||
if contains_char(s, i) { | ||
count := count + 1; | ||
contained := contained + {i}; | ||
} | ||
i := (i as int + 1) as char; | ||
} | ||
assert contained == set c | 'a' <= c <= 'z' && contains_char(s, c); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
method remove_duplicates(a: seq<int>) returns (result: seq<int>) | ||
requires forall i :: 0 <= i < |a| ==> count_rec(a, a[i]) >= 1 | ||
ensures forall i :: 0 <= i < |result| ==> count_rec(a, result[i]) == 1 | ||
ensures forall i :: 0 <= i < |a| ==> (a[i] in result <==> count_rec(a, a[i]) == 1) | ||
{ | ||
var res: seq<int> := []; | ||
var i := 0; | ||
while i < |a| | ||
invariant 0 <= i <= |a| | ||
invariant forall j :: 0 <= j < |res| ==> count_rec(a, res[j]) == 1 | ||
invariant forall j :: 0 <= j < i ==> (a[j] in res <==> count_rec(a, a[j]) == 1) | ||
invariant forall j :: 0 <= j < |res| ==> res[j] in a[..i] | ||
{ | ||
var cnt := count(a, a[i]); | ||
if cnt == 1 { | ||
res := res + [a[i]]; | ||
} | ||
i := i + 1; | ||
} | ||
result := res; | ||
} | ||
|
||
function count_rec(a: seq<int>, x: int): int { | ||
if |a| == 0 then 0 | ||
else count_rec(a[1..], x) + (if a[0] == x then 1 else 0) | ||
} | ||
|
||
lemma count_prop(s: seq<int>, x: int) | ||
requires |s| > 0 | ||
ensures count_rec(s, x) == count_rec(s[..|s| - 1], x) + if s[|s| - 1] == x then 1 else 0 | ||
{ | ||
if (|s| > 1) { | ||
assert (s[1..][..|s[1..]| - 1]) == s[1..|s| - 1]; | ||
} | ||
} | ||
|
||
method count(a: seq<int>, x: int) returns (cnt: int) | ||
ensures cnt == |set i | 0 <= i < |a| && a[i] == x| | ||
ensures cnt == count_rec(a, x) | ||
{ | ||
cnt := 0; | ||
ghost var positions: set<int> := {}; | ||
var i := 0; | ||
while i < |a| | ||
invariant 0 <= i <= |a| | ||
invariant cnt == |positions| | ||
invariant positions == set k | 0 <= k < i && a[k] == x | ||
invariant cnt == count_rec(a[..i], x) | ||
{ | ||
if a[i] == x { | ||
cnt := cnt + 1; | ||
positions := positions + {i}; | ||
} | ||
assert count_rec(a[..i + 1], x) == count_rec(a[..i], x) + (if a[i] == x then 1 else 0) by { | ||
assert a[..i+1][..i] == a[..i]; | ||
count_prop(a[..i + 1], x); | ||
} | ||
i := i + 1; | ||
} | ||
assert a == a[..|a|]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
method filter_by_prefix(xs: seq<string>, p: string) returns (filtered: seq<string>) | ||
ensures forall i :: 0 <= i < |filtered| ==> starts_with(filtered[i], p) | ||
{ | ||
filtered := []; | ||
var i := 0; | ||
while i < |xs| | ||
invariant 0 <= i <= |xs| | ||
invariant forall j :: 0 <= j < |filtered| ==> starts_with(filtered[j], p) | ||
{ | ||
if starts_with(xs[i], p) { | ||
filtered := filtered + [xs[i]]; | ||
} | ||
i := i + 1; | ||
} | ||
} | ||
|
||
function starts_with(s: string, p: string): bool { | ||
|p| == 0 || (|s| != 0 && |s| >= |p| && s[0] == p[0] && starts_with(s[1..], p[1..])) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters