Skip to content

Commit f531e5f

Browse files
add documentation for hybrid coeff, add tests for cg plan hybrid coeff, minor changes hybrid coeff
1 parent 1a5e75b commit f531e5f

4 files changed

Lines changed: 59 additions & 39 deletions

File tree

docs/src/solvers/conjugate_gradient_descent.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ DaiYuanCoefficient
2727
FletcherReevesCoefficient
2828
HagerZhangCoefficient
2929
HestenesStiefelCoefficient
30+
HybridCoefficient
3031
LiuStoreyCoefficient
3132
PolakRibiereCoefficient
3233
SteepestDescentCoefficient
@@ -52,6 +53,7 @@ Manopt.DaiYuanCoefficientRule
5253
Manopt.FletcherReevesCoefficientRule
5354
Manopt.HagerZhangCoefficientRule
5455
Manopt.HestenesStiefelCoefficientRule
56+
Manopt.HybridCoefficientRule
5557
Manopt.LiuStoreyCoefficientRule
5658
Manopt.PolakRibiereCoefficientRule
5759
Manopt.SteepestDescentCoefficientRule

src/Manopt.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,8 @@ export SteepestDescentCoefficient,
446446
#
447447
# Restart Conditions
448448
export AbstractRestartCondition
449-
export NeverRestart,
450-
RestartOnNonDescent,
449+
export NeverRestart,
450+
RestartOnNonDescent,
451451
RestartOnNonSufficientDescent
452452
#
453453
#

src/plans/conjugate_gradient_plan.jl

Lines changed: 53 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,17 +1043,17 @@ A functor `(problem, state, k) -> β_k` to compute hybrid conjugate gradient upd
10431043
10441044
# Fields
10451045
1046-
coefficients::AbstractArray{DirectionUpdateRuleStorage}
1047-
coefficient_fallback::DirectionUpdateRuleStorage
1048-
scalar_fallback::Real
1046+
* `coefficients::NTuple{DirectionUpdateRuleStorage, N}`: `NTuple` containing storage wrappers of CG coefficients of which the minimum is taken
1047+
* `lower_bound::DirectionUpdateRuleStorage`: storage wrapper of lower bound CG coefficient
1048+
* `lower_bound_scale::Real`: scalar the lower bound is multiplied with
10491049
10501050
# Constructor
10511051
10521052
HybridCoefficientRule(
10531053
M::AbstractManifold,
1054-
coefficients::AbstractArray{Union{DirectionUpdateRule,ManifoldDefaultsFactory}},
1055-
coefficient_fallback::Union{DirectionUpdateRule,ManifoldDefaultsFactory},
1056-
scalar_fallback::Real
1054+
coefficients::NTuple{N, DirectionUpdateRuleStorage},
1055+
lower_bound::Union{DirectionUpdateRule,ManifoldDefaultsFactory},
1056+
lower_bound_scale::Real
10571057
)
10581058
10591059
Construct the hybrid coefficient update rule.
@@ -1062,60 +1062,76 @@ Construct the hybrid coefficient update rule.
10621062
10631063
[`HybridCoefficient`](@ref), [`conjugate_gradient_descent`](@ref)
10641064
"""
1065-
struct HybridCoefficientRule <: DirectionUpdateRule
1066-
coefficients::AbstractArray{DirectionUpdateRuleStorage}
1067-
coefficient_fallback::DirectionUpdateRuleStorage
1068-
scalar_fallback::Real
1065+
struct HybridCoefficientRule{N} <: DirectionUpdateRule where N
1066+
coefficients::NTuple{N, DirectionUpdateRuleStorage}
1067+
lower_bound::DirectionUpdateRuleStorage
1068+
lower_bound_scale::Real
10691069
end
10701070
function HybridCoefficientRule(
1071-
M::AbstractManifold,
1072-
args...;
1073-
coefficient_fallback::Union{DirectionUpdateRule,ManifoldDefaultsFactory}=SteepestDescentCoefficient(),
1074-
scalar_fallback::Real=1.0
1075-
)
1076-
coefficients_new = [DirectionUpdateRuleStorage(M, _produce_type(c,M)) for c in args]
1077-
coefficient_fallback_new = DirectionUpdateRuleStorage(M, _produce_type(coefficient_fallback,M))
1078-
return Manopt.HybridCoefficientRule(coefficients_new, coefficient_fallback_new, scalar_fallback)
1071+
M::AbstractManifold,
1072+
args...;
1073+
lower_bound::Union{DirectionUpdateRule, ManifoldDefaultsFactory} = SteepestDescentCoefficient(),
1074+
lower_bound_scale::Real = 1.0
1075+
)
1076+
N = length(args)
1077+
coefficients_new = NTuple{N, DirectionUpdateRuleStorage}([DirectionUpdateRuleStorage(M, _produce_type(c, M)) for c in args])
1078+
lower_bound_new = DirectionUpdateRuleStorage(M, _produce_type(lower_bound, M))
1079+
return Manopt.HybridCoefficientRule(coefficients_new, lower_bound_new, lower_bound_scale)
10791080
end
10801081

10811082
update_rule_storage_points(::HybridCoefficientRule) = Tuple{}
10821083
update_rule_storage_vectors(::HybridCoefficientRule) = Tuple{}
10831084

10841085
function (u::DirectionUpdateRuleStorage{<:HybridCoefficientRule})(
1085-
amp::AbstractManoptProblem, cgs::ConjugateGradientDescentState, i
1086-
)
1087-
βs = [c(amp, cgs, i) for c = u.coefficient.coefficients]
1088-
β_fallback = u.coefficient.coefficient_fallback(amp, cgs, i)
1089-
return max(u.coefficient.scalar_fallback * β_fallback, min(βs...))
1086+
amp::AbstractManoptProblem, cgs::ConjugateGradientDescentState, i
1087+
)
1088+
βs = [c(amp, cgs, i) for c in u.coefficient.coefficients]
1089+
β_lower_bound = u.coefficient.lower_bound(amp, cgs, i)
1090+
return max(u.coefficient.lower_bound_scale * β_lower_bound, min(βs...))
10901091
end
10911092
function show(io::IO, u::HybridCoefficientRule)
1092-
print(
1093+
coefficient_str = join([repr(c.coefficient) for c = u.coefficients], ", ")
1094+
return print(
10931095
io,
1094-
"Manopt.HybridCoefficientRule(coefficents=$(u.coefficents),coefficent_fallback=$(u.coefficent_fallback),scalar_fallback=$(u.scalar_fallback))",
1096+
"Manopt.HybridCoefficientRule(coefficients=($coefficient_str)),lower_bound=$(repr(u.lower_bound.coefficient)),lower_bound_scale=$(u.lower_bound_scale))",
10951097
)
10961098
end
10971099

10981100
"""
1099-
HybridCoefficient(coefficents::AbstractArray{Union{DirectionUpdateRule,ManifoldDefaultsFactory}}; kwargs...)
1100-
HybridCoefficient(M::AbstractManifold, coefficents::AbstractArray{Union{DirectionUpdateRule,ManifoldDefaultsFactory}}; kwargs...)
1101+
HybridCoefficient(coefficients::AbstractArray{Union{DirectionUpdateRule,ManifoldDefaultsFactory}}; kwargs...)
1102+
HybridCoefficient(M::AbstractManifold, coefficients::AbstractArray{Union{DirectionUpdateRule,ManifoldDefaultsFactory}}; kwargs...)
11011103
1102-
Computes an hybrid update coefficient for the [`conjugate_gradient_descent`](@ref). Given coefficents ``β_i`` for ``i = 1,...,m``,
1103-
a fallback coefficent ``β_0`` and a scalar factor for the fallback ``σ``, it returns ``β_k = max(σ * β_0, min(β_1, .... β_m))``.
1104-
This includes the HS-DY and FR-PRP hybrid parameters introduced in [`SakaiIiduka:2020`](cite) and [`SakaiIiduka:2021`](cite).
1104+
Computes an hybrid update coefficient for the [`conjugate_gradient_descent`](@ref). Given coefficients ``β_i`` for ``i = 1,...,m``,
1105+
a lower bound coefficient ``β_0`` and a scalar factor for the lower bound ``σ``, it returns ``β_k = max(σ * β_0, min(β_1, .... β_m))``.
1106+
This includes the HS-DY and FR-PRP hybrid parameters introduced in [`SakaiIiduka:2020`](cite) and [`SakaiIiduka:2021`](cite)
11051107
11061108
## Input
11071109
1108-
* `coefficents` : an array of [`DirectionUpdateRule`](@ref) or a corresponding
1109-
[`ManifoldDefaultsFactory`](@ref) to produce such a rule.
1110+
* `args...` : CG coefficients of type [`DirectionUpdateRule`](@ref) or a corresponding
1111+
[`ManifoldDefaultsFactory`](@ref) to produce such a rule, of which the minimum is taken in the
1112+
hybrid rule
11101113
11111114
## Keyword arguments
11121115
1113-
* `coefficent_fallback=[`SteepestDescentCoefficient`](@ref)`()` : a fallback [`DirectionUpdateRule`](@ref) or a corresponding
1114-
[`ManifoldDefaultsFactory`](@ref) to produce such a rule, which marks a lower bound for the resulting coefficent.
1115-
* `scalar_fallback=1.0` : a scalar to multiply the fallback coefficent by.
1116+
* `lower_bound=[`SteepestDescentCoefficient`](@ref)`()` : a lower bound [`DirectionUpdateRule`](@ref) or a corresponding
1117+
[`ManifoldDefaultsFactory`](@ref) for the resulting value of `β`
1118+
* `lower_bound_scale=1.0` : a scalar to multiply the lower bound coefficient by.
1119+
1120+
## Examples
1121+
1122+
The FR-PRP parameter reads
1123+
```math
1124+
\\beta_k^{FR-PRP} = \\max\\{0, \\min\\{\\beta_k^{FR}, \\beta_k^{PRP}\\}\\}
1125+
```
1126+
and can be implemented using
1127+
[`HybridCoefficient`](@ref)`(`[`FletcherReevesCoefficient`](@ref)`(),`[`PolakRibiereCoefficient`](@ref)`())`
11161128
1117-
coefficient_fallback::Union{DirectionUpdateRule,ManifoldDefaultsFactory},
1118-
scalar_fallback::Real)
1129+
The HS-DY parameter with parameter `0<σ<1` reads
1130+
```math
1131+
\\beta_k^{HS-DY} = \\max\\{-\\sigma\\beta_k^{DY}, \\min\\{\\beta_k^{HS}, \\beta_k^{DY}\\}\\}
1132+
```
1133+
and can be implemented using
1134+
[`HybridCoefficient`](@ref)`(`[`HestenesStiefelCoefficient`](@ref)`(),`[`DaiYuanCoefficient`](@ref)`(); lower_bound = `[`DaiYuanCoefficient`](@ref)`(), lower_bound_scale = -σ)`
11191135
11201136
11211137
$(_note(:ManifoldDefaultFactory, "HybridCoefficientRule"))

test/plans/test_conjugate_gradient_plan.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,7 @@ Manopt.update_rule_storage_vectors(::DummyCGCoeff) = Tuple{}
6363
@test cgbr.threshold == cgbr.threshold
6464
@test repr(LiuStoreyCoefficient(M)()) ==
6565
"Manopt.LiuStoreyCoefficientRule(; vector_transport_method=$pt)"
66+
@test repr(HybridCoefficient(PolakRibiereCoefficient(), FletcherReevesCoefficient())(M)) ==
67+
"Manopt.HybridCoefficientRule(coefficients=(Manopt.PolakRibiereCoefficientRule(; vector_transport_method=$(pt)), Manopt.FletcherReevesCoefficientRule())),lower_bound=Manopt.SteepestDescentCoefficientRule(),lower_bound_scale=1.0)"
6668
end
6769
end

0 commit comments

Comments
 (0)