#![cfg(feature = "formal-verification")]
use creusot_contracts::macros::{ensures, requires};
use super::verified::VerifiedMultivector;
use num_traits::{Zero, One, Float};
pub trait Associative {
fn op(&self, other: &Self) -> Self;
fn associativity_property(&self, b: &Self, c: &Self) -> bool {
true
}
}
pub trait Distributive {
fn mul(&self, other: &Self) -> Self;
fn add(&self, other: &Self) -> Self;
#[law]
#[ensures(forall(|a: &Self, b: &Self, c: &Self|
a.mul(&b.add(c)) == a.mul(b).add(&a.mul(c))
))]
fn left_distributivity() {}
#[law]
#[ensures(forall(|a: &Self, b: &Self, c: &Self|
a.add(b).mul(c) == a.mul(c).add(&b.mul(c))
))]
fn right_distributivity() {}
}
pub trait CliffordSignature<const P: usize, const Q: usize, const R: usize> {
#[law]
#[ensures(forall(|i: usize|
i < P ==> self.basis_vector_square(i) == 1.0
))]
#[ensures(forall(|i: usize|
P <= i && i < P + Q ==> self.basis_vector_square(i) == -1.0
))]
#[ensures(forall(|i: usize|
P + Q <= i && i < P + Q + R ==> self.basis_vector_square(i) == 0.0
))]
fn signature_law(&self) -> f64;
fn basis_vector_square(&self, i: usize) -> f64;
}
pub trait AnticommutativeBasis {
#[law]
#[ensures(forall(|i: usize, j: usize|
i != j ==> self.basis_product(i, j) == -self.basis_product(j, i)
))]
fn anticommutativity_law(&self);
fn basis_product(&self, i: usize, j: usize) -> f64;
}
pub trait GradeProjection {
type Scalar;
#[law]
#[ensures(forall(|mv: &Self, k: usize|
self.project_grade(k).project_grade(k) == self.project_grade(k)
))]
fn idempotence_law(&self);
#[law]
#[ensures(forall(|mv: &Self, i: usize, j: usize|
i != j ==> self.project_grade(i).project_grade(j).is_zero()
))]
fn orthogonality_law(&self);
fn project_grade(&self, grade: usize) -> Self;
fn is_zero(&self) -> bool;
}
pub trait RotorProperties<T: Float> {
#[law]
#[ensures(forall(|rotor: &Self, vector: &Self|
(rotor.apply(vector).norm() - vector.norm()).abs() < T::epsilon()
))]
fn norm_preservation(&self);
#[law]
#[ensures(forall(|r1: &Self, r2: &Self, v: &Self|
r1.compose(r2).apply(v) == r1.apply(&r2.apply(v))
))]
fn composition_law(&self);
fn apply(&self, vector: &Self) -> Self;
fn compose(&self, other: &Self) -> Self;
fn norm(&self) -> T;
}
pub trait QuaternionIdentity {
#[law]
#[ensures(
self.bivector_square(2, 3) == -1.0 &&
self.bivector_square(3, 1) == -1.0 &&
self.bivector_square(1, 2) == -1.0
)]
fn quaternion_squares(&self);
#[law]
#[ensures(
self.triple_product(
self.bivector(2, 3),
self.bivector(3, 1),
self.bivector(1, 2)
) == -1.0
)]
fn hamilton_identity(&self);
fn bivector(&self, i: usize, j: usize) -> f64;
fn bivector_square(&self, i: usize, j: usize) -> f64;
fn triple_product(&self, i: f64, j: f64, k: f64) -> f64;
}
pub struct GeometricAlgebraLaws<T, const P: usize, const Q: usize, const R: usize>
where
T: Float + Zero + One,
{
_phantom: std::marker::PhantomData<T>,
}
impl<T, const P: usize, const Q: usize, const R: usize>
GeometricAlgebraLaws<T, P, Q, R>
where
T: Float + Zero + One,
{
#[proof]
#[ensures(forall(|s: T, mv: VerifiedMultivector<T, P, Q, R>|
scalar_product(s, &mv) == scalar_product_reverse(&mv, s)
))]
pub fn scalar_commutativity() {}
#[proof]
#[ensures(forall(|mv: VerifiedMultivector<T, P, Q, R>|
mv.geometric_product(&VerifiedMultivector::scalar(T::one())) == mv
))]
#[ensures(forall(|mv: VerifiedMultivector<T, P, Q, R>|
VerifiedMultivector::scalar(T::one()).geometric_product(&mv) == mv
))]
pub fn multiplicative_identity() {}
#[proof]
#[ensures(forall(|mv: VerifiedMultivector<T, P, Q, R>|
mv.add(&VerifiedMultivector::scalar(T::zero())) == mv
))]
pub fn additive_identity() {}
#[proof]
#[ensures(forall(|a: VerifiedMultivector<T, P, Q, R>, b: VerifiedMultivector<T, P, Q, R>|
grade_involution(&a.geometric_product(&b)) ==
grade_involution(&a).geometric_product(&grade_involution(&b))
))]
pub fn grade_involution_law() {}
#[proof]
#[ensures(forall(|a: VerifiedMultivector<T, P, Q, R>, b: VerifiedMultivector<T, P, Q, R>|
reverse(&a.geometric_product(&b)) ==
reverse(&b).geometric_product(&reverse(&a))
))]
pub fn reversion_antiautomorphism() {}
}
fn scalar_product<T, const P: usize, const Q: usize, const R: usize>(
scalar: T,
mv: &VerifiedMultivector<T, P, Q, R>,
) -> VerifiedMultivector<T, P, Q, R>
where
T: Float + Zero + One,
{
let coefficients = mv.coefficients.iter().map(|c| *c * scalar).collect();
VerifiedMultivector {
coefficients,
_signature: PhantomData,
}
}
fn scalar_product_reverse<T, const P: usize, const Q: usize, const R: usize>(
mv: &VerifiedMultivector<T, P, Q, R>,
scalar: T,
) -> VerifiedMultivector<T, P, Q, R>
where
T: Float + Zero + One,
{
scalar_product(scalar, mv)
}
fn grade_involution<T, const P: usize, const Q: usize, const R: usize>(
mv: &VerifiedMultivector<T, P, Q, R>,
) -> VerifiedMultivector<T, P, Q, R>
where
T: Float + Zero + One,
{
let coefficients = mv
.coefficients
.iter()
.enumerate()
.map(|(i, c)| {
let grade = i.count_ones() as usize;
if grade.is_multiple_of(2) { *c } else { -*c }
})
.collect();
VerifiedMultivector {
coefficients,
_signature: PhantomData,
}
}
fn reverse<T, const P: usize, const Q: usize, const R: usize>(
mv: &VerifiedMultivector<T, P, Q, R>,
) -> VerifiedMultivector<T, P, Q, R>
where
T: Float + Zero + One,
{
let coefficients = mv
.coefficients
.iter()
.enumerate()
.map(|(i, c)| {
let grade = i.count_ones() as usize;
if grade >= 2 && (grade * (grade - 1) / 2) % 2 == 1 {
-*c
} else {
*c
}
})
.collect();
VerifiedMultivector {
coefficients,
_signature: PhantomData,
}
}
#[cfg(test)]
mod verification_tests {
use super::*;
#[test]
#[cfg_attr(feature = "formal-verification", creusot::proof)]
fn verify_associativity() {
GeometricAlgebraLaws::<f64, 3, 0, 0>::multiplicative_identity();
}
#[test]
#[cfg_attr(feature = "formal-verification", creusot::proof)]
fn verify_distributivity() {
GeometricAlgebraLaws::<f64, 3, 0, 0>::additive_identity();
}
}