From 07e90d36c3314d8bbf448a81afb9d7ae8e533720 Mon Sep 17 00:00:00 2001
From: Stephan Hilb <stephan.hilb@mathematik.uni-stuttgart.de>
Date: Sat, 15 Sep 2018 09:15:59 +0200
Subject: [PATCH] code: more work
---
FD/src/FD.jl | 111 +++++++++++++++++++++++++++--
chambollefp.jl | 20 +++---
chambollefp_dd.jl | 178 ++++++++++++++++++++++++++++++----------------
3 files changed, 234 insertions(+), 75 deletions(-)
diff --git a/FD/src/FD.jl b/FD/src/FD.jl
index 6bd0c1b..d5621fc 100644
--- a/FD/src/FD.jl
+++ b/FD/src/FD.jl
@@ -5,6 +5,13 @@ using StaticArrays
using OffsetArrays
#using LinearMaps
#using IterativeSolvers
+import Colors: Gray
+import Plots: plot
+
+
+export Grid, MetaGrid, GridView, GridFunction
+export grid
+
include("filtering.jl")
@@ -54,6 +61,7 @@ Base.ndims(grid::AbstractGrid{d}) where d = d
Base.axes(grid::AbstractGrid) = Base.OneTo.(size(grid))
Base.length(grid::AbstractGrid) = prod(size(grid))
Base.IndexStyle(::Type{<:AbstractGrid}) = IndexCartesian()
+Base.parent(grid::AbstractGrid) = grid
# aka `StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}`
const FDStepRange = typeof(0:0.1:1)
@@ -91,6 +99,9 @@ Base.iterate(grid::GridView, state) = iterate([grid.grid[I] for I in CartesianIn
Base.getindex(grid::GridView, idx...) = getindex(grid.grid, (first.(grid.indices) .- 1 .+ Base.to_indices(grid, idx))...)
+Base.parent(grid::GridView) = grid.grid
+
+
# MetaGrid
@@ -146,6 +157,7 @@ domaindim(f::AbstractGridFunction{G,T,d}) where {G,T,d} = d
Base.similar(f::F, ::Type{S}, dims::Int...) where {F<:AbstractGridFunction, S} =
GridFunction(f.grid, Array{S}(undef, length(f)))
+Base.parent(f::AbstractGridFunction) = f
"""
@@ -169,10 +181,9 @@ end
#GridFunction(grid::G, data::AbstractArray{T,D}) where {d,G<:AbstractGrid{d},T,D} =
# GridFunction{G,T,d,size(data, d+1),typeof(data),d+1}(grid, data)
function GridFunction(grid::G, data::AbstractArray, ::Val{n}) where {d,G<:AbstractGrid{d}, n}
- if length(data) ÷ length(grid) == 1 && n > 1
+ if length(data) == length(grid) && n > 1
data = repeat(data, inner=ntuple(i -> i == d+1 ? n : 1, d+1))
- else
- # TODO: check size(data)
+ elseif size(data) != (size(grid)..., n)
data = reshape(data, size(grid)..., n)
end
length(data) ÷ length(grid) == n || throw(ArgumentError("dimensions don't match"))
@@ -208,16 +219,80 @@ Base.setindex!(f::GridFunction, v, idx::Int) = setindex!(f.data, v, idx)
#Base.IndexStyle(::Type{<:GridFunction}) = IndexLinear()
#component(f::GridFunction, k::Integer) = view(reshape(f.data,
+grid(f::GridFunction) = f.grid
+# TODO: call is different, so maybe make thin not part of Base
Base.view(f::AbstractGridFunction{G}, idx...) where G<:MetaGrid =
GridFunction(GridView(f.grid, indices(f.grid, idx...)), view(f.data, indices(f.grid, idx...)..., :))
-grid(f::GridFunction) = f.grid
+Base.parent(f::AbstractGridFunction{<:GridView}) =
+ GridFunction(parent(grid(f)), parent(f.data))
+
+
+function _check_shape(a::GridFunction, b::GridFunction)
+ #TODO: why does fv.grid == gv.grid fail?
+ a.grid === b.grid || throw(ArgumentError("grids need to match"))
+ rangedim(a) == rangedim(b) || throw(ArgumentError("range dimensions need to match"))
+end
Base.:*(a::Number, b::GridFunction) = GridFunction(b.grid, a * b.data, Val(rangedim(b)))
+Base.:-(a::GridFunction) = GridFunction(a.grid, -a.data, Val(rangedim(a)))
+function Base.:+(a::GridFunction, b::GridFunction)
+ _check_shape(a, b)
+ GridFunction(a.grid, a.data .+ b.data, Val(rangedim(a)))
+end
+function Base.:-(a::GridFunction, b::GridFunction)
+ _check_shape(a, b)
+ GridFunction(a.grid, a.data .- b.data, Val(rangedim(a)))
+end
+function Base.:+(a::GridFunction, b::GridFunction{<:GridView})
+ a.grid == parent(b.grid) || throw(ArgumentError("grids need to match"))
+ data = copy(a.data)
+ datav = view(data, b.grid.indices..., :)
+ datav .+= b.data
+ GridFunction(a.grid, data, Val(rangedim(a)))
+end
+Base.:+(a::GridFunction{<:GridView}, b::GridFunction) = b + a
+
+# TODO: cleanup! use metaprogramming
+function Base.:+(a::GridFunction{<:GridView}, b::GridFunction{<:GridView})
+ _check_shape(a, b)
+ GridFunction(a.grid, a.data .+ b.data, Val(rangedim(a)))
+end
+# TODO: cleanup! use metaprogramming
+function Base.:-(a::GridFunction{<:GridView}, b::GridFunction{<:GridView})
+ _check_shape(a, b)
+ GridFunction(a.grid, a.data .- b.data, Val(rangedim(a)))
+end
+
+function Base.:-(a::GridFunction, b::GridFunction{<:GridView})
+ a.grid == parent(b.grid) || throw(ArgumentError("grids need to match"))
+ data = copy(a.data)
+ datav = view(data, b.grid.indices..., :)
+ datav .-= b.data
+ GridFunction(a.grid, data, Val(rangedim(a)))
+end
+Base.:-(a::GridFunction{<:GridView}, b::GridFunction) = b - a
+
+
+
+function my_plot(img::FD.GridFunction{G,T,d,1}) where {G,T,d}
+ print("Plotting ... ")
+
+ data = reshape(copy(img.data), size(img.grid))
+
+ min = minimum(data)
+ max = maximum(data)
+ @show min, max
+
+ #@. data = (data - min) / (max - min)
+ @. data = clamp(data, 0, 1)
+
+ plot(Gray.(data), show=true)
+end
## Operations
@@ -260,6 +335,34 @@ function divergence(f::GridFunction{G,T,d}; fd=FDiff.backward) where {d,G<:Abstr
GridFunction(f.grid, A)
end
+function _kernel_zero_right_bnd!(kernel, bidx, k)
+ if bidx[k] == 1
+ kernel[ntuple(i -> 0, ndims(kernel))...] = 0
+ end
+ kernel
+end
+
+function gradient_c(f::GridFunction{G,T,d,1}; fd=FDiff.forward) where {G,T,d}
+ #A = Array{T,d+1}(undef, (size(f.grid)..., d))
+ A = zeros(size(f.grid)..., d)
+ for k = 1:d
+ vidx = ntuple(i -> i <= d ? Colon() : k, d + 1)
+ vidx2 = ntuple(i -> i <= d ? Colon() : 1, d + 1)
+ imfilter!(view(A, vidx...), f.data[vidx2...], bidx -> trim_kernel(_fdkern(fd, ndims(f.grid), k), bidx))
+ end
+ GridFunction(f.grid, A)
+end
+
+function divergence_z(f::GridFunction{G,T,d}; fd=FDiff.backward) where {d,G<:AbstractGrid{d},T}
+ A = zeros(size(f.grid)..., 1)
+ for k = 1:d
+ vidx = ntuple(i -> i <= d ? Colon() : 1, d + 1)
+ vidx2 = ntuple(i -> i <= d ? Colon() : k, d + 1)
+ imfilter!(view(A, vidx...), f.data[vidx2...], bidx -> _kernel_zero_right_bnd!(trim_kernel(_fdkern(fd, ndims(f.grid), k), bidx), bidx, k))
+ end
+ GridFunction(f.grid, A)
+end
+
function pw_norm(f::GridFunction)
d = domaindim(f)
GridFunction(f.grid, sqrt.(sum(f.data.^2, dims=d+1)), Val(1))
diff --git a/chambollefp.jl b/chambollefp.jl
index 70e9833..56f3495 100644
--- a/chambollefp.jl
+++ b/chambollefp.jl
@@ -10,13 +10,14 @@ using FD
imf(f, grid) = [f(x) for x in grid]
-imshow(grid, img) = plot(Gray.((reshape(float.(img), size(grid)) .- minimum(float.(img))) / (maximum(float.(img)) - minimum(float.(img))) ), show=true)
+imshow(grid, img) = FD.my_plot(FD.GridFunction(grid, img))
+#plot(Gray.((reshape(float.(img), size(grid)) .- minimum(float.(img))) / (maximum(float.(img)) - minimum(float.(img))) ), show=true)
function _fpiter(grid, p, f, A, α, β, τ)
- x = (A'*A + β*I) \ (FD.divergence(grid, p) .+ A'*f ./ α)
+ x = (A'*A + β*I) \ (FD.divergence(grid, p) .+ A'*f)
q = FD.gradient(grid, x)
- p_new = (p .+ τ .* q) ./ (1 .+ τ .* FD.my_norm(grid, q))
+ p_new = (p .+ τ .* q) ./ (1 .+ (τ/α) .* FD.my_norm(grid, q))
reserr = maximum(sum((p_new .- p).^2, dims=ndims(p)))
(p_new, reserr)
@@ -27,17 +28,16 @@ function fpalg(grid, f, A; α, β, τ = 1/8, ϵ = 1e-4)
reserr = 1
k = 0
- while reserr > ϵ && k < 30e1
+ while reserr > ϵ && k < 300e1
k += 1
#sleep(0.1 / k)
(p, reserr) = _fpiter(grid, p, f, A, α, β, τ)
- uimg = (A'*A + β*I) \ (α * FD.divergence(grid, p) .+ A'*f)
+ uimg = (A'*A + β*I) \ (FD.divergence(grid, p) .+ A'*f)
imshow(grid, uimg)
println("[$(lpad(k, 4))] res = $(round(reserr, digits=5))")
- println("min/max: $(minimum(uimg)) / $(maximum(uimg))")
- println("min/max: $(minimum(p)) / $(maximum(p))")
+ println("min/max: $(minimum(FD.my_norm(FD.GridFunction(grid,p)))) / $(maximum(FD.my_norm(FD.GridFunction(grid,p))))")
end
end
@@ -54,15 +54,15 @@ f = reshape([float(norm(x .- [0.5, 0.5]) < 0.4) for x in grid], length(grid))
#f += clamp.(0.2 * rand(eltype(f), size(f)), 0, 1)
-#A = I
-A = spdiagm(0 => ones(length(grid)), 1 => ones(length(grid)-1) )
+A = I
+#A = spdiagm(0 => ones(length(grid)), 1 => ones(length(grid)-1) )
f = A * f
#imshow(grid, f)
#sleep(5)
-img = fpalg(grid, f, A, α=1, β=1, τ=1/100, ϵ=1e-7)
+img = fpalg(grid, f, A, α=10000, β=0, τ=1/8, ϵ=1e-7)
#A = Array{Float64}(undef, (length(grid), length(grid)))
diff --git a/chambollefp_dd.jl b/chambollefp_dd.jl
index 7a942f9..10e73b0 100644
--- a/chambollefp_dd.jl
+++ b/chambollefp_dd.jl
@@ -8,9 +8,6 @@ import FD
import Colors: Gray
import Plots: plot
-# TODO: add clamp option
-my_plot(img::FD.AbstractGridFunction{G,T,d,1}) where {G,T,d} =
- plot(reshape(Gray.((img .- minimum(img)) ./ (maximum(img) - minimum(img))), size(img.grid)), show=true)
"partition of unity function"
@@ -31,115 +28,174 @@ function theta(grid, idx...)
FD.GridFunction(grid, dst)
end
+
function p2u(grid, p, A, f; α, β)
- FD.GridFunction(grid, (A'*A + β*I) \ (α .* FD.divergence(p).data[:] .+ A'*f.data[:]))
+ FD.GridFunction(grid, (A'*A + β*I) \ (FD.divergence_z(p).data[:] .+ A'*f.data[:]))
end
+
# TODO: investigate matrix multiplication performance with GridFunctions
-function fpiter(grid, p, w, A, α, β, τ)
- x = FD.GridFunction(grid, (A'*A + β*I) \ (FD.divergence(p).data[:] .+ w ./ α))
- q = FD.gradient(x)
+function fpiter(grid, p, wg, A, α, β, τ)
+ ## local variant
+ #w = FD.GridFunction(grid, view(wg.data, grid.indices..., :))
+ #x = FD.GridFunction(grid, (A'*A + β*I) \ (FD.divergence(p) + w).data[:])
+ #q = FD.gradient(x)
+
+ ## global variant
+ x = FD.GridFunction(FD.parent(grid), (A'*A + β*I) \ (FD.divergence(p) + wg).data[:])
+ #FD.my_plot(FD.divergence(p) + wg)
+
+ q = FD.GridFunction(grid, view(FD.gradient(x).data, grid.indices..., :))
+ q2 = FD.gradient(FD.GridFunction(grid, view(x.data, grid.indices..., :)))
+
+ #display(x.data[10:13,51:54,1])
+ #display(q.data[10:13,52:53,2])
+ #display(q2.data[10:13,52:53,2])
+ #sleep(0.1)
+
+ #q = FD.gradient(FD.GridFunction(grid, view(x.data, grid.indices..., :)))
+
- #display(x.data)
+ #FD.my_plot(FD.pw_norm(q))
#FD.my_plot(x)
- #checknan(q)
- p_new = FD.GridFunction(grid, FD.pwmul(FD.GridFunction(grid, 1 ./ (1 .+ τ .* FD.pw_norm(q))), FD.GridFunction(grid, p .+ τ .* q)))
+ #FD.my_plot(α)
+
+ p_new = FD.GridFunction(grid, FD.pwmul(FD.GridFunction(grid, α ./ (α .+ τ .* FD.pw_norm(q))),
+ FD.GridFunction(grid, p .+ τ .* q)))
+
+
reserr = maximum(sum((p_new .- p).^2, dims=ndims(p)))
(p_new, reserr)
end
-function fpalg(grid, w, A; α, β, τ = 1/8, ϵ = 1e-4)
+
+function fpalg(grid, w, A, p = FD.GridFunction(x -> 0, ndims(grid), grid);
+ α, β, τ = 1/8, ϵ = 1e-4)
local uimg
- p = FD.GridFunction(x -> 0, ndims(grid), grid)
reserr = 1
k = 0
- while reserr > ϵ && k < 30e1
+ while reserr > ϵ && k < 10e1
k += 1
(p, reserr) = fpiter(grid, p, w, A, α, β, τ)
- #FD.my_plot(uimg)
- #println("[$(lpad(k, 4))] res = $(round(reserr, digits=5))")
- #println("min/max: $(minimum(uimg)) / $(maximum(uimg))")
- #println("min/max: $(minimum(p)) / $(maximum(p))")
+ #u = p2u(grid, p, A, f, α=α, β=β)
+ #@show k
+ #FD.my_plot(u)
end
- p
- #uimg
+ return p
end
-grid = FD.MetaGrid((0:0.01:1, 0:0.01:1), (3, 3), 5)
-
-A = I
-#A = spdiagm(0 => ones(length(grid)), 1 => ones(length(grid)-1) )
-#f = A * f
-
-
-f = FD.GridFunction(x -> float(norm(x .- [0.5, 0.5]) < 0.4), 1, grid)
-g = FD.GridFunction(x -> norm(x), 2, grid)
-
-α=1
-β=1
-τ=1/100
-ϵ=1e-7
-ρ=0.25
-
-p = FD.GridFunction(x -> 0, 2, grid)
function dditer(grid, p, A, f; α, β, τ, ϵ, ρ)
- p .= (1-ρ) .* p
+ #pzero = FD.GridFunction(x -> 0, ndims(grid), grid)
+ p̂ = (1-ρ) * p
+
+ i = 0
for part in FD.parts(grid)
gridv = view(grid, Tuple(part)...)
fv = view(f, Tuple(part)...)
#p.data .= 0
+ p̂v = view(p̂, Tuple(part)...)
pv = view(p, Tuple(part)...)
+ #pzerov = view(pzero, Tuple(part)...)
θ = theta(grid, Tuple(part)...)
θv = view(θ, Tuple(part)...)
- w = FD.GridFunction(grid, A' * f.data[:] - FD.divergence(FD.pwmul(FD.GridFunction(grid, 1 .- θ), p)))
+
+ #y = FD.divergence(FD.pwmul(FD.GridFunction(grid, 1 .- θ), p))
+ #FD.my_plot(y)
+ #sleep(1)
+
+ w = FD.GridFunction(grid, A' * f.data[:]) + FD.divergence(FD.pwmul(FD.GridFunction(grid, 1 .- θ), p))
wv = view(w, Tuple(part)...)
+ #FD.my_plot(w)
+ #sleep(1)
+
#wv = A' * fv
- pv .+= ρ .* fpalg(gridv, wv, A, α=α*θv, β=β, τ=τ, ϵ=ϵ)
+ #u = p2u(grid, p̂, A, f, α=α, β=β)
+ #uv = view(u, Tuple(part)...)
- #u = p2u(grid, p, A, f, α=α*θ, β=β)
- u = p2u(grid, p, A, f, α=α, β=β)
- uv = view(u, Tuple(part)...)
+ #FD.my_plot(uv)
- my_plot(θv)
- #sleep(1)
- #my_plot(FD.pw_norm(pv))
- @show maximum(pv), minimum(pv)
#sleep(1)
- #my_plot(θv)
- return
- end
-end
-
-dditer(grid, p, A, f, α=α, β=β, τ=τ, ϵ=ϵ, ρ=ρ)
-#for n = 1:10
-# println("iteration $n")
-# dditer(grid, p, A, f, α=α, β=β, τ=τ, ϵ=ϵ, ρ=ρ)
-#end
+ p̂v .+= ρ .* fpalg(gridv, w, A, α=α*θv, β=β, τ=τ, ϵ=ϵ)
+ #p̂v .= fpalg(gridv, wv, A, α=α*θv, β=β, τ=τ, ϵ=ϵ)
+
+ #FD.my_plot(FD.pw_norm(p))
+ #sleep(1)
+ #FD.my_plot(FD.pw_norm(f))
+ #sleep(1)
+ #FD.my_plot(FD.pw_norm(p̂))
+ #display(p̂.data[10:13,52:54,:])
+ #break
+ #FD.my_plot(FD.pw_norm(p̂))
+ #sleep(1)
+ #FD.my_plot(θ)
+ #display(p̂v.data)
+ #break
+ #sleep(1)
+ #u = p2u(grid, p, A, f, α=α*θ, β=β)
+ u = p2u(grid, p̂, A, f, α=α, β=β)
+ uv = view(u, Tuple(part)...)
+ #FD.my_plot(θv)
+ #sleep(1)
+ #FD.my_plot(FD.pw_norm(p̂v))
+ #@show maximum(u), minimum(u)
+ #@show maximum(p̂v), minimum(p̂v)
+ #sleep(1)
+ #FD.my_plot(FD.pw_norm(p̂))
+ #FD.my_plot(u)
+ #FD.my_plot(p̂v)
+ #y = FD.GridFunction(gridv, FD.gradient(θv).data[:,:,1])
+ #display(y.data)
+ #display(θv.data)
+ #FD.my_plot(FD.GridFunction(gridv, FD.gradient(θv).data[:,:,2]))
-#gridv = view(grid, 1, 1)
-#fv = view(f, 1, 1)
-#g = view(g, 1, 1)
+ #display(FD.gradient(θv).data)
+ #break
+ #@show size(θv.data), size(p̂v.data)
-#FD.my_plot(f)
+ #FD.my_plot(FD.pw_norm(p̂))
+ i += 1
+ #break
+ #i > 3 && break
+ end
+ p .= p̂
+ u = p2u(grid, p, A, f, α=α, β=β)
+ #FD.my_plot(u)
+ FD.my_plot(FD.pw_norm(p))
+end
-#FD.plot(f)
+grid = FD.MetaGrid((0:0.01:1, 0:0.01:1), (1, 2), 5)
+A = I
+#A = spdiagm(0 => ones(length(grid)), 1 => ones(length(grid)-1) )
+#f = A * f
+f = FD.GridFunction(x -> float(norm(x .- [0.5, 0.5]) < 0.4), 1, grid)
+g = FD.GridFunction(x -> norm(x), 2, grid)
+α=100000
+β=0
+τ=1/8
+ϵ=1e-9
+ρ=0.5
+p = FD.GridFunction(x -> 0, 2, grid)
+for n = 1:1
+ println("iteration $n")
+ dditer(grid, p, A, f, α=α, β=β, τ=τ, ϵ=ϵ, ρ=ρ)
+end
--
GitLab