Skip to content

Commit 37a612a

Browse files
refactor: rework discrete indexing behavior
1 parent 4183188 commit 37a612a

11 files changed

+657
-510
lines changed

docs/src/api.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ allvariables
3131
```@docs
3232
observed
3333
parameter_observed
34-
ParameterObservedFunction
3534
```
3635

3736
#### Parameter timeseries
@@ -46,6 +45,8 @@ may change at different times.
4645
is_timeseries_parameter
4746
timeseries_parameter_index
4847
ParameterTimeseriesIndex
48+
get_all_timeseries_indexes
49+
ContinuousTimeseries
4950
```
5051

5152
## Value provider interface

docs/src/complete_sii.md

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,8 @@ end
132132
In case a type does not support such observed quantities, `is_observed` must be
133133
defined to always return `false`, and `observed` does not need to be implemented.
134134

135-
The same process can be followed for [`parameter_observed`](@ref), with the exception
136-
that the returned function must not have `u` in its signature, and must be wrapped in a
137-
[`ParameterObservedFunction`](@ref). In-place versions can also be implemented for
138-
`parameter_observed`.
135+
The same process can be followed for [`parameter_observed`](@ref). In-place versions
136+
can also be implemented for `parameter_observed`.
139137

140138
#### Note about constant structure
141139

@@ -334,7 +332,9 @@ end
334332
# To be able to access parameter values
335333
SymbolicIndexingInterface.parameter_values(mpo::MyParameterObject) = mpo.p
336334
# Update the parameter object with new values
337-
function SymbolicIndexingInterface.with_updated_parameter_timeseries_values(mpo::MyParameterObject, args::Pair...)
335+
# Here, we don't need the index provider but it may be necessary for other implementations
336+
function SymbolicIndexingInterface.with_updated_parameter_timeseries_values(
337+
::SymbolCache, mpo::MyParameterObject, args::Pair...)
338338
for (ts_idx, val) in args
339339
mpo.p[mpo.disc_idxs[ts_idx]] = val
340340
end
@@ -440,15 +440,15 @@ sol.ps[:b, idxs]
440440
```
441441

442442
```@example param_timeseries
443-
sol.ps[[:a, :b]] # returns the values at the last timestep, since :a is not timeseries
443+
sol.ps[[:a, :b]] # :a has the same value at all time points
444444
```
445445

446446
```@example param_timeseries
447447
# throws an error since :b and :d belong to different timeseries
448448
try
449449
sol.ps[[:b, :d]]
450450
catch e
451-
@show e
451+
showerror(stdout, e)
452452
end
453453
```
454454

@@ -457,11 +457,15 @@ sol.ps[:(b + c)] # observed quantities work too
457457
```
458458

459459
```@example param_timeseries
460-
getu(sol, :b)(sol) # returns the values :b takes at the times in the state timeseries
460+
getu(sol, :b)(sol) # works
461461
```
462462

463463
```@example param_timeseries
464-
getu(sol, [:b, :d])(sol) # works
464+
try
465+
getu(sol, [:b, :d])(sol) # errors since :b and :d belong to different timeseries
466+
catch e
467+
showerror(stdout, e)
468+
end
465469
```
466470

467471
## Custom containers

src/SymbolicIndexingInterface.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ include("trait.jl")
1414
export is_variable, variable_index, variable_symbols, is_parameter, parameter_index,
1515
is_timeseries_parameter, timeseries_parameter_index, ParameterTimeseriesIndex,
1616
parameter_symbols, is_independent_variable, independent_variable_symbols,
17-
is_observed, observed, parameter_observed, ParameterObservedFunction,
17+
is_observed, observed, parameter_observed,
18+
ContinuousTimeseries, get_all_timeseries_indexes,
1819
is_time_dependent, constant_structure, symbolic_container,
1920
all_variable_symbols, all_symbols, solvedvariables, allvariables, default_values,
2021
symbolic_evaluate

src/index_provider_interface.jl

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -98,38 +98,17 @@ function timeseries_parameter_index(indp, sym)
9898
end
9999
end
100100

101-
"""
102-
struct ParameterObservedFunction
103-
function ParameterObservedFunction(timeseries_idx, observed_fn::Function)
104-
function ParameterObservedFunction(observed_fn::Function)
105-
106-
A struct which stores the parameter observed function and optional timeseries index for
107-
a particular symbol. The timeseries index is optional and may be omitted. Specifying the
108-
timeseries index allows [`getp`](@ref) to return the appropriate timeseries for a
109-
timeseries parameter.
110-
111-
For time-dependent index providers (where `is_time_dependent(indp)`) `observed_fn` must
112-
have the signature `(p, t) -> [values...]`. For non-time-dependent index providers
113-
(where `!is_time_dependent(indp)`) `observed_fn` must have the signature
114-
`(p) -> [values...]`. To support in-place `getp` methods, `observed_fn` must also have an
115-
additional method which takes `buffer::AbstractArray` as its first argument. The required
116-
values must be written to the buffer in the appropriate order.
117-
"""
118-
struct ParameterObservedFunction{I, F <: Function}
119-
timeseries_idx::I
120-
observed_fn::F
121-
end
122-
123101
"""
124102
parameter_observed(indp, sym)
125103
126-
Return the observed function of `sym` in `indp` as a [`ParameterObservedFunction`](@ref).
127-
If `sym` only involves variables from a single parameter timeseries (optionally along
128-
with non-timeseries parameters) the timeseries index of the parameter timeseries should
129-
be provided in the [`ParameterObservedFunction`](@ref). In all other cases, just the
130-
observed function should be returned as part of the `ParameterObservedFunction` object.
104+
Return the observed function of `sym` in `indp`. This functions similarly to
105+
[`observed`](@ref) except that `u` is not an argument of the returned function. For time-
106+
dependent systems, the returned function must have the signature `(p, t) -> [values...]`.
107+
For time-independent systems, the returned function must have the signature
108+
`(p) -> [values...]`.
131109
132-
By default, this function returns `nothing`.
110+
By default, this function returns `nothing`, indicating that the index provider does not
111+
support generating parameter observed functions.
133112
"""
134113
function parameter_observed(indp, sym)
135114
if hasmethod(symbolic_container, Tuple{typeof(indp)})
@@ -139,6 +118,38 @@ function parameter_observed(indp, sym)
139118
end
140119
end
141120

121+
"""
122+
struct ContinuousTimeseries end
123+
124+
A singleton struct corresponding to the timeseries index of the continuous timeseries.
125+
"""
126+
struct ContinuousTimeseries end
127+
128+
"""
129+
get_all_timeseries_indexes(indp, sym)
130+
131+
Return a `Set` of all unique timeseries indexes of variables in symbolic variable
132+
`sym`. `sym` may be a symbolic variable or expression, an array of symbolics, an index,
133+
or an array of indices. Continuous variables correspond to the
134+
[`ContinuousTimeseries`](@ref) timeseries index. Non-timeseries parameters do not have a
135+
timeseries index. Timeseries parameters have the same timeseries index as that returned by
136+
[`timeseries_parameter_index`](@ref). Note that the independent variable corresponds to
137+
the `ContinuousTimeseries` timeseries index.
138+
139+
Any ambiguities should be resolved in favor of variables. For example, if `1` could refer
140+
to the variable at index `1` or parameter at index `1`, it should be interpreted as the
141+
variable.
142+
143+
By default, this function returns `Set([ContinuousTimeseries()])`.
144+
"""
145+
function get_all_timeseries_indexes(indp, sym)
146+
if hasmethod(symbolic_container, Tuple{typeof(indp)})
147+
return get_all_timeseries_indexes(symbolic_container(indp), sym)
148+
else
149+
return Set([ContinuousTimeseries()])
150+
end
151+
end
152+
142153
"""
143154
parameter_symbols(indp)
144155

0 commit comments

Comments
 (0)