A Test suite

The submodule Manifolds.Test provides functions to test mathematical properties of functions defined for a manifold according to the API from ManifoldsBase.jl.

Manifolds.Test โ€” Module
Manifolds.Test

The module Manifolds.Test contains functions to test functions from Manifolds.jl. Most functionality is provided only when Test.jl is loaded as well, i.e. populated with methods by the extension.

The test functions provided are meant to verify that the defined functions on a specific manifold behave as expected, for example that an allocating and in-place version of a function give the same result, or that for example the exponential map computes a point on the manifold, and calling the logarithmic map on the result yields the original tangent vector again, for tangent vectors within the injectivity radius.

In general for every function defined in the API for manifolds, this module shall provide a test function with

  • the same name prefixed by test_
  • the same function arguments as the original function
  • keyword arguments to control which tests to perform
source

The main function is

Manifolds.Test.test_manifold โ€” Function
test_manifold(G::AbstractManifold, properties::Dict, expectations::Dict)

Test the AbstractManifold $\mathcal M$ based on a Dict of properties and a Dict of expectations.

Three functions are expected to be defined (without explicitly being passed in the properties): is_point(M, p), is_vector(M, p, X), and isapprox(M, p, q) / isapprox(M, p, X, Y), since these are essential for verifying results.

From the following properties, the two often expected to be defined are :Points and :Vectors, which should contain at least two points and two tangent vectors, respectively.

Possible properties are

  • :Aliased is a boolean (same as :Mutating by default) whether to test the mutating variants with aliased input
  • :Atlases is a vector of atlases, which can be used to test chart related functions like get_parameters and get_point at each of the :Points, each in the chart selected by get_chart_index. Transition maps are tested from the chart of the first to the chart of the last point. Since atlases usually differ in which functions they implement, call test_manifold separately for atlases with different sets of :Functions.
  • :Bases is a vector of bases, which can be used to test basis related functions, one basis for each entry in :Coordinates
  • :Covectors is a vector of covectors, which should be in the cotangent space of the correspondinig point entry in :Points
  • :Coordinates is a vector of coordinates, which can be used to test coordinate related functions, one coordinate vector for each entry in :Bases
  • :EmbeddedPoints is a vector of points in the embedding space of M, to test project
  • :EmbeddedVectors is a vector of tangent vectors in the embedding space of M, to test project
  • :Functions is a vector of all defined functions for M note a test is activated by the function (like exp), adding the mutating function (like exp!) overwrites the global default (see :Mutating) to true.
  • :GeodesicMaxTime is a real number indicating the time parameter to use when testing geodesic
  • :GeodesicSamples is an integer indicating the number of samples to use when testing geodesic and shortest_geodesic (defaults to 100)
  • :InvalidPoints is a vector of points that are not on M, e.g. to test is_point
  • :InvalidVectors is a vector of tangent vectors that are not in the tangent space of the first point from :Points
  • :InverseRetractionMethods is a vector of inverse retraction methods to test on M these should have the same order as :RetractionMethods (use missing for skipping one)
  • :Mutating is a boolean (true by default) whether to test the mutating variants of functions or not. when setting this to false, you can still activate single functions mutation checks by adding the mutating function to :Functions
  • :Name is a name of the test. If not provided, defaults to "$M"
  • :NormalVectors is a vector of normal vectors, where each should be in the normal space of the corresponding point entries in :Points
  • :OtherMetrics is a vector of metrics that are not the default metric of M, to test is_default_metric
  • :Points is a vector of at least 2 points on M, which should not be the same point
  • :RetractionMethods is a vector of retraction methods to test on M these should have the same order as :InverseRetractionMethods (use missing for skipping one)
  • :Rng is a random number generator to use for generating random points/vectors if needed
  • :Seed is a seed to use for generating random points/vectors if needed
  • :ShortestGeodesicTime is a real number indicating the time parameter to use when testing shortest_geodesic (defaults to 0.5)
  • :Vectors is a vector of at least 2 tangent vectors, which should be in the tangent space of the correspondinig point entries in :Points
  • :SecondVector is a single second vector in the tangent space of the first entry of :Points, for example to test inner
  • :VectorTransportMethods is a vector of vector transport methods to test on M
  • :TestVectorArithmetic is a boolean (true by default) whether to test basic arithmetic and broadcasting of the first two :Vectors (or the first one and :SecondVector), if at least one tangent vector is provided
  • :TestRandReproducibility is a boolean (by default the value of :Mutating, or true if rand! is among the :Functions) whether to test that rand and rand! draw the same points and tangent vectors from copies of a random number generator
  • :TestRandScaling is a boolean (false by default) whether to test that random tangent vectors scale linearly with the keyword ฯƒ of rand
  • :TestMidpointSymmetry is a boolean (true by default) whether to test the symmetry property of the midpoint function
  • :TestChartIndexParameters is a boolean (false by default) whether to test the variant get_chart_index(M, A, i, a) for the :Atlases
  • :InducedBasisBackend is a differentiation backend (missing by default, which deactivates the test), for example AutoFiniteDifferences(central_fdm(5, 1)), to test the induced_basis of the :Atlases against the derivative of get_point, see test_induced_basis
  • :TestInfo is a boolean (true by default) whether to test that whether error=:info in verification functions issues info messages.
  • :TestWarn is a boolean (true by default) whether to test that whether error=:warn in verification functions issues warning.

Possible entries of the expectations dictionary are

  • any function tested to provide their expected resulting value, e.g. exp => p for the result of exp(M, p, X)
  • for retractions, inverse retractions, and vector transports, the key is a tuple of the function and the method, e.g. (retract, method) => q
  • for embed, and project, the key is a tuple of the function and :Point or :Vector, e.g. `(embed, :Point) of expected (embedded) points or vectors, omitting that symbol is interpreted as the expected point.
  • for injectivity_radius
    • you can provide the global test for just the function,
    • you can provide the radius for a specific point with (injectivity_radius, p)
    • you can provide a global or local one for retractions as well usinr (injectivity_radius, rm) and injectivity_radius, p, rm, respectively
  • for get_basis, the key is a tuple of the function and the basis, e.g. (get_basis, B) => ... to the expected basis
  • for get_coordinates the key is a tuple of the function and the basis, e.g. (get_coordinates, B) => c
  • for get_vector the key is a tuple of the function, the coordinate vector, and the basis, e.g. (get_vector, c, B) => X
  • for atlas related functions, the key is a tuple of the function and the atlas A for the result at the first point in the chart selected by get_chart_index, e.g. (get_parameters, A) => a, (get_chart_index, A) => i, (check_chart_switch, A) => false, (local_metric, A) => g, (Manifolds.inverse_chart_injectivity_radius, A) => r, and (transition_map_diff, A) => c for the coordinates of the first vector, while (transition_map, A_from, A_to) => b is keyed by both atlases
  • for get_embedding the key (get_embedding, T) with the type T of the first point is the expected embedding for points of that type, which defaults to the expectation for get_embedding
  • for get_vectors the key is a tuple of the function and the basis, e.g. (get_vectors, B) => :Symbol where
    • :Orthogonal tests for orthogonality
    • :Orthonormal tests additionally to the previous for unit length
    For any basis this test calls get_basis on any provided basis, if that function is available.
  • for is_default_metric, the value is the default metric
  • for rand, (number_eltype, rand) => T specifies the expected number type T of random points and tangent vectors
  • :atol => 0.0 a global absolute tolerance
  • :atols -> Dict() a dictionary function -> atol for tolerances of specific function tested.
  • :Types -> Dict() a dictionary function -> Type for specifying expected types of results of specific functions, for example manifold_dimension => Int.
  • :IsPointErrors is a vector of expected error types for each invalid point provided in :InvalidPoints, use missing to skip testing for errors for a specific point.
  • :IsVectorErrors is a vector of expected error types for each invalid vector provided in :InvalidVectors, use missing to skip testing for errors for a specific vector.
  • :IsVectorBasepointError is an expected error type when the base point is invalid e.g. for is_vector
source

A manifold is described by two dictionaries, one of properties and one of expected results.

using Manifolds, TestM = Sphere(2)p = [1.0, 0.0, 0.0]q = [0.0, 1.0, 0.0]X = [0.0, ฯ€ / 4, 0.0]Manifolds.Test.test_manifold(    M,    Dict(        :Functions => [distance, exp, log, manifold_dimension, norm, repr],        :Points => [p, q],        :Vectors => [X],    ),    Dict(:atol => 1.0e-14, manifold_dimension => 2, repr => "Sphere(2)"),);
Test.DefaultTestSet("Manifolds.Test suite for Sphere(2)", Any[Test.DefaultTestSet("distance(M, p, q)", Any[], 4, false, false, true, 1.794242241867623e9, 1.794242241883777e9, false, "/home/runner/work/Manifolds.jl/Manifolds.jl/ext/ManifoldsTestExt/ManifoldsTestExt.jl", Random.Xoshiro(0x2f2ce35de88c7a62, 0x71f7bd268f5ed591, 0x673327e47b0401f8, 0xb824f4b810157ef7, 0x921693506e537dae)), Test.DefaultTestSet("exp(M, p, X)", Any[], 7, false, false, true, 1.794242242209917e9, 1.79424224238828e9, false, "/home/runner/work/Manifolds.jl/Manifolds.jl/ext/ManifoldsTestExt/ManifoldsTestExt.jl", Random.Xoshiro(0x2f2ce35de88c7a62, 0x71f7bd268f5ed591, 0x673327e47b0401f8, 0xb824f4b810157ef7, 0x921693506e537dae)), Test.DefaultTestSet("log(M, p, q)", Any[], 5, false, false, true, 1.794242242654159e9, 1.794242242654225e9, false, "/home/runner/work/Manifolds.jl/Manifolds.jl/ext/ManifoldsTestExt/ManifoldsTestExt.jl", Random.Xoshiro(0x2f2ce35de88c7a62, 0x71f7bd268f5ed591, 0x673327e47b0401f8, 0xb824f4b810157ef7, 0x921693506e537dae)), Test.DefaultTestSet("manifold_dimension(M)", Any[], 3, false, false, true, 1.794242242733498e9, 1.794242242733515e9, false, "/home/runner/work/Manifolds.jl/Manifolds.jl/ext/ManifoldsTestExt/ManifoldsTestExt.jl", Random.Xoshiro(0x2f2ce35de88c7a62, 0x71f7bd268f5ed591, 0x673327e47b0401f8, 0xb824f4b810157ef7, 0x921693506e537dae)), Test.DefaultTestSet("norm(M, p, X)", Any[], 2, false, false, true, 1.794242242814586e9, 1.794242242814602e9, false, "/home/runner/work/Manifolds.jl/Manifolds.jl/ext/ManifoldsTestExt/ManifoldsTestExt.jl", Random.Xoshiro(0x2f2ce35de88c7a62, 0x71f7bd268f5ed591, 0x673327e47b0401f8, 0xb824f4b810157ef7, 0x921693506e537dae)), Test.DefaultTestSet("repr(M)", Any[], 1, false, false, true, 1.794242242881511e9, 1.794242242881526e9, false, "/home/runner/work/Manifolds.jl/Manifolds.jl/ext/ManifoldsTestExt/ManifoldsTestExt.jl", Random.Xoshiro(0x2f2ce35de88c7a62, 0x71f7bd268f5ed591, 0x673327e47b0401f8, 0xb824f4b810157ef7, 0x921693506e537dae)), Test.DefaultTestSet("Tangent vector arithmetic", Any[], 18, false, false, true, 1.794242243437351e9, 1.79424224343747e9, false, "/home/runner/work/Manifolds.jl/Manifolds.jl/ext/ManifoldsTestExt/ManifoldsTestExt.jl", Random.Xoshiro(0x2f2ce35de88c7a62, 0x71f7bd268f5ed591, 0x673327e47b0401f8, 0xb824f4b810157ef7, 0x921693506e537dae))], 0, false, false, true, 1.794242241474175e9, 1.79424224343748e9, false, "/home/runner/work/Manifolds.jl/Manifolds.jl/ext/ManifoldsTestExt/ManifoldsTestExt.jl", Random.Xoshiro(0x2f2ce35de88c7a62, 0x71f7bd268f5ed591, 0x673327e47b0401f8, 0xb824f4b810157ef7, 0x921693506e537dae))

Functions for individual tests

Manifolds.Test.test_affine_connection โ€” Function
Manifolds.Test.test_affine_connection(
    M, A, i, a, Xc, Yc;
    available_functions = [],
    expected_value = NoExpectation(),
    name = "affine_connection on $M in $A",
    test_mutating = true,
    test_symmetry = true,
    kwargs...
)

Test the affine_connection on manifold M at the point with parameters a in chart i of atlas A for vectors with coordinates Xc and Yc in the induced basis.

  • that the result is a coordinate vector of the same length as a
  • that the result matches expected_value, if given
  • that the result is linear in Xc and in Yc
  • that the result is symmetric in Xc and Yc, i.e. the connection is torsion-free (if activated)
  • that the mutating version affine_connection! matches the non-mutating version, (if activated)
  • that the result matches levi_civita_affine_connection (if activated)
source
Manifolds.Test.test_copy โ€” Function
Manifolds.Test.test_copy(M, p, X;
    name = "copying on $M for $(typeof(p)) points",
    kwargs...
)

Test copy(M, p) and copy(M, p, X) on a manifold M.

  • that the copied point/vector is a valid point/vector on the manifold / tangent space
  • that the copied point/vector matches the original point/vector but is new memory
source
Manifolds.Test.test_copyto โ€” Function
Manifolds.Test.test_copyto(M, p, X;
    name = "copying on $M for $(typeof(p)) points",
    kwargs...
)

Test copyto!(M, q, p) and copyto!(M, Y, p, X) on a manifold M.

  • that the copied point/vector is a valid point/vector on the manifold / tangent space
  • that the copied point/vector matches the original point/vector and is the same memory

Note that since this function does not modify its input, is is called test_copyto.

source
Manifolds.Test.test_default_retraction โ€” Function
Manifolds.Test.test_default_retraction(
    M, T=missing;
    expected_value = NoExpectation(),
    expected_type = isexpected(expected_value) ? Expect(typeof(expect(expected_value))) : NoExpectation(),
    name = "default_retraction_method on $M $(ismissing(T) ? "" : "for type $T")",
)

Test the default_retraction_method on manifold M.

  • that it returns an AbstractRetractionMethod
  • that the result matches expected_value, if given
  • that the result is of type expected_type, if given, defaults to the type of the value
source
Manifolds.Test.test_default_inverse_retraction โ€” Function
Manifolds.Test.test_default_inverse_retraction(
    M, T=missing;
    expected_value = NoExpectation(),
    expected_type = !isexpected(expected_value) ? NoExpectation() : typeof(expected_value),
    name = "default_inverse_retraction_method on $M $(ismissing(T) ? "" : "for type $T")",
)

Test the default_inverse_retraction_method on manifold M.

  • that it returns an AbstractInverseRetractionMethod
  • that the result matches expected_value, if given
  • that the result is of type expected_type, if given, defaults to the type of the value
source
Manifolds.Test.test_default_vector_transport_method โ€” Function
Manifolds.Test.test_default_vector_transport_method(
    M, T=missing;
    expected_value = NoExpectation(),
    expected_type = isexpected(expected_value) ? Expect(typeof(expect(expected_value))) : NoExpectation(),
    name = "default_vector_transport_method on $M $(ismissing(T) ? "" : "for type $T")",
)

Test the default_vector_transport_method on manifold M.

  • that it returns an AbstractVectorTransportMethod
  • that the result matches expected_value, if given
  • that the result is of type expected_type, if given, defaults to the type of the value
source
Manifolds.Test.test_distance โ€” Function
Manifolds.Test.test_distance(
    M, p, q;
    available_functions=[], expected_value=NoExpectation(),
    name = "Distance on $M between $(typeof(p)) points",
    kwargs...
)

Test the distance function on manifold M between points p and q.

  • that the result is a nonnegative number
  • that the distance from p to p is zero
  • that the distance is symmetric
  • that the result matches expected_value, if given
  • that the distance is equal to the norm of the logarithmic map (if log and norm are available) (only performed if either injectivity_radius is not available or the points are within)
source
Manifolds.Test.test_exp โ€” Function
Manifolds.Test.test_exp(
    M, p, X, t=1.0;
    available_functions=[], expected_value=NoExpectation(), test_mutating=true,
    test_log = (log in available_functions),
    test_aliased = true,
    test_fused = true,
    test_injectivity_radius = (injectivity_radius in available_functions),
    name = "Exponential map on $M for $(typeof(p)) points",
    kwargs...
)

Test the exponential map on manifold M at point p with tangent vector X.

  • that the result is a valid point on the manifold
  • that the result matches expected_value, if given
  • that the mutating version exp! matches the non-mutating version, (if activated)
  • that exp! works on aliased in put (p=q) (if activated for mutating)
  • that the logarithmic map inverts the exponential map (if activated)

(only performed if either injectivity_radius is not available or X is within)

  • that the fused version exp_fused(M, p, t, X) matches the non-fused version (if activated)
source
Manifolds.Test.test_embed โ€” Function
Manifolds.Test.test_embed(
    M, p, X=missing;
    available_functions=[],
    expected_point=NoExpectation(),
    expected_vector=NoExpectation(),
    test_aliased=true,
    test_mutating=true,
    name = "Embedding on $M for $(typeof(p)) points",
    kwargs...
)

Test the embed(M, p) and embed(M, p, X) to embed points and tangent vectors (if not missing).

Besides a simple call of embed (for both variants) the following ones are prefoemd if get_embedding is available:

  • that the embedded point is a valid point on the embedding manifold
  • that the embedded vector is a valid tangent vector on the embedding manifold (if get_embedding is available and X is not missing)
  • that the result matches expected_point and expected_vector, respectively, if given
  • that the projection inverts the embedding (if project is available)
  • that the mutating version embed! produces the same result(s) (if activated and get_embedding is available)
  • that embed! works on aliased input (p=q or X=Y) (if activated and p/q or X/Y are of same type)
source
Manifolds.Test.test_embed_project โ€” Function
Manifolds.Test.test_embed_project(
    M, ap, aX = missing;
    available_functions=[],
    expected_point=NoExpectation(),
    expected_vector=NoExpectation(),
    test_aliased=true,
    test_mutating=true,
    name = "Projection on $M for $(typeof(q)) points",
    kwargs...
)

Test the p=embed_project(M, ap) and embed_project(M, p, aX) to project points and tangent vectors (if not aX is not missing) after embedding them. Besides a simple call of embed_project (for both variants) the following tests are performed

  • that the projected point is a valid point on the manifold
  • that the projected vector is a valid tangent vector on the manifold
  • that the result matches expected_point and expected_vector, respectively, if given
  • that the mutating version embed_project! produces the same result(s) (if activated)
  • that embed_project! works on aliased input (p=q or X=Y) (if activated and p/q or X/Y are of same type)
source
Manifolds.Test.test_flat โ€” Function
Manifolds.Test.test_flat(M, p, X;
    available_functions = [],
    expected_value= NoExpectation(),
    test_mutating = true,
    name = "Flat on $M for $(typeof(p)) points",
    kwargs...
)

Test the flat operation on manifold M at point p with tangent vector X.

  • (we can not yet test valid cotangent vectors)
  • that the result matches expected_value, if given
  • that sharp is the inverse
  • that mutating version flat! matches non-mutating version (if activated)
source
Manifolds.Test.test_induced_basis โ€” Function
Manifolds.Test.test_induced_basis(
    M, A, i, p, X;
    available_functions = [],
    differential_atol = 1.0e-8,
    differential_backend = missing,
    expected_value = NoExpectation(),
    name = "induced_basis on $M in $A",
    kwargs...
)

Test the induced_basis on manifold M of chart i in atlas A using a point p in the domain of the chart and a tangent vector X at p.

source
Manifolds.Test.test_injectivity_radius โ€” Function
Manifolds.Test.test_injectivity_radius(M, p = missing;
    expected_value = NoExpectation(),
    expected_global_value = NoExpectation(),
    retraction_method = missing,
    name = "Injectivity radius on $M at point $(ismissing(p) ? "" : "$typeof(p)")) and $(retraction_method)",
    kwargs...
)

Test the injectivity radius on manifold M at point p.

  • that the result is a nonnegative real number
  • that the result matches expected_value, if given
  • if a point p is given, that the result is larger or equal to the global injectivity radius
source
Manifolds.Test.test_inner โ€” Function
Manifolds.Test.test_inner(M, p, X, Y;
    available_functions=[], expected_value = NoExpectation(),
    name = "Inner product on $M at point $(typeof(p))",
    test_norm = (norm in available_functions),
    kwargs...
)

Test the inner product on the manifold M at point p for tangent vectors X and Y.

  • that the result is a number, which may be complex, e.g. on complex manifolds
  • that the result matches expected_value, if given
  • that the inner product is conjugate symmetric
  • that the inner product of X with itself is real and, if the metric is positive definite, see is_positive_definite_metric, nonnegative
  • that the inner product of X with itself is the same as its norm squared (if activated)
source
Manifolds.Test.test_inner(M, A::AbstractAtlas, i, a, Xc, Yc;
    available_functions=[], expected_value = NoExpectation(),
    name = "Inner product on $M in $A",
    test_norm = (norm in available_functions),
    kwargs...
)

Test the inner product on the manifold M at the point with parameters a in chart i of atlas A for tangent vectors with coordinates Xc and Yc in the induced basis.

  • that the result is a number
  • that the result matches expected_value, if given
  • that the inner product is conjugate symmetric
  • that the inner product of Xc with itself is the same as its norm squared (if activated)
  • that the result matches the inner product of the corresponding tangent vectors (if get_vector is available)
source
Manifolds.Test.test_inverse_retract โ€” Function
Manifolds.Test.test_inverse_retract(
    M, p, q, m::AbstractInverseRetractionMethod;
    available_functions=[],
    expected_value = NoExpectation(),
    name = "Inverse retraction $m on $M at point $(typeof(p))",
    retraction_method = missing,
    test_mutating = true,
    test_retraction = (retract in available_functions) && !ismissing(retraction_method),
    kwargs...
)

Test the inverse retraction method m on manifold M at point p towards point q.

  • that the result is a valid tangent vector at p on the manifold
  • that the result matches expected_value, if given
  • that the mutating version inverse_retract! matches the non-mutating version, (if activated)
  • that the retraction inverts the inverse retraction (if activated)
source
Manifolds.Test.test_is_default_metric โ€” Function
Manifolds.Test.test_is_default_metric(M, metric::AbstractMetric, other_metrics = [];
name = "is_default_metric on $M",
)

Test the is_default_metric on manifold M.

  • that it returns true for the given metric
  • that it returns false for all other provided metrics
source
Manifolds.Test.test_is_flat โ€” Function
Manifolds.Test.test_is_flat(
M;
expected_value = NoExpectation(),
name = "is_flat on $M",
)

Test the function is_flat on manifold M. Since it returns a boolean, there is also only the check that it agrees with the expected_value, if given.

source
Manifolds.Test.test_is_point โ€” Function
Manifolds.Test.test_is_point(
    M, p, qs...;
    errors = [],
    name = "is_point on $M for $(typeof(p)) points",
    test_warn = true,
    test_info = true,
    kwargs...
)

Test the function is_point for a point p on manifold M.

  • that for p it returns true.
  • that for each q in qs it
    • returns false
    • issues a warning (if activated)
    • issues an info message (if activated)
    • throws the corresponding error from error_types (if not missing)
source
Manifolds.Test.test_is_vector โ€” Function
Manifolds.Test.test_is_vector(
    M, p, X, Ys...;
    basepoint_error = NoExpectation(),
    check_basepoint = true,
    errors = [],
    name = "is_vector on $M for $(typeof(p)) points",
    test_warn = true,
    test_info = true,
    q = missing,
    kwargs...
)

Test the function is_vector on manifold M at point p for tangent vector X.

  • that for X it returns true.
  • that for each Y in Ys it
    • returns false
    • issues a warning (if activated)
    • issues an info message (if activated)
    • throws the corresponding error from error_types (if not missing)
  • if check_basepoint is true, then it checks that
    • for p this still returns true
    • for the base point q it
      • returns false
      • issues a warning (if activated)
      • issues an info message (if activated)
      • throws the corresponding error from basepoint_error (if given)
source
Manifolds.Test.test_geodesic โ€” Function
Manifolds.Test.test_geodesic(M, p, X, t=1.0;
    available_functions=[],
    expected_value = NoExpectation(),
    N = 10,
    name = "Geodesic on $M for $(typeof(p)) points",
    kwargs...
)

Test the geodesic on manifold M at point p with tangent vector X at time t.

  • that at time 0 the geodesic returns p
  • that the function ฮณ = geodesic(M, p, X) is consistent with evaluation at 0 and t`
  • that the result is a valid point on the manifold
  • that the result matches expected_value, if given
  • that the geodesic has constant speed (if activated): between N samples on [0, t] the speed is the same and equal to norm(M, p, X)
source
Manifolds.Test.test_get_basis โ€” Function
Manifolds.Test.test_get_basis(
    M, p, b::AbstractBasis;
    available_functions = [],
    expected_value = NoExpectation(),
    expected_type = isexpected(expected_value) ? Expect(typeof(expect(expected_value))) : Expect(CachedBasis),
    name = "get_basis on $M at point $(typeof(p)) for basis $(typeof(b))",
)

Test the get_basis on manifold M at point p for basis b.

  • that it returns a basis of type expected_type, which defaults to CachedBasis.
  • that the result matches expected_value, if given
source
Manifolds.Test.test_get_chart_index โ€” Function
Manifolds.Test.test_get_chart_index(
    M, A, p;
    available_functions = [],
    expected_value = NoExpectation(),
    name = "get_chart_index on $M in $A for point $(typeof(p))",
    test_parameters = false,
    kwargs...
)

Test the get_chart_index on manifold M in atlas A for point p.

  • that the chart selection is deterministic
  • that the result matches expected_value, if given
  • that p lies in the domain of the selected chart, i.e. get_point inverts get_parameters there (if both are available)
  • that the variant get_chart_index(M, A, i, a) selecting a chart based on parameters a in chart i is deterministic and selects a chart, whose domain contains p (if activated)
source
Manifolds.Test.test_get_coordinates โ€” Function
Manifolds.Test.test_get_coordinates(
    M, p, X, B;
    available_functions = [],
    expected_value = NoExpectation(),
    name = "get_coordinates on $M at point $(typeof(p))",
    test_mutating = true,
)

Test the get_coordinates on manifold M at point p for a tangent vector X and a basis B.

  • that the result is a valid coordinate vector, that is of correct length
  • that the result matches expected_value, if given
  • that the mutating version get_coordinates! matches the non-mutating version, (if activated)
  • that get_vector inverts get_coordinates (if activated)
source
Manifolds.Test.test_get_embedding โ€” Function
Manifolds.Test.test_get_embedding(M, P=missing;
    expected_value = NoExpectation(),
    expected_type = isexpected(expected_value) ? Expect(typeof(expect(expected_value))) : NoExpectation(),
    name = "get_embedding on $M $(ismissing(P) ? "" : "for type $P")",
)

Test the get_embedding on manifold M.

  • that it returns an AbstractManifold.
  • that its type matches expected_type, if given, defaults to the type of the expected value
  • that the result matches expected_value, if given
source
Manifolds.Test.test_get_parameters โ€” Function
Manifolds.Test.test_get_parameters(
    M, A, i, p;
    available_functions = [],
    expected_value = NoExpectation(),
    name = "get_parameters on $M in $A for point $(typeof(p))",
    test_mutating = true,
    kwargs...
)

Test the get_parameters on manifold M for point p in chart i of atlas A.

  • that the result is a vector of length manifold_dimension
  • that the result matches expected_value, if given
  • that the mutating version get_parameters! matches the non-mutating version, (if activated)
  • that get_point inverts get_parameters (if activated)
source
Manifolds.Test.test_get_point โ€” Function
Manifolds.Test.test_get_point(
    M, A, i, a;
    available_functions = [],
    expected_value = NoExpectation(),
    name = "get_point on $M in $A for parameters $(typeof(a))",
    test_mutating = true,
    kwargs...
)

Test the get_point on manifold M for parameters a in chart i of atlas A.

  • that the result is a valid point on the manifold
  • that the result matches expected_value, if given
  • that the mutating version get_point! matches the non-mutating version, (if activated)
  • that get_parameters inverts get_point (if activated)
source
Manifolds.Test.test_get_vector โ€” Function
Manifolds.Test.test_get_vector(
    M, p, c, B;
    available_functions=[],
    expected_value = NoExpectation(),
    name = "get_vector on $M at point $(typeof(p))",
    test_mutating = true,
    kwargs...
)

Test the get_vector on manifold M at point p for a vector of coordinates c in basis B.

  • that the result is a valid tangent vector at p on the manifold
  • that the result matches expected_value, if given
  • that the mutating version get_vector! matches the non-mutating version, (if activated)
  • that get_coordinates inverts get_vector (if activated)
source
Manifolds.Test.test_get_vectors โ€” Function
Manifolds.Test.test_get_vectors(
    M, p, b;
    available_functions=[],
    name = "get_vectors on $M at point $(typeof(p))",
    test_orthogonality = false,
    test_normality = false,
    kwargs...
)

Test the get_vectors on manifold M at point p for basis b, where the basis is assumed to come from a call to get_basis.

  • that there are as many vectors as the manifold dimension (if available)
  • that each vector is a valid tangent vector at p on the manifold
  • that the vectors are orthogonal (if activated)
  • that the vectors are normal (if activated)
source
Manifolds.Test.test_local_metric โ€” Function
Manifolds.Test.test_local_metric(
    M, A, i, a;
    available_functions = [],
    expected_value = NoExpectation(),
    name = "local_metric on $M in $A",
    test_positive_definite = true,
    kwargs...
)

Test the local_metric on manifold M at the point with parameters a in chart i of atlas A.

  • that the result is a symmetric matrix of size nร—n, where n is the length of a
  • that the result is positive definite (if activated)
  • that the result matches expected_value, if given
  • that the result is the Gram matrix of the induced_basis vectors with respect to inner (if get_vector is available)
  • that inverse_local_metric is its inverse (if available)
  • that det_local_metric is its determinant (if available)
  • that log_local_metric_density is the logarithm of the square root of the absolute value of its determinant (if available)
source
Manifolds.Test.test_log โ€” Function
Manifolds.Test.test_log(
    M, p, q;
    available_functions=[], expected_value=NoExpectation(), test_mutating=true,
    test_exp = (exp in available_functions),
    test_injectivity_radius = (injectivity_radius in available_functions),
    name = "Logarithmic map on $M for $(typeof(p)) points",
    kwargs...
)

Test the logarithmic map on manifold M at point p towards q.

  • that the result is a valid tangent vector at p on the manifold
  • that the result matches expected_value, if given
  • that the mutating version log! matches the non-mutating version, (if activated)
  • that the exponential map inverts the logarithmic map (if activated) (only performed if either injectivity_radius is not available or X is within)
source
Manifolds.Test.test_manifold_dimension โ€” Function
test_manifold_dimension(
    M;
    expected_value = NoExpectation(),
    expected_type = Int,
    name = "Manifold dimension for $M",
)

Test that the dimension of the manifold M is consistent.

  • that the dimension is nonnegative
  • that it is an integer (of type expected_type, Int by default)
  • that it matches the expected value (if provided)
source
Manifolds.Test.test_manifold_volume โ€” Function
Manifolds.Test.test_manifold_volume(
    M;
    expected_value = NoExpectation(),
    name = "Manifold volume for $M",
)

Test the volume of the manifold M.

  • that the volume is nonnegative
  • that it matches the expected value (if provided)
source
Manifolds.Test.test_mid_point โ€” Function
Manifolds.Test.test_mid_point(M, p, q;
    available_functions=[],
    expected_value = NoExpectation(),
    test_aliased = true,
    test_mutating = true,
    test_symmetry = true,
    name = "Mid-point on $M between $(typeof(p)) points",
    kwargs...
)

Test the mid-point function on manifold M between points p and q.

  • that the result is a valid point on the manifold
  • that the result matches expected_value, if given
  • that the mid-point is symmetric (if activated)
  • that the distance from p and q to the mid-point is half the distance from p to q (if distance is present)
  • that the mutating version mid_point! matches the non-mutating version (if activated)
  • that mid_point! works on aliased in put (r=p or r=q) (if activated for mutating)
source
Manifolds.Test.test_norm โ€” Function
Manifolds.Test.test_norm(M, p, X;
    available_functions = [], expected_value = NoExpectation(),
    name = "Norm on $M at point $(typeof(p))",
    test_inner = (inner in available_functions),
    kwargs...
)

Test the norm on the manifold M at point p for tangent vector X.

  • that the result is a real number
  • that the result matches expected_value, if given
  • that the norm of X with itself is non negative
  • that the inner product of X with itself is the same as its norm squared (if activated)
source
Manifolds.Test.test_norm(M, A::AbstractAtlas, i, a, Xc;
    available_functions = [], expected_value = NoExpectation(),
    name = "Norm on $M in $A",
    test_inner = (inner in available_functions),
    kwargs...
)

Test the norm on the manifold M at the point with parameters a in chart i of atlas A for the tangent vector with coordinates Xc in the induced basis.

  • that the result is a real number
  • that the result matches expected_value, if given
  • that the norm is non negative
  • that the inner product of Xc with itself in the chart is the same as its norm squared (if activated)
  • that the result matches the norm of the corresponding tangent vector (if get_vector is available)
source
Manifolds.Test.test_parallel_transport โ€” Function
Manifolds.Test.test_parallel_transport(
    M, p, X, q;
    available_functions=[],
    direction = (log in available_functions) ? log(M, p, q) : missing,
    expected_value=NoExpectation(),
    expected_value_direction=NoExpectation(),
    name = "Parallel transport on $M at point $(typeof(p))",
    test_aliased = true,
    test_mutating = true,
    kwargs...
)

Test the parallel transport on manifold M at point p with tangent vector X to a point q.

this defaults to testing parallel_transport_to, but can also be used to test parallel_transport_direction, by passing that function to the available_functions, using the direction argument. The direction has to be the one that transports X also to q. If it is missing, it is computed with the default inverse retraction when vector_transport_direction is tested, and nothing deactivates the test of vector_transport_direction.

  • that the result is a valid tangent vector at q on the manifold
  • that the result matches expected_value, if given
  • that the mutating version parallel_transport! matches the non-mutating version
  • that parallel_transport_to works on aliased in put (Y=X) (if activated)
  • that the direction of the transport is consistent with expected_direction, if given
  • that the mutating version parallel_transport_direction! matches the non-mutating version (if activated)
  • that parallel_transport_direction works on aliased in put (Y=X or Y=d) (if activated for mutating)
  • that both functions are consistent
source
Manifolds.Test.test_project โ€” Function
Manifolds.Test.test_project(
    M, q, Y = missing;
    available_functions = [],
    expected_point = NoExpectation(),
    expected_vector = NoExpectation(),
    test_aliased = true,
    test_mutating = true,
    name = "Projection on $M for $(typeof(q)) points",
    kwargs...
)

Test the project(M, q) and project(M, q, Y) to project points and tangent vectors (if not missing).

Besides a simple call of project (for both variants) the following tests are performed

  • that the projected point is a valid point on the manifold
  • that the projected vector is a valid tangent vector on the manifold
  • that the result matches expected_point and expected_vector, respectively, if given
  • that the mutating version project! produces the same result(s) (if activated)
  • that project! works on aliased input (p=q or X=Y) (if activated and p/q or X/Y are of same type)
source
Manifolds.Test.test_rand โ€” Function
Manifolds.Test.test_rand(M;
    vector_at = missing,
    expected_eltype = NoExpectation(),
    seed = missing,
    test_mutating = true,
    test_reproducibility = test_mutating,
    test_scaling = false,
    rng = missing,
    name = "Random sampling on $M",
    kwargs...
)

Test the random sampling functions rand(M) and rand(M; vector_at=p) on manifold M, where p is the point drawn by rand(M) unless the keyword vector_at provides one.

  • that the result of rand(M) is a valid point on the manifold
  • that the result of rand(M; vector_at=p) is a valid tangent vector at p on the manifold
  • that the mutating versions rand! match the non-mutating versions (if activated)
  • that the four mentioned functions also work with a seed upfront.
  • that both the point and the tangent vector have the number type expected_eltype (if provided)
  • that rand and rand! draw the same point and the same tangent vector from copies of the random number generator rng, or of the default one (if test_reproducibility is activated)
  • that rand(M; vector_at=p, ฯƒ=2) is twice the tangent vector drawn with the default ฯƒ from the same random number generator state (if test_scaling is activated)
source
Manifolds.Test.test_repr โ€” Function
Manifolds.Test.test_repr(
    M;
    expected_value = NoExpectation(),
    name = "(String) repr_esentation of $M",
)

Test that the default show method works as expected by calling repr(M).

source
Manifolds.Test.test_representation_size โ€” Function
Manifolds.Test.test_representation_size(
    M;
    expected_value = NoExpectation(),
    name = "Representation size of $M",
)

Test the representation size of the manifold M.

  • that the result is tuple of nonnegative integers or nothing (if there is no reasonable representation)
  • that it matches the expected value (if provided)
source
Manifolds.Test.test_retract โ€” Function
Manifolds.Test.test_retract(
    M, p, X, m::AbstractRetractionMethod;
    available_functions=[],
    expected_value = NoExpectation(),
    inverse_retraction_method = missing,
    name = "Retraction $m on $M at point $(typeof(p))",
    t = 1.0,
    test_aliased = true,
    test_fused = true,
    test_mutating = true,
    test_inverse_retraction = (inverse_retract in available_functions) && !ismissing(inverse_retraction_method),
    kwargs...
)

Test the retraction method m on manifold M at point p with tangent vector X.

  • that the result is a valid point on the manifold
  • that the result matches expected_value, if given
  • that the mutating version retract! matches the non-mutating version, (if activated)
  • that retract! works on aliased in put (p=q) (if activated for mutating)
  • that the inverse retraction inverts the retraction (if activated)
  • that the fused version retract_fused(M, p, X, t, m) matches the non-fused version (if activated)
source
Manifolds.Test.test_sectional_curvature โ€” Function
Manifolds.Test.test_sectional_curvature(
    M, p, X, Y;
    available_functions = [],
    expected_value = NoExpectation(),
    expected_min = NoExpectation(),
    expected_max = NoExpectation(),
    name = "Sectional curvature on $M at point $(typeof(p))",
    kwargs...
)

Test the sectional curvature on manifold M at point p for tangent vectors X and Y.

  • that the result is a real number
  • that the result matches expected_value, if given
  • that the minimum sectional curvature at p is less than or equal to the sectional curvature
  • that the maximum sectional curvature at p is greater than or equal to the sectional curvature
  • that the minimum and maximum sectional curvatures match expected_min and expected_max, if given
source
Manifolds.Test.test_sharp โ€” Function
Manifolds.Test.test_sharp(M, p, ฮพ;
    available_functions=[],
    expected_value = NoExpectation(),
    test_mutating = true,
    name = "Sharp on $M for $(typeof(p)) points",
    kwargs...
)

Test the sharp operation on manifold M at point p with cotangent vector ฮพ.

  • test that the result is a valid tangent vector at p on the manifold
  • that the result matches expected_value, if given
  • that flat is the inverse
  • that mutating version sharp! matches non-mutating version (if activated)
source
Manifolds.Test.test_shortest_geodesic โ€” Function
Manifolds.Test.test_shortest_geodesic(M, p, q, t=0.5;
    available_functions=[],
    expected_value = NoExpectation(),
    N = 10,
    name = "Shortest geodesic on $M for $(typeof(p)) points",
    kwargs...
)

Test the shortest geodesic on manifold M from p to q at time t.

  • that at time 0 the geodesic returns p, at time 1 it returns q
  • that the function ฮณ = shortest_geodesic(M, p, q) is consistent with evaluation at 0, 1 and t
  • that the result at t is a valid point on the manifold
  • that the geodesic has constant speed (if activated) using N samples and the approximated derivative via finite differences
  • that the geodesic is length minimizing, i.e. the sum of the segments is approximately equal to the distance from p to q (if activated)
source
Manifolds.Test.test_transition_map โ€” Function
Manifolds.Test.test_transition_map(
    M, A_from, i_from, A_to, i_to, a;
    available_functions = [],
    expected_value = NoExpectation(),
    name = "transition_map on $M from $A_from to $A_to",
    test_mutating = true,
    kwargs...
)

Test the transition_map on manifold M of parameters a from chart i_from of atlas A_from to chart i_to of atlas A_to.

  • that the result is a vector of the same length as a
  • that the result matches expected_value, if given
  • that the short form transition_map(M, A, i_from, i_to, a) agrees, if A_from == A_to
  • that both parameters represent the same point, i.e. get_point agrees on them (if available)
  • that the transition map back to (A_from, i_from) inverts it
  • that the mutating version transition_map! matches the non-mutating version, (if activated)
source
Manifolds.Test.test_transition_map_diff โ€” Function
Manifolds.Test.test_transition_map_diff(
    M, A, i_from, a, c, i_to;
    available_functions = [],
    expected_value = NoExpectation(),
    name = "transition_map_diff on $M in $A",
    test_mutating = true,
    kwargs...
)

Test the transition_map_diff on manifold M from chart i_from to chart i_to of atlas A at the point with parameters a for the tangent vector with coordinates c in the induced basis.

  • that the result is a vector of the same length as c
  • that the result matches expected_value, if given
  • that both coordinates represent the same tangent vector in the respective induced_basis (if get_vector is available)
  • that the differential of the transition map back to i_from inverts it
  • that the mutating version transition_map_diff! matches the non-mutating version, (if activated)
source
Manifolds.Test.test_vector_arithmetic โ€” Function
Manifolds.Test.test_vector_arithmetic(
    M, p, X, Y;
    name = "Tangent vector arithmetic on $M at point $(typeof(p))",
    test_inplace = !(X isa Number),
    kwargs...
)

Test that tangent vectors X and Y at p on M support the basic arithmetic of a vector space.

  • that X + Y, X - Y, 2 * X, X * 2, X / 2, 2 \ X, +X and -X are tangent vectors and consistent with each other
  • that broadcasting, e.g. 2 .* X .+ Y, agrees with the non-broadcasting operations and returns the same type as X (unless X is a zero-dimensional array)
  • that in-place broadcasting, e.g. Z .= 2 .* X .+ Y, works (if activated)
source
Manifolds.Test.test_vector_transport โ€” Function
Manifolds.Test.test_vector_transport(
    M, p, X, q, m = default_vector_transport_method(M);
    available_functions=[],
    direction = missing,
    expected_value = NoExpectation(),
    expected_value_direction = NoExpectation(),
    test_aliased = true,
    test_mutating = true,
    name = "Vector transport method $(m) on $M at point $(typeof(p))",
    kwargs...
)

Test the vector transport on manifold M at point p with tangent vector X to a point q.

this defaults to testing vector_transport_to, but can also be used to test vector_transport_direction, by passing that function to the available_functions, using the direction argument. The direction has to be the one that transports X also to q.

  • that the result is a valid tangent vector at q on the manifold
  • that the result matches expected_value, if given
  • that the mutating version vector_transport! matches the non-mutating version
  • that vector_transport_to works on aliased in put (Y=X) (if activated)
  • that the direction of the transport is consistent with expected_direction, if given
  • that the mutating version vector_transport_direction! matches the non-mutating version (if activated)
  • that vector_transport_direction works on aliased in put (Y=X or Y=d) (if activated for mutating)
  • that both functions are consistent
source
Manifolds.Test.test_Weingarten โ€” Function
Manifolds.Test.test_Weingarten(
    M, p, X, V;
    available_functions = [],
    expected_value = NoExpectation(),
    test_aliased = true,
    test_mutating = true,
    name = "Weingarten map on $M at point $(typeof(p))",
    kwargs...
)

Test the Weingarten map on manifold M at point p for tangent vector X and normal vector V.

  • that the result is a valid tangent vector at p on the manifold
  • that the result matches expected_value, if given
  • that the result is consistent with the mutating version weingarten! (if activated)
  • that Weingarten! works on aliased in put (Y=X) (if activated for mutating)
source
Manifolds.Test.test_zero_vector โ€” Function
Manifolds.Test.test_zero_vector(M, p;
    available_functions=[],
    test_mutating = true,
    test_norm = (norm in available_functions),
    name = "Zero vector test on $M at point $(typeof(p))",
)

Test the zero vector on the manifold M at point p.

  • verify that it is a valid tangent vector
  • verify that its norm is zero (if provided)
  • verify that the mutating version zero_vector! matches the non-mutating version (if activated)
source

Internals to handle expectations

Manifolds.Test.Expect โ€” Type
Expect{T} <: AbstractExpectation

A struct to hold expected values for tests of type T.

Fields

  • value::T the expected value

Constructor

Expect(value::T)
source