From d8d1eddaf672af01f130e597437b2a98de0e50ad Mon Sep 17 00:00:00 2001 From: Rafael Arutjunjan Date: Wed, 20 Nov 2024 13:34:29 +0100 Subject: [PATCH] Fix GetStepRanges --- Project.toml | 2 +- src/CustomIO.jl | 4 ++-- src/InformationGeometry.jl | 1 + src/NumericalTools/Multistart.jl | 36 ++++++++++++++++++++++++++++---- 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/Project.toml b/Project.toml index a9c4089e..965b7100 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "InformationGeometry" uuid = "ee9d1287-bbdf-432c-9920-c447cf97a828" authors = ["Rafael Arutjunjan"] -version = "1.15.2" +version = "1.16.0" [deps] BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" diff --git a/src/CustomIO.jl b/src/CustomIO.jl index c31cd152..e9cd1769 100644 --- a/src/CustomIO.jl +++ b/src/CustomIO.jl @@ -53,7 +53,7 @@ end Base.summary(P::ParameterProfiles) = string(TYPE_COLOR, "ParameterProfiles", NO_COLOR, " with pdim="* string(pdim(P)), !HasTrajectories(P) ? string(", ", ORANGE_COLOR, "no trajectories", NO_COLOR) : "") Base.summary(PV::ParameterProfilesView) = string(TYPE_COLOR, "ParameterProfile", NO_COLOR, " for index "* string(PV.i) *"/"* string(pdim(PV)), !HasTrajectories(PV) ? string(", ", ORANGE_COLOR, "no trajectories", NO_COLOR) : "") -Base.summary(R::MultistartResults) = string(TYPE_COLOR, "MultistartResults", NO_COLOR, " with "* string(findlast(isfinite, R.FinalObjectives)) *"/"* string(length(R)) *" successful starts") +Base.summary(R::MultistartResults) = string(TYPE_COLOR, "MultistartResults", NO_COLOR, " with "* string(FindLastIndSafe(R)) *"/"* string(length(R)) *" successful starts") # http://docs.junolab.org/stable/man/info_developer/# @@ -199,7 +199,7 @@ Base.show(io::IO, P::Union{ParameterProfiles,ParameterProfilesView}) = print(io, # Multi-line display when used on its own in REPL function Base.show(io::IO, ::MIME"text/plain", R::MultistartResults) - LastFinite = findlast(isfinite, R.FinalObjectives) + LastFinite = FindLastIndSafe(R) FirstStepInd = GetFirstStepInd(R, LastFinite) println(io, Base.summary(R)) println(io, "Median number of iterations: "*string(Int(round(median(@view R.Iterations[1:LastFinite]))))) diff --git a/src/InformationGeometry.jl b/src/InformationGeometry.jl index 0edee2c3..95e7b194 100644 --- a/src/InformationGeometry.jl +++ b/src/InformationGeometry.jl @@ -244,6 +244,7 @@ export PlotRelativeParameterTrajectories include("NumericalTools/Multistart.jl") export MultistartFit, LocalMultistartFit, MultistartResults, WaterfallPlot, ParameterPlot +export DistanceMatrixWithinStep, DistanceMatrixBetweenSteps include("Divergences.jl") diff --git a/src/NumericalTools/Multistart.jl b/src/NumericalTools/Multistart.jl index e3525fce..23846309 100644 --- a/src/NumericalTools/Multistart.jl +++ b/src/NumericalTools/Multistart.jl @@ -180,10 +180,13 @@ catch E; (E isa ErrorException ? throw("StatsPlots.jl needs to be loaded before using ParameterPlot.") : rethrow(E)) end -# Implement findlast in safe manner so "nothing" is never returned -GetStepInds(R::MultistartResults, ymaxind::Int=findlast(isfinite,R.FinalObjectives); StepTol::Real=0.01) = ((@assert 1 ≤ ymaxind ≤ length(R) && StepTol > 0); F=-R.FinalObjectives; [i for i in 1:ymaxind-1 if isfinite(F[i+1]) && abs(F[i+1]-F[i]) > StepTol]) +FindLastIndSafe(R::MultistartResults) = (LastFinite=findlast(isfinite, R.FinalObjectives); isnothing(LastFinite) ? 0 : LastFinite) -function GetFirstStepInd(R::MultistartResults, ymaxind::Int=findlast(isfinite,R.FinalObjectives); StepTol::Real=0.01) +# GetStepInds always includes last point of lower step +GetStepInds(R::MultistartResults, ymaxind::Int=FindLastIndSafe(R); StepTol::Real=0.01) = ((@assert 1 ≤ ymaxind ≤ length(R) && StepTol > 0); F=-R.FinalObjectives; [i for i in 1:ymaxind-1 if isfinite(F[i+1]) && abs(F[i+1]-F[i]) > StepTol]) +GetStepRanges(R::MultistartResults, ymaxind::Int=FindLastIndSafe(R), StepInds::AbstractVector{<:Int}=GetStepInds(R,ymaxind)) = vcat([1:StepInds[1]], [StepInds[i]+1:StepInds[i+1] for i in 1:length(StepInds)-1], [StepInds[end]+1:ymaxind]) + +function GetFirstStepInd(R::MultistartResults, ymaxind::Int=FindLastIndSafe(R); StepTol::Real=0.01) (@assert 1 ≤ ymaxind ≤ length(R) && StepTol > 0); F=-R.FinalObjectives FirstStepInd = findfirst(i->isfinite(F[i+1]) && abs(F[i+1]-F[i]) > StepTol, 1:ymaxind-1) isnothing(FirstStepInd) ? ymaxind : FirstStepInd @@ -249,7 +252,7 @@ RecipesBase.@recipe function f(R::MultistartResults, ::Union{Val{:ParameterPlot} ymaxind = (Q=findlast(x->isfinite(x) && abs(x-Fin[1]) < MaxValue, Fin); isnothing(Q) ? length(Fin) : Q) @assert StepTol > 0 StepInds = GetStepInds(R, ymaxind; StepTol=StepTol) - AllSteps = vcat([1:StepInds[1]], [StepInds[i]:StepInds[i+1] for i in 1:length(StepInds)-1], [StepInds[end]:ymaxind]) + AllSteps = GetStepRanges(R, ymaxind, StepInds) Steps = @view AllSteps[1:min(Nsteps, length(AllSteps))] dfs = [(DoBiLog ? BiLog : identity)(reduce(vcat, R.FinalPoints[step])) for step in Steps] Xvals = 1.0:Spacer*length(dfs):Spacer*length(dfs)*length(pnames) |> collect @@ -275,3 +278,28 @@ RecipesBase.@recipe function f(R::MultistartResults, ::Union{Val{:ParameterPlot} end end end + +""" + DistanceMatrixWithinStep(DM::AbstractDataModel, R::MultistartResults, Ind::Int; logarithmic::Bool=true, plot::Bool=true, kwargs...) +Returns matrix of mutual distances between optima in step `Ind` with respect to Fisher Metric of first entry in step. +""" +function DistanceMatrixWithinStep(DM::AbstractDataModel, R::MultistartResults, Ind::Int; logarithmic::Bool=true, plot::Bool=true, kwargs...) + ymaxind = FindLastIndSafe(R); StepInds = GetStepInds(R, ymaxind); Steps = GetStepRanges(R, ymaxind, StepInds) + @assert 1 ≤ Ind ≤ length(Steps) + F = FisherMetric(DM, R.FinalPoints[Steps[Ind][1]]) # get first point in ProfileDomain + Dists = [sqrt(InnerProduct(F, R.FinalPoints[i] - R.FinalPoints[j])) for i in Steps[Ind], j in Steps[Ind]] + plot && display(RecipesBase.plot((logarithmic ? log1p : identity).(Dists + Diagonal(fill(NaN, size(Dists,1)))); st=:heatmap, clims=(0, Inf), margin=2Plots.mm, kwargs...)) + Dists +end + +""" + DistanceMatrixBetweenSteps(DM::AbstractDataModel, R::MultistartResults; logarithmic::Bool=true, plot::Bool=true, kwargs...) +Returns matrix of mutual distances between first optima in steps with respect to Fisher Metric of best optimum. +""" +function DistanceMatrixBetweenSteps(DM::AbstractDataModel, R::MultistartResults; logarithmic::Bool=true, plot::Bool=true, kwargs...) + ymaxind = FindLastIndSafe(R); StepInds = GetStepInds(R, ymaxind); Steps = GetStepRanges(R, ymaxind, StepInds) + F = FisherMetric(DM, R.FinalPoints[1]) + Dists = [sqrt(InnerProduct(F, R.FinalPoints[Steps[i][1]] - R.FinalPoints[Steps[j][1]])) for i in eachindex(Steps), j in eachindex(Steps)] + plot && display(RecipesBase.plot((logarithmic ? log1p : identity).(Dists + Diagonal(fill(NaN, size(Dists,1)))); st=:heatmap, clims=(0, Inf), margin=2Plots.mm, kwargs...)) + Dists +end \ No newline at end of file