euclidean simplify fail draft dev

Mon, 12 May 2025 17:10:39 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Mon, 12 May 2025 17:10:39 -0500
branch
dev
changeset 131
8264d72aa347
parent 130
0a689881b0f1

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))

mercurial