From 490ed8fcf478ed1d80b68e793c40267572425625 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Fri, 13 Oct 2023 10:01:47 +0200 Subject: [PATCH 01/10] Change is_point and is_vector signatures and explain them in the news. --- NEWS.md | 18 ++++++++ src/ManifoldsBase.jl | 97 +++++++++++++++++++++----------------------- 2 files changed, 64 insertions(+), 51 deletions(-) diff --git a/NEWS.md b/NEWS.md index 5627adaa..c19b0027 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.15.0] xx/xx/xx + +### Changed + +- The signature of `is_point` was changed to be consistent with `isapprox.`. + The error positional symbol (third argument) is now a keyword argument. + We left the boolean shortcut in place. + That means + * `is_point(M, p, true)` works the same as before (`false` is the default anyways) + * `is_point(M, p, :warn)` has to be changed to `is_point(M, p; error=:warn)` +- The signature of `is_vector` was changed to be consistent with `isapprox` and `is_point`. + The error positional symbol (fourth argument) is now a keyword argument. + The error positional boolean (fourth argument) hence moved to fifth place (after `check_base_point`) + This means + * `is_vector(M, p, X, true)` should now be `is_vector(M, p, X; error=:error)` + * `is_vector(M, p, X, err, base)` for two booleans `err, base` should now be `is_vector(M, p, X, base, err)` + * `is_vector(M, p, X, err, base)` for a symbol `err` should now be `is_vector(M, p, X, base; error=err)` + ## [0.14.11] 25/08/2023 ### Added diff --git a/src/ManifoldsBase.jl b/src/ManifoldsBase.jl index 9296f1fc..e81de54c 100644 --- a/src/ManifoldsBase.jl +++ b/src/ManifoldsBase.jl @@ -549,6 +549,7 @@ Check if points `p` and `q` from [`AbstractManifold`](@ref) `M` are approximatel The keyword argument can be used to get more information for the case that the result is false, if the concrete manifold provides such information. Currently the following are supported + * `:error` - throws an error if `isapprox` evaluates to false, providing possibly a more detailed error. Note that this turns `isapprox` basically to an `@assert`. * `:info` – prints the information in an `@info` @@ -643,41 +644,41 @@ function _isapprox(M::AbstractManifold, p, X, Y; kwargs...) end """ - is_point(M::AbstractManifold, p, throw_error::Boolean = false; kwargs...) - is_point(M::AbstractManifold, p, report_error::Symbol; kwargs...) + is_point(M::AbstractManifold, p; error::Symbol = :none, kwargs...) + is_point(M::AbstractManifold, p, throw_error::Bool; kwargs...) Return whether `p` is a valid point on the [`AbstractManifold`](@ref) `M`. +By default the function calls [`check_point`](@ref), which returns an `ErrorException` or `nothing`. + +How to report a potential error can be set using the `error=` keyword -If `throw_error` is `false`, the function returns either `true` or `false`. If `throw_error` -is `true`, the function either returns `true` or throws an error. By default the function -calls [`check_point`](@ref) and checks whether the returned value -is `nothing` or an error. +* `:error` - throws an error if `p` is not a point +* `:info` - displays the error message as an `@info` +* `:warn` - displays the error message as a `@warning` +* `:none` (default) – the function just returns `true`/`false` -A more precise way can be set using a symbol as the optional parameter, where -' `:error` is the same as setting `throw_error=true` -' `:info` displays the error message as an `@info` -* `:warn` displays the error message as a `@warning` +all other symbols are equivalent to `error=:none`. -all other symbols are equivalent to `throw_error=false`. +The second signature is a shorthand, where the boolean is used for `error=:error` (`true`) +and `error=:none` (default, `false`). This case ignores the `error=` keyword """ -function is_point(M::AbstractManifold, p, throw_error = false; kwargs...) - mps = check_size(M, p) - if mps !== nothing - throw_error && throw(mps) - return false - end - mpe = check_point(M, p; kwargs...) - mpe === nothing && return true - return throw_error ? throw(mpe) : false +function is_point( + M::AbstractManifold, + p, + throw_error::Bool; + error::Symbol = :none, + kwargs..., +) + return is_point(M, p; error = throw_error ? :error : :none) end - -function is_point(M::AbstractManifold, p, error::Symbol; kwargs...) +function is_point(M::AbstractManifold, p; error::Symbol = :none, kwargs...) (error === :error) && return is_point(M, p, true; kwargs...) mps = check_size(M, p) if mps !== nothing s = "$(typeof(mps)) with $(mps.val)\n$(mps.msg)" (error === :info) && @info s (error === :warn) && @warn s + (error === :error) && throw(mps) return false end mpe = check_point(M, p; kwargs...) @@ -685,6 +686,7 @@ function is_point(M::AbstractManifold, p, error::Symbol; kwargs...) s = "$(typeof(mpe)) with $(mpe.val)\n$(mpe.msg)" (error === :info) && @info s (error === :warn) && @warn s + (error === :error) && throw(mpe) return false end return true @@ -692,56 +694,47 @@ end """ - is_vector(M::AbstractManifold, p, X, throw_error = false, check_base_point=true; kwargs...) - is_vector(M::AbstractManifold, p, X, error::Symbol, check_base_point::Bool=true; kwargs...) + is_vector(M::AbstractManifold, p, X, check_base_point::Bool=true; error::Symbol=:none, kwargs...) + is_vector(M::AbstractManifold, p, X, check_base_point::Bool=true, throw_error::Boolean; kwargs...) Return whether `X` is a valid tangent vector at point `p` on the [`AbstractManifold`](@ref) `M`. Returns either `true` or `false`. -If `throw_error` is `false`, the function returns either `true` or `false`. If `throw_error` -is `true`, the function either returns `true` or throws an error. By default the function -calls [`check_vector`](@ref) and checks whether the returned +If `check_base_point` is set to true, this function also (first) calls [`is_point`](@ref) +on `p`. +Then, the function calls [`check_vector`](@ref) and checks whether the returned value is `nothing` or an error. -If `check_base_point` is true, then the point `p` will be first checked using the -[`check_point`](@ref) function. +How to report a potential error can be set using the `error=` keyword + +* `:error` - throws an error if `X` is not a tangent vector and/or `p` is not point +^ `:info` - displays the error message as an `@info` +* `:warn` - displays the error message as a `@warn`ing. +* `:none` - (default) the function just returns `true`/`false` -A more precise way can be set using a symbol as the optional parameter, where -' `:error` is the same as setting `throw_error=true` -' `:info` displays the error message as an `@info` -* `:warn` displays the error message as a `@warn`ing. +all other symbols are equivalent to `error=:none` -all other symbols are equivalent to `throw_error=false`. +The second signature is a shorthand, where `throw_error` is used for `error=:error` (`true`) +and `error=:none` (default, `false`). This case ignores the `error=` keyword. """ function is_vector( M::AbstractManifold, p, X, - throw_error = false, - check_base_point = true; + check_base_point, + throw_error::Bool + ; + error::Symbol = :none, kwargs..., ) - if check_base_point - s = is_point(M, p, throw_error; kwargs...) # if throw_error, is_point throws, - !s && return false # otherwise if not a point return false - end - mXs = check_size(M, p, X) - if mXs !== nothing - throw_error && throw(mXs) - return false - end - mXe = check_vector(M, p, X; kwargs...) - mXe === nothing && return true - throw_error && throw(mXe) - return false +return is_vector(M, p, X, check_base_point; error = throw_error ? :error : :none, kwargs...) end - function is_vector( M::AbstractManifold, p, X, - error::Symbol, check_base_point = true; + error::Symbol = :none, kwargs..., ) (error === :error) && return is_vector(M, p, X, true, check_base_point; kwargs...) @@ -754,6 +747,7 @@ function is_vector( s = "$(typeof(mXs)) with $(mXs.val)\n$(mXs.msg)" (error === :info) && @info s (error === :warn) && @warn s + (error === :error) && throw(mXs) return false end mXe = check_vector(M, p, X; kwargs...) @@ -761,6 +755,7 @@ function is_vector( s = "$(typeof(mXe)) with $(mXe.val)\n$(mXe.msg)" (error === :info) && @info s (error === :warn) && @warn s + (error === :error) && throw(mXe) return false end return true From 9cd30a27eade9425252c8b5ff5c87e5252a29a7b Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Fri, 13 Oct 2023 10:40:00 +0200 Subject: [PATCH 02/10] Unify error keyword interfaces. --- src/ManifoldsBase.jl | 24 ++++++++++-------- src/ValidationManifold.jl | 14 +++++------ src/decorator_trait.jl | 50 ++++++++++++++++--------------------- test/default_manifold.jl | 4 +-- test/power.jl | 14 +++++++++-- test/validation_manifold.jl | 9 ++++--- 6 files changed, 62 insertions(+), 53 deletions(-) diff --git a/src/ManifoldsBase.jl b/src/ManifoldsBase.jl index e81de54c..6ebc4254 100644 --- a/src/ManifoldsBase.jl +++ b/src/ManifoldsBase.jl @@ -672,7 +672,6 @@ function is_point( return is_point(M, p; error = throw_error ? :error : :none) end function is_point(M::AbstractManifold, p; error::Symbol = :none, kwargs...) - (error === :error) && return is_point(M, p, true; kwargs...) mps = check_size(M, p) if mps !== nothing s = "$(typeof(mps)) with $(mps.val)\n$(mps.msg)" @@ -721,41 +720,46 @@ function is_vector( M::AbstractManifold, p, X, - check_base_point, - throw_error::Bool - ; + check_base_point::Bool, + throw_error::Bool; error::Symbol = :none, kwargs..., ) -return is_vector(M, p, X, check_base_point; error = throw_error ? :error : :none, kwargs...) + return is_vector( + M, + p, + X, + check_base_point; + error = throw_error ? :error : :none, + kwargs..., + ) end function is_vector( M::AbstractManifold, p, X, - check_base_point = true; + check_base_point::Bool = true; error::Symbol = :none, kwargs..., ) - (error === :error) && return is_vector(M, p, X, true, check_base_point; kwargs...) if check_base_point - s = is_point(M, p, error; kwargs...) # if error, is_point throws, + s = is_point(M, p; error = error, kwargs...) # if error, is_point throws, !s && return false # otherwise if not a point return false end mXs = check_size(M, p, X) if mXs !== nothing + (error === :error) && throw(mXs) s = "$(typeof(mXs)) with $(mXs.val)\n$(mXs.msg)" (error === :info) && @info s (error === :warn) && @warn s - (error === :error) && throw(mXs) return false end mXe = check_vector(M, p, X; kwargs...) if mXe !== nothing + (error === :error) && throw(mXe) s = "$(typeof(mXe)) with $(mXe.val)\n$(mXe.msg)" (error === :info) && @info s (error === :warn) && @warn s - (error === :error) && throw(mXe) return false end return true diff --git a/src/ValidationManifold.jl b/src/ValidationManifold.jl index 17b983b4..132e7965 100644 --- a/src/ValidationManifold.jl +++ b/src/ValidationManifold.jl @@ -267,17 +267,17 @@ function inner(M::ValidationManifold, p, X, Y; kwargs...) end -function is_point(M::ValidationManifold, p, te::Bool = false; kw...) +function is_point(M::ValidationManifold, p, te::Bool; kw...) return is_point(M.manifold, array_value(p), te; kw...) end -function is_point(M::ValidationManifold, p, e::Symbol; kw...) - return is_point(M.manifold, array_value(p), e; kw...) +function is_point(M::ValidationManifold, p; kw...) + return is_point(M.manifold, array_value(p); kw...) end -function is_vector(M::ValidationManifold, p, X, te::Bool = false, cbp = true; kw...) - return is_vector(M.manifold, array_value(p), array_value(X), te, cbp; kw...) +function is_vector(M::ValidationManifold, p, X, cbp::Bool, te::Bool; kw...) + return is_vector(M.manifold, array_value(p), array_value(X), cbp, te; kw...) end -function is_vector(M::ValidationManifold, p, X, e::Symbol, cbp = true; kw...) - return is_vector(M.manifold, array_value(p), array_value(X), e, cbp; kw...) +function is_vector(M::ValidationManifold, p, X, cbp::Bool = true; kw...) + return is_vector(M.manifold, array_value(p), array_value(X), cbp; kw...) end function isapprox(M::ValidationManifold, p, q; kwargs...) diff --git a/src/decorator_trait.jl b/src/decorator_trait.jl index d46e872e..e87f49e0 100644 --- a/src/decorator_trait.jl +++ b/src/decorator_trait.jl @@ -418,16 +418,8 @@ end M::AbstractDecoratorManifold, p, X, - te::Bool = false, - cbp = true; - kwargs..., -) -@trait_function is_vector( - M::AbstractDecoratorManifold, - p, - X, - e::Symbol, - cbp = true; + cbp::Bool = true, + te::Bool = false; kwargs..., ) # EmbeddedManifold @@ -437,34 +429,33 @@ function is_vector( M::AbstractDecoratorManifold, p, X, - te::Bool = false, - cbp = true; + check_base_point::Bool = true; + error::Symbol = :none, kwargs..., ) - es = check_size(M, p, X) - if es !== nothing - te && throw(es) # error & throw? - return false - end - if cbp - # check whether p is valid before embedding the tangent vector - # throws it te=true + if check_base_point try - ep = is_point(M, p, te; kwargs...) + ep = is_point(M, p; error = error, kwargs...) !ep && return false catch e if e isa DomainError || e isa AbstractManifoldDomainError - e = ManifoldDomainError( - "$X is not a tangent vector to $p on $M because its bas epoint is not valid point on $M.", + ManifoldDomainError( + "$X is not a tangent vector to $p on $M because $p is not a valid point on $p", e, ) end throw(e) end end - # Check vector in embedding try - tv = is_vector(get_embedding(M, p), embed(M, p), embed(M, p, X), te, cbp; kwargs...) + tv = is_vector( + get_embedding(M, p), + embed(M, p), + embed(M, p, X), + cbp; + error = error, + kwargs..., + ) !tv && return false # no error thrown (deactivated) but returned false -> return false catch e if e isa DomainError || e isa AbstractManifoldDomainError @@ -476,9 +467,12 @@ function is_vector( throw(e) end # Check (additional) local stuff - mtve = check_vector(M, p, X; kwargs...) - mtve === nothing && return true - te && throw(mtve) + mXe = check_vector(M, p, X; kwargs...) + mXe === nothing && return true + (error === :error) && throw(mXe) + s = "$(typeof(mXe)) with $(mXe.val)\n$(mXe.msg)" + (error === :info) && @info s + (error === :warn) && @warn s return false end diff --git a/test/default_manifold.jl b/test/default_manifold.jl index 73e34b3f..2518a28d 100644 --- a/test/default_manifold.jl +++ b/test/default_manifold.jl @@ -852,8 +852,8 @@ Base.size(x::MatrixVectorTransport) = (size(x.m, 2),) XF = [0.0, 0.0] m = ExponentialRetraction() @test_throws DomainError is_point(M, pF, true) - @test_throws DomainError is_vector(M, p, XF, true) - @test_throws DomainError is_vector(M, pF, XF, true; check_point = true) + @test_throws DomainError is_vector(M, p, XF; error = :error) + @test_throws DomainError is_vector(M, pF, XF, true; error = :error) @test injectivity_radius(M) == Inf @test injectivity_radius(M, p) == Inf @test injectivity_radius(M, p, m) == Inf diff --git a/test/power.jl b/test/power.jl index b5494922..fef2f7f3 100644 --- a/test/power.jl +++ b/test/power.jl @@ -113,8 +113,18 @@ struct TestArrayRepresentation <: AbstractPowerRepresentation end @test is_vector(N, p, p, true) @test !is_vector(N, p, pE1) @test !is_vector(N, p, pE2) - @test_throws ComponentManifoldError is_vector(N, p, pE1, true) - @test_throws CompositeManifoldError is_vector(N, p, pE2, true) + @test_throws ComponentManifoldError is_vector( + N, + p, + pE1; + error = :error, + ) + @test_throws CompositeManifoldError is_vector( + N, + p, + pE2; + error = :error, + ) end end @testset "specific functions" begin diff --git a/test/validation_manifold.jl b/test/validation_manifold.jl index 5b2340de..2fbac976 100644 --- a/test/validation_manifold.jl +++ b/test/validation_manifold.jl @@ -36,10 +36,10 @@ end @test ManifoldsBase.check_size(A, x2) === ManifoldsBase.check_size(M, x) end @testset "is_point / is_vector error." begin - @test is_point(A, x, :error) - @test_throws DomainError is_point(A, [1, 2, 3, 4], :error) - @test is_vector(A, x, v, :error) - @test_throws DomainError is_vector(A, x, [1, 2, 3, 4], :error) + @test is_point(A, x; error = :error) + @test_throws DomainError is_point(A, [1, 2, 3, 4]; error = :error) + @test is_vector(A, x, v; error = :error) + @test_throws DomainError is_vector(A, x, [1, 2, 3, 4]; error = :error) end @testset "Types and Conversion" begin @test convert(typeof(M), A) == M @@ -157,6 +157,7 @@ end for BT in (DefaultBasis, DefaultOrthonormalBasis, DefaultOrthogonalBasis) @testset "Basis $(BT)" begin cb = BT() + println(cb) @test b == get_vectors(M, x, get_basis(A, x, cb)) v = similar(x) v2 = similar(x) From 4ffe9f672fd8fd7838ce9c09af02958024cec795 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Fri, 13 Oct 2023 11:00:56 +0200 Subject: [PATCH 03/10] friemel friemel friemel. --- NEWS.md | 4 ++ src/ValidationManifold.jl | 127 ++++++++++++++++++++---------------- src/decorator_trait.jl | 19 +++--- test/embedded_manifold.jl | 8 +-- test/validation_manifold.jl | 1 - 5 files changed, 87 insertions(+), 72 deletions(-) diff --git a/NEWS.md b/NEWS.md index c19b0027..276e5d06 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.15.0] xx/xx/xx +### Added +- A keyword to `ValidationManifold` which `error=` mode to use. + This is by default the previous `:error` mode. + ### Changed - The signature of `is_point` was changed to be consistent with `isapprox.`. diff --git a/src/ValidationManifold.jl b/src/ValidationManifold.jl index 132e7965..80f26b0b 100644 --- a/src/ValidationManifold.jl +++ b/src/ValidationManifold.jl @@ -8,9 +8,20 @@ encapsulated/stripped automatically when needed. This manifold is a decorator for a manifold, i.e. it decorates a [`AbstractManifold`](@ref) `M` with types points, vectors, and covectors. + +# Constructor + +ValidationManifold(M; error::Symbol = :error) + +Generate the Validation manifold, where `error` is used as the symbol passed to all checks. +This `:error`s by default but could also be set to `:warn` for example """ struct ValidationManifold{𝔽,M<:AbstractManifold{𝔽}} <: AbstractDecoratorManifold{𝔽} manifold::M + mode::Symbol +end +function ValidationManifold(M::AbstractManifold; error::Symbol = :error) + return ValidationManifold(M, error) end """ @@ -99,9 +110,9 @@ function convert( end function copyto!(M::ValidationManifold, q::ValidationMPoint, p::ValidationMPoint; kwargs...) - is_point(M, p, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) copyto!(M.manifold, q.value, p.value) - is_point(M, q, true; kwargs...) + is_point(M, q; error = M.mode, kwargs...) return q end function copyto!( @@ -111,35 +122,35 @@ function copyto!( X::ValidationFibreVector{TType}; kwargs..., ) where {TType} - is_point(M, p, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) copyto!(M.manifold, Y.value, p.value, X.value) return p end function distance(M::ValidationManifold, p, q; kwargs...) - is_point(M, p, true; kwargs...) - is_point(M, q, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) + is_point(M, q; error = M.mode, kwargs...) return distance(M.manifold, array_value(p), array_value(q)) end function exp(M::ValidationManifold, p, X; kwargs...) - is_point(M, p, true; kwargs...) - is_vector(M, p, X, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) + is_vector(M, p, X; error = M.mode, kwargs...) y = exp(M.manifold, array_value(p), array_value(X)) - is_point(M, y, true; kwargs...) + is_point(M, y; error = M.mode, kwargs...) return ValidationMPoint(y) end function exp!(M::ValidationManifold, q, p, X; kwargs...) - is_point(M, p, true; kwargs...) - is_vector(M, p, X, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) + is_vector(M, p, X; error = M.mode, kwargs...) exp!(M.manifold, array_value(q), array_value(p), array_value(X)) - is_point(M, q, true; kwargs...) + is_point(M, q; error = M.mode, kwargs...) return q end function get_basis(M::ValidationManifold, p, B::AbstractBasis; kwargs...) - is_point(M, p, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) Ξ = get_basis(M.manifold, array_value(p), B) bvectors = get_vectors(M, p, Ξ) N = length(bvectors) @@ -159,7 +170,7 @@ function get_basis(M::ValidationManifold, p, B::AbstractBasis; kwargs...) ), ) end - map(X -> is_vector(M, p, X, true; kwargs...), bvectors) + map(X -> is_vector(M, p, X; error = M.mode, kwargs...), bvectors) return Ξ end function get_basis( @@ -168,7 +179,7 @@ function get_basis( B::Union{AbstractOrthogonalBasis,CachedBasis{𝔽,<:AbstractOrthogonalBasis{𝔽}}}; kwargs..., ) where {𝔽} - is_point(M, p, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) Ξ = invoke(get_basis, Tuple{ValidationManifold,Any,AbstractBasis}, M, p, B; kwargs...) bvectors = get_vectors(M, p, Ξ) N = length(bvectors) @@ -192,7 +203,7 @@ function get_basis( B::Union{AbstractOrthonormalBasis,CachedBasis{𝔽,<:AbstractOrthonormalBasis{𝔽}}}; kwargs..., ) where {𝔽} - is_point(M, p, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) get_basis_invoke_types = Tuple{ ValidationManifold, Any, @@ -214,19 +225,19 @@ function get_basis( end function get_coordinates(M::ValidationManifold, p, X, B::AbstractBasis; kwargs...) - is_point(M, p, true; kwargs...) - is_vector(M, p, X, true; kwargs...) + is_point(M, p; error = :error, kwargs...) + is_vector(M, p, X; error = :error, kwargs...) return get_coordinates(M.manifold, p, X, B) end function get_coordinates!(M::ValidationManifold, Y, p, X, B::AbstractBasis; kwargs...) - is_vector(M, p, X, true; kwargs...) + is_vector(M, p, X; error = M.mode, kwargs...) get_coordinates!(M.manifold, Y, p, X, B) return Y end function get_vector(M::ValidationManifold, p, X, B::AbstractBasis; kwargs...) - is_point(M, p, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) size(X) == (manifold_dimension(M),) || error("Incorrect size of coefficient vector X") Y = get_vector(M.manifold, p, X, B) size(Y) == representation_size(M) || error("Incorrect size of tangent vector Y") @@ -234,7 +245,7 @@ function get_vector(M::ValidationManifold, p, X, B::AbstractBasis; kwargs...) end function get_vector!(M::ValidationManifold, Y, p, X, B::AbstractBasis; kwargs...) - is_point(M, p, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) size(X) == (manifold_dimension(M),) || error("Incorrect size of coefficient vector X") get_vector!(M.manifold, Y, p, X, B) size(Y) == representation_size(M) || error("Incorrect size of tangent vector Y") @@ -246,7 +257,7 @@ function injectivity_radius(M::ValidationManifold, method::AbstractRetractionMet return injectivity_radius(M.manifold, method) end function injectivity_radius(M::ValidationManifold, p; kwargs...) - is_point(M, p, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) return injectivity_radius(M.manifold, array_value(p)) end function injectivity_radius( @@ -255,14 +266,14 @@ function injectivity_radius( method::AbstractRetractionMethod; kwargs..., ) - is_point(M, p, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) return injectivity_radius(M.manifold, array_value(p), method) end function inner(M::ValidationManifold, p, X, Y; kwargs...) - is_point(M, p, true; kwargs...) - is_vector(M, p, X, true; kwargs...) - is_vector(M, p, Y, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) + is_vector(M, p, X; error = M.mode, kwargs...) + is_vector(M, p, Y; error = M.mode, kwargs...) return inner(M.manifold, array_value(p), array_value(X), array_value(Y)) end @@ -281,46 +292,46 @@ function is_vector(M::ValidationManifold, p, X, cbp::Bool = true; kw...) end function isapprox(M::ValidationManifold, p, q; kwargs...) - is_point(M, p, true; kwargs...) - is_point(M, q, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) + is_point(M, q; error = M.mode, kwargs...) return isapprox(M.manifold, array_value(p), array_value(q); kwargs...) end function isapprox(M::ValidationManifold, p, X, Y; kwargs...) - is_point(M, p, true; kwargs...) - is_vector(M, p, X, true; kwargs...) - is_vector(M, p, Y, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) + is_vector(M, p, X; error = M.mode, kwargs...) + is_vector(M, p, Y; error = M.mode, kwargs...) return isapprox(M.manifold, array_value(p), array_value(X), array_value(Y); kwargs...) end function log(M::ValidationManifold, p, q; kwargs...) - is_point(M, p, true; kwargs...) - is_point(M, q, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) + is_point(M, q; error = M.mode, kwargs...) X = log(M.manifold, array_value(p), array_value(q)) - is_vector(M, p, X, true; kwargs...) + is_vector(M, p, X; error = M.mode, kwargs...) return ValidationTVector(X) end function log!(M::ValidationManifold, X, p, q; kwargs...) - is_point(M, p, true; kwargs...) - is_point(M, q, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) + is_point(M, q; error = M.mode, kwargs...) log!(M.manifold, array_value(X), array_value(p), array_value(q)) - is_vector(M, p, X, true; kwargs...) + is_vector(M, p, X; error = M.mode, kwargs...) return X end function mid_point(M::ValidationManifold, p1, p2; kwargs...) - is_point(M, p1, true; kwargs...) - is_point(M, p2, true; kwargs...) + is_point(M, p1; error = M.mode, kwargs...) + is_point(M, p2; error = M.mode, kwargs...) q = mid_point(M.manifold, array_value(p1), array_value(p2)) - is_point(M, q, true; kwargs...) + is_point(M, q; error = M.mode, kwargs...) return q end function mid_point!(M::ValidationManifold, q, p1, p2; kwargs...) - is_point(M, p1, true; kwargs...) - is_point(M, p2, true; kwargs...) + is_point(M, p1; error = M.mode, kwargs...) + is_point(M, p2; error = M.mode, kwargs...) mid_point!(M.manifold, array_value(q), array_value(p1), array_value(p2)) - is_point(M, q, true; kwargs...) + is_point(M, q; error = M.mode, kwargs...) return q end @@ -328,9 +339,9 @@ number_eltype(::Type{ValidationMPoint{V}}) where {V} = number_eltype(V) number_eltype(::Type{ValidationFibreVector{TType,V}}) where {TType,V} = number_eltype(V) function project!(M::ValidationManifold, Y, p, X; kwargs...) - is_point(M, p, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) project!(M.manifold, array_value(Y), array_value(p), array_value(X)) - is_vector(M, p, Y, true; kwargs...) + is_vector(M, p, Y; error = M.mode, kwargs...) return Y end @@ -342,9 +353,9 @@ function vector_transport_along( m::AbstractVectorTransportMethod; kwargs..., ) - is_vector(M, p, X, true; kwargs...) + is_vector(M, p, X; error = M.mode, kwargs...) Y = vector_transport_along(M.manifold, array_value(p), array_value(X), c, m) - is_vector(M, c[end], Y, true; kwargs...) + is_vector(M, c[end], Y; error = M.mode, kwargs...) return Y end @@ -357,7 +368,7 @@ function vector_transport_along!( m::AbstractVectorTransportMethod; kwargs..., ) - is_vector(M, p, X, true; kwargs...) + is_vector(M, p, X; error = M.mode, kwargs...) vector_transport_along!( M.manifold, array_value(Y), @@ -366,7 +377,7 @@ function vector_transport_along!( c, m, ) - is_vector(M, c[end], Y, true; kwargs...) + is_vector(M, c[end], Y; error = M.mode, kwargs...) return Y end @@ -378,10 +389,10 @@ function vector_transport_to( m::AbstractVectorTransportMethod; kwargs..., ) - is_point(M, q, true; kwargs...) - is_vector(M, p, X, true; kwargs...) + is_point(M, q; error = M.mode, kwargs...) + is_vector(M, p, X; error = M.mode, kwargs...) Y = vector_transport_to(M.manifold, array_value(p), array_value(X), array_value(q), m) - is_vector(M, q, Y, true; kwargs...) + is_vector(M, q, Y; error = M.mode, kwargs...) return Y end function vector_transport_to!( @@ -393,8 +404,8 @@ function vector_transport_to!( m::AbstractVectorTransportMethod; kwargs..., ) - is_point(M, q, true; kwargs...) - is_vector(M, p, X, true; kwargs...) + is_point(M, q; error = M.mode, kwargs...) + is_vector(M, p, X; error = M.mode, kwargs...) vector_transport_to!( M.manifold, array_value(Y), @@ -403,20 +414,20 @@ function vector_transport_to!( array_value(q), m, ) - is_vector(M, q, Y, true; kwargs...) + is_vector(M, q, Y; error = M.mode, kwargs...) return Y end function zero_vector(M::ValidationManifold, p; kwargs...) - is_point(M, p, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) w = zero_vector(M.manifold, array_value(p)) - is_vector(M, p, w, true; kwargs...) + is_vector(M, p, w; error = M.mode, kwargs...) return w end function zero_vector!(M::ValidationManifold, X, p; kwargs...) - is_point(M, p, true; kwargs...) + is_point(M, p; error = M.mode, kwargs...) zero_vector!(M.manifold, array_value(X), array_value(p); kwargs...) - is_vector(M, p, X, true; kwargs...) + is_vector(M, p, X; error = M.mode, kwargs...) return X end diff --git a/src/decorator_trait.jl b/src/decorator_trait.jl index e87f49e0..7bc54104 100644 --- a/src/decorator_trait.jl +++ b/src/decorator_trait.jl @@ -414,14 +414,7 @@ function is_point( end # Introduce Deco Trait | automatic foward | fallback -@trait_function is_vector( - M::AbstractDecoratorManifold, - p, - X, - cbp::Bool = true, - te::Bool = false; - kwargs..., -) +@trait_function is_vector(M::AbstractDecoratorManifold, p, X, cbp::Bool = true; kwargs...) # EmbeddedManifold # I am not yet sure how to properly document this embedding behaviour here in a docstring. function is_vector( @@ -433,6 +426,14 @@ function is_vector( error::Symbol = :none, kwargs..., ) + es = check_size(M, p, X) + if es !== nothing + (error === :error) && throw(es) + s = "$(typeof(es)) with $(es.val)\n$(es.msg)" + (error === :info) && @info s + (error === :warn) && @warn s + return false + end if check_base_point try ep = is_point(M, p; error = error, kwargs...) @@ -452,7 +453,7 @@ function is_vector( get_embedding(M, p), embed(M, p), embed(M, p, X), - cbp; + check_base_point; error = error, kwargs..., ) diff --git a/test/embedded_manifold.jl b/test/embedded_manifold.jl index 8b90a9af..2214f8fc 100644 --- a/test/embedded_manifold.jl +++ b/test/embedded_manifold.jl @@ -216,14 +216,14 @@ ManifoldsBase.decorated_manifold(::FallbackManifold) = DefaultManifold(3) @test !is_point(M, [-1 0 0]) # right size but <0 1st @test_throws DomainError is_point(M, [-1 0 0], true) # right size but <0 1st @test !is_vector(M, [1 0 0], [1]) # right point, wrong size vector - @test_throws ManifoldDomainError is_vector(M, [1 0 0], [1], true) + @test_throws ManifoldDomainError is_vector(M, [1 0 0], [1]; error = :error) @test !is_vector(M, [1 0 0], [1]) - @test_throws DomainError is_vector(M, [1 0 0], [-1 0 0], true) # right point, vec 1st <0 + @test_throws DomainError is_vector(M, [1 0 0], [-1 0 0]; error = :error) # right point, vec 1st <0 @test !is_vector(M, [1 0 0], [-1 0 0]) @test is_vector(M, [1 0 0], [1 0 1], true) @test !is_vector(M, [-1, 0, 0], [0, 0, 0]) - @test_throws ManifoldDomainError is_vector(M, [-1, 0, 0], [0, 0, 0], true) - @test_throws DomainError is_vector(M, [1, 0, 0], [-1, 0, 0], true) + @test_throws ManifoldDomainError is_vector(M, [-1, 0, 0], [0, 0, 0]; error = :error) + @test_throws DomainError is_vector(M, [1, 0, 0], [-1, 0, 0]; error = :error) @test !is_vector(M, [-1, 0, 0], [0, 0, 0]) @test !is_vector(M, [1, 0, 0], [-1, 0, 0]) # check manifold domain error from embedding to obtain ManifoldDomainErrors diff --git a/test/validation_manifold.jl b/test/validation_manifold.jl index 2fbac976..0dbf97a7 100644 --- a/test/validation_manifold.jl +++ b/test/validation_manifold.jl @@ -157,7 +157,6 @@ end for BT in (DefaultBasis, DefaultOrthonormalBasis, DefaultOrthogonalBasis) @testset "Basis $(BT)" begin cb = BT() - println(cb) @test b == get_vectors(M, x, get_basis(A, x, cb)) v = similar(x) v2 = similar(x) From 957dfb7040e8b443bbefbedb66c0ad228620d57b Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Fri, 13 Oct 2023 11:28:41 +0200 Subject: [PATCH 04/10] Finish adapting tests. --- Project.toml | 2 +- src/ManifoldsBase.jl | 32 +++++++++++++++++++------------ src/decorator_trait.jl | 27 ++++++++++++++++---------- test/domain_errors.jl | 40 +++++++++++++++++++-------------------- test/embedded_manifold.jl | 6 +++--- 5 files changed, 61 insertions(+), 46 deletions(-) diff --git a/Project.toml b/Project.toml index 33e92c23..5f6fa20c 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ManifoldsBase" uuid = "3362f125-f0bb-47a3-aa74-596ffd7ef2fb" authors = ["Seth Axen ", "Mateusz Baran ", "Ronny Bergmann ", "Antoine Levitt "] -version = "0.14.12" +version = "0.15.0" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" diff --git a/src/ManifoldsBase.jl b/src/ManifoldsBase.jl index 6ebc4254..5d805a12 100644 --- a/src/ManifoldsBase.jl +++ b/src/ManifoldsBase.jl @@ -674,18 +674,22 @@ end function is_point(M::AbstractManifold, p; error::Symbol = :none, kwargs...) mps = check_size(M, p) if mps !== nothing - s = "$(typeof(mps)) with $(mps.val)\n$(mps.msg)" - (error === :info) && @info s - (error === :warn) && @warn s (error === :error) && throw(mps) + if (error === :info) || (error === :warn) + s = "$(typeof(mps)) with $(mps.val)\n$(mps.msg)" + (error === :info) && @info s + (error === :warn) && @warn s + end return false end mpe = check_point(M, p; kwargs...) if mpe !== nothing - s = "$(typeof(mpe)) with $(mpe.val)\n$(mpe.msg)" - (error === :info) && @info s - (error === :warn) && @warn s (error === :error) && throw(mpe) + if (error === :info) || (error === :warn) + s = "$(typeof(mpe)) with $(mpe.val)\n$(mpe.msg)" + (error === :info) && @info s + (error === :warn) && @warn s + end return false end return true @@ -749,17 +753,21 @@ function is_vector( mXs = check_size(M, p, X) if mXs !== nothing (error === :error) && throw(mXs) - s = "$(typeof(mXs)) with $(mXs.val)\n$(mXs.msg)" - (error === :info) && @info s - (error === :warn) && @warn s + if (error === :info) || (error === :warn) + s = "$(typeof(mXs)) with $(mXs.val)\n$(mXs.msg)" + (error === :info) && @info s + (error === :warn) && @warn s + end return false end mXe = check_vector(M, p, X; kwargs...) if mXe !== nothing (error === :error) && throw(mXe) - s = "$(typeof(mXe)) with $(mXe.val)\n$(mXe.msg)" - (error === :info) && @info s - (error === :warn) && @warn s + if (error === :info) || (error === :warn) + s = "$(typeof(mXe)) with $(mXe.val)\n$(mXe.msg)" + (error === :info) && @info s + (error === :warn) && @warn s + end return false end return true diff --git a/src/decorator_trait.jl b/src/decorator_trait.jl index 7bc54104..6ea94fdd 100644 --- a/src/decorator_trait.jl +++ b/src/decorator_trait.jl @@ -379,24 +379,26 @@ end @trait_function is_flat(M::AbstractDecoratorManifold) # Introduce Deco Trait | automatic foward | fallback -@trait_function is_point(M::AbstractDecoratorManifold, p, te::Bool = false; kwargs...) -@trait_function is_point(M::AbstractDecoratorManifold, p, e::Symbol; kwargs...) +@trait_function is_point(M::AbstractDecoratorManifold, p; kwargs...) # Embedded function is_point( ::TraitList{IsEmbeddedManifold}, M::AbstractDecoratorManifold, - p, - te::Bool = false; + p; + error::Symbol = :none, kwargs..., ) # to be safe check_size first es = check_size(M, p) if es !== nothing - te && throw(es) + (error === :error) && throw(es) + s = "$(typeof(es)) with $(es)" + (error === :info) && @info s + (error === :warn) && @warn s return false end try - pt = is_point(get_embedding(M, p), embed(M, p), te; kwargs...) + pt = is_point(get_embedding(M, p), embed(M, p); error = error, kwargs...) !pt && return false # no error thrown (deactivated) but returned false -> return false catch e if e isa DomainError || e isa AbstractManifoldDomainError @@ -408,9 +410,14 @@ function is_point( throw(e) #an error occured that we do not handle ourselves -> rethrow. end mpe = check_point(M, p; kwargs...) - mpe === nothing && return true - te && throw(mpe) - return false + if mpe !== nothing + s = "$(typeof(mpe)) with $(mpe.val)\n$(mpe.msg)" + (error === :info) && @info s + (error === :warn) && @warn s + (error === :error) && throw(mpe) + return false + end + return true end # Introduce Deco Trait | automatic foward | fallback @@ -429,7 +436,7 @@ function is_vector( es = check_size(M, p, X) if es !== nothing (error === :error) && throw(es) - s = "$(typeof(es)) with $(es.val)\n$(es.msg)" + s = "$(typeof(es)) with $(es)" (error === :info) && @info s (error === :warn) && @warn s return false diff --git a/test/domain_errors.jl b/test/domain_errors.jl index ca049b28..7e23e5fc 100644 --- a/test/domain_errors.jl +++ b/test/domain_errors.jl @@ -36,38 +36,38 @@ end @test !is_point(M, [-1, 1]) @test !is_point(M, [1, 1, 1]) # checksize fails @test_throws DomainError is_point(M, [-1, 1, 1], true) # checksize errors - @test_throws DomainError is_point(M, [-1, 1, 1], :error) # checksize errors + @test_throws DomainError is_point(M, [-1, 1, 1]; error = :error) # checksize errors cs = "DomainError with (3,)\nsize [-1, 1, 1] not (2,)" - @test_logs (:info, cs) is_point(M, [-1, 1, 1], :info) - @test_logs (:warn, cs) is_point(M, [-1, 1, 1], :warn) + @test_logs (:info, cs) is_point(M, [-1, 1, 1]; error = :info) + @test_logs (:warn, cs) is_point(M, [-1, 1, 1]; error = :warn) @test is_point(M, [1, 1]) - @test is_point(M, [1, 1], :error) + @test is_point(M, [1, 1]; error = :error) @test_throws DomainError is_point(M, [-1, 1], true) - @test_throws DomainError is_point(M, [-1, 1], :error) + @test_throws DomainError is_point(M, [-1, 1]; error = :error) ps = "DomainError with [-1, 1]\n<0" - @test_logs (:info, ps) is_point(M, [-1, 1], :info) - @test_logs (:warn, ps) is_point(M, [-1, 1], :warn) + @test_logs (:info, ps) is_point(M, [-1, 1]; error = :info) + @test_logs (:warn, ps) is_point(M, [-1, 1]; error = :warn) @test isa(ManifoldsBase.check_vector(M, [1, 1], [-1, 1]), DomainError) @test ManifoldsBase.check_vector(M, [1, 1], [1, 1]) === nothing @test !is_vector(M, [1, 1], [-1, 1]) @test !is_vector(M, [1, 1], [1, 1, 1]) - @test_throws DomainError is_vector(M, [1, 1], [-1, 1, 1], true) - @test_throws DomainError is_vector(M, [1, 1], [-1, 1, 1], :error) + @test_throws DomainError is_vector(M, [1, 1], [-1, 1, 1], false, true) + @test_throws DomainError is_vector(M, [1, 1], [-1, 1, 1]; error = :error) vs = "DomainError with (3,)\nsize [-1, 1, 1] not (2,)" - @test_logs (:info, vs) is_vector(M, [1, 1], [-1, 1, 1], :info) - @test_logs (:warn, vs) is_vector(M, [1, 1], [-1, 1, 1], :warn) - @test !is_vector(M, [1, 1, 1], [1, 1, 1], false, true) + @test_logs (:info, vs) is_vector(M, [1, 1], [-1, 1, 1]; error = :info) + @test_logs (:warn, vs) is_vector(M, [1, 1], [-1, 1, 1]; error = :warn) + @test !is_vector(M, [1, 1, 1], [1, 1, 1], false) @test_throws DomainError is_vector(M, [1, 1, 1], [1, 1], true, true) - @test_throws DomainError is_vector(M, [1, 1, 1], [1, 1], :error, true) + @test_throws DomainError is_vector(M, [1, 1, 1], [1, 1], true; error = :error) ps2 = "DomainError with (3,)\nsize [1, 1, 1] not (2,)" - @test_logs (:info, ps2) is_vector(M, [1, 1, 1], [1, 1], :info, true) - @test_logs (:warn, ps2) is_vector(M, [1, 1, 1], [1, 1], :warn, true) + @test_logs (:info, ps2) is_vector(M, [1, 1, 1], [1, 1], true; error = :info) + @test_logs (:warn, ps2) is_vector(M, [1, 1, 1], [1, 1], true; error = :warn) @test is_vector(M, [1, 1], [1, 1]) - @test is_vector(M, [1, 1], [1, 1], :none) #default just true/false - @test_throws DomainError is_vector(M, [1, 1], [-1, 1], true) - @test_throws DomainError is_vector(M, [1, 1], [-1, 1], :error, true) + @test is_vector(M, [1, 1], [1, 1]; error = :none) + @test_throws DomainError is_vector(M, [1, 1], [-1, 1]; error = :error) + @test_throws DomainError is_vector(M, [1, 1], [-1, 1], true; error = :error) ps3 = "DomainError with [-1, 1]\n<0" - @test_logs (:info, ps3) is_vector(M, [1, 1], [-1, 1], :info, true) - @test_logs (:warn, ps3) is_vector(M, [1, 1], [-1, 1], :warn, true) + @test_logs (:info, ps3) is_vector(M, [1, 1], [-1, 1], true; error = :info) + @test_logs (:warn, ps3) is_vector(M, [1, 1], [-1, 1], true; error = :warn) end diff --git a/test/embedded_manifold.jl b/test/embedded_manifold.jl index 2214f8fc..a9b6b0e3 100644 --- a/test/embedded_manifold.jl +++ b/test/embedded_manifold.jl @@ -222,15 +222,15 @@ ManifoldsBase.decorated_manifold(::FallbackManifold) = DefaultManifold(3) @test !is_vector(M, [1 0 0], [-1 0 0]) @test is_vector(M, [1 0 0], [1 0 1], true) @test !is_vector(M, [-1, 0, 0], [0, 0, 0]) - @test_throws ManifoldDomainError is_vector(M, [-1, 0, 0], [0, 0, 0]; error = :error) + @test_throws DomainError is_vector(M, [-1, 0, 0], [0, 0, 0]; error = :error) @test_throws DomainError is_vector(M, [1, 0, 0], [-1, 0, 0]; error = :error) @test !is_vector(M, [-1, 0, 0], [0, 0, 0]) @test !is_vector(M, [1, 0, 0], [-1, 0, 0]) # check manifold domain error from embedding to obtain ManifoldDomainErrors @test !is_point(N, [0, 0, 0]) - @test_throws ManifoldDomainError is_point(N, [0, 0, 0], true) + @test_throws ManifoldDomainError is_point(N, [0, 0, 0]; error = :error) @test !is_vector(N, [1, 1, 0], [0, 0, 0]) - @test_throws ManifoldDomainError is_vector(N, [1, 1, 0], [0, 0, 0], true) + @test_throws ManifoldDomainError is_vector(N, [1, 1, 0], [0, 0, 0]; error = :error) p = [1.0 1.0 0.0] q = [1.0 0.0 0.0] X = q - p From e693c84edb9df771ccf41fee2bddba416199fd53 Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Fri, 13 Oct 2023 11:44:25 +0200 Subject: [PATCH 05/10] Remove two cases, that are now already covered in the default. --- src/ValidationManifold.jl | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/ValidationManifold.jl b/src/ValidationManifold.jl index 80f26b0b..322a490a 100644 --- a/src/ValidationManifold.jl +++ b/src/ValidationManifold.jl @@ -277,16 +277,9 @@ function inner(M::ValidationManifold, p, X, Y; kwargs...) return inner(M.manifold, array_value(p), array_value(X), array_value(Y)) end - -function is_point(M::ValidationManifold, p, te::Bool; kw...) - return is_point(M.manifold, array_value(p), te; kw...) -end function is_point(M::ValidationManifold, p; kw...) return is_point(M.manifold, array_value(p); kw...) end -function is_vector(M::ValidationManifold, p, X, cbp::Bool, te::Bool; kw...) - return is_vector(M.manifold, array_value(p), array_value(X), cbp, te; kw...) -end function is_vector(M::ValidationManifold, p, X, cbp::Bool = true; kw...) return is_vector(M.manifold, array_value(p), array_value(X), cbp; kw...) end From b651c513264779b6f5efd746618424daac077ffb Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Fri, 13 Oct 2023 11:56:57 +0200 Subject: [PATCH 06/10] Adapt docs (though the two errors on 1.0 are resolved in another PR). --- docs/Project.toml | 4 ++-- docs/make.jl | 1 + tutorials/Project.toml | 4 +--- tutorials/implement-a-manifold.qmd | 14 +++++++------- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index 9629fb2c..7945e652 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -5,5 +5,5 @@ ManifoldsBase = "3362f125-f0bb-47a3-aa74-596ffd7ef2fb" [compat] CondaPkg = "0.2" -Documenter = "0.27" -ManifoldsBase = "0.14" +Documenter = "1" +ManifoldsBase = "0.15" diff --git a/docs/make.jl b/docs/make.jl index bdfc8d99..a42759f4 100755 --- a/docs/make.jl +++ b/docs/make.jl @@ -21,6 +21,7 @@ if "--quarto" ∈ ARGS tutorials_folder = (@__DIR__) * "/../tutorials" # instantiate the tutorials environment if necessary Pkg.activate(tutorials_folder) + Pkg.develop(PackageSpec(; path = (@__DIR__) * "/../")) Pkg.resolve() Pkg.instantiate() Pkg.build("IJulia") # build IJulia to the right version. diff --git a/tutorials/Project.toml b/tutorials/Project.toml index 53127daa..f7d96b90 100644 --- a/tutorials/Project.toml +++ b/tutorials/Project.toml @@ -1,11 +1,9 @@ [deps] IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" -Manifolds = "1cead3c2-87b3-11e9-0ccd-23c62b72b94e" ManifoldsBase = "3362f125-f0bb-47a3-aa74-596ffd7ef2fb" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" [compat] IJulia = "1" -Manifolds = "0.8.46" -ManifoldsBase = "0.14.5" +ManifoldsBase = "0.15" Plots = "1.38" diff --git a/tutorials/implement-a-manifold.qmd b/tutorials/implement-a-manifold.qmd index 5da80cd1..1c724413 100644 --- a/tutorials/implement-a-manifold.qmd +++ b/tutorials/implement-a-manifold.qmd @@ -149,9 +149,9 @@ end And we can directly test the function. To see all 3 failing ones, we switch from errors to warnings in the check ```{julia} -is_point(M, [1.5, 0.0], :warn) # wrong size -is_point(M, [1.0, 0.0, 0.0], :warn) # wrong norm -is_point(M, [1.5, 0.0, 0.0], :warn) # on the manifold, returns true +is_point(M, [1.5, 0.0], error=:warn) # wrong size +is_point(M, [1.0, 0.0, 0.0], error=:warn) # wrong norm +is_point(M, [1.5, 0.0, 0.0], error=:warn) # on the manifold, returns true ``` similarly for vectors, we just have to implement the orthogonality check. @@ -174,10 +174,10 @@ and again, the high level interface can be used to display warning for vectors n activate a check for the point using the last positional argument ```{julia} -is_vector(M, [1.5, 0.0, 0.0], [0.0, 1.0], :warn) # wrong size -is_vector(M, [1.5, 0.0, 0.0], [1.0, 1.0, 0.0], :warn) # not orthogonal norm -is_vector(M, [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], :warn, true) # point not valid -is_vector(M, [1.5, 0.0, 0.0], [0.0, 1.0, 0.0], :warn, true) # returns true +is_vector(M, [1.5, 0.0, 0.0], [0.0, 1.0]; error=:warn) # wrong size +is_vector(M, [1.5, 0.0, 0.0], [1.0, 1.0, 0.0]; error=:warn) # not orthogonal norm +is_vector(M, [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], true; error=:warn) # point not valid +is_vector(M, [1.5, 0.0, 0.0], [0.0, 1.0, 0.0], true; error=:warn) # returns true ``` From 27781c5607d99ae95e6c3936e82c283c9641468f Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Mon, 16 Oct 2023 18:09:26 +0200 Subject: [PATCH 07/10] fix 2 tests from the other PRs. --- test/product_manifold.jl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/product_manifold.jl b/test/product_manifold.jl index 3f124c5c..10ced9b9 100644 --- a/test/product_manifold.jl +++ b/test/product_manifold.jl @@ -47,7 +47,13 @@ include("test_sphere.jl") # test that arrays are not points @test_throws DomainError is_point(M, [1, 2], true) @test ManifoldsBase.check_point(M, [1, 2]) isa DomainError - @test_throws DomainError is_vector(M, 1, [1, 2], true; check_base_point = false) + @test_throws DomainError is_vector( + M, + 1, + [1, 2]; + error = :error, + check_base_point = false, + ) @test ManifoldsBase.check_vector(M, 1, [1, 2]; check_base_point = false) isa DomainError #default fallbacks for check_size, Product not working with Arrays @test ManifoldsBase.check_size(M, zeros(2)) isa DomainError @@ -247,8 +253,8 @@ include("test_sphere.jl") Xf = ArrayPartition(X1, p2) @test is_point(Mpr, p, true) @test_throws CompositeManifoldError is_point(Mpr, X, true) - @test_throws ComponentManifoldError is_vector(Mpr, pf, X, true) - @test_throws ComponentManifoldError is_vector(Mpr, p, Xf, true) + @test_throws ComponentManifoldError is_vector(Mpr, pf, X; error = :error) + @test_throws ComponentManifoldError is_vector(Mpr, p, Xf; error = :error) end end From 3ea076467c9f8af7e10b03e6f1741cee8b50940f Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Mon, 16 Oct 2023 18:27:29 +0200 Subject: [PATCH 08/10] Update ValidationManifold.jl Co-authored-by: Mateusz Baran --- src/ValidationManifold.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ValidationManifold.jl b/src/ValidationManifold.jl index 322a490a..417db8d1 100644 --- a/src/ValidationManifold.jl +++ b/src/ValidationManifold.jl @@ -11,7 +11,7 @@ with types points, vectors, and covectors. # Constructor -ValidationManifold(M; error::Symbol = :error) + ValidationManifold(M::AbstractManifold; error::Symbol = :error) Generate the Validation manifold, where `error` is used as the symbol passed to all checks. This `:error`s by default but could also be set to `:warn` for example From 54beb5900fddaf4e649aa206d042aa4be54b047a Mon Sep 17 00:00:00 2001 From: Ronny Bergmann Date: Tue, 17 Oct 2023 18:30:21 +0200 Subject: [PATCH 09/10] Simplify a few lines. --- src/ManifoldsBase.jl | 6 +++--- src/decorator_trait.jl | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ManifoldsBase.jl b/src/ManifoldsBase.jl index c04a098e..7b527b50 100644 --- a/src/ManifoldsBase.jl +++ b/src/ManifoldsBase.jl @@ -670,7 +670,7 @@ function is_point( error::Symbol = :none, kwargs..., ) - return is_point(M, p; error = throw_error ? :error : :none) + return is_point(M, p; error = throw_error ? :error : :none, kwargs...) end function is_point(M::AbstractManifold, p; error::Symbol = :none, kwargs...) mps = check_size(M, p) @@ -748,8 +748,8 @@ function is_vector( kwargs..., ) if check_base_point - s = is_point(M, p; error = error, kwargs...) # if error, is_point throws, - !s && return false # otherwise if not a point return false + # if error, is_point throws, otherwise if not a point return false + !is_point(M, p; error = error, kwargs...) && return false end mXs = check_size(M, p, X) if mXs !== nothing diff --git a/src/decorator_trait.jl b/src/decorator_trait.jl index 6ea94fdd..e916660b 100644 --- a/src/decorator_trait.jl +++ b/src/decorator_trait.jl @@ -411,10 +411,10 @@ function is_point( end mpe = check_point(M, p; kwargs...) if mpe !== nothing + (error === :error) && throw(mpe) s = "$(typeof(mpe)) with $(mpe.val)\n$(mpe.msg)" (error === :info) && @info s (error === :warn) && @warn s - (error === :error) && throw(mpe) return false end return true From 4704c8aa4e6fdfae2c5138030f45fe95a71ad778 Mon Sep 17 00:00:00 2001 From: Mateusz Baran Date: Tue, 17 Oct 2023 19:24:44 +0200 Subject: [PATCH 10/10] improve docstring --- src/ManifoldsBase.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ManifoldsBase.jl b/src/ManifoldsBase.jl index 7b527b50..41eb275c 100644 --- a/src/ManifoldsBase.jl +++ b/src/ManifoldsBase.jl @@ -543,7 +543,7 @@ tensor is everywhere zero. is_flat(M::AbstractManifold) """ - isapprox(M::AbstractManifold, p, q; error::Symbol=none, kwargs...) + isapprox(M::AbstractManifold, p, q; error::Symbol=:none, kwargs...) Check if points `p` and `q` from [`AbstractManifold`](@ref) `M` are approximately equal.