diff --git a/Project.toml b/Project.toml index 196f38d7e1..2bd4c56eea 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Manifolds" uuid = "1cead3c2-87b3-11e9-0ccd-23c62b72b94e" authors = ["Seth Axen ", "Mateusz Baran ", "Ronny Bergmann ", "Antoine Levitt "] -version = "0.8.57" +version = "0.8.58" [deps] Colors = "5ae59095-9a9b-59fe-a467-6f913c188581" diff --git a/src/manifolds/Circle.jl b/src/manifolds/Circle.jl index aac82d5448..e5c3d954e3 100644 --- a/src/manifolds/Circle.jl +++ b/src/manifolds/Circle.jl @@ -317,61 +317,22 @@ i.e. $\dim(𝕊^1) = 1$. """ manifold_dimension(::Circle) = 1 -@doc raw""" - mean(M::Circle{ℝ}, x::AbstractVector[, w::AbstractWeights]) - -Compute the Riemannian [`mean`](@ref mean(M::AbstractManifold, args...)) of `x` of points on -the [`Circle`](@ref) $𝕊^1$, reprsented by real numbers, i.e. the angular mean -````math -\operatorname{atan}\Bigl( \sum_{i=1}^n w_i\sin(x_i), \sum_{i=1}^n w_i\sin(x_i) \Bigr). -```` """ -mean(::Circle{ℝ}, ::Any) -function Statistics.mean(::Circle{ℝ}, x::AbstractVector{<:Real}; kwargs...) - return atan(1 / length(x) * sum(sin, x), 1 / length(x) * sum(cos, x)) -end -function Statistics.mean( - ::Circle{ℝ}, - x::AbstractVector{<:Real}, - w::AbstractVector; - kwargs..., -) - return atan(sum(w .* sin.(x)), sum(w .* cos.(x))) -end -@doc raw""" - mean(M::Circle{ℂ}, x::AbstractVector[, w::AbstractWeights]) - -Compute the Riemannian [`mean`](@ref mean(M::AbstractManifold, args...)) of `x` of points on -the [`Circle`](@ref) $𝕊^1$, reprsented by complex numbers, i.e. embedded in the complex plane. -Comuting the sum -````math -s = \sum_{i=1}^n x_i -```` -the mean is the angle of the complex number $s$, so represented in the complex plane as -$\frac{s}{\lvert s \rvert}$, whenever $s \neq 0$. + mean( + M::Circle, + x::AbstractVector, + [w::AbstractWeights,] + method = GeodesicInterpolationWithinRadius(π/2); + kwargs..., + ) -If the sum $s=0$, the mean is not unique. For example for opposite points or equally spaced -angles. +Compute the Riemannian [`mean`](@ref mean(M::AbstractManifold, args...)) of points in vector +`x` using [`GeodesicInterpolationWithinRadius`](@ref). """ -mean(::Circle{ℂ}, ::Any) -function Statistics.mean(M::Circle{ℂ}, x::AbstractVector{<:Complex}; kwargs...) - s = sum(x) - abs(s) == 0 && return error( - "The mean for $(x) on $(M) is not defined/unique, since the sum of the complex numbers is zero", - ) - return s / abs(s) -end -function Statistics.mean( - M::Circle{ℂ}, - x::AbstractVector{<:Complex}, - w::AbstractVector; - kwargs..., -) - s = sum(w .* x) - abs(s) == 0 && error( - "The mean for $(x) on $(M) is not defined/unique, since the sum of the complex numbers is zero", - ) - return s /= abs(s) +mean(::Circle, ::Any...) + +function default_estimation_method(::Circle, ::typeof(mean)) + return GeodesicInterpolationWithinRadius(π / 2) end mid_point(M::Circle{ℝ}, p1, p2) = exp(M, p1, 0.5 * log(M, p1, p2)) diff --git a/src/statistics.jl b/src/statistics.jl index 717498ecc4..3ac78cd8bf 100644 --- a/src/statistics.jl +++ b/src/statistics.jl @@ -71,8 +71,8 @@ points are in an open geodesic ball about the mean with corresponding radius + [`Euclidean`](@ref) + [`SymmetricPositiveDefinite`](@ref) [^Ho2013] * Other manifolds: - + [`Sphere`](@ref): $\frac{π}{2}$ [^Salehian2015] - + [`Grassmann`](@ref): $\frac{π}{4}$ [^Chakraborty2015] + + [`Sphere`](@ref)/[`Circle`](@ref): $\frac{π}{2}$ [^Salehian2015] + + [`Grassmann`](@ref)/[`ProjectiveSpace`](@ref): $\frac{π}{4}$ [^Chakraborty2015] + [`Stiefel`](@ref)/[`Rotations`](@ref): $\frac{π}{2 \sqrt 2}$ [^Chakraborty2019] For online variance computation, the algorithm additionally uses an analogous