Skip to content

Commit 16457cf

Browse files
Merge pull request #26 from SciML/as/parameter-indexing-proxy
feat: add `ParameterIndexingProxy`
2 parents ba13520 + 9189b4d commit 16457cf

File tree

5 files changed

+53
-2
lines changed

5 files changed

+53
-2
lines changed

docs/src/api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ parameter_values
3636
set_parameter!
3737
getp
3838
setp
39+
ParameterIndexingProxy
3940
```
4041

4142
### State indexing

docs/src/complete_sii.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,35 @@ function SymbolicIndexingInterface.set_state!(integrator::ExampleIntegrator, val
262262
end
263263
```
264264

265+
# The `ParameterIndexingProxy`
266+
267+
[`ParameterIndexingProxy`](@ref) is a wrapper around another type which implements the
268+
interface and allows using [`getp`](@ref) and [`setp`](@ref) to get and set parameter
269+
values. This allows for a cleaner interface for parameter indexing. Consider the
270+
following example for `ExampleIntegrator`:
271+
272+
```julia
273+
function Base.getproperty(obj::ExampleIntegrator, sym::Symbol)
274+
if sym === :ps
275+
return ParameterIndexingProxy(obj)
276+
else
277+
return getfield(obj, sym)
278+
end
279+
end
280+
```
281+
282+
This enables the following API:
283+
284+
```julia
285+
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)
286+
287+
integrator.ps[:a] # 4.0
288+
getp(integrator, :a)(integrator) # functionally the same as above
289+
290+
integrator.ps[:b] = 3.0
291+
setp(integrator, :b)(integrator, 3.0) # functionally the same as above
292+
```
293+
265294
# Implementing the `SymbolicTypeTrait` for a type
266295

267296
The `SymbolicTypeTrait` is used to identify values that can act as symbolic variables. It

src/SymbolicIndexingInterface.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ export Timeseries,
2020
NotTimeseries, is_timeseries, state_values, set_state!, current_time, getu, setu
2121
include("state_indexing.jl")
2222

23+
export ParameterIndexingProxy
24+
include("parameter_indexing_proxy.jl")
2325
end

src/parameter_indexing_proxy.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""
2+
struct ParameterIndexingProxy
3+
4+
This struct wraps any struct implementing the symbolic indexing interface. It allows
5+
`getindex` and `setindex!` operations to get/set parameter values. Requires that the
6+
wrapped type support [`getp`](@ref) and [`setp`](@ref) for getting and setting
7+
parameter values respectively.
8+
"""
9+
struct ParameterIndexingProxy{T}
10+
wrapped::T
11+
end
12+
13+
function Base.getindex(p::ParameterIndexingProxy, idx)
14+
return getp(p.wrapped, idx)(p.wrapped)
15+
end
16+
17+
function Base.setindex!(p::ParameterIndexingProxy, val, idx)
18+
return setp(p.wrapped, idx)(p.wrapped, val)
19+
end

test/parameter_indexing_test.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ for (i, sym) in [(1, :a), (2, :b), ([1, 2], [:a, :b]), ((1, 2), (:a, :b))]
1616
get = getp(sys, sym)
1717
set! = setp(sys, sym)
1818
true_value = i isa Tuple ? getindex.((p,), i) : p[i]
19-
@test get(fi) == true_value
19+
@test get(fi) == ParameterIndexingProxy(fi)[sym] == true_value
2020
set!(fi, 0.5 .* i)
21-
@test get(fi) == 0.5 .* i
21+
@test get(fi) == ParameterIndexingProxy(fi)[sym] == 0.5 .* i
2222
set!(fi, true_value)
2323
end

0 commit comments

Comments
 (0)