using OptimalTransport using Distances using Plots using PythonOT: PythonOT using Tulip using LinearAlgebra using Random Random.seed!(1234) const POT = PythonOT M = 200 μ = fill(1 / M, M) μsupport = rand(M) N = 250 ν = fill(1 / N, N) νsupport = rand(N); C = pairwise(SqEuclidean(), μsupport', νsupport'; dims=2); γ = emd(μ, ν, C, Tulip.Optimizer()); emd2(μ, ν, C, Tulip.Optimizer()) ε = 0.01 γ = sinkhorn(μ, ν, C, ε); γpot = POT.sinkhorn(μ, ν, C, ε) norm(γ - γpot, Inf) sinkhorn2(μ, ν, C, ε) quadreg(μ, ν, C, ε; maxiter=100); ε = 0.005 γ = sinkhorn_stabilized(μ, ν, C, ε; maxiter=5_000); γ_pot = POT.sinkhorn(μ, ν, C, ε; method="sinkhorn_stabilized", numItermax=5_000) norm(γ - γ_pot, Inf) γ = sinkhorn_stabilized_epsscaling(μ, ν, C, ε; maxiter=5_000); γpot = POT.sinkhorn(μ, ν, C, ε; method="sinkhorn_epsilon_scaling", numItermax=5000) norm(γ - γpot, Inf) M = 100 μ = fill(1 / M, M) μsupport = rand(M) N = 200 ν = fill(1 / M, N) νsupport = rand(N); C = pairwise(SqEuclidean(), μsupport', νsupport'; dims=2); ε = 0.01 λ = 1 γ = sinkhorn_unbalanced(μ, ν, C, λ, λ, ε); γpot = POT.sinkhorn_unbalanced(μ, ν, C, ε, λ) norm(γ - γpot, Inf) μsupport = νsupport = range(-2, 2; length=100) C = pairwise(SqEuclidean(), μsupport', νsupport'; dims=2) μ = normalize!(exp.(-μsupport .^ 2 ./ 0.5^2), 1) ν = normalize!(νsupport .^ 2 .* exp.(-νsupport .^ 2 ./ 0.5^2), 1) plot(μsupport, μ; label=raw"$\mu$", size=(600, 400)) plot!(νsupport, ν; label=raw"$\nu$") γ = sinkhorn(μ, ν, C, 0.01) heatmap( μsupport, νsupport, γ; title="Entropically regularised optimal transport", size=(600, 600), ) γquad = quadreg(μ, ν, C, 5; maxiter=100); heatmap( μsupport, νsupport, γquad; title="Quadratically regularised optimal transport", size=(600, 600), ) support = range(-1, 1; length=250) mu1 = normalize!(exp.(-(support .+ 0.5) .^ 2 ./ 0.1^2), 1) mu2 = normalize!(exp.(-(support .- 0.5) .^ 2 ./ 0.1^2), 1) plt = plot(; size=(800, 400), legend=:outertopright) plot!(plt, support, mu1; label=raw"$\mu_1$") plot!(plt, support, mu2; label=raw"$\mu_2$") mu = hcat(mu1, mu2) C = pairwise(SqEuclidean(), support'; dims=2) for λ1 in (0.25, 0.5, 0.75) λ2 = 1 - λ1 a = sinkhorn_barycenter(mu, C, 0.01, [λ1, λ2], SinkhornGibbs()) plot!(plt, support, a; label="\$\\mu \\quad (\\lambda_1 = $λ1)\$") end plt