Mon, 12 May 2025 17:10:39 -0500
euclidean simplify fail
| src/convex.rs | file | annotate | diff | comparison | revisions | |
| src/direct_product.rs | file | annotate | diff | comparison | revisions | |
| src/euclidean.rs | file | annotate | diff | comparison | revisions | |
| src/linops.rs | file | annotate | diff | comparison | revisions | |
| src/loc.rs | file | annotate | diff | comparison | revisions | |
| src/nalgebra_support.rs | file | annotate | diff | comparison | revisions | |
| src/norms.rs | file | annotate | diff | comparison | revisions | |
| src/sets.rs | file | annotate | diff | comparison | revisions |
--- a/src/convex.rs Mon May 12 16:28:50 2025 -0500 +++ b/src/convex.rs Mon May 12 17:10:39 2025 -0500 @@ -359,7 +359,7 @@ } } -impl<X: Euclidean<F>, F: Float> Mapping<X> for Norm222<F> { +impl<X: Euclidean<Field = F>, F: Float> Mapping<X> for Norm222<F> { type Codomain = F; /// Compute the value of `self` at `x`. @@ -368,13 +368,13 @@ } } -impl<X: Euclidean<F>, F: Float> ConvexMapping<X, F> for Norm222<F> { +impl<X: Euclidean<Field = F>, F: Float> ConvexMapping<X, F> for Norm222<F> { fn factor_of_strong_convexity(&self) -> F { F::ONE } } -impl<X: Euclidean<F>, F: Float> Conjugable<X, F> for Norm222<F> { +impl<X: Euclidean<Field = F>, F: Float> Conjugable<X, F> for Norm222<F> { type Conjugate<'a> = Self where @@ -386,7 +386,7 @@ } } -impl<X: Euclidean<F>, F: Float> Preconjugable<X, X, F> for Norm222<F> { +impl<X: Euclidean<Field = F>, F: Float> Preconjugable<X, X, F> for Norm222<F> { type Preconjugate<'a> = Self where @@ -401,7 +401,7 @@ impl<X, F> Prox<X> for Norm222<F> where F: Float, - X: Euclidean<F, Output = X>, + X: Euclidean<Field = F, Output = X>, { type Prox<'a> = Scaled<F> @@ -416,7 +416,7 @@ impl<X, F> DifferentiableImpl<X> for Norm222<F> where F: Float, - X: Euclidean<F, Output = X>, + X: Euclidean<Field = F, Output = X>, { type Derivative = X; @@ -428,7 +428,7 @@ impl<X, F> LipschitzDifferentiableImpl<X, L2> for Norm222<F> where F: Float, - X: Euclidean<F, Output = X>, + X: Euclidean<Field = F, Output = X>, { type FloatType = F;
--- a/src/direct_product.rs Mon May 12 16:28:50 2025 -0500 +++ b/src/direct_product.rs Mon May 12 17:10:39 2025 -0500 @@ -264,10 +264,10 @@ /// We only support 'closed' `Euclidean` `Pair`s, as more general ones cause /// compiler overflows. -impl<A, B, F: Float> Euclidean<F> for Pair<A, B> +impl<A, B, F: Float> Euclidean for Pair<A, B> where - A: Euclidean<F>, - B: Euclidean<F>, + A: Euclidean<Field = F>, + B: Euclidean<Field = F>, //Pair<A, B>: Euclidean<F>, Self: Sized + Mul<F, Output = Pair<A, B>> @@ -284,8 +284,6 @@ + for<'b> SubAssign<&'b Self> + Neg<Output = Pair<A, B>>, { - type Output = Pair<A, B>; - fn dot<I: Instance<Self>>(&self, other: I) -> F { let Pair(u, v) = other.decompose(); self.0.dot(u) + self.1.dot(v)
--- a/src/euclidean.rs Mon May 12 16:28:50 2025 -0500 +++ b/src/euclidean.rs Mon May 12 17:10:39 2025 -0500 @@ -3,7 +3,8 @@ */ use crate::instance::Instance; -use crate::norms::{HasDual, Reflexive}; +use crate::linops::AXPY; +use crate::norms::{HasDual, NormExponent, Normed, Reflexive, L2}; use crate::types::*; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; @@ -12,66 +13,68 @@ /// The type should implement vector space operations (addition, subtraction, scalar /// multiplication and scalar division) along with their assignment versions, as well /// as an inner product. -pub trait Euclidean<F: Float = f64>: - HasDual<F, DualSpace = Self> - + Reflexive<F> - + Mul<F, Output = <Self as Euclidean<F>>::Output> - + MulAssign<F> - + Div<F, Output = <Self as Euclidean<F>>::Output> - + DivAssign<F> - + Add<Self, Output = <Self as Euclidean<F>>::Output> - + Sub<Self, Output = <Self as Euclidean<F>>::Output> - + for<'b> Add<&'b Self, Output = <Self as Euclidean<F>>::Output> - + for<'b> Sub<&'b Self, Output = <Self as Euclidean<F>>::Output> +pub trait Euclidean: + AXPY<Owned = Self::Owned_> + + HasDual<Self::Field, DualSpace = Self> + //+ Normed<Self::Field, NormExp = L2> + + Reflexive<Self::Field> + + Mul<Self::Field, Output = <Self as AXPY>::Owned> + + MulAssign<Self::Field> + + Div<Self::Field, Output = <Self as AXPY>::Owned> + + DivAssign<Self::Field> + + Add<Self, Output = <Self as AXPY>::Owned> + + Sub<Self, Output = <Self as AXPY>::Owned> + + for<'b> Add<&'b Self, Output = <Self as AXPY>::Owned> + + for<'b> Sub<&'b Self, Output = <Self as AXPY>::Owned> + AddAssign<Self> + for<'b> AddAssign<&'b Self> + SubAssign<Self> + for<'b> SubAssign<&'b Self> - + Neg<Output = <Self as Euclidean<F>>::Output> + + Neg<Output = <Self as AXPY>::Owned> { - type Output: Euclidean<F>; + type Owned_: Euclidean<Field = Self::Field>; // Inner product - fn dot<I: Instance<Self>>(&self, other: I) -> F; + fn dot<I: Instance<Self>>(&self, other: I) -> Self::Field; /// Calculate the square of the 2-norm, $\frac{1}{2}\\|x\\|_2^2$, where `self` is $x$. /// /// This is not automatically implemented to avoid imposing /// `for <'a> &'a Self : Instance<Self>` trait bound bloat. - fn norm2_squared(&self) -> F; + fn norm2_squared(&self) -> Self::Field; /// Calculate the square of the 2-norm divided by 2, $\frac{1}{2}\\|x\\|_2^2$, /// where `self` is $x$. #[inline] - fn norm2_squared_div2(&self) -> F { - self.norm2_squared() / F::TWO + fn norm2_squared_div2(&self) -> Self::Field { + self.norm2_squared() / Self::Field::TWO } /// Calculate the 2-norm $‖x‖_2$, where `self` is $x$. #[inline] - fn norm2(&self) -> F { + fn norm2(&self) -> Self::Field { self.norm2_squared().sqrt() } /// Calculate the 2-distance squared $\\|x-y\\|_2^2$, where `self` is $x$. - fn dist2_squared<I: Instance<Self>>(&self, y: I) -> F; + fn dist2_squared<I: Instance<Self>>(&self, y: I) -> Self::Field; /// Calculate the 2-distance $\\|x-y\\|_2$, where `self` is $x$. #[inline] - fn dist2<I: Instance<Self>>(&self, y: I) -> F { + fn dist2<I: Instance<Self>>(&self, y: I) -> Self::Field { self.dist2_squared(y).sqrt() } /// Projection to the 2-ball. #[inline] - fn proj_ball2(mut self, ρ: F) -> Self { + fn proj_ball2(mut self, ρ: Self::Field) -> Self { self.proj_ball2_mut(ρ); self } /// In-place projection to the 2-ball. #[inline] - fn proj_ball2_mut(&mut self, ρ: F) { + fn proj_ball2_mut(&mut self, ρ: Self::Field) { let r = self.norm2(); if r > ρ { *self *= ρ / r @@ -80,7 +83,7 @@ } /// Trait for [`Euclidean`] spaces with dimensions known at compile time. -pub trait StaticEuclidean<F: Float = f64>: Euclidean<F> { +pub trait StaticEuclidean: Euclidean { /// Returns the origin - fn origin() -> <Self as Euclidean<F>>::Output; + fn origin() -> <Self as AXPY>::Owned; }
--- a/src/linops.rs Mon May 12 16:28:50 2025 -0500 +++ b/src/linops.rs Mon May 12 17:10:39 2025 -0500 @@ -29,12 +29,12 @@ #[replace_float_literals(Self::Field::cast_from(literal))] pub trait AXPY<X = Self>: Space - + MulAssign<Self::Field> - + DivAssign<Self::Field> - + AddAssign<Self> - + AddAssign<Self::Owned> - + SubAssign<Self> - + SubAssign<Self::Owned> + //+ MulAssign<Self::Field> + //+ DivAssign<Self::Field> + //+ AddAssign<Self> + //+ AddAssign<Self::Owned> + //+ SubAssign<Self> + //+ SubAssign<Self::Owned> + Mul<Self::Field, Output = Self::Owned> + Div<Self::Field, Output = Self::Owned> + Add<Self, Output = Self::Owned> @@ -45,7 +45,7 @@ where X: Space, { - type Field: Num; + type Field: Float; type Owned: AXPY<X, Field = Self::Field>; // type OriginGen<'a>: OriginGenerator<Self::Owned, F> // where
--- a/src/loc.rs Mon May 12 16:28:50 2025 -0500 +++ b/src/loc.rs Mon May 12 17:10:39 2025 -0500 @@ -432,9 +432,7 @@ domination!(Linfinity, L2); domination!(L2, L1); -impl<F: Float, const N: usize> Euclidean<F> for Loc<N, F> { - type Output = Self; - +impl<F: Float, const N: usize> Euclidean for Loc<N, F> { /// This implementation is not stabilised as it's meant to be used for very small vectors. /// Use [`nalgebra`] for larger vectors. #[inline] @@ -565,7 +563,7 @@ } } -impl<F: Float, const N: usize> StaticEuclidean<F> for Loc<N, F> { +impl<F: Float, const N: usize> StaticEuclidean for Loc<N, F> { #[inline] fn origin() -> Self { Self::ORIGIN
--- a/src/nalgebra_support.rs Mon May 12 16:28:50 2025 -0500 +++ b/src/nalgebra_support.rs Mon May 12 17:10:39 2025 -0500 @@ -215,15 +215,13 @@ // TODO: should allow different input storages in `Euclidean`. -impl<E, M, S> Euclidean<E> for Vector<E, M, S> +impl<E, M, S> Euclidean for Vector<E, M, S> where M: Dim, S: StorageMut<E, M> + Clone, E: Float + Scalar + Zero + One + RealField, DefaultAllocator: Allocator<M>, { - type Output = OVector<E, M>; - #[inline] fn dot<I: Instance<Self>>(&self, other: I) -> E { Vector::<E, M, S>::dot(self, other.ref_instance()) @@ -240,7 +238,7 @@ } } -impl<E, M, S> StaticEuclidean<E> for Vector<E, M, S> +impl<E, M, S> StaticEuclidean for Vector<E, M, S> where M: DimName, S: StorageMut<E, M> + Clone,
--- a/src/norms.rs Mon May 12 16:28:50 2025 -0500 +++ b/src/norms.rs Mon May 12 17:10:39 2025 -0500 @@ -146,7 +146,7 @@ fn dist(&self, other : &Self, _p : L2) -> F { self.dist2(other) } }*/ -impl<F: Float, E: Euclidean<F> + Norm<L2, F>> Projection<F, L2> for E { +impl<F: Float, E: Euclidean<Field = F> + Norm<L2, F>> Projection<F, L2> for E { #[inline] fn proj_ball(self, ρ: F, _p: L2) -> Self { self.proj_ball2(ρ) @@ -176,13 +176,13 @@ } } -impl<F: Float, E: Euclidean<F> + Normed<F, NormExp = L2>> Norm<HuberL1<F>, F> for E { +impl<F: Float, E: Euclidean<Field = F> + Normed<F, NormExp = L2>> Norm<HuberL1<F>, F> for E { fn norm(&self, huber: HuberL1<F>) -> F { huber.apply(self.norm2_squared()) } } -impl<F: Float, E: Euclidean<F> + Normed<F, NormExp = L2>> Dist<F, HuberL1<F>> for E { +impl<F: Float, E: Euclidean<Field = F> + Normed<F, NormExp = L2>> Dist<F, HuberL1<F>> for E { fn dist<I: Instance<Self>>(&self, other: I, huber: HuberL1<F>) -> F { huber.apply(self.dist2_squared(other)) }
--- a/src/sets.rs Mon May 12 16:28:50 2025 -0500 +++ b/src/sets.rs Mon May 12 17:10:39 2025 -0500 @@ -72,22 +72,20 @@ /// The halfspace is $H = \\{ t v + a \mid a^⊤ v = 0 \\}$, where $v$ is the orthogonal /// vector and $t$ the offset. #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] -pub struct Halfspace<A, F> +pub struct Halfspace<A> where - A: Euclidean<F>, - F: Float, + A: Euclidean, { pub orthogonal: A, - pub offset: F, + pub offset: A::Field, } -impl<A, F> Halfspace<A, F> +impl<A> Halfspace<A> where - A: Euclidean<F>, - F: Float, + A: Euclidean, { #[inline] - pub fn new(orthogonal: A, offset: F) -> Self { + pub fn new(orthogonal: A, offset: A::Field) -> Self { Halfspace { orthogonal: orthogonal, offset: offset, @@ -96,29 +94,26 @@ } /// Trait for generating a halfspace spanned by another set `Self` of elements of type `U`. -pub trait SpannedHalfspace<F> -where - F: Float, -{ +pub trait SpannedHalfspace { /// Type of the orthogonal vector describing the halfspace. - type A: Euclidean<F>; + type A: Euclidean; /// Returns the halfspace spanned by this set. - fn spanned_halfspace(&self) -> Halfspace<Self::A, F>; + fn spanned_halfspace(&self) -> Halfspace<Self::A>; } // TODO: Gram-Schmidt for higher N. -impl<F: Float> SpannedHalfspace<F> for [Loc<1, F>; 2] { +impl<F: Float> SpannedHalfspace for [Loc<1, F>; 2] { type A = Loc<1, F>; - fn spanned_halfspace(&self) -> Halfspace<Self::A, F> { + fn spanned_halfspace(&self) -> Halfspace<Self::A> { let (x0, x1) = (self[0], self[1]); Halfspace::new(x1 - x0, x0[0]) } } // TODO: Gram-Schmidt for higher N. -impl<F: Float> SpannedHalfspace<F> for [Loc<2, F>; 2] { +impl<F: Float> SpannedHalfspace for [Loc<2, F>; 2] { type A = Loc<2, F>; - fn spanned_halfspace(&self) -> Halfspace<Self::A, F> { + fn spanned_halfspace(&self) -> Halfspace<Self::A> { let (x0, x1) = (&self[0], &self[1]); let d = x1 - x0; let orthog = loc![d[1], -d[0]]; // We don't normalise for efficiency @@ -127,10 +122,9 @@ } } -impl<A, F> Set<A> for Halfspace<A, F> +impl<A> Set<A> for Halfspace<A> where - A: Euclidean<F>, - F: Float, + A: Euclidean, { #[inline] fn contains<I: Instance<A>>(&self, item: I) -> bool { @@ -139,17 +133,10 @@ } /// Polygons defined by `N` `Halfspace`s. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct NPolygon<A, const N: usize, F = f64>(pub [Halfspace<A, F>; N]) -where - A: Euclidean<F>, - F: Float; +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct NPolygon<A: Euclidean, const N: usize>(pub [Halfspace<A>; N]); -impl<A, F, const N: usize> Set<A> for NPolygon<A, N, F> -where - A: Euclidean<F>, - F: Float, -{ +impl<A: Euclidean, const N: usize> Set<A> for NPolygon<A, N> { fn contains<I: Instance<A>>(&self, item: I) -> bool { let r = item.ref_instance(); self.0.iter().all(|halfspace| halfspace.contains(r))