Skip to content

Commit aa55fdc

Browse files
committed
Merge branch 'master' of github.com:kellertuer/Manopt.jl
# Conflicts: # src/solvers/NelderMead.jl
2 parents 5a9daae + ae1dd5b commit aa55fdc

File tree

6 files changed

+113
-40
lines changed

6 files changed

+113
-40
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "Manopt"
22
uuid = "0fc0a36d-df90-57f3-8f93-d78a9fc72bb5"
33
authors = ["Ronny Bergmann <manopt@ronnybergmann.net>"]
4-
version = "0.2.9"
4+
version = "0.2.10"
55

66
[deps]
77
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"

src/plans/cost_plan.jl

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ after the description
3838
* `ρ` – (`1/2`) contraction parameter, $0 < \rho \leq \frac{1}{2}$,
3939
* `σ` – (`1/2`) shrink coefficient, $0 < \sigma \leq 1$
4040
* `x` – (`p[1]`) - a field to collect the current best value
41+
* `retraction_method` – `ExponentialRetraction` the rectraction to use, defaults to
42+
the exponential map
43+
* `inverse_retraction_method` - `LogarithmicInverseRetraction` an `inverse_retraction(M,x,y)` to use.
4144
4245
# Constructors
4346
@@ -49,7 +52,15 @@ construct a Nelder-Mead Option with a set of `dimension(M)+1` random points.
4952
5053
construct a Nelder-Mead Option with a set `p` of points
5154
"""
52-
mutable struct NelderMeadOptions{T,Tα<:Real,Tγ<:Real,Tρ<:Real,Tσ<:Real} <: Options
55+
mutable struct NelderMeadOptions{
56+
T,
57+
<:Real,
58+
<:Real,
59+
<:Real,
60+
<:Real,
61+
TR<:AbstractRetractionMethod,
62+
TI<:AbstractInverseRetractionMethod,
63+
} <: Options
5364
population::Vector{T}
5465
stop::StoppingCriterion
5566
α::Tα
@@ -58,17 +69,29 @@ mutable struct NelderMeadOptions{T,Tα<:Real,Tγ<:Real,Tρ<:Real,Tσ<:Real} <: O
5869
σ::Tσ
5970
x::T
6071
costs::Vector{Float64}
72+
retraction_method::TR
73+
inverse_retraction_method::TI
6174
function NelderMeadOptions(
6275
M::MT;
6376
stop::StoppingCriterion=StopAfterIteration(2000),
6477
α=1.0,
6578
γ=2.0,
6679
ρ=1 / 2,
6780
σ=1 / 2,
81+
retraction_method::AbstractRetractionMethod=ExponentialRetraction(),
82+
inverse_retraction_method::AbstractInverseRetractionMethod=LogarithmicInverseRetraction(),
6883
) where {MT<:Manifold}
6984
p = [random_point(M) for i in 1:(manifold_dimension(M) + 1)]
70-
return new{eltype(p),typeof(α),typeof(γ),typeof(ρ),typeof(σ)}(
71-
p, stop, α, γ, ρ, σ, p[1], []
85+
return new{
86+
eltype(p),
87+
typeof(α),
88+
typeof(γ),
89+
typeof(ρ),
90+
typeof(σ),
91+
typeof(retraction_method),
92+
typeof(inverse_retraction_method),
93+
}(
94+
p, stop, α, γ, ρ, σ, p[1], [], retraction_method, inverse_retraction_method
7295
)
7396
end
7497
function NelderMeadOptions(
@@ -78,9 +101,28 @@ mutable struct NelderMeadOptions{T,Tα<:Real,Tγ<:Real,Tρ<:Real,Tσ<:Real} <: O
78101
γ=2.0,
79102
ρ=1 / 2,
80103
σ=1 / 2,
104+
retraction_method::AbstractRetractionMethod=ExponentialRetraction(),
105+
inverse_retraction_method::AbstractInverseRetractionMethod=LogarithmicInverseRetraction(),
81106
) where {T}
82-
return new{T,typeof(α),typeof(γ),typeof(ρ),typeof(σ)}(
83-
population, stop, α, γ, ρ, σ, population[1], []
107+
return new{
108+
T,
109+
typeof(α),
110+
typeof(γ),
111+
typeof(ρ),
112+
typeof(σ),
113+
typeof(retraction_method),
114+
typeof(inverse_retraction_method),
115+
}(
116+
population,
117+
stop,
118+
α,
119+
γ,
120+
ρ,
121+
σ,
122+
population[1],
123+
[],
124+
retraction_method,
125+
inverse_retraction_method,
84126
)
85127
end
86128
end

src/plans/particle_swarm_plan.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ a default value is given in brackets if a parameter can be left out in initializ
1616
* `cognitive_weight` – (`1.4`) a cognitive weight factor
1717
* `stopping_criterion` – ([`StopWhenAny`](@ref)`(`[`StopAfterIteration`](@ref)`(500)`, [`StopWhenChangeLess`](@ref)`(10^{-4})))`
1818
a functor inheriting from [`StoppingCriterion`](@ref) indicating when to stop.
19-
* `retraction_method` – `ExponentialRetraction` the rectraction to use, defaults to
20-
the exponential map
21-
* `inverse_retraction_method` - `LogarithmicInverseRetraction` an `inverse_retraction(M,x,y)` to use.
19+
* `retraction_method` – (`ExponentialRetraction`) the rectraction to use
20+
* `inverse_retraction_method` - (`LogarithmicInverseRetraction`) an inverse retraction to use.
2221
2322
# Constructor
2423

src/solvers/NelderMead.jl

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ and
2323
* `γ` – (`2.`) expansion parameter ($\gamma$)
2424
* `ρ` – (`1/2`) contraction parameter, $0 < \rho \leq \frac{1}{2}$,
2525
* `σ` – (`1/2`) shrink coefficient, $0 < \sigma \leq 1$
26+
* `retraction_method` – (`ExponentialRetraction`) the rectraction to use
27+
* `inverse_retraction_method` - (`LogarithmicInverseRetraction`) an inverse retraction to use.
2628
2729
and the ones that are passed to [`decorate_options`](@ref) for decorators.
2830
@@ -40,11 +42,22 @@ function NelderMead(
4042
γ=2.0,
4143
ρ=1 / 2,
4244
σ=1 / 2,
45+
retraction_method::AbstractRetractionMethod=ExponentialRetraction(),
46+
inverse_retraction_method::AbstractInverseRetractionMethod=LogarithmicInverseRetraction(),
4347
return_options=false,
4448
kwargs..., #collect rest
4549
) where {MT<:Manifold,TF}
4650
p = CostProblem(M, F)
47-
o = NelderMeadOptions(population, stopping_criterion; α=α, γ=γ, ρ=ρ, σ=σ)
51+
o = NelderMeadOptions(
52+
population,
53+
stopping_criterion;
54+
α=α,
55+
γ=γ,
56+
ρ=ρ,
57+
σ=σ,
58+
retraction_method=retraction_method,
59+
inverse_retraction_method=inverse_retraction_method,
60+
)
4861
o = decorate_options(o; kwargs...)
4962
resultO = solve(p, o)
5063
if return_options
@@ -56,17 +69,17 @@ end
5669
#
5770
# Solver functions
5871
#
59-
function initialize_solver!(p::P, o::O) where {P<:CostProblem,O<:NelderMeadOptions}
72+
function initialize_solver!(p::CostProblem, o::NelderMeadOptions)
6073
# init cost and x
6174
o.costs = get_cost.(Ref(p), o.population)
6275
return o.x = o.population[argmin(o.costs)] # select min
6376
end
64-
function step_solver!(p::P, o::O, iter) where {P<:CostProblem,O<:NelderMeadOptions}
77+
function step_solver!(p::CostProblem, o::NelderMeadOptions, iter)
6578
m = mean(p.M, o.population)
6679
ind = sortperm(o.costs) # reordering for cost and p, i.e. minimizer is at ind[1]
67-
ξ = log(p.M, m, o.population[last(ind)])
80+
ξ = inverse_retract(p.M, m, o.population[last(ind)], o.inverse_retraction_method)
6881
# reflect last
69-
xr = exp(p.M, m, -o.α * ξ)
82+
xr = retract(p.M, m, -o.α * ξ, o.retraction_method)
7083
Costr = get_cost(p, xr)
7184
# is it better than the worst but not better than the best?
7285
if Costr >= o.costs[first(ind)] && Costr < o.costs[last(ind)]
@@ -90,15 +103,15 @@ function step_solver!(p::P, o::O, iter) where {P<:CostProblem,O<:NelderMeadOptio
90103
if Costr > o.costs[ind[end - 1]] # even worse than second worst
91104
if Costr < o.costs[last(ind)] # but at least better tham last
92105
# outside contraction
93-
xc = exp(p.M, m, -o.ρ * ξ)
106+
xc = retract(p.M, m, -o.ρ * ξ, o.retraction_method)
94107
Costc = get_cost(p, xc)
95108
if Costc < Costr # better than reflected -> store as last
96109
o.population[last(ind)] = xr
97110
o.costs[last(ind)] = Costr
98111
end
99112
else # even worse than last -> inside contraction
100113
# outside contraction
101-
xc = exp(p.M, m, o.ρ * ξ)
114+
xc = retract(p.M, m, o.ρ * ξ, o.retraction_method)
102115
Costc = get_cost(p, xc)
103116
if Costc < o.costs[last(ind)] # better than last ? -> store
104117
o.population[last(ind)] = xr

src/solvers/particle_swarm.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ i.e. $p_k^{(i)}$ is the best known position for the particle $k$ and $g^{(i)}$ i
5555
* `inertia` – (`0.65`) the inertia of the patricles
5656
* `social_weight` – (`1.4`) a social weight factor
5757
* `cognitive_weight` – (`1.4`) a cognitive weight factor
58-
* `retraction_method` – `ExponentialRetraction` a `retraction(M,x,ξ)` to use.
59-
* `inverse_retraction_method` - `LogarithmicInverseRetraction` an `inverse_retraction(M,x,y)` to use.
60-
* `vector_transport_mthod` - `ParallelTransport` a vector transport method to use.
58+
* `retraction_method` – (`ExponentialRetraction`) a `retraction(M,x,ξ)` to use.
59+
* `inverse_retraction_method` - (`LogarithmicInverseRetraction`) an `inverse_retraction(M,x,y)` to use.
60+
* `vector_transport_mthod` - (`ParallelTransport`) a vector transport method to use.
6161
* `stopping_criterion` – ([`StopWhenAny`](@ref)`(`[`StopAfterIteration`](@ref)`(500)`, [`StopWhenChangeLess`](@ref)`(10^{-4})))`
6262
a functor inheriting from [`StoppingCriterion`](@ref) indicating when to stop.
6363
* `return_options` – (`false`) – if activated, the extended result, i.e. the

test/solvers/test_Nelder_Mead.jl

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,47 @@
11
#
22
#
33
#
4-
using Random
4+
using Random, Manifolds, Manopt, LinearAlgebra
55
Random.seed!(29)
66
@testset "Test Nelder-Mead" begin
7-
M = Euclidean(6)
8-
# From Wikipedia https://en.wikipedia.org/wiki/Rosenbrock_function
9-
function Rosenbrock(x)
10-
return sum([
11-
100 * (x[2 * i - 1]^2 - x[2 * i])^2 + (x[2 * i - 1] - 1)^2
12-
for i in 1:div(length(x), 2)
13-
])
14-
end
15-
x0 = [randn(6) for i in 1:7]
16-
o = NelderMead(M, Rosenbrock, x0; record=[RecordCost()], return_options=true)
17-
18-
x = get_solver_result(o)
19-
rec = get_record(o)
20-
21-
x2 = o = NelderMead(M, Rosenbrock, x0)
22-
23-
@test x == x2
7+
@testset "Euclidean" begin
8+
M = Euclidean(6)
9+
# From Wikipedia https://en.wikipedia.org/wiki/Rosenbrock_function
10+
function Rosenbrock(x)
11+
return sum([
12+
100 * (x[2 * i - 1]^2 - x[2 * i])^2 + (x[2 * i - 1] - 1)^2
13+
for i in 1:div(length(x), 2)
14+
])
15+
end
16+
x0 = [randn(6) for i in 1:7]
17+
o = NelderMead(M, Rosenbrock, x0; record=[RecordCost()], return_options=true)
18+
x = get_solver_result(o)
19+
rec = get_record(o)
20+
nonincreasing = [rec[i] >= rec[i + 1] for i in 1:(length(rec) - 1)]
21+
@test any(map(!, nonincreasing)) == false
2422

25-
nonincreasing = [rec[i] >= rec[i + 1] for i in 1:(length(rec) - 1)]
26-
27-
@test any(map(!, nonincreasing)) == false
23+
x2 = o = NelderMead(M, Rosenbrock, x0)
24+
@test x == x2
25+
end
26+
@testset "Rotations" begin
27+
M = Rotations(3)
28+
A = randn(3, 3)
29+
A .= (A - A') ./ 2
30+
f(x) = norm(A * x * x * A)
31+
x0 = [random_point(M) for _ in 1:12]
32+
o = NelderMead(
33+
M,
34+
f,
35+
x0;
36+
record=[RecordCost()],
37+
return_options=true,
38+
retraction_method=QRRetraction(),
39+
inverse_retraction_method=QRInverseRetraction(),
40+
stopping_criterion=StopAfterIteration(500),
41+
)
42+
x = get_solver_result(o)
43+
rec = get_record(o)
44+
nonincreasing = [rec[i] >= rec[i + 1] for i in 1:(length(rec) - 1)]
45+
@test any(map(!, nonincreasing)) == false
46+
end
2847
end

0 commit comments

Comments
 (0)