Decorators for Objectives
Manopt.AbstractDecoratedManifoldObjective — Type
AbstractDecoratedManifoldObjective{E<:AbstractEvaluationType,O<:AbstractManifoldObjective}A common supertype for all decorators of AbstractManifoldObjectives to simplify dispatch. The second parameter should refer to the undecorated objective (the most inner one).
An objective can be decorated using the following trait and function to initialize
Manopt.dispatch_objective_decorator — Function
dispatch_objective_decorator(o::AbstractManoptSolverState)Indicate internally, whether an AbstractManifoldObjective o to be of decorating type, it stores (encapsulates) an object in itself, by default in the field o.objective.
Decorators indicate this by returning Val{true} for further dispatch.
The default is Val{false}, so by default an state is not decorated.
Manopt.is_objective_decorator — Function
is_object_decorator(s::AbstractManifoldObjective)Indicate, whether AbstractManifoldObjective s are of decorator type.
Manopt.decorate_objective! — Function
decorate_objective!(M, o::AbstractManifoldObjective)decorate the AbstractManifoldObjectiveo with specific decorators.
Optional arguments
optional arguments provide necessary details on the decorators. A specific one is used to activate certain decorators.
cache=missing: specify a cache. Currently:Simpleis supported and:LRUif you loadLRUCache.jl. For this case a tuple specifying what to cache and how many can be provided, has to be specified. For example(:LRU, [:Cost, :Gradient], 10)states that the last 10 used cost function evaluations and gradient evaluations should be stored. Seeobjective_cache_factoryfor details.count=missing: specify calls to the objective to be called, seeManifoldCountObjectivefor the full listobjective_type=:Riemannian: specify that an objective is:Riemannianor:Euclidean. The:Euclideansymbol is equivalent to specifying it as:Embedded, since in the end, both refer to converting an objective from the embedding (whether its Euclidean or not) to the Riemannian one.
See also
Embedded objectives
Manopt.EmbeddedManifoldObjective — Type
EmbeddedManifoldObjective{P, T, E, O2, O1<:AbstractManifoldObjective{E}} <:
AbstractDecoratedManifoldObjective{E,O2}Declare an objective to be defined in the embedding. This also declares the gradient to be defined in the embedding, and especially being the Riesz representer with respect to the metric in the embedding. The types can be used to still dispatch on also the undecorated objective type O2.
Fields
objective: the objective that is defined in the embeddingp=nothing: a point in the embedding.X=nothing: a tangent vector in the embedding
When a point in the embedding p is provided, embed! is used in place of this point to reduce memory allocations. Similarly X is used when embedding tangent vectors
Scaled objectives
Manopt.ScaledManifoldObjective — Type
ScaledManifoldObjective{E, O2, O1<:AbstractManifoldObjective{E},F} <:
AbstractDecoratedManifoldObjective{E,O2}Declare an objective to be defined as a scaled version of an existing objective.
This rescales all involved functions.
For now the functions rescaled are
- the cost
- the gradient
- the Hessian
Fields
objective: the objective that is defined in the embeddingscale=1: the scaling applied
Constructors
ScaledManifoldObjective(objective, scale::Real=1)Generate a scaled manifold objective based on objective with scale being 1 by default in the first, scale=-1 in the second case. The multiplication from the left with a scalar is also overloaded.
-objectiveThe single-parameter minus is overloaded to have a short notation turning a maximization problem into a minimization one, which would fit the framework provided within Manopt.jl
scale * objectiveEquivalent to the first constructor, but might be nicer to write in a few places.
Cache objective
Since single function calls, for example to the cost or the gradient, might be expensive, a simple cache objective exists as a decorator, that caches one cost value or gradient.
It can be activated/used with the cache= keyword argument available for every solver.
Manopt.reset_counters! — Function
reset_counters(co::ManifoldCountObjective, value::Integer=0)Reset all values in the count objective to value.
Manopt.objective_cache_factory — Function
objective_cache_factory(M::AbstractManifold, o::AbstractManifoldObjective, cache::Symbol)Generate a cached variant of the AbstractManifoldObjective o on the AbstractManifold M based on the symbol cache.
The following caches are available
:Simplegenerates aSimpleManifoldCachedObjective:LRUgenerates aManifoldCachedObjectivewhere you should use the form(:LRU, [:Cost, :Gradient])to specify what should be cached or(:LRU, [:Cost, :Gradient], 100)to specify the cache size. Here this variant defaults to(:LRU, [:Cost, :Gradient], 100), caching up to 100 cost and gradient values.[1]
objective_cache_factory(M::AbstractManifold, o::AbstractManifoldObjective, cache::Tuple{Symbol, Array, Array})
objective_cache_factory(M::AbstractManifold, o::AbstractManifoldObjective, cache::Tuple{Symbol, Array})Generate a cached variant of the AbstractManifoldObjective o on the AbstractManifold M based on the symbol cache[1], where the second element cache[2] are further arguments to the cache and the optional third is passed down as keyword arguments.
For all available caches see the simpler variant with symbols.
A simple cache
A first generic cache is always available, but it only caches one gradient and one cost function evaluation (for the same point).
Manopt.SimpleManifoldCachedObjective — Type
SimpleManifoldCachedObjective{O<:AbstractManifoldFirstOrderObjective{E}, P, T,C} <: AbstractDecoratedManifoldObjective{E,O}Provide a simple cache for an AbstractManifoldFirstOrderObjective that is, this cache stores a point p and a gradient $\operatorname{grad} f(p)$ in X as well as a cost value $f(p)$ in c. It can also easily evaluate the differential based on the cached gradient.
Both X and c are accompanied by booleans to keep track of their validity.
While this does not provide a cache for the differential, it uses the cached gradient as a help to evaluate the differential, if an up-to-date gradient is available. It otherwise does call the original differential.
This simple cache does not take into account, that some first order objectives have a common function for cost & grad. It only caches the function that is actually called.
Constructors
SimpleManifoldCachedObjective(M::AbstractManifold, obj::AbstractManifoldFirstOrderObjective; kwargs...)Keyword arguments
p=rand(M): a point on the manifold to initialize the cache withX=get_gradient(M, obj, p)orzero_vector(M,p): a tangent vector to store the gradient in, see alsoinitialize=c=[get_cost](@ref)(M, obj, p)or0.0: a value to store the cost function ininitialize`initialized=true: whether to initialize the cachedXandcor not.
where both for p and X copies are generated before they are stored.
SimpleManifoldCachedObjective(obj::AbstractManifoldFirstOrderObjective, p, X, c; initialized = false)Similar as above but initialising all fields directly and without copies and initialized indicated whether the three values correspond to an evaluation from obj.
A generic cache
For the more advanced cache, you need to implement some type of cache yourself, that provides a get! and implement init_caches. This is for example provided if you load LRUCache.jl. Then you obtain
Manopt.ManifoldCachedObjective — Type
ManifoldCachedObjective{E,P,O<:AbstractManifoldObjective{<:E},C<:NamedTuple{}} <: AbstractDecoratedManifoldObjective{E,P}Create a cache for an objective, based on a NamedTuple that stores some kind of cache.
Constructor
ManifoldCachedObjective(M, o::AbstractManifoldObjective, caches::Vector{Symbol}; kwargs...)Create a cache for the AbstractManifoldObjective where the Symbols in caches indicate, which function evaluations to cache.
Supported symbols
| Symbol | Caches calls to (incl. ! variants) | Comment |
|---|---|---|
:Cost | get_cost | |
:Differential | get_differential(M, p, X). | |
:EqualityConstraint | get_equality_constraint(M, p, i) | |
:EqualityConstraints | get_equality_constraint(M, p, :) | |
:GradEqualityConstraint | get_grad_equality_constraint | tangent vector per (p,i) |
:GradInequalityConstraint | get_inequality_constraint | tangent vector per (p,i) |
:Gradient | get_gradient(M,p) | tangent vectors |
:Hessian | get_hessian | tangent vectors |
:InequalityConstraint | get_inequality_constraint(M, p, j) | |
:InequalityConstraints | get_inequality_constraint(M, p, :) | |
:Preconditioner | get_preconditioner | tangent vectors |
:ProximalMap | get_proximal_map | point per (p,λ,i) |
:StochasticGradients | get_gradients | vector of tangent vectors |
:StochasticGradient | get_gradient(M, p, i) | tangent vector per (p,i) |
:SubGradient | get_subgradient | tangent vectors |
:SubtrahendGradient | get_subtrahend_gradient | tangent vectors |
Keyword arguments
p=rand(M): the type of the keys to be used in the caches. Defaults to the default representation onM.value=get_cost(M, objective, p): the type of values for numeric values in the cacheX=zero_vector(M,p): the type of values to be cached for gradient and Hessian calls.cache=[:Cost]: a vector of symbols indicating which function calls should be cached.cache_size=10: number of (least recently used) calls to cachecache_sizes=Dict{Symbol,Int}(): a named tuple or dictionary specifying the sizes individually for each cache.
Manopt.init_caches — Function
init_caches(caches, T::Type{LRU}; kwargs...)Given a vector of symbols caches, this function sets up the NamedTuple of caches, where T is the type of cache to use.
Keyword arguments
p=rand(M): a point on a manifold, to both infer its type for keys and initialize cachesvalue=0.0: a value both typing and initialising number-caches, the default is for (Float) values like the cost.X=zero_vector(M, p): a tangent vector atpto both type and initialize tangent vector cachescache_size=10: a default cache size to usecache_sizes=Dict{Symbol,Int}(): a dictionary of sizes for thecachesto specify different (non-default) sizes
init_caches(M::AbstractManifold, caches, T; kwargs...)Given a vector of symbols caches, this function sets up the NamedTuple of caches for points/vectors on M, where T is the type of cache to use.
Count objective
Manopt.ManifoldCountObjective — Type
ManifoldCountObjective{E,P,O<:AbstractManifoldObjective,I<:Integer} <: AbstractDecoratedManifoldObjective{E,P}A wrapper for any AbstractManifoldObjective of type O to count different calls to parts of the objective.
Fields
countsa dictionary of symbols mapping to integers keeping the counted valuesobjectivethe wrapped objective
Supported symbols
| Symbol | Counts calls to (incl. ! variants) | Comment |
|---|---|---|
:Cost | get_cost | |
:Differential | get_differential. | |
:EqualityConstraint | get_equality_constraint | requires vector of counters |
:EqualityConstraints | get_equality_constraint | when evaluating all of them with : |
:GradEqualityConstraint | get_grad_equality_constraint | requires vector of counters |
:GradEqualityConstraints | get_grad_equality_constraint | when evaluating all of them with : |
:GradInequalityConstraint | get_inequality_constraint | requires vector of counters |
:GradInequalityConstraints | get_inequality_constraint | when evaluating all of them with : |
:Gradient | get_gradient(M,p) | |
:Hessian | get_hessian | |
:InequalityConstraint | get_inequality_constraint | requires vector of counters |
:InequalityConstraints | get_inequality_constraint | when evaluating all of them with : |
:Preconditioner | get_preconditioner | |
:ProximalMap | get_proximal_map | |
:StochasticGradients | get_gradients | |
:StochasticGradient | get_gradient(M, p, i) | |
:SubGradient | get_subgradient | |
:SubtrahendGradient | get_subtrahend_gradient |
Constructors
ManifoldCountObjective(objective::AbstractManifoldObjective, counts::Dict{Symbol, <:Integer})Initialise the ManifoldCountObjective to wrap objective initializing the set of counts
ManifoldCountObjective(M::AbstractManifold, objective::AbstractManifoldObjective, count::AbstractVecor{Symbol}, init=0)Count function calls on objective using the symbols in count initialising all entries to init.
Internal decorators and functions
Manopt.ReturnManifoldObjective — Type
ReturnManifoldObjective{E,O2,O1<:AbstractManifoldObjective{E}} <: AbstractDecoratedManifoldObjective{E,O2}A wrapper to indicate that get_solver_result should return the inner objective.
The types are such that one can still dispatch on the undecorated type O2 of the original objective as well.
- 1This cache requires
LRUCache.jlto be loaded as well.