Skip to content

Commit

Permalink
Merge pull request #26 from SciML/as/parameter-indexing-proxy
Browse files Browse the repository at this point in the history
feat: add `ParameterIndexingProxy`
  • Loading branch information
ChrisRackauckas authored Jan 4, 2024
2 parents ba13520 + 9189b4d commit 16457cf
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ parameter_values
set_parameter!
getp
setp
ParameterIndexingProxy
```

### State indexing
Expand Down
29 changes: 29 additions & 0 deletions docs/src/complete_sii.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/SymbolicIndexingInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
19 changes: 19 additions & 0 deletions src/parameter_indexing_proxy.jl
Original file line number Diff line number Diff line change
@@ -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
4 changes: 2 additions & 2 deletions test/parameter_indexing_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 16457cf

Please sign in to comment.