This is a fork of calf for demonstrating our work on verified cost analysis of joinable red black trees.
We present our mechanization of correctness and cost verification of joinable red black trees in calf, which is embedded in Agda.
To type-check the code, we require Agda version 2.6.3. Moreover, we make use of the latest (unreleased) Agda standard library. The commit hash for the version we have tested with is here.
- Sequence signature and derived algorithms: Examples.Sequence and Examples.Sequence.MSequence
- Joinable red black tree implementation and correctness verification: Examples.Sequence.RedBlackTree
- Cost verification in section 3: Examples.Sequence.RedBlackTree and Examples.Sequence.RedBlackMSequence
- Case studies in section 4: Examples.Sequence and Examples.Sequence.DerivedFormsRBT
The calf language is a cost-aware logical framework for studying quantitative aspects of functional programs.
This repository contains the Agda implementation of calf, as well as some case studies of varying complexity.
The source code may be viewed interactively with (semantic) syntax highlighting in the browser using the HTML files in the ./html directory.
These files were generated by running:
agda --html --html-dir=html src/index.agdaYou may want to start by opening html/index.html.
To view a specific module M, open html/M.html in a web browser.
For example, open html/Examples.Sorting.Parallel.html to view the module Examples.Sorting.Parallel.
This implementation of calf has been tested using:
- Agda v2.6.3, with
agda-stdlibv1.7.1 (preferred) - Agda v2.6.2, with
agda-stdlibv1.7 - Agda v2.6.1.3, with
agda-stdlibv1.6
Installation instructions may be found in INSTALL.md.
calf is parameterized by a cost monoid (ℂ, +, zero, ≤).
The formal definition, CostMonoid, is given in Calf.CostMonoid.
The definition of a parallel cost monoid (ℂ, ⊕, 𝟘, ⊗, 𝟙, ≤) is given, as well, as ParCostMonoid.
Some common cost monoids and parallel cost monoids are given in Calf.CostMonoids; for example, ℕ-CostMonoid simply tracks sequential cost.
Note that every ParCostMonoid induces a CostMonoid via the additive substructure (ℂ, ⊕, 𝟘, ≤).
The language itself is implemented via the following files, which are given in a dependency-respecting order.
The following modules are not parameterized:
Calf.Preludecontains commonly-used definitions.Calf.Metalanguagedefines the basic dependent Call-By-Push-Value (CBPV) language, using Agdapostulates and rewrite rules.Calf.PhaseDistinctiondefines the phase distinction of extension and intension, including the extensional phaseext, the open/extensional modality◯, and the closed/intensional modality●.Calf.Noninterferencecontains theorems related to the phase distinction/noninterference.
The following modules are parameterized by a CostMonoid:
Calf.Stepdefines the computational effectstepand the associated coherence laws via rewrite rules.
The following modules are parameterized by a ParCostMonoid:
Calf.ParMetalanguagedefines the parallel pairing operation_&_whose cost structure is given by the product operation of aParCostMonoid(i.e.,_⊗_).
In src/Calf/Types, we provide commonly-used types.
The following modules are not parameterized:
Calf.Types.Nat,Calf.Types.Unit,Calf.Types.Bool,Calf.Types.Sum, andCalf.Types.Listinternalize the associated Agda types viameta. Notably, this means that their use does not incur cost.Calf.Types.Eqdefines the equality type.
The following modules are parameterized by a CostMonoid:
Calf.Types.Boundeddefines a recordIsBounded A e cthat contains a proof that the cost ofe(of typeA) is bounded byc : ℂ. Additionally, it provides lemmas for proving the boundedness of common forms of computations.Calf.Types.BoundedFunctiondefines cost-bounded functions usingIsBounded.Calf.Types.BigOgives a definition of "big-O" asymptotic bounds as a relaxation ofIsBounded. In particular, an element of the typegiven A measured-via size , f ∈𝓞(g)(i.e., "given an input of typeAand a size measuresizeonA,fis in𝓞(g)) is a lower bound on input sizesn'and a constant multiplierkalong with a proofhthat for all inputsxwithn' ≤ size x,f xis bounded bykmultiples ofg (size x), denotedn' ≤n⇒f[n]≤ k g[n]via h.
We provide a variety of case studies in src/Examples.
module Easy- Definition of the program
idwhich trivially returns its input. - Theorem
id/correctstating the (trivially true) correctness ofid. - Theorem
id≤id/coststating that the cost ofid nis bounded byid/cost n = 0. - Theorem
id/asymptotic : given nat measured-via (λ n → n) , id ∈𝓞(λ n → 0)stating thatidis in𝓞(0).
- Definition of the program
module Hard- Definition of the program
idwhich reconstructs its input via induction. - Theorem
id/correctstating the correctness ofid. - Theorem
id≤id/cost/closedstating that the cost ofid nis bounded byn. - Theorem
id/asymptotic : given nat measured-via (λ n → n) , id ∈𝓞(λ n → n)stating thatidis in𝓞(n), wherenis the input number.
- Definition of the program
- A proof that
Easy.idandHard.idare extensionally equivalent,easy≡hard : ◯ (Easy.id ≡ Hard.id).
- A calf implementation of Euclid's algorithm for gcd.
Examples.Gcd.Euclid- Specification of the cost model via the instrumented operation
mod. - Definition of the type
gcd/i, which specifies that inputs to Euclid's algorithm should be ordered (first is greater than second). - Definition of the program
gcd/depththat computes the recursion depth of Euclid's algorithm.
- Specification of the cost model via the instrumented operation
Examples.Gcd.Clocked- The clocked version of Euclid's algorithm
gcd/clockedin which the first parameter is used to justify recursive calls. - The actual algorithm
gcd, obtained by instantiating the clock parameter bygcd/depth. - The theorem
gcd≤gcd/depthstating that the cost of Euclid's algorithm is bounded by the recursion depthgcd/depth.
- The clocked version of Euclid's algorithm
Examples.Gcd.Spec- Theorems
gcd≡spec/zeroandgcd≡spec/sucstating the behavioral correctness ofgcdin terms of the defining equations of Euclid's algorithm.
- Theorems
Examples.Gcd.Refine- Refinement of the bound
gcd/depth-- the theoremgcd/depth≤gcd/depth/closedstates that the cost ofgcdis bounded bysuc ∘ fib⁻¹.
- Refinement of the bound
- A calf implementation of Batched queues.
- Specification of the cost model as the number of list iterations via the axiom
list/ind/cons. - Upper bounds on the cost of individual enqueue and dequeue operations:
- The theorem
enq≤enq/coststating that enqueue has zero cost. - The theorem
deq≤deq/coststating that dequeue has linear cost.
- The theorem
- Amortized analysis of sequences of enqueue and dequeue operations:
- The theorem
acost≤2*|l|stating that the amortized cost of a sequence of queue operations is at most twice the length of the sequence.
- The theorem
- Definition of the program
sumwhich sums the elements of a tree, incurring unit cost when performing each addition operation. At each node, the recursive calls are computed in parallel. - Theorem
sum≤sum/cost/closedstating that the cost ofsum tis bounded bysum/cost/closed t = size t , depth t.
module Slow- Definition of the program
exp₂which computes the exponentation of two by its input by performing two identical recursive calls. - Theorem
exp₂/correctstating the correctness ofexp₂. - Theorem
exp₂≤exp₂/cost/closedstating that the cost ofexp₂ nis bounded byexp₂/cost/closed n = (pred[2^ n ] , n), wherepred[2^ n ] = (2 ^ n) - 1. Since two identical recursive calls are made, the work is exponential, but the span is still linear.
- Definition of the program
module Fast- Definition of the program
exp₂which computes the exponentation of two by its input via a standard recursive algorithm. - Theorem
exp₂/correctstating the correctness ofexp₂. - Theorem
exp₂≤exp₂/cost/closedstating that the cost ofexp₂ nis bounded byexp₂/cost/closed n = (n , n).
- Definition of the program
- A proof that
Slow.exp₂andFast.exp₂are extensionally equivalent,slow≡fast : ◯ (Slow.exp₂ ≡ Fast.exp₂).
First, we develop a common collection of definitions and theorems used in both sequential and parallel sorting.
Examples.Sorting.Comparable- Record
Comparabledescribing the requirements for a type to be comparable, includingh-cost, a hypothesis that each comparison is bounded by unit cost. This serves as the cost model for sorting.
- Record
Examples.Sorting.Core- Predicates for correctness of sorting, based on
Sortedand the permutation relation↭fromagda-stdlib. The predicateIsSort sortstates thatsortis a correct sorting algorithm. - Theorem
IsSort⇒≡, which states that any two correct sorting algorithms are extensionally equivalent.
- Predicates for correctness of sorting, based on
Here, we use cost monoid ℕ-CostMonoid, tracking the total number of sequential steps incurred.
Examples.Sorting.Sequential.InsertionSort- Definition of the program
sortimplementing insertion sort. - Theorem
sort/correct : IsSort sortverifying the correctness ofsort. - Theorem
sort≤sort/cost/closedstating that the cost ofsort lis bounded bysort/cost/closed l = length l ². - Theorem
sort/asymptotic : given (list A) measured-via length , sort ∈𝓞(λ n → n ²)stating thatsortis in𝓞(n ²), wherenis the length of the input list.
- Definition of the program
Examples.Sorting.Sequential.MergeSortExamples.Sorting.Sequential.MergeSort.Split- Definition of the program
split, which splits a list in halves. - Theorem
split/correctverifying correctness properties ofsplit. - Theorem
split≤split/coststating that the cost ofsplit lis bounded byzero, since splitting a list into halves requires no comparisons.
- Definition of the program
Examples.Sorting.Sequential.MergeSort.Merge- Definition of the program
merge, which merges a pair of sorted lists. - Theorem
merge/correctverifying correctness properties ofmerge. - Theorem
merge≤merge/cost/closedstating that the cost ofmerge (l₁ , l₂)is bounded bylength l₁ + length l₂.
- Definition of the program
- Definition of the program
sortimplementing merge sort. - Theorem
sort/correct : IsSort sortverifying the correctness ofsort. - Theorem
sort≤sort/cost/closedstating that the cost ofsort lis bounded bysort/cost/closed l = ⌈log₂ length l ⌉ * length l. - Theorem
sort/asymptotic : given (list A) measured-via length , sort ∈𝓞(λ n → n * ⌈log₂ n ⌉)stating thatsortis in𝓞(n * ⌈log₂ n ⌉), wherenis the length of the input list.
Theorem isort≡msort : ◯ (ISort.sort ≡ MSort.sort) states that InsertionSort.sort and MergeSort.sort are extensionally equivalent.
Here, we use parallel cost monoid ℕ²-ParCostMonoid, tracking a pair of natural numbers corresponding to the work (sequential cost) and span (idealized parallel cost), respectively.
Examples.Sorting.Parallel.InsertionSort- Definition of the program
sortimplementing insertion sort. - Theorem
sort/correct : IsSort sortverifying the correctness ofsort. - Theorem
sort≤sort/cost/closedstating that the cost ofsort lis bounded bysort/cost/closed l = (length l ² , length l ²). - Theorem
sort/asymptotic : given (list A) measured-via length , sort ∈𝓞(λ n → n ² , n ²)stating thatsortis in𝓞(n ²)work and𝓞(n ²)span, wherenis the length of the input list.
- Definition of the program
Examples.Sorting.Parallel.MergeSortExamples.Sorting.Parallel.MergeSort.Split- Definition of the program
split, which splits a list in halves. - Theorem
split/correctverifying correctness properties ofsplit. - Theorem
split≤split/coststating that the cost ofsplit lis bounded by𝟘 = (zero , zero), since splitting a list into halves requires no comparisons.
- Definition of the program
Examples.Sorting.Parallel.MergeSort.Merge- Definition of the program
merge, which sequentially merges a pair of sorted lists. - Theorem
merge/correctverifying correctness properties ofmerge. - Theorem
merge≤merge/cost/closedstating that the cost ofmerge (l₁ , l₂)is bounded by(length l₁ + length l₂ , length l₁ + length l₂), since this implementation ofmergeis sequential.
- Definition of the program
- Definition of the program
sortimplementing merge sort, where both recursive calls tosortare performed in parallel (via the parallel pairing operation_&_). - Theorem
sort/correct : IsSort sortverifying the correctness ofsort. - Theorem
sort≤sort/cost/closedstating that the cost ofsort lis bounded bysort/cost/closed l = (⌈log₂ length l ⌉ * length l , 2 * length l + ⌈log₂ length l ⌉). - Theorem
sort/asymptotic : given (list A) measured-via length , sort ∈𝓞(λ n → n * ⌈log₂ n ⌉ , n)stating thatsortis in𝓞(n * ⌈log₂ n ⌉)work and𝓞(n)span, wherenis the length of the input list.
Examples.Sorting.Parallel.MergeSortParExamples.Sorting.Parallel.MergeSortPar.Merge- Definition of the program
merge, which merges a pair of sorted lists in parallel using auxiliary functionssplitMidandsplitBy. - Theorem
merge/correctverifying correctness properties ofmerge. - Theorem
merge≤merge/cost/closedstating that the cost ofmerge (l₁ , l₂)is bounded by(pred[2^ ⌈log₂ suc (length l₁) ⌉ ] * ⌈log₂ suc (length l₂) ⌉ , ⌈log₂ suc (length l₁) ⌉ * ⌈log₂ suc (length l₂) ⌉), wherepred[2^ n ] = (2 ^ n) - 1.
- Definition of the program
- Definition of the program
sortimplementing merge sort, where both recursive calls tosortare performed in parallel. This is identical toMergeSort.sort, but using the parallel merge operationMergeSortPar.Merge.Merge. - Theorem
sort/correct : IsSort sortverifying the correctness ofsort. - Theorem
sort≤sort/cost/closedstating that the cost ofsort lis bounded bysort/cost/closed l = (⌈log₂ length l ⌉ * length l * ⌈log₂ suc ⌈ length l /2⌉ ⌉ , ⌈log₂ length l ⌉ * ⌈log₂ suc ⌈ length l /2⌉ ⌉ ²). - Theorem
sort/asymptotic : given (list A) measured-via length , sort ∈𝓞(λ n → n * ⌈log₂ n ⌉ ² , ⌈log₂ n ⌉ ^ 3)stating thatsortis in𝓞(n * ⌈log₂ n ⌉ ²)work and𝓞(⌈log₂ n ⌉ ^ 3)span, wherenis the length of the input list.
Theorem isort≡msort : ◯ (ISort.sort ≡ MSort.sort) states that InsertionSort.sort and MergeSort.sort are extensionally equivalent.
Similarly, msort≡psort : ◯ (MSort.sort ≡ PSort.sort) states that MergeSort.sort and MergeSortPar.sort are extensionally equivalent.