This section illustrates the space of γ for monotonicity with a toy example J = 4.

using LaTeXStrings
using Plots
using RCall
using MonotoneSplines

# illustration of space of γ for monotonicity
function plot_intervals(; step = 0.1, γ3 = 3, γ4 = 4, boundary = false)
    f(γ1, γ2) = γ3 ≥ γ2 ≥ γ1
    function xstar(γ1, γ2, γ3 = 3, γ4 = 4)
        w = 1 - (γ4 - 2γ3 + γ2) / (γ4 - 3γ3 + 3γ2 - γ1)
        return 1.0 * (w > 1) + w * (0 < w < 1)
    end
    b2(x) = (1-x)^2
    b3(x) = 2x * (1-x)
    b4(x) = x^2
    function fp(γ1, γ2, γ3 = 3, γ4 = 4)
        t = xstar(γ1, γ2)
        return 3(b2(t) * (γ2 - γ1) + b3(t) * (γ3 - γ2) + b4(t) * (γ4 - γ3))
    end

    xs = range(-15, 15, step = step)
    ys = range(-15, 15, step = step)
    z = [f(xi, yi) for yi in ys, xi in xs] ## TODO: compare with for for
    # heatmap(z) #cons: overlap

    z2 = [(abs(xstar(xi, yi, γ3, γ4) - 0.5) >= 0.5) * (yi ≥ xi) for yi in ys, xi in xs]
    # heatmap!(z2) #cons: overlap
    z3 = [(fp(xi, yi, γ3, γ4) ≥ 0) * (yi ≥ xi) for yi in ys, xi in xs]

    cidx = findall(z .> 0)
    i1 = [i[1] for i in cidx]
    i2 = [i[2] for i in cidx]
    yt = [-10, -5, 0, 3, 5, 10]
    plt = scatter(xs[i2], ys[i1],
            markershape = :vline,  # more clear
            # markershape = :x, # slightly dense
            markersize = 3, xlim = (-10, 10), ylim = (-10, 10),
            xlab = latexstring("\$\\gamma_1\$"), ylab = latexstring("\$\\gamma_2\$"),
            title = latexstring("\$\\gamma_3 = $γ3, \\gamma_4 = $γ4\$"),
            yticks = (yt, string.(yt)),
            label = "sufficient", legend = :bottomright)
    cidx3 = findall(max.(z2, z3) .> 0)
    i31 = [i[1] for i in cidx3]
    i32 = [i[2] for i in cidx3]
    scatter!(plt, xs[i32], ys[i31],
            markershape = :hline,
            markersize = 3, alpha = 0.5, label = "sufficient & necessary")
    plot!(plt, xs, ys, label = "necessary", fillrange = 10, fillalpha = 0.3, linealpha = 0)
    # calculated boundary
    γ2s = range(γ3, 10, step = 0.01)
    γ1s = γ2s .- (γ2s .- γ3).^2 / (γ4 - γ3)
    if boundary
        plot!(plt, γ1s, γ2s, label = "")
    end
    return plt
    # plot_intervals(γ3 = 3, γ4 = 3.1, step = 0.4)
    # savefig("~/PGitHub/overleaf/MonotoneFitting/res/conditions_case1.pdf")
    # plot_intervals(γ3 = 3, γ4 = 5, step = 0.4)
    # savefig("~/PGitHub/overleaf/MonotoneFitting/res/conditions_case2.pdf")
    # savefig("~/PGitHub/overleaf/MonotoneFitting/res/conditions_case2_boundary.pdf")
end
plot_intervals (generic function with 1 method)

reproduce the figure in the paper

plot_intervals()

we can also evaluate the space volumes under different conditions using Monte Carlo methods

function cmpr_volume(a = -10, b = 10, step = 1)
    ξ = [0, 1]
    τ = vcat(zeros(3), ξ, ones(3))
    bbasis = R"fda::create.bspline.basis(breaks = $ξ, norder = 4)"
    num_suff_nece = 0
    num_suff = 0
    for γ1 in a:step:b
        for γ2 in a:step:b
            for γ3 in a:step:b
                for γ4 in a:step:b
                    γ = [γ1, γ2, γ3, γ4]
                    num_suff_nece += is_sufficient_and_necessary(γ, τ, bbasis)
                    num_suff += is_sufficient(γ)
                end
            end
        end
    end
    r = num_suff / num_suff_nece
    println("num_suff = $num_suff, num_suff_nece = $num_suff_nece, suff/suff_nece = $r")
    return num_suff, num_suff_nece
end

cmpr_volume(-10, 10, 2)
(1001, 1907)

with smaller grid size, the ratio can be smaller, but it takes a longer time to evaluate.

plot the curves that do not satisfy the condition

function plot_curves()
    ξ = [0, 1]
    τ = vcat(zeros(3), ξ, ones(3))
    bbasis = R"fda::create.bspline.basis(breaks = $ξ, norder = 4)"
    x = 0:0.05:1.0
    B = rcopy(R"fda::eval.basis($x, $bbasis)")
    y7 = B * [-2, 7, 3, 5]
    y5 = B * [-2, 5, 3, 5]
    mfit7 = mono_cs(x, y7, 7)
    mfit5 = mono_cs(x, y5, 5)
    plot(x, B * [-2, 3, 3, 5], label = latexstring("\$J=4, \\gamma_2 = 3\$"), legend = :bottomright, xlab = L"x", ylab = L"y")
    plot!(x, B * [-2, 5, 3, 5], label = latexstring("\$J=4,\\gamma_2 = 5\$"))
    plot!(x, B * [-2, 7, 3, 5], label = latexstring("\$J=4,\\gamma_2 = 7\$"))
    plot!(x, mfit5.fitted, label = "J = 5", ls = :dash, lw = 2)
    plot!(x, mfit7.fitted, label = "J = 7", ls = :dash, lw = 2)
end

plot_curves()