Skip to content

interior_point_Newton on ProductManifold #540

@JoshuaLampert

Description

@JoshuaLampert

I'm trying to solve a constrained optimization problem with the interior_point_Newton method on a ProductManifold and come across two problems (so far), where I think I was able to solve the first one, but am still struggling with the second one.
The MWE I am using is:

using Manifolds, Manopt
using RecursiveArrayTools

N = 5
M1 = SkewSymmetricMatrices(N)
M2 = PositiveVectors(N)
M = ProductManifold(M1, M2)

# Just some dummy objective and constraint
f(M, x) = 1.0
grad_f(M, x) = 0.0
h(M, x) = 0.0
grad_h(M, x) = 0.0
objective = ConstrainedManifoldObjective(f, grad_f; h = h, grad_h = grad_h, g = nothing,
                                         grad_g = nothing, equality_constraints = 1)

p = rand(M)
interior_point_Newton(M, objective, p)

For the first one I needed to adjust Manopt.jl in three places, namely:

N = M × vector_space(length(μ)) × vector_space(length(λ)) × vector_space(length(s)),

_step_M::AbstractManifold = M × vector_space(length(μ)) × vector_space(length(λ)) ×

and
_sub_M = M × vector_space(length(λ)),

where in each place I needed to replace the × by explicit calls to ProductManifold (e.g., for the first one N = ProductManifold(M, vector_space(length(μ)), vector_space(length(λ)), vector_space(length(s))). As I understand this is necessary for M being already a ProductManifold because the code relies on things like N[1] being M again, which in the × case would only return the first component of M and not the ProductManifold itself. However, by using ProductManifold(M, ...) one gets a nested ProductManifold, which seems to me as the wanted behavior in this case. If you agree, I am happy to create a PR for that.
After resolving this, I get the stacktrace

ERROR: LoadError: MethodError: no method matching get_hessian(::ProductManifold{…}, ::ManifoldFirstOrderObjective{…}, ::ArrayPartition{…}, ::ArrayPartition{…})
The function `get_hessian` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  get_hessian(::AbstractManifold, ::EmbeddedManifoldObjective{P, Missing, E} where E, ::Any, ::Any) where P
   @ Manopt ~/.julia/dev/Manopt/src/plans/embedded_objective.jl:139
  get_hessian(::AbstractManifold, ::EmbeddedManifoldObjective{P, T, E} where E, ::Any, ::Any) where {P, T}
   @ Manopt ~/.julia/dev/Manopt/src/plans/embedded_objective.jl:151
  get_hessian(::AbstractManifold, ::ScaledManifoldObjective, ::Any, ::Any)
   @ Manopt ~/.julia/dev/Manopt/src/plans/scaled_objective.jl:105
  ...

Stacktrace:
 [1] get_hessian(M::ProductManifold{…}, co::ConstrainedManifoldObjective{…}, p::ArrayPartition{…}, X::ArrayPartition{…})
   @ Manopt ~/.julia/dev/Manopt/src/plans/constrained_plan.jl:805
 [2] (::CondensedKKTVectorFieldJacobian{…})(N::ProductManifold{…}, Y::ArrayPartition{…}, q::ArrayPartition{…}, X::ArrayPartition{…})
   @ Manopt ~/.julia/dev/Manopt/src/plans/interior_point_Newton_plan.jl:432
 [3] (::CondensedKKTVectorFieldJacobian{…})(N::ProductManifold{…}, q::ArrayPartition{…}, X::ArrayPartition{…})
   @ Manopt ~/.julia/dev/Manopt/src/plans/interior_point_Newton_plan.jl:420
 [4] get_hessian(TpM::Fiber{…}, slso::SymmetricLinearSystemObjective{…}, X::ArrayPartition{…}, V::ArrayPartition{…})
   @ Manopt ~/.julia/dev/Manopt/src/plans/conjugate_residual_plan.jl:149
 [5] get_gradient(TpM::Fiber{…}, slso::SymmetricLinearSystemObjective{…}, X::ArrayPartition{…})
   @ Manopt ~/.julia/dev/Manopt/src/plans/conjugate_residual_plan.jl:113
 [6] interior_point_Newton(M::ProductManifold{…}, cmo::ConstrainedManifoldObjective{…}, p::ArrayPartition{…}; kwargs::@Kwargs{})
   @ Manopt ~/.julia/dev/Manopt/src/solvers/interior_point_Newton.jl:142
 [7] top-level scope
   @ ~/.julia/dev/SummationByPartsOperatorsExtra/run/debug_Manopt.jl:89
 [8] include(mapexpr::Function, mod::Module, _path::String)
   @ Base ./Base.jl:307
 [9] top-level scope
   @ REPL[1]:1
in expression starting at /home/lampert/.julia/dev/SummationByPartsOperatorsExtra/run/debug_Manopt.jl:89
Some type information was truncated. Use `show(err)` to see complete types.

which comes from trying to create the sub_state here:

sub_state::St = decorate_state!(
ConjugateResidualState(
TangentSpace(_sub_M, _sub_p),
sub_objective;
X = _sub_X,
stop = sub_stopping_criterion,
sub_kwargs...,
);
sub_kwargs...,
),

Reducing this even further one can also get the same error by calling

Xp = rand(M)
get_hessian(M, objective, p, Xp)

instead of the whole call to interior_point_Newton in the MWE above. Is there a missing definition of get_hessian or do you have an idea how to fix this?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions