Finding the minimizer region of a function

Consider one-dimensional “slices” across the function (using the above MWE as a starting point), say along x1 = 0:

Q(x2) = t -> R([ t, x2])
S(x1) = t -> R([x1,  t])

xc = 0.0

F = S(xc)
p1 = plot(scatter(; x=xs, y=F.(xs), name="Function at $(xc)"));
p1

G = t -> ForwardDiff.derivative(F, t)
p2 = plot(scatter(; x=xs, y=G.(xs), name="Gradient at $(xc)"));

H = t -> ForwardDiff.derivative(G, t)
p3 = plot(scatter(; x=xs, y=H.(xs), name="2nd deriv. at $(xc)"));

[p1; p2; p3]

By convexity, the gradient is monotonic non-decreasing, where the “vacuole” is the “step” in the centre. If we know an interior point of the middle step, then tracking when the function changes indicates the boundary of those regions. Of course, the numerical behaviour means that tuning tolerances for distinguishing “zero” from “non-zero” becomes dependent on the function.

nonzero_tol = 0.1
E_L = Tuple[]
E_R = Tuple[] # {Float64,Float64}

x_scan = -2:0.05:1;
y_scan = -2:0.05:2;

for y1 in y_scan
    G = t -> ForwardDiff.derivative(S(y1), t)
    D = collect(zip(x_scan, G.(x_scan)))
    left_edge = D[findlast(x -> x[2] < -nonzero_tol, collect(D))]
    right_edge = D[findfirst(x -> x[2] > nonzero_tol, collect(D))]
    push!(E_L, (y1, left_edge...))
    push!(E_R, (y1, right_edge...))
end

traceE_L = scatter(x=getindex.(E_L,2), y=getindex.(E_L,1))
traceE_R = scatter(x=getindex.(E_R,2), y=getindex.(E_R,1))

fig = plot(trace1, Layout( yaxis=attr(scaleanchor="x"), showlegend=false))
add_trace!(fig, traceE_L)
add_trace!(fig, traceE_R)
display(fig)

2 Likes