diff --git a/docs/src/api.md b/docs/src/api.md index dbc3a3f..3c049c7 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -36,6 +36,7 @@ parameter_values set_parameter! getp setp +ParameterIndexingProxy ``` ### State indexing diff --git a/docs/src/complete_sii.md b/docs/src/complete_sii.md index 12c1623..e5d592a 100644 --- a/docs/src/complete_sii.md +++ b/docs/src/complete_sii.md @@ -262,6 +262,35 @@ function SymbolicIndexingInterface.set_state!(integrator::ExampleIntegrator, val end ``` +# The `ParameterIndexingProxy` + +[`ParameterIndexingProxy`](@ref) is a wrapper around another type which implements the +interface and allows using [`getp`](@ref) and [`setp`](@ref) to get and set parameter +values. This allows for a cleaner interface for parameter indexing. Consider the +following example for `ExampleIntegrator`: + +```julia +function Base.getproperty(obj::ExampleIntegrator, sym::Symbol) + if sym === :ps + return ParameterIndexingProxy(obj) + else + return getfield(obj, sym) + end +end +``` + +This enables the following API: + +```julia +integrator = ExampleIntegrator([1.0, 2.0, 3.0], [4.0, 5.0], 6.0, Dict(:x => 1, :y => 2, :z => 3), Dict(:a => 1, :b => 2), :t) + +integrator.ps[:a] # 4.0 +getp(integrator, :a)(integrator) # functionally the same as above + +integrator.ps[:b] = 3.0 +setp(integrator, :b)(integrator, 3.0) # functionally the same as above +``` + # Implementing the `SymbolicTypeTrait` for a type The `SymbolicTypeTrait` is used to identify values that can act as symbolic variables. It diff --git a/src/SymbolicIndexingInterface.jl b/src/SymbolicIndexingInterface.jl index a730d3e..7077e92 100644 --- a/src/SymbolicIndexingInterface.jl +++ b/src/SymbolicIndexingInterface.jl @@ -20,4 +20,6 @@ export Timeseries, NotTimeseries, is_timeseries, state_values, set_state!, current_time, getu, setu include("state_indexing.jl") +export ParameterIndexingProxy +include("parameter_indexing_proxy.jl") end diff --git a/src/parameter_indexing_proxy.jl b/src/parameter_indexing_proxy.jl new file mode 100644 index 0000000..0b92587 --- /dev/null +++ b/src/parameter_indexing_proxy.jl @@ -0,0 +1,19 @@ +""" + struct ParameterIndexingProxy + +This struct wraps any struct implementing the symbolic indexing interface. It allows +`getindex` and `setindex!` operations to get/set parameter values. Requires that the +wrapped type support [`getp`](@ref) and [`setp`](@ref) for getting and setting +parameter values respectively. +""" +struct ParameterIndexingProxy{T} + wrapped::T +end + +function Base.getindex(p::ParameterIndexingProxy, idx) + return getp(p.wrapped, idx)(p.wrapped) +end + +function Base.setindex!(p::ParameterIndexingProxy, val, idx) + return setp(p.wrapped, idx)(p.wrapped, val) +end diff --git a/test/parameter_indexing_test.jl b/test/parameter_indexing_test.jl index b67fb61..8f858e6 100644 --- a/test/parameter_indexing_test.jl +++ b/test/parameter_indexing_test.jl @@ -16,8 +16,8 @@ for (i, sym) in [(1, :a), (2, :b), ([1, 2], [:a, :b]), ((1, 2), (:a, :b))] get = getp(sys, sym) set! = setp(sys, sym) true_value = i isa Tuple ? getindex.((p,), i) : p[i] - @test get(fi) == true_value + @test get(fi) == ParameterIndexingProxy(fi)[sym] == true_value set!(fi, 0.5 .* i) - @test get(fi) == 0.5 .* i + @test get(fi) == ParameterIndexingProxy(fi)[sym] == 0.5 .* i set!(fi, true_value) end