Skip to content

Commit 5fd9705

Browse files
committed
Merge branch 'dev-0.6' into kellertuer/JuMP-on-non-array-points
# Conflicts: # Changelog.md
2 parents 300f640 + 33c090d commit 5fd9705

130 files changed

Lines changed: 4558 additions & 4109 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Changelog.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
## [0.6.0] unreleased
1010

11-
This is a breaking change since the JuMP extension is dropped.
12-
13-
### Changed
14-
15-
* removed the JuMP extension, since it was a bit incomplete and hard to maintain, and not possible to extend to all manifolds. The main reason is, that matrices are a bit tough to represent in JuMP, which is vector based, and types points are nearly impossible to represent. Distinguishing between points and tangent vectors is also a bit hard to track.
16-
17-
## [0.5.35] April 3, 2026
11+
This is a breaking change since the JuMP extension is dropped.
1812

1913
### Changed
2014

15+
* `NonlinearLeastSquaresObjective` is now called `ManifoldNonlinearLeastSquaresObjective` (#569).
16+
* This is a breaking release in order to move a few parts to a unified naming and since we
17+
discontinue the `JuMP` extension. (#532)
2118
* Improved formatting of the references in the Readme.md (#586)
2219
* Bump compat for RecursiveArrayTools.jl to include version 4
2320
* deactivate CompatHelper Action and solely use dependabot
2421

22+
### Fixed
23+
24+
* Fixed `show` methods of various state and stopping criteria to properly handle both `repr` and multiline printing (#569)
25+
* Unified all `show` methods and their human readable analoga `status_summary` throughout the package (#569)
26+
* Fixed some text descriptions of a few stopping criteria.
27+
* unify naming of fields, `debugDictionary` of the debug state is now called `debug_dictionary`
28+
* the `NesterovRule` now also stores an actual `AbstractRetractionMethod` instead of implicitly always using the default one.
29+
30+
2531
## [0.5.34] March 3, 2026
2632

2733
### Fixed

_typos.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ methodes = "methodes" # french
33
Serie = "Serie" # french
44
sur = "sur" # french
55
cmo = "cmo" # often used abbreviation for constrained manifold objective
6-
6+
nd = "nd" # like in 2nd
77
[files]
88
extend-exclude = [
99
"tutorials/*.html",

docs/src/plans/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ The following symbols are used.
2828
| `:Activity` | [`DebugWhenActive`](@ref) | activity of the debug action stored within |
2929
| `:Basepoint` | [`TangentSpace`](@extref ManifoldsBase `ManifoldsBase.TangentSpace`) | the point the tangent space is at |
3030
| `:Cost` | generic |the cost function (within an objective, as pass down) |
31-
| `:Debug` | [`DebugSolverState`](@ref) | the stored `debugDictionary` |
31+
| `:Debug` | [`DebugSolverState`](@ref) | the stored `debug_dictionary` |
3232
| `:Gradient` | generic | the gradient function (within an objective, as pass down) |
3333
| `:Iterate` | generic | the (current) iterate, similar to [`set_iterate!`](@ref), within a state |
3434
| `:Manifold` | generic |the manifold (within a problem, as pass down) |

docs/src/plans/objective.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ AbstractManifoldFirstOrderObjective
115115
ManifoldFirstOrderObjective
116116
ManifoldAlternatingGradientObjective
117117
ManifoldStochasticGradientObjective
118-
NonlinearLeastSquaresObjective
118+
ManifoldNonlinearLeastSquaresObjective
119119
```
120120

121121
While the [`ManifoldFirstOrderObjective`](@ref) allows to provide different

src/Manopt.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
"""
99
module Manopt
1010

11+
# When indenting something in print, use two spaces (or maybe \t later?)
12+
_MANOPT_INDENT = " "
13+
1114
import Base: &, copy, getindex, identity, length, setindex!, show, |
1215
import LinearAlgebra: reflect!
1316
import ManifoldsBase: embed!, plot_slope, prepare_check_result, find_best_slope_window
@@ -286,7 +289,7 @@ export AbstractDecoratedManifoldObjective,
286289
EmbeddedManifoldObjective,
287290
ScaledManifoldObjective,
288291
ManifoldCountObjective,
289-
NonlinearLeastSquaresObjective,
292+
ManifoldNonlinearLeastSquaresObjective,
290293
ManifoldAlternatingGradientObjective,
291294
ManifoldCostGradientObjective,
292295
ManifoldCostObjective,
@@ -341,6 +344,7 @@ export AbstractGradientSolverState,
341344
ProjectedGradientMethodState,
342345
ProximalBundleMethodState,
343346
ProximalGradientMethodState,
347+
ProximalPointState,
344348
RecordSolverState,
345349
StepsizeState,
346350
StochasticGradientDescentState,
@@ -595,7 +599,7 @@ export render_asymptote
595599
#
596600
# Debugs
597601
export DebugSolverState, DebugAction, DebugGroup, DebugEntry, DebugEntryChange, DebugEvery
598-
export DebugChange, DebugGradientChange
602+
export DebugCallback, DebugChange, DebugGradientChange
599603
export DebugIterate, DebugIteration, DebugDivider, DebugTime
600604
export DebugFeasibility
601605
export DebugCost, DebugStoppingCriterion

src/helpers/LineSearchesTypes.jl

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ Wrapper for line searches available in the `LineSearches.jl` library.
77
88
LineSearchesStepsize(M::AbstractManifold, linesearch; kwargs...
99
LineSearchesStepsize(
10-
linesearch;
11-
retraction_method=ExponentialRetraction(),
12-
vector_transport_method=ParallelTransport(),
10+
linesearch; retraction_method=ExponentialRetraction(), vector_transport_method=ParallelTransport(),
1311
)
1412
1513
Wrap `linesearch` (for example [`HagerZhang`](https://julianlsolvers.github.io/LineSearches.jl/latest/reference/linesearch.html#LineSearches.HagerZhang)
@@ -34,9 +32,7 @@ function LineSearchesStepsize(
3432
linesearch;
3533
initial_guess::AbstractInitialLinesearchGuess = ConstantInitialGuess(),
3634
retraction_method::AbstractRetractionMethod = default_retraction_method(M),
37-
vector_transport_method::AbstractVectorTransportMethod = default_vector_transport_method(
38-
M
39-
),
35+
vector_transport_method::AbstractVectorTransportMethod = default_vector_transport_method(M),
4036
last_stepsize::Real = NaN,
4137
)
4238
return LineSearchesStepsize(
@@ -49,21 +45,32 @@ function LineSearchesStepsize(
4945
end
5046
function LineSearchesStepsize(
5147
linesearch;
52-
initial_guess::AbstractInitialLinesearchGuess = ConstantInitialGuess(),
53-
retraction_method::AbstractRetractionMethod = ExponentialRetraction(),
54-
vector_transport_method::AbstractVectorTransportMethod = ParallelTransport(),
48+
initial_guess::ILG = ConstantInitialGuess(),
49+
retraction_method::RM = ExponentialRetraction(),
50+
vector_transport_method::VTM = ParallelTransport(),
5551
last_stepsize::Real = NaN,
56-
)
57-
return LineSearchesStepsize{
58-
typeof(linesearch), typeof(initial_guess), typeof(retraction_method), typeof(vector_transport_method), typeof(last_stepsize),
59-
}(
52+
) where {ILG <: AbstractInitialLinesearchGuess, RM <: AbstractRetractionMethod, VTM <: AbstractVectorTransportMethod}
53+
return LineSearchesStepsize{typeof(linesearch), ILG, RM, VTM, typeof(last_stepsize)}(
6054
linesearch, initial_guess, retraction_method, vector_transport_method, last_stepsize
6155
)
6256
end
63-
6457
function Base.show(io::IO, cs::LineSearchesStepsize)
6558
return print(
6659
io,
6760
"LineSearchesStepsize($(cs.linesearch); initial_guess=$(cs.initial_guess), retraction_method=$(cs.retraction_method), vector_transport_method=$(cs.vector_transport_method), last_stepsize=$(cs.last_stepsize))",
6861
)
6962
end
63+
function status_summary(cs::LineSearchesStepsize; context::Symbol = :default)
64+
(context === :short) && return repr(cs)
65+
(context === :inline) && return "A linesearch stepsize wrapper for LineSearches.jl (last step size $(cs.last_stepsize))"
66+
return """
67+
A step size wrapper for LineSearches.jl
68+
(last step size: $(cs.last_stepsize))
69+
70+
## Parameters
71+
* line search: $(_MANOPT_INDENT)$(cs.linesearch)
72+
* initial guess: $(_MANOPT_INDENT)$(cs.initial_guess)
73+
* retraction method: $(_MANOPT_INDENT)$(cs.retraction_method)
74+
* vector transport method:$(_MANOPT_INDENT)$(cs.vector_transport_method)
75+
"""
76+
end

src/helpers/test.jl

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,28 @@ using ManifoldDiff
2525
# Dummy types
2626
struct DummyManifold <: AbstractManifold{ManifoldsBase.ℝ} end
2727

28-
struct DummyDecoratedObjective{E, O <: AbstractManifoldObjective} <:
29-
Manopt.AbstractDecoratedManifoldObjective{E, O}
28+
struct DummyDecoratedObjective{E, O <: AbstractManifoldObjective} <: Manopt.AbstractDecoratedManifoldObjective{E, O}
3029
objective::O
3130
end
32-
function DummyDecoratedObjective(
33-
o::O
34-
) where {E <: AbstractEvaluationType, O <: AbstractManifoldObjective{E}}
31+
function DummyDecoratedObjective(o::O) where {E <: AbstractEvaluationType, O <: AbstractManifoldObjective{E}}
3532
return DummyDecoratedObjective{E, O}(o)
3633
end
34+
function Manopt.status_summary(
35+
ddo::DummyDecoratedObjective; kwargs...
36+
)
37+
return "A dummy decorator for " * Manopt.status_summary(ddo.objective; kwargs...)
38+
end
39+
function Base.show(io::IO, ddo::DummyDecoratedObjective)
40+
print(io, "DummyDecoratedObjective(")
41+
print(io, ddo.objective)
42+
return print(io, ")")
43+
end
44+
struct DummyEmptyDecoratedObjective{E, O <: AbstractManifoldObjective} <: Manopt.AbstractDecoratedManifoldObjective{E, O}
45+
objective::O
46+
function DummyEmptyDecoratedObjective(o::O) where {E <: AbstractEvaluationType, O <: AbstractManifoldObjective{E}}
47+
return new{E, O}(o)
48+
end
49+
end
3750

3851
struct DummyProblem{M <: AbstractManifold} <: AbstractManoptProblem{M} end
3952
struct DummyStoppingCriteriaSet <: StoppingCriterionSet end
@@ -43,6 +56,8 @@ mutable struct DummyState <: AbstractManoptSolverState
4356
storage::Vector{Float64}
4457
end
4558
DummyState() = DummyState([])
59+
Manopt.status_summary(ds::DummyState; context = :Default) = "A Manopt Test state with storage $(ds.storage)"
60+
Base.show(io::IO, ds::DummyState) = print(io, "Manopt.Test.DummyState($(ds.storage))")
4661
Manopt.get_iterate(::DummyState) = NaN
4762
Manopt.set_parameter!(s::DummyState, ::Val, v) = s
4863
Manopt.set_parameter!(s::DummyState, ::Val{:StoppingCriterion}, v) = s

src/plans/adaptive_regularization_with_cubics_plan.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,21 @@ end
104104
function get_gradient_function(arcmo::AdaptiveRegularizationWithCubicsModelObjective)
105105
return (TpM, X) -> get_gradient(TpM, arcmo, X)
106106
end
107+
function Base.show(io::IO, arcmo::AdaptiveRegularizationWithCubicsModelObjective)
108+
print(io, "AdaptiveRegularizationWithCubicsModelObjective(")
109+
print(io, arcmo.objective); print(io, ", ")
110+
print(io, arcmo.σ)
111+
return print(io, ")")
112+
end
113+
function status_summary(arcmo::AdaptiveRegularizationWithCubicsModelObjective; context::Symbol = :default)
114+
(context === :short) && return repr(arcmo)
115+
(context === :inline) && return "The (tangent space) model for the adaptive regularization with cubics sub problem with parameter σ=$(arcmo.σ) for the objective $(status_summary(arcmo.objective; context = context))"
116+
return """
117+
The cubic polynomial based model for the sub problem of the Adaptive Regularization with cubics solver
118+
119+
## Regularization parameter
120+
σ = $(arcmo.σ)
121+
122+
## Objective
123+
$(_in_str(status_summary(arcmo.objective)))"""
124+
end

src/plans/alternating_gradient_plan.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,20 @@ function get_gradient!(
149149
mago.gradient!![k](M, X, p)
150150
return X
151151
end
152+
153+
function Base.show(io::IO, mago::ManifoldAlternatingGradientObjective{E}) where {E}
154+
print(io, "ManifoldAlternatingGradientObjective(")
155+
print(io, mago.cost); print(io, ", "); print(io, mago.gradient!!); print(io, "; ")
156+
print(io, _to_kw(E))
157+
return print(io, ")")
158+
end
159+
function status_summary(mago::ManifoldAlternatingGradientObjective; context::Symbol = :default)
160+
(context === :short) && (return repr(mago))
161+
(context === :inline) && (return "An alternating gradient objective on a manifold.")
162+
return """
163+
An alternating gradient objective providing the gradient as components with which to alternate
164+
165+
## Functions
166+
* cost: $(_MANOPT_INDENT)$(mago.cost)
167+
* gradient:$(_MANOPT_INDENT)$(mago.gradient!!)"""
168+
end

src/plans/bundle_plan.jl

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,20 +140,20 @@ function get_reason(sc::StopWhenLagrangeMultiplierLess)
140140
return ""
141141
end
142142

143-
function status_summary(sc::StopWhenLagrangeMultiplierLess)
143+
function status_summary(sc::StopWhenLagrangeMultiplierLess; context::Symbol = :default)
144144
s = (sc.at_iteration >= 0) ? "reached" : "not reached"
145145
msg = "Lagrange multipliers"
146146
isnothing(sc.names) && (msg *= " with tolerances $(sc.tolerances)")
147147
if !isnothing(sc.names)
148148
msg *= join(["$si < $bi" for (si, bi) in zip(sc.names, sc.tolerances)], ", ")
149149
end
150-
return "$(msg) :\t$(s)"
150+
return (_is_inline(context) ? "" : "A stopping criterion to stop when the Lagrange multipliers are less than $(sc.tolerances).\n$(_MANOPT_INDENT)") * "$(msg):$(_MANOPT_INDENT)$(s)"
151151
end
152152
function show(io::IO, sc::StopWhenLagrangeMultiplierLess)
153153
n = isnothing(sc.names) ? "" : ", $(names)"
154154
return print(
155155
io,
156-
"StopWhenLagrangeMultiplierLess($(sc.tolerances); mode=:$(sc.mode)$n)\n $(status_summary(sc))",
156+
"StopWhenLagrangeMultiplierLess($(sc.tolerances); mode=:$(sc.mode)$n)",
157157
)
158158
end
159159

@@ -181,6 +181,12 @@ mutable struct DebugWarnIfLagrangeMultiplierIncreases <: DebugAction
181181
return new(warn, Float64(Inf), tol)
182182
end
183183
end
184-
function show(io::IO, di::DebugWarnIfLagrangeMultiplierIncreases)
185-
return print(io, "DebugWarnIfLagrangeMultiplierIncreases(; tol=\"$(di.tol)\")")
184+
function show(io::IO, d::DebugWarnIfLagrangeMultiplierIncreases)
185+
m = (d.status === :No ? "" : ":$(d.status)")
186+
return print(io, "DebugWarnIfLagrangeMultiplierIncreases($(m); tol=\"$(d.tol)\")")
187+
end
188+
function status_summary(d::DebugWarnIfLagrangeMultiplierIncreases; context::Symbol = :default)
189+
(context === :short) && return repr(d)
190+
m = (d.status === :Once) ? "once" : (d.status === :No ? "(inactive)" : "")
191+
return "a DebugAction warning if the lagange multiplier increases in an iteration $m."
186192
end

0 commit comments

Comments
 (0)