Skip to content

Commit 9859f1f

Browse files
add custom regularizer example
1 parent 62b105f commit 9859f1f

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed

docs/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ ADNLPModels = "54578032-b7ea-4c30-94aa-7cbd1cce6c9a"
33
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
44
DocumenterCitations = "daee34ce-89f3-4625-b898-19384cb65244"
55
LLSModels = "39f5bc3e-5160-4bf8-ac48-504fd2534d24"
6+
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
67
NLPModelsModifiers = "e01155f1-5c6f-4375-a9d8-616dd036575f"
78
ProximalOperators = "a725b495-10eb-56fe-b38b-717eba820537"
89
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
910
RegularizedProblems = "ea076b23-609f-44d2-bb12-a4ae45328278"
11+
ShiftedProximalOperators = "d4fd37fa-580c-4e43-9b30-361c21aae263"
1012

1113
[compat]
1214
Documenter = "1"
Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,86 @@
1-
# Custom regularizers
1+
# Custom regularizers
2+
3+
In the case where the regularizer for your application is not already implemented you can still implement one yourself and use our solvers.
4+
In this tutorial we are going to model the (nonsmooth) function
5+
```math
6+
h : \mathbb{R}^n \mapsto \mathbb{R} \cup \{\infty\} : x \mapsto \chi(x; \mathbb{B}_\infty)
7+
```
8+
where $\chi(\cdot; A)$ is the indicator function on the set $A$ and $\mathbb{B}_\infty$ is the unit ball in the infinity norm, i.e,
9+
```math
10+
\chi(x; \mathbb{B}_\infty) =
11+
\begin{cases}
12+
0 & \text{if } \|x\|_\infty \leq 1,\\
13+
\infty & \text{otherwise}.
14+
\end{cases}
15+
```
16+
17+
```@example
18+
using LinearAlgebra
19+
using ShiftedProximalOperators
20+
using RegularizedProblems
21+
using RegularizedOptimization
22+
23+
# First we create a type for our indicator function
24+
struct SimpleIndicator end
25+
26+
# Then, we add a evaluation function
27+
function (h::SimpleIndicator)(x)
28+
return norm(x, Inf) <= 1 ? 0.0 : Inf
29+
end
30+
31+
# Now, we add a type that represents the function t -> h(shift + t)
32+
mutable struct ShiftedSimpleIndicator{V} <: ShiftedProximableFunction
33+
shift::V
34+
temp::V
35+
end
36+
37+
# Add the evaluation function for the shifted type
38+
function (ψ::ShiftedSimpleIndicator)(x)
39+
@. ψ.temp = ψ.shift + x
40+
return norm(ψ.temp, Inf) <= 1 ? 0.0 : Inf
41+
end
42+
43+
# Add the shifted function
44+
function ShiftedProximalOperators.shifted(h::SimpleIndicator, xk::Vector{T}) where{T}
45+
return ShiftedSimpleIndicator(xk, similar(xk))
46+
end
47+
48+
# Add the shift! function
49+
function ShiftedProximalOperators.shift!(ψ::ShiftedSimpleIndicator{Vector{T}}, xk::Vector{T}) where{T}
50+
ψ.shift .= xk
51+
end
52+
53+
# Add the prox! function for both the unshifted and shifted types, we can solve the proximal problem analytically by hand.
54+
function ShiftedProximalOperators.prox!(
55+
y::AbstractVector{T},
56+
h::SimpleIndicator,
57+
q::AbstractVector{T},
58+
σ::T,
59+
) where{T}
60+
for i ∈ eachindex(y)
61+
y[i] = min(max(q[i], -1), 1)
62+
end
63+
end
64+
65+
function ShiftedProximalOperators.prox!(
66+
y::AbstractVector{T},
67+
ψ::ShiftedSimpleIndicator{Vector{T}},
68+
q::AbstractVector{T},
69+
σ::T,
70+
) where{T}
71+
for i ∈ eachindex(y)
72+
y[i] = min(max(q[i], -1 - ψ.shift[i]), 1 - ψ.shift[i])
73+
end
74+
end
75+
76+
# We can try to use this new regularizer with R2 :
77+
78+
# define a small smooth problem
79+
using ADNLPModels
80+
f_model = ADNLPModel(x -> (x[1] - 4)^2, 3*ones(1), name = "Simple quadratic model")
81+
h = SimpleIndicator()
82+
regularized_nlp = RegularizedNLPModel(f_model, h)
83+
84+
out = R2(regularized_nlp, verbose = 1)
85+
println("R2 converged after $(out.iter) iterations to the solution x = $(out.solution)")
86+
```

src/R2_alg.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ function SolverCore.solve!(
354354
hk = @views h(xk[selected])
355355
if hk == Inf
356356
verbose > 0 && @info "R2: finding initial guess where nonsmooth term is finite"
357-
prox!(xk, h, xk, one(eltype(x0)))
357+
prox!(xk, h, xk, one(eltype(xk)))
358358
hk = @views h(xk[selected])
359359
hk < Inf || error("prox computation must be erroneous")
360360
verbose > 0 && @debug "R2: found point where h has value" hk

0 commit comments

Comments
 (0)