algorithmsbooks / algforopt-notebooks

Jupyter notebooks associated with the Algorithms for Optimization textbook

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Dirichlet.

AlexandrParkhomenko opened this issue · comments

Hello professors!

This is only question not issue.
How you plot Dirichlet distribution in Julia?
Maybe I'm bad at searching, but I can't find the code on juliaplot site.

Thank you,
Alexandr.

Hello Alexandr,

The Dirichlet figure (Example 16.3) has the following plotting code:

p = plot(
			Dirichlet([2,1,5]),
			xlabel=L"T(s_1 \mid s_1, a_1)",
			ylabel=L"T(s_2 \mid s_1, a_1)",
			zlabel=L"T(s_3 \mid s_1, a_1)",
			colorbar=true,
			style="colormap/viridis,width=6cm")

which calls the following support function:

function PGFPlots.plot(D::Dirichlet; style="", bins=41, title=nothing, colorbar=nothing, xlabel=nothing, ylabel=nothing, zlabel=nothing)
    s_arr = collect(range(0.0,stop=1.0,length=bins))

    function coordinate_string(vertex; ϵ = 1e-5)
        s1 = s_arr[vertex[1]]
        s2 = s_arr[vertex[2]]
        s3 = clamp(1.0 - s1 - s2, 0.0, 1.0)
        if s1 == 1.0
            s1 -= ϵ
            s2 += ϵ/2
            s3 += ϵ/2
        elseif s2 == 1.0
            s2 -= ϵ
            s1 += ϵ/2
            s3 += ϵ/2
        elseif s3 == 1.0
            s3 -= ϵ
            s1 += ϵ/2
            s2 += ϵ/2
        elseif s1 == 0.0
            s1 += ϵ
            s2 -= ϵ/2
            s3 -= ϵ/2
        elseif s2 == 0.0
            s2 += ϵ
            s1 -= ϵ/2
            s3 -= ϵ/2
        elseif s3 == 0.0
            s3 += ϵ
            s1 -= ϵ/2
            s2 -= ϵ/2
        end
        p = pdf(D, [s1,s2,s3])
        return @sprintf("           %.3f    %.3f    %.3f    %.3f\n", s1, s2, s3, p)
    end

    vertex_is_valid(vertex) = -0.00001 <= 1.0 - s_arr[vertex[1]] - s_arr[vertex[2]] <= 1.000001

    tikz_string = ""
    tikz_string *= "    \\addplot3[patch, shader=interp, point meta=\\thisrow{p}]\n"
    tikz_string *= "        table[x=s1,y=s2,z=s3]{\n"
    tikz_string *= "            s1 s2 s3 p\n"
    for i in 1:(length(s_arr)-1)
        for j in 1:(length(s_arr)-1)
            v1 = (i,j)
            v2 = (i+1,j)
            v3 = (i,j+1)
            v4 = (i+1,j+1)

            if vertex_is_valid(v1) && vertex_is_valid(v2) && vertex_is_valid(v3)
                tikz_string *= coordinate_string(v1)
                tikz_string *= coordinate_string(v2)
                tikz_string *= coordinate_string(v3)
            end

            if vertex_is_valid(v2) && vertex_is_valid(v4) && vertex_is_valid(v3)
                tikz_string *= coordinate_string(v2)
                tikz_string *= coordinate_string(v4)
                tikz_string *= coordinate_string(v3)
            end
        end
    end
    tikz_string *= "};\n"

    return TernaryAxis(Plots.Command(tikz_string),
        xlabel=xlabel,
        ylabel=ylabel,
        zlabel=zlabel,
        style="axis on top,ternary limits relative=false," * style,
        colorbar=colorbar,
        title=title
    )
end

It tessellates the distribution into a bunch of triangles and plots them in a ternary axis.

Thank you!!!