Verified linear algebra
with the Rust programming language
CHOOSE


Index
Project goal
Formally verify vector 2-norm
- Write code in Rust
- Define complex numbers
- Define vectors in
- Translate code to Coq
- Verify norm properties
- Positive definiteness
- Nonnegative homogeneity
- Triangle inequality
2
Verus Installation was relatively straight forward. The Rust compiler could not find the Verus package. This did not affect Verus verifiying code, but rendered issues within the Rust toolchain. Ultimately, Verus proved to lack support of floats (decimals)
3
Aeneas Simple to install (like verus), but with an extra dependency on a related project. Lacks support of floats (decimals)
4
coq-of-rust Easy installation using Rust cargo tool. Same issue as Aeneas (and Verus)
6
Property-based Testing / Model-checking Not as rigorous as a formal proof, but far more robust than nothing. Kani is a viable library.
(in progress)
5
Creusot Straight-forward installation. Provides annotations that appear to support floats and translates Rust to WhyML.
(in progress)
1
Environment Develop container-based environment work writing Rust code that has Why3 with provers, Coq, and Lean installed
Project timeline
...the use of tools that mathematically analyze the space of possible behaviors of a design, rather than computing results for particular values.
...a powerful technique used to mathematically prove that an appropriately scaled model of a system does or does not exhibit desirable properties. [1]
Formal verification
Testing is a poor substitute for proof.
Category Theory for Programmers
[A] proof is rigorous when it is (or could be) written out in the first-order predicate language… as a sequence of inferences from the axioms ZFC, each inference made according to one of the stated rules…
Formally Verified Mathematics [2]

I verified some code
I don't need to understand linear algebra, OCaml, Coq, Why3, Rust, and the de Bruijn Criterion to understand your project, right?
I don't have to, right?
mind the gap
"formality gap"
Model
Implementation
"Math" world
"Real" world
< />
Real & math
Removes formality gap
Single code base
Well known language
Better than nothing
real = math
Removes formality gap
Single code base
Well known language
Better than nothing
crossing the gap
real math
Removes formality gap
Single code base
Well known language
Better than nothing
code translation
Real & math
"Math" world
"Real" world



Real = math



"Math" world
"Real" world
code translation


Intermediate
Representation

Why3
"Real" world
"Math" world
Code translation options
& coq-of-rust
verus
Formally verify Rust
Supports float type
Popular backends
Rigorous verification
creusot
Formally verify Rust
Supports float type
Popular backends
Rigorous verification
aeneas
Formally verify Rust
Supports float type
Popular backends
Rigorous verification
Summary: Verification toolchain for Rust programs. Built with OCaml and has F*, Lean, Coq, and HOL backends...relies on a translation from Rust's mid-level intermediate representation (MIR) internal language to a pure lambda calculus
Issues: Only supports integers and natural numbers
aeneas
creusot
Summary: Tool for deductive verification of Rust code. It allows you to annotate your code with specifications, invariants and assertions and then verify them formally and automatically, returning a proof that your code satisfies the specs.
Issues: NSTR (in progress)
verus
Summary: Tool for verifying the correctness of code written in Rust. Developers write specifications of what their code should do, and Verus statically checks that the executable Rust code will always satisfy the specifications for all possible executions of the code
Issues: Only supports integers and natural numbers
Environment setup and usage
creATE container
docker run -it \
--privileged \
--name notebook \
--hostname $(hostname) \
-p 1337:1337 \
ghcr.io/jhwohlgemuth/lambda
verify environment
# Verify Coq opam packages are installed
opam list | grep coq
# Verify Coq version (installed with opam)
coqc --version
# Read Lean help
lean --help
# View installed Why3 provers
why3 config list-provers
install technologies
# https://github.com/AeneasVerif/aeneas
install_aeneas
aeneas --help
# https://github.com/xldenis/creusot/tree/master
install_creusot
cargo --list | grep creusot
# https://github.com/verus-lang/verus
install_verus
verus --help
open vscode in web browser
https://localhost:1337

status and way-ahead
GitHub repository (jhwohlgemuth/verified-linear-algebra)
- Implemented complex numbers
- Implemented complex vectors (using Rust vec)
- Implemented vector 2-norm in
- Use property-based testing (model checking with Kani) to "verify" properties of 2-norm
- Issue Kani does not support f64 square root
- Note Perform model checking on
- Future goal is to build up to vectors and address lack of support for floats (f64) directly. Try using Creusot.
model-checking with kani
Summary: Bit-precise model checker for Rust. Verifies memory safety, the absence of some types of unexpected behavior (e.g., arithmetic overflows), user inserted assert!, and more. Somewhere in between property-based testing and formal verification.
Issues: Not rigorous verification
install kani
# Install
cargo install --locked kani-verifier
# Configure
cargo kani setup
# Use
cargo kani
# Visualize (useful after failures)
cargo kani --visualize --enable-unstable
type Number = f64;
type Vector = Vec<Complex>;
#[derive(Debug, PartialEq, Copy, Clone)]
struct Complex {
re: Number,
im: Number,
}
#[cfg(kani)]
#[kani::proof]
fn complex_numbers_identity() -> bool {
let a: f64 = kani::any();
let b: f64 = kani::any();
let x: Complex = Complex::new(a, b);
let additive_identity = Complex::new(0.0, 0.0);
x.plus(&additive_identity) == x
}
complex numbers additive identity
#[cfg(kani)]
#[kani::proof]
fn two_norm_squared_positive_definiteness() -> () {
let limit = 4000.0;
let a: f64 = kani::any();
let b: f64 = kani::any();
let c: f64 = kani::any();
let d: f64 = kani::any();
let e: f64 = kani::any();
let f: f64 = kani::any();
let g: f64 = kani::any();
let h: f64 = kani::any();
for i in vec![a, b, c, d, e, f, g, h] {
kani::assume(-limit < i && i < limit);
}
let zero: Complex = Complex::new(0.0, 0.0);
let x = vec![
Complex::new(a, b),
Complex::new(c, d),
Complex::new(e, f),
Complex::new(g, h),
];
if two_norm_squared(x.clone()) != 0.0 {
assert!(x != vec![zero, zero, zero, zero]);
}
}
vector 2-norm positive definiteness
#[cfg(kani)]
#[kani::proof]
fn two_norm_squared_nonnegative_homogeneity() -> bool {
let limit = 4000.0;
let value: f64 = kani::any();
let a: f64 = kani::any();
let b: f64 = kani::any();
let c: f64 = kani::any();
let d: f64 = kani::any();
let e: f64 = kani::any();
let f: f64 = kani::any();
let g: f64 = kani::any();
let h: f64 = kani::any();
kani::assume(-limit < value && value < limit);
for i in vec![a, b, c, d, e, f, g, h] {
kani::assume(-limit < i && i < limit);
}
let x = vec![
Complex::new(a, b),
Complex::new(c, d),
Complex::new(e, f),
Complex::new(g, h),
];
let product: Vector = x.iter()
.map(|i| i.mult_scalar(value))
.collect();
two_norm_squared(product) == value.abs() * two_norm_squared(x)
}
vector 2-norm non-negative homogeneity
#[cfg(kani)]
#[kani::proof]
fn two_norm_squared_triangle_inequality() -> bool {
let limit = 4000.0;
let value: f64 = kani::any();
let a: f64 = kani::any();
let b: f64 = kani::any();
let c: f64 = kani::any();
let d: f64 = kani::any();
let e: f64 = kani::any();
let f: f64 = kani::any();
let g: f64 = kani::any();
let h: f64 = kani::any();
kani::assume(-limit < value && value < limit);
for i in vec![a, b, c, d, e, f, g, h] {
kani::assume(-limit < i && i < limit);
}
let x = vec![
Complex::new(a, b),
Complex::new(c, d),
Complex::new(e, f),
Complex::new(g, h),
];
let sum: Vector = x.iter().enumerate()
.map(|(index, element)| element.plus(&x[index]))
.collect();
two_norm_squared(sum) <= two_norm_squared(x) + two_norm_squared(x)
}
vector 2-norm triangle inequality
reproduce results
# Build Docker container
docker run -it --name notebook -p 1337:1337 ghcr.io/jhwohlgemuth/lambda
# Clone GitHub project
git clone https://github.com/jhwohlgemuth/verified-linear-algebra
cd verified-linear-algebra
# Install Kani
cargo install --locked kani-verifier
cargo kani setup
# Execute proofs
cargo kani
“Reverse” code translation


"Math" world
"Real" world
Verified Linear Algebra
By Jason Wohlgemuth
Verified Linear Algebra
- 30