Skip to content

Instantly share code, notes, and snippets.

@mateuszbaran
Last active June 5, 2019 17:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mateuszbaran/6ac0115866562d09ea5e856216568a73 to your computer and use it in GitHub Desktop.
Save mateuszbaran/6ac0115866562d09ea5e856216568a73 to your computer and use it in GitHub Desktop.
abstract type Manifold
end
# Retraction type should be a part of the type of manifold,
# either by different concrete types or a single type with a type parameter
# that selects the retraction type.
retr(M::Manifold, v, x, t=1) = error("Not implemented")
retr!(M::Manifold, y, v, x, t=1) = error("Not implemented")
# just a reasonable default
distance(M::Manifold, x, y) = norm(log(M, x, y))
# inner product of ξ and ν that are tangent vectors at x
# Manopt.jl and ManifoldProjections.jl calls this dot, Manopt and OptimKit use inner, FunManifolds uses innerproduct
dot(M::Manifold, x, ξ, ν) = error("Not implemented")
norm(M::Manifold, x, v) = sqrt(inner(M, x, v, v))
# Proper exponential map
# mutating version saves the result to y
exp(M::Manifold, x, ξ, t=1) = error("Not implemented")
exp!(M::Manifold, y, x, ξ, t=1) = error("Not implemented")
# Proper logarithmic map
log(M::Manifold, x, y) = error("Not implemented")
log!(M::Manifold, v, x, y) = error("Not implemented")
# dimension of given manifold
manifold_dimension(M::Manifold) = error("Not implemented")
# type of vector transport (isometric, some approximation or something else)
# should be a part of the type of manifold,
# either by different concrete types or a single type with a type parameter
# that selects the retraction type.
vector_transport(M::Manifold, xfrom, xat, v) = error("Not implemented")
vector_transport!(M::Manifold, vto, xfrom, xat, v) = error("Not implemented")
random_point(M::Manifold, options...) = error("Not implemented")
random_tvector(M::Manifold, x, options...) = error("Not implemented")
typical_distance(M::Manifold) = error("Not implemented")
zero_tvector(M::Manifold, x) = log(M, x, x)
zero_tvector!(M::Manifold, v, x) = log!(M, v, x, x)
geodesic(M::Manifold, x, y, t) = exp(M, x, log(M, x, y), t)
@antoine-levitt
Copy link

antoine-levitt commented Jun 5, 2019

Looks very nice!

On top of that, solvers should probably be able to use different retraction methods
So, probably the Julian way of doing this would be using dispatch

I think that information can be put into the manifold type, see how I do with the different orthogonalization for Stiefel in https://github.com/JuliaNLSolvers/ManifoldProjections.jl/. That way the manifold M can be entirely specified by the user and the intermediate library (eg optimizer) can just do retract(M, x)

Solvers should probably rely on tangent vector retractions anyway (like OptimKit.jl, Manopt)

So retract(M, x, v) instead of retract(M, x+v)? I agree, I used this for easy interfacing with Optim.

@kellertuer
Copy link

  • Manifold.jl does have retractions - just not yet the fallback (but I'll add that for the next version=
  • I am in favour of CamelCase – but that's just naming
  • I also think the main idea of the manifold type is to encapsulate such things like the metric and such, too, such that we don't need keyword arguments.
  • I am against overloading + to combine points and vectors, I've read a books that did that and that leads to confusion for the reader/programmer, because for every plus you have to think: Is that now an exp or really a plus? I would favour retract(M,x,v)
  • I arges we should not to keyword arguments for retract – but how would you then distinguish different retractions? I have atm two retractions on Stiefel (and the default retraction maps to one of them). Is that the way we go?
  • do we also want to go the opposite way and embed instead of project, too? semantically a point on the sphere is in its embedding, but for tangent vectors that's already different.

In general I would aim to provide more detailed error messages, but since this is e first sketch, that's of course still fine.
For me the fallbacks I did ( see https://github.com/kellertuer/Manopt.jl/blob/master/src/manifolds/defaults/manifoldFallbacks.jl ) also helped me, wen I was working with two manifolds and took the wrong one here and there. Thats actually also one reason for my typing, to be able to tell the user, that on Sphere the exp for an SPDPoint with an StiefelVector is nothing useful ;)

Thanks for the first sketch.

@antoine-levitt
Copy link

I arges we should not to keyword arguments for retract – but how would you then distinguish different retractions? I have atm two retractions on Stiefel (and the default retraction maps to one of them). Is that the way we go?

I think https://github.com/JuliaNLSolvers/ManifoldProjections.jl/blob/master/src/ManifoldProjections.jl#L84 is the simplest

I am in favour of CamelCase – but that's just naming

Julia favours camel case for types, and underscores for functions.

@kellertuer
Copy link

Ah subtypes for retraction, hm, I am not sure yet.

Oh I did not know about the mix. I might think about refactoring my parallelTransport then.

@mateuszbaran
Copy link
Author

Thank you for feedback 👍

I am in favour of CamelCase – but that's just naming

Julia favours camel case for types, and underscores for functions.

I agree with using underscores in function names.

  • do we also want to go the opposite way and embed instead of project, too? semantically a point on the sphere is in its embedding, but for tangent vectors that's already different.

This is a very good question. Thinking about it now, this interface provides no way of actually obtaining a point or vector that requires projecting. I think I'll remove this (at least for now).

I'll make a few changes:

  • Retraction type and vector transport type will be a property of manifold (either as a subtype or adding a type parameter).
  • Better error messages.
  • Removal of retract and project_tangent.

@kellertuer
Copy link

Then its underscores for functions.

For Manopt.jl my idea was to do both (but I think I wrote that) project(M,N,x) and embed(N,M,y) but only really of both are known. Whether that can be included in our common interface, I am not sure.

Wy remove retract? I favour or retr? I'd be fine with that.

@mateuszbaran
Copy link
Author

For Manopt.jl my idea was to do both (but I think I wrote that) project(M,N,x) and embed(N,M,y) but only really of both are known. Whether that can be included in our common interface, I am not sure.

I think the safe choice would be to wait with project and embed until there is a clear use case. We can always add new functions.

Wy remove retract? I favour or retr? I'd be fine with that.

Yes, I think retr should be sufficient.

@kellertuer
Copy link

retr is sufficient.

Yes, I'll work on that as one of my next features, so I'll provide an update, when I have more details on that and for now we should omit those two.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment