From 4b5c6668ae100cc08b2e5d955357ee06eb3325d7 Mon Sep 17 00:00:00 2001 From: fjebaker Date: Fri, 4 Oct 2024 12:30:42 +0100 Subject: [PATCH] fix: allow even more complex bindings One of the outstanding problems is a two model mutli-bind where B.K_1 -> A.K_1 B.K_2 -> A.K_2 A.K_2 -> A.K_1 in which case the bindings for `B` might come out as index `[1, 2]`, but `A` only has 1 parameter in its parameter vector, leading to index out of bounds. --- src/fitting/binding.jl | 10 +++++++--- test/fitting/test-binding.jl | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/fitting/binding.jl b/src/fitting/binding.jl index 002fc8bc..319ff1cb 100644 --- a/src/fitting/binding.jl +++ b/src/fitting/binding.jl @@ -17,18 +17,22 @@ function _construct_bound_mapping(bindings, parameter_count) parameter_mapping[b[1]][b[2]] = reference[2] # mark for removal: find the parameter index in the global array - N = sum(length(parameter_mapping[q]) for q = 1:(b[1]-1)) + N = if b[1] > 1 + sum(length(parameter_mapping[q]) for q = 1:b[1]-1) + else + 0 + end index = N + b[2] push!(remove, index) # need to now shuffle all the indices greater than this one down by 1 - for k = (b[2]+1):length(parameter_mapping[b[1]]) + for k = b[2]+1:length(parameter_mapping[b[1]]) if (parameter_mapping[b[1]][k] > parameter_number) parameter_mapping[b[1]][k] -= 1 end end # and for subsequent models - for j = (b[1]+1):length(parameter_count) + for j = b[1]+1:length(parameter_count) for k = 1:length(parameter_mapping[j]) if parameter_mapping[j][k] > parameter_number parameter_mapping[j][k] -= 1 diff --git a/test/fitting/test-binding.jl b/test/fitting/test-binding.jl index 9af44133..6b2bd02b 100644 --- a/test/fitting/test-binding.jl +++ b/test/fitting/test-binding.jl @@ -123,3 +123,22 @@ new_bindings = SpectralFitting.adjust_free_bindings(prob.model, prob.bindings) @test new_bindings == [[1 => 1, 2 => 3]] # TODO: free parameters should not be allowed to bind to frozen parameters + + +# can we bind parameters within the same model +prob = FittingProblem(model1 => dummy_data1) +bind!(prob, 1 => :K_1, 1 => :a_1) +_, mapping = SpectralFitting._build_parameter_mapping(prob.model, prob.bindings) +@test mapping == ([1, 1, 2],) + +# can we bind parameters within the same model +model1.a_2.frozen = false +prob = FittingProblem(model1 => dummy_data1, model1 => dummy_data1) +bind!(prob, 1 => :K_1, 2 => :K_1) +bind!(prob, 1 => :a_1, 2 => :a_1) +bind!(prob, 1 => :K_2, 2 => :K_2) +bind!(prob, 1 => :a_2, 2 => :a_2) +bind!(prob, 1 => :K_1, 1 => :a_1) +details(prob) +params, mapping = SpectralFitting._build_parameter_mapping(prob.model, prob.bindings) +@test mapping == ([1, 1, 2],)