Skip to content
Snippets Groups Projects
Commit c8c50744 authored by Stephan Hilb's avatar Stephan Hilb
Browse files

revert to global dd

parent 18f638d7
No related branches found
No related tags found
No related merge requests found
...@@ -11,16 +11,22 @@ include("projgrad.jl") ...@@ -11,16 +11,22 @@ include("projgrad.jl")
using Makie: heatmap using Makie: heatmap
function run() function run()
g = ones(20,20) #g = [0. 2; 1 0.]
g = rand(10,10)
#g[4:17,4:17] .= 1 #g[4:17,4:17] .= 1
#g[:size(g, 1)÷2,:] .= 1 #g[:size(g, 1)÷2,:] .= 1
#g = [0. 2; 1 0.] #g = [0. 2; 1 0.]
B = diagm(fill(100, length(g))) display(g)
α = 0.1
B = 0.1 * rand(length(g), length(g))
B .+= diagm(ones(length(g)))
α = 0.025
display(norm(B))
md = DualTVDD.OpROFModel(g, B, α) md = DualTVDD.OpROFModel(g, B, α)
alg = DualTVDD.ChambolleAlgorithm() ctx = DualTVDD.init(md, DualTVDD.ChambolleAlgorithm())
ctx = DualTVDD.init(md, alg) ctx2 = DualTVDD.init(md, DualTVDD.ProjGradAlgorithm(λ=1/sqrt(8)/norm(B)))
#scene = vbox( #scene = vbox(
# heatmap(ctx.s, colorrange=(0,1), colormap=:gray, scale_plot=false, show_axis=false), # heatmap(ctx.s, colorrange=(0,1), colormap=:gray, scale_plot=false, show_axis=false),
...@@ -31,41 +37,51 @@ function run() ...@@ -31,41 +37,51 @@ function run()
#hm = last(scene) #hm = last(scene)
for i in 1:10000 for i in 1:10000
step!(ctx) step!(ctx)
step!(ctx2)
#hm[1] = ctx.s #hm[1] = ctx.s
#yield() #yield()
#sleep(0.2) #sleep(0.2)
end end
display(ctx.p) display(copy(ctx.p))
display(recover_u!(ctx)) display(copy(recover_u!(ctx)))
println(energy(ctx))
println()
ctx display(copy(ctx2.p))
display(copy(recover_u!(ctx2)))
println(energy(ctx2))
ctx, ctx2
#hm[1] = ctx.s #hm[1] = ctx.s
#yield() #yield()
end end
function rundd() function rundd()
β = 0 β = 0
f = zeros(2,2) f = zeros(4,4)
f[1,:] .= 1 f[1,1] = 1
#g = [0. 2; 1 0.] #f = [0. 2; 1 0.]
#A = diagm(vcat(fill(1, length(f)÷2), fill(1/10, length(f)÷2))) #A = diagm(vcat(fill(1, length(f)÷2), fill(1/10, length(f)÷2)))
A = rand(length(f), length(f)) #A = rand(length(f), length(f))
display(A) A = 0. * rand(length(f), length(f))
println(cond(A)) A .+= diagm(ones(length(f)))
display(eigen(A))
#A = diagm(fill(1/2, length(f))) #display(A)
B = inv(A'*A + β*I) B = inv(A'*A + β*I)
println(norm(sqrt(B))) println(norm(A))
#println(norm(sqrt(B))) #println(norm(sqrt(B)))
g = similar(f) g = similar(f)
vec(g) .= A' * vec(f) vec(g) .= A' * vec(f)
α = .025 α = 1/4
md = DualTVDD.DualTVDDModel(f, A, α, 0., 0.) md = DualTVDD.DualTVDDModel(f, A, α, 0., 0.)
alg = DualTVDD.DualTVDDAlgorithm(M=(1,1), overlap=(1,1), σ=1) alg = DualTVDD.DualTVDDAlgorithm(M=(2,2), overlap=(2,2), σ=1)
ctx = DualTVDD.init(md, alg) ctx = DualTVDD.init(md, alg)
md2 = DualTVDD.OpROFModel(g, B, α) md2 = DualTVDD.OpROFModel(g, B, α)
...@@ -73,11 +89,13 @@ function rundd() ...@@ -73,11 +89,13 @@ function rundd()
ctx2 = DualTVDD.init(md2, alg2) ctx2 = DualTVDD.init(md2, alg2)
for i in 1:1 for i in 1:1000
step!(ctx) step!(ctx)
#println(energy(ctx))
end end
for i in 1:1000000 for i in 1:10000
step!(ctx2) step!(ctx2)
#println(energy(ctx2))
end end
#scene = heatmap(ctx.s, #scene = heatmap(ctx.s,
...@@ -95,11 +113,11 @@ function rundd() ...@@ -95,11 +113,11 @@ function rundd()
#hm[1] = ctx.s #hm[1] = ctx.s
#yield() #yield()
println("p result") println("\np result")
display(ctx.p) display(ctx.p)
display(ctx2.p) display(ctx2.p)
println("u result") println("\nu result")
display(recover_u!(ctx)) display(recover_u!(ctx))
display(recover_u!(ctx2)) display(recover_u!(ctx2))
...@@ -111,7 +129,7 @@ end ...@@ -111,7 +129,7 @@ end
function run3() function run3()
f = rand(20,20) f = rand(20,20)
A = rand(length(f), length(f)) A = 0.1*rand(length(f), length(f))
A .+= diagm(ones(length(f))) A .+= diagm(ones(length(f)))
g = reshape(A'*vec(f), size(f)) g = reshape(A'*vec(f), size(f))
...@@ -160,9 +178,10 @@ function energy(ctx::Union{DualTVDDContext,ProjGradContext}) ...@@ -160,9 +178,10 @@ function energy(ctx::Union{DualTVDDContext,ProjGradContext})
# v = div(p) + A'*f # v = div(p) + A'*f
map!(, v, extend(ctx.p, StaticKernels.ExtensionNothing())) map!(, v, extend(ctx.p, StaticKernels.ExtensionNothing()))
v .+= ctx.g v .+= ctx.g
#display(v)
# |v|_B^2 / 2
u = ctx.B * vec(v) u = ctx.B * vec(v)
return sum(u .* vec(v)) / 2 return sum(u .* vec(v)) / 2
end end
...@@ -177,9 +196,10 @@ function energy(ctx::ChambolleContext) ...@@ -177,9 +196,10 @@ function energy(ctx::ChambolleContext)
# v = div(p) + g # v = div(p) + g
map!(, v, extend(ctx.p, StaticKernels.ExtensionNothing())) map!(, v, extend(ctx.p, StaticKernels.ExtensionNothing()))
v .+= ctx.model.g v .+= ctx.model.g
#display(v)
# |v|_B^2 / 2
u = ctx.model.B * vec(v) u = ctx.model.B * vec(v)
return sum(u .* vec(v)) / 2 return sum(u .* vec(v)) / 2
end end
......
...@@ -16,7 +16,7 @@ using LinearAlgebra ...@@ -16,7 +16,7 @@ using LinearAlgebra
struct ChambolleAlgorithm <: Algorithm struct ChambolleAlgorithm <: Algorithm
"fixed point inertia parameter" "fixed point inertia parameter"
τ::Float64 τ::Float64
function ChambolleAlgorithm(; τ=1/4) function ChambolleAlgorithm(; τ=1/8)
return new(τ) return new(τ)
end end
end end
......
...@@ -34,11 +34,11 @@ function init(md::DualTVDDModel, alg::DualTVDDAlgorithm) ...@@ -34,11 +34,11 @@ function init(md::DualTVDDModel, alg::DualTVDDAlgorithm)
ax = axes(md.f) ax = axes(md.f)
# subdomain axes # subdomain axes
subax = subaxes(md.f, alg.M, alg.overlap) subax = subaxes(size(md.f), alg.M, alg.overlap)
# preallocated data for subproblems # preallocated data for subproblems
subg = [Array{Float64, d}(undef, length.(subax[i])) for i in CartesianIndices(subax)] subg = [Array{Float64, d}(undef, length.(ax)) for i in CartesianIndices(subax)]
# locally dependent tv parameter # locally dependent tv parameter
subα = [md.α .* theta.(Ref(ax), Ref(subax[i]), Ref(alg.overlap), CartesianIndices(subax[i])) subα = [md.α .* theta.(Ref(ax), Ref(subax[i]), Ref(alg.overlap), CartesianIndices(ax))
for i in CartesianIndices(subax)] for i in CartesianIndices(subax)]
# this is the global g, the local gs are getting initialized in step!() # this is the global g, the local gs are getting initialized in step!()
...@@ -53,9 +53,8 @@ function init(md::DualTVDDModel, alg::DualTVDDAlgorithm) ...@@ -53,9 +53,8 @@ function init(md::DualTVDDModel, alg::DualTVDDAlgorithm)
B = diagm(ones(length(md.f))) + md.β * I B = diagm(ones(length(md.f))) + md.β * I
# create subproblem contexts # create subproblem contexts
# TODO: extraction of B subparts only makes sense for blockdiagonal B (i.e. A too)
li = LinearIndices(size(md.f)) li = LinearIndices(size(md.f))
submds = [OpROFModel(subg[i], B[vec(li[subax[i]...]), vec(li[subax[i]...])], subα[i]) submds = [OpROFModel(subg[i], B, subα[i])
for i in CartesianIndices(subax)] for i in CartesianIndices(subax)]
subalg = ChambolleAlgorithm() subalg = ChambolleAlgorithm()
subctx = [init(submds[i], subalg) for i in CartesianIndices(subax)] subctx = [init(submds[i], subalg) for i in CartesianIndices(subax)]
...@@ -67,62 +66,32 @@ function init(md::DualTVDDModel, alg::DualTVDDAlgorithm) ...@@ -67,62 +66,32 @@ function init(md::DualTVDDModel, alg::DualTVDDAlgorithm)
end end
function step!(ctx::DualTVDDContext) function step!(ctx::DualTVDDContext)
σ = ctx.algorithm.σ
d = ndims(ctx.p) d = ndims(ctx.p)
ax = axes(ctx.p) ax = axes(ctx.p)
overlap = ctx.algorithm.overlap overlap = ctx.algorithm.overlap
li = LinearIndices(size(ctx.model.f))
@inline kfΛ(w) = @inbounds -divergence_global(w) @inline kfΛ(w) = @inbounds divergence_global(w)
= Kernel{ntuple(_->-1:1, d)}(kfΛ) = Kernel{ntuple(_->-1:1, d)}(kfΛ)
λ = 2*norm(sqrt(ctx.B))^2 # TODO: algorithm parameter
# call run! on each cell (this can be threaded) # call run! on each cell (this can be threaded)
for i in eachindex(ctx.subctx) for (i, sax) in pairs(ctx.subax)
sax = ctx.subax[i] sg = ctx.subg[i] # julia-bug workaround
ci = CartesianIndices(sax)
# TODO: make p computation local! # TODO: make p computation local!
# g_i = (A*f - Λ(1-theta_i)p^n)|_{\Omega_i} ctx.ptmp .= (1 .- theta.(Ref(ax), Ref(sax), Ref(overlap), CartesianIndices(ctx.p))) .* ctx.p
# subctx[i].p is used as a buffer map!(, sg, ctx.ptmp)
sg .+= ctx.g
ctx.ptmp .= .-(1 .- theta.(Ref(ax), Ref(sax), Ref(overlap), CartesianIndices(ctx.p))) .* ctx.p
#tmp3 = .-(1 .- theta.(Ref(ax), Ref(sax), Ref(overlap), CartesianIndices(ctx.p)))
#ctx.subctx[i].p .= .-(1 .- theta.(Ref(ax), Ref(sax), Ref(overlap), ci)) .* ctx.p[ctx.subax[i]...]
ctx.subg[i] .= map(, ctx.ptmp)[sax...]
#map!(kΛ, ctx.subg[i], ctx.subctx[i].p)
ctx.subg[i] .+= ctx.g[sax...]
# set sensible starting value
reset!(ctx.subctx[i])
# precomputed: B/λ * (A'f - Λ(1-θ_i)p^n)
gloc = copy(ctx.subg[i])
# v_0
ctx.ptmp .= theta.(Ref(ax), Ref(sax), Ref(overlap), CartesianIndices(ctx.p)) .* ctx.p
ctx.subctx[i].p .= ctx.ptmp[sax...]
# subcontext B is identity! for j in 1:1000
subIB = I - ctx.B[vec(li[sax...]), vec(li[sax...])]./λ step!(ctx.subctx[i])
subB = ctx.B[vec(li[sax...]), vec(li[sax...])]./λ
for j in 1:10000
subΛp = map(, ctx.subctx[i].p)
vec(ctx.subg[i]) .= subIB * vec(subΛp) .+ subB * vec(gloc)
for k in 1:1000
step!(ctx.subctx[i])
end
end end
end end
# aggregate (not thread-safe!) # aggregate (not thread-safe!)
σ = ctx.algorithm.σ
ctx.p .*= 1 - σ ctx.p .*= 1 - σ
for i in CartesianIndices(ctx.subax) for (i, sax) in pairs(ctx.subax)
ctx.p[ctx.subax[i]...] .+= σ .* ctx.subctx[i].p ctx.p .+= σ .* ctx.subctx[i].p
end end
end end
...@@ -167,8 +136,8 @@ This assumes that subdomains have size at least 2 .* overlap. ...@@ -167,8 +136,8 @@ This assumes that subdomains have size at least 2 .* overlap.
theta(ax, sax, overlap, i::CartesianIndex) = prod(theta.(ax, sax, overlap, Tuple(i))) theta(ax, sax, overlap, i::CartesianIndex) = prod(theta.(ax, sax, overlap, Tuple(i)))
theta(ax, sax, overlap::Int, i::Int) = theta(ax, sax, overlap::Int, i::Int) =
max(0., min(1., max(0., min(1.,
first(ax) == first(sax) && i < first(ax) + overlap ? 1. : (i - first(sax)) / overlap, first(ax) == first(sax) && i < first(ax) + overlap ? 1. : (i - first(sax) + 1) / (overlap + 1),
last(ax) == last(sax) && i > last(ax) - overlap ? 1. : (last(sax) - i) / overlap)) last(ax) == last(sax) && i > last(ax) - overlap ? 1. : (last(sax) - i + 1) / (overlap + 1)))
""" """
...@@ -177,21 +146,21 @@ theta(ax, sax, overlap::Int, i::Int) = ...@@ -177,21 +146,21 @@ theta(ax, sax, overlap::Int, i::Int) =
Determine axes for all subdomains, given per dimension number of domains Determine axes for all subdomains, given per dimension number of domains
`pnum` and overlap `overlap` `pnum` and overlap `overlap`
""" """
function subaxes(domain, pnum, overlap) function subaxes(sizes, pnum, overlap)
overlap = 1 .+ overlap d = Val(length(sizes))
d = ndims(domain) ax = partition.(sizes, pnum, overlap)
tsize = size(domain) .+ (pnum .- 1) .* overlap return [ntuple(i -> ax[i][I[i]], d) for I in CartesianIndices(pnum)]
end
psize = tsize pnum
osize = tsize .- pnum .* psize
overhang(I, j) = I[j] == pnum[j] ? osize[j] : 0
indices = Array{NTuple{d, UnitRange{Int}}, d}(undef, pnum) function partition(n, k, o)
for I in CartesianIndices(pnum) part = UnitRange[]
indices[I] = ntuple(j -> ((I[j] - 1) * psize[j] - (I[j] - 1) * overlap[j] + 1) : i = 1
( I[j] * psize[j] - (I[j] - 1) * overlap[j] + overhang(I, j)), d) while k > 1
s = (n + (k-1)*o) ÷ k
push!(part, i:i+s-1)
i = i + s - o
n -= s - o
k -= 1
end end
@assert all(length.(sax) >= 1 .* overlap for sax in indices) push!(part, i:i+n-1)
return indices
end end
...@@ -29,7 +29,7 @@ struct DualTVDDModel{U,VV} <: Model ...@@ -29,7 +29,7 @@ struct DualTVDDModel{U,VV} <: Model
γ::Float64 γ::Float64
end end
"min_p 1/2 * |div(p) - g|_B^2 + χ_{|p|<=λ}" "min_p 1/2 * |-div(p) - g|_B^2 + χ_{|p|<=λ}"
struct OpROFModel{U,VV,Λ} <: Model struct OpROFModel{U,VV,Λ} <: Model
"given data" "given data"
g::U g::U
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment