Skip to content

Commit 98eb805

Browse files
committed
reapply formatting
1 parent 063783b commit 98eb805

File tree

8 files changed

+139
-130
lines changed

8 files changed

+139
-130
lines changed

.JuliaFormatter.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
style = "sciml"
2+
format_markdown = true
3+
format_docstrings = true

README.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,14 @@ Pkg.add("SymbolicIndexingInterface")
1616

1717
The symbolic indexing interface has 2 levels:
1818

19-
1. The user level. At the user level, a modeler or engineer simply uses terms from a
20-
domain-specific language (DSL) inside of SciML functionality and will receive the requested
21-
values. For example, if a DSL defines a symbol `x`, then `sol[x]` returns the solution
22-
value(s) for `x`.
23-
2. The DSL system structure level. This is the structure which defines the symbolic indexing
24-
for a given problem/solution. DSLs can tag a constructed problem/solution with this
25-
object in order to endow the SciML tools with the ability to index symbolically according
26-
to the definitions the DSL writer wants.
27-
19+
1. The user level. At the user level, a modeler or engineer simply uses terms from a
20+
domain-specific language (DSL) inside of SciML functionality and will receive the requested
21+
values. For example, if a DSL defines a symbol `x`, then `sol[x]` returns the solution
22+
value(s) for `x`.
23+
2. The DSL system structure level. This is the structure which defines the symbolic indexing
24+
for a given problem/solution. DSLs can tag a constructed problem/solution with this
25+
object in order to endow the SciML tools with the ability to index symbolically according
26+
to the definitions the DSL writer wants.
2827

2928
## Example
3029

docs/src/complete_sii.md

Lines changed: 99 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ This tutorial will show how to define the entire Symbolic Indexing Interface on
55

66
```julia
77
struct ExampleSystem
8-
state_index::Dict{Symbol,Int}
9-
parameter_index::Dict{Symbol,Int}
10-
independent_variable::Union{Symbol,Nothing}
11-
defaults::Dict{Symbol, Float64}
12-
# mapping from observed variable to Expr to calculate its value
13-
observed::Dict{Symbol,Expr}
8+
state_index::Dict{Symbol, Int}
9+
parameter_index::Dict{Symbol, Int}
10+
independent_variable::Union{Symbol, Nothing}
11+
# mapping from observed variable to Expr to calculate its value
12+
observed::Dict{Symbol, Expr}
1413
end
1514
```
1615

@@ -25,58 +24,58 @@ These are the simple functions which describe how to turn symbols into indices.
2524

2625
```julia
2726
function SymbolicIndexingInterface.is_variable(sys::ExampleSystem, sym)
28-
haskey(sys.state_index, sym)
27+
haskey(sys.state_index, sym)
2928
end
3029

3130
function SymbolicIndexingInterface.variable_index(sys::ExampleSystem, sym)
32-
get(sys.state_index, sym, nothing)
31+
get(sys.state_index, sym, nothing)
3332
end
3433

3534
function SymbolicIndexingInterface.variable_symbols(sys::ExampleSystem)
36-
collect(keys(sys.state_index))
35+
collect(keys(sys.state_index))
3736
end
3837

3938
function SymbolicIndexingInterface.is_parameter(sys::ExampleSystem, sym)
40-
haskey(sys.parameter_index, sym)
39+
haskey(sys.parameter_index, sym)
4140
end
4241

4342
function SymbolicIndexingInterface.parameter_index(sys::ExampleSystem, sym)
44-
get(sys.parameter_index, sym, nothing)
43+
get(sys.parameter_index, sym, nothing)
4544
end
4645

4746
function SymbolicIndexingInterface.parameter_symbols(sys::ExampleSystem)
48-
collect(keys(sys.parameter_index))
47+
collect(keys(sys.parameter_index))
4948
end
5049

5150
function SymbolicIndexingInterface.is_independent_variable(sys::ExampleSystem, sym)
52-
# note we have to check separately for `nothing`, otherwise
53-
# `is_independent_variable(p, nothing)` would return `true`.
54-
sys.independent_variable !== nothing && sym === sys.independent_variable
51+
# note we have to check separately for `nothing`, otherwise
52+
# `is_independent_variable(p, nothing)` would return `true`.
53+
sys.independent_variable !== nothing && sym === sys.independent_variable
5554
end
5655

5756
function SymbolicIndexingInterface.independent_variable_symbols(sys::ExampleSystem)
58-
sys.independent_variable === nothing ? [] : [sys.independent_variable]
57+
sys.independent_variable === nothing ? [] : [sys.independent_variable]
5958
end
6059

6160
function SymbolicIndexingInterface.is_time_dependent(sys::ExampleSystem)
62-
sys.independent_variable !== nothing
61+
sys.independent_variable !== nothing
6362
end
6463

6564
SymbolicIndexingInterface.constant_structure(::ExampleSystem) = true
6665

6766
function SymbolicIndexingInterface.all_solvable_symbols(sys::ExampleSystem)
68-
return vcat(
69-
collect(keys(sys.state_index)),
70-
collect(keys(sys.observed)),
71-
)
67+
return vcat(
68+
collect(keys(sys.state_index)),
69+
collect(keys(sys.observed))
70+
)
7271
end
7372

7473
function SymbolicIndexingInterface.all_symbols(sys::ExampleSystem)
75-
return vcat(
76-
all_solvable_symbols(sys),
77-
collect(keys(sys.parameter_index)),
78-
sys.independent_variable === nothing ? Symbol[] : sys.independent_variable
79-
)
74+
return vcat(
75+
all_solvable_symbols(sys),
76+
collect(keys(sys.parameter_index)),
77+
sys.independent_variable === nothing ? Symbol[] : sys.independent_variable
78+
)
8079
end
8180

8281
function SymbolicIndexingInterface.default_values(sys::ExampleSystem)
@@ -95,36 +94,38 @@ RuntimeGeneratedFunctions.init(@__MODULE__)
9594

9695
# this type accepts `Expr` for observed expressions involving state/parameter/observed
9796
# variables
98-
SymbolicIndexingInterface.is_observed(sys::ExampleSystem, sym) = sym isa Expr || sym isa Symbol && haskey(sys.observed, sym)
97+
function SymbolicIndexingInterface.is_observed(sys::ExampleSystem, sym)
98+
sym isa Expr || sym isa Symbol && haskey(sys.observed, sym)
99+
end
99100

100101
function SymbolicIndexingInterface.observed(sys::ExampleSystem, sym::Expr)
101-
# generate a function with the appropriate signature
102-
if is_time_dependent(sys)
103-
fn_expr = :(
104-
function gen(u, p, t)
105-
# assign a variable for each state symbol it's value in u
106-
$([:($var = u[$idx]) for (var, idx) in pairs(sys.state_index)]...)
107-
# assign a variable for each parameter symbol it's value in p
108-
$([:($var = p[$idx]) for (var, idx) in pairs(sys.parameter_index)]...)
109-
# assign a variable for the independent variable
110-
$(sys.independent_variable) = t
111-
# return the value of the expression
112-
return $sym
113-
end
114-
)
115-
else
116-
fn_expr = :(
117-
function gen(u, p)
118-
# assign a variable for each state symbol it's value in u
119-
$([:($var = u[$idx]) for (var, idx) in pairs(sys.state_index)]...)
120-
# assign a variable for each parameter symbol it's value in p
121-
$([:($var = p[$idx]) for (var, idx) in pairs(sys.parameter_index)]...)
122-
# return the value of the expression
123-
return $sym
124-
end
125-
)
126-
end
127-
return @RuntimeGeneratedFunction(fn_expr)
102+
# generate a function with the appropriate signature
103+
if is_time_dependent(sys)
104+
fn_expr = :(
105+
function gen(u, p, t)
106+
# assign a variable for each state symbol it's value in u
107+
$([:($var = u[$idx]) for (var, idx) in pairs(sys.state_index)]...)
108+
# assign a variable for each parameter symbol it's value in p
109+
$([:($var = p[$idx]) for (var, idx) in pairs(sys.parameter_index)]...)
110+
# assign a variable for the independent variable
111+
$(sys.independent_variable) = t
112+
# return the value of the expression
113+
return $sym
114+
end
115+
)
116+
else
117+
fn_expr = :(
118+
function gen(u, p)
119+
# assign a variable for each state symbol it's value in u
120+
$([:($var = u[$idx]) for (var, idx) in pairs(sys.state_index)]...)
121+
# assign a variable for each parameter symbol it's value in p
122+
$([:($var = p[$idx]) for (var, idx) in pairs(sys.parameter_index)]...)
123+
# return the value of the expression
124+
return $sym
125+
end
126+
)
127+
end
128+
return @RuntimeGeneratedFunction(fn_expr)
128129
end
129130
```
130131

@@ -136,16 +137,17 @@ defined to always return `false`, and `observed` does not need to be implemented
136137
Note that the method definitions are all assuming `constant_structure(p) == true`.
137138

138139
In case `constant_structure(p) == false`, the following methods would change:
139-
- `constant_structure(::ExampleSystem) = false`
140-
- `variable_index(sys::ExampleSystem, sym)` would become
141-
`variable_index(sys::ExampleSystem, sym i)` where `i` is the time index at which
142-
the index of `sym` is required.
143-
- `variable_symbols(sys::ExampleSystem)` would become
144-
`variable_symbols(sys::ExampleSystem, i)` where `i` is the time index at which
145-
the variable symbols are required.
146-
- `observed(sys::ExampleSystem, sym)` would become
147-
`observed(sys::ExampleSystem, sym, i)` where `i` is either the time index at which
148-
the index of `sym` is required or a `Vector` of state symbols at the current time index.
140+
141+
- `constant_structure(::ExampleSystem) = false`
142+
- `variable_index(sys::ExampleSystem, sym)` would become
143+
`variable_index(sys::ExampleSystem, sym i)` where `i` is the time index at which
144+
the index of `sym` is required.
145+
- `variable_symbols(sys::ExampleSystem)` would become
146+
`variable_symbols(sys::ExampleSystem, i)` where `i` is the time index at which
147+
the variable symbols are required.
148+
- `observed(sys::ExampleSystem, sym)` would become
149+
`observed(sys::ExampleSystem, sym, i)` where `i` is either the time index at which
150+
the index of `sym` is required or a `Vector` of state symbols at the current time index.
149151

150152
## Optional methods
151153

@@ -163,7 +165,7 @@ them is not necessary.
163165

164166
```julia
165167
function SymbolicIndexingInterface.parameter_values(sys::ExampleSystem)
166-
sys.p
168+
sys.p
167169
end
168170
```
169171

@@ -179,10 +181,10 @@ Consider the following `ExampleIntegrator`
179181

180182
```julia
181183
mutable struct ExampleIntegrator
182-
u::Vector{Float64}
183-
p::Vector{Float64}
184-
t::Float64
185-
sys::ExampleSystem
184+
u::Vector{Float64}
185+
p::Vector{Float64}
186+
t::Float64
187+
sys::ExampleSystem
186188
end
187189

188190
# define a fallback for the interface methods
@@ -193,6 +195,7 @@ SymbolicIndexingInterface.current_time(sys::ExampleIntegrator) = sys.t
193195
```
194196

195197
Then the following example would work:
198+
196199
```julia
197200
sys = ExampleSystem(Dict(:x => 1, :y => 2, :z => 3), Dict(:a => 1, :b => 2), :t, Dict())
198201
integrator = ExampleIntegrator([1.0, 2.0, 3.0], [4.0, 5.0], 6.0, sys)
@@ -215,10 +218,10 @@ the [`Timeseries`](@ref) trait. The type would then return a timeseries from
215218

216219
```julia
217220
struct ExampleSolution
218-
u::Vector{Vector{Float64}}
219-
t::Vector{Float64}
220-
p::Vector{Float64}
221-
sys::ExampleSystem
221+
u::Vector{Vector{Float64}}
222+
t::Vector{Float64}
223+
p::Vector{Float64}
224+
sys::ExampleSystem
222225
end
223226

224227
# define a fallback for the interface methods
@@ -233,6 +236,7 @@ SymbolicIndexingInterface.current_time(sol::ExampleSolution) = sol.t
233236
```
234237

235238
Then the following example would work:
239+
236240
```julia
237241
# using the same system that the ExampleIntegrator used
238242
sol = ExampleSolution([[1.0, 2.0, 3.0], [1.5, 2.5, 3.5]], [4.0, 5.0], [6.0, 7.0], sys)
@@ -262,8 +266,8 @@ follows:
262266

263267
```julia
264268
function SymbolicIndexingInterface.set_state!(integrator::ExampleIntegrator, val, idx)
265-
integrator.u[idx] = val
266-
integrator.u_modified = true
269+
integrator.u[idx] = val
270+
integrator.u_modified = true
267271
end
268272
```
269273

@@ -279,24 +283,25 @@ performed for a bulk parameter update.
279283
# The `ParameterIndexingProxy`
280284

281285
[`ParameterIndexingProxy`](@ref) is a wrapper around another type which implements the
282-
interface and allows using [`getp`](@ref) and [`setp`](@ref) to get and set parameter
286+
interface and allows using [`getp`](@ref) and [`setp`](@ref) to get and set parameter
283287
values. This allows for a cleaner interface for parameter indexing. Consider the
284288
following example for `ExampleIntegrator`:
285289

286290
```julia
287291
function Base.getproperty(obj::ExampleIntegrator, sym::Symbol)
288-
if sym === :ps
289-
return ParameterIndexingProxy(obj)
290-
else
291-
return getfield(obj, sym)
292-
end
292+
if sym === :ps
293+
return ParameterIndexingProxy(obj)
294+
else
295+
return getfield(obj, sym)
296+
end
293297
end
294298
```
295299

296300
This enables the following API:
297301

298302
```julia
299-
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)
303+
integrator = ExampleIntegrator([1.0, 2.0, 3.0], [4.0, 5.0], 6.0,
304+
Dict(:x => 1, :y => 2, :z => 3), Dict(:a => 1, :b => 2), :t)
300305

301306
integrator.ps[:a] # 4.0
302307
getp(integrator, :a)(integrator) # functionally the same as above
@@ -310,25 +315,25 @@ setp(integrator, :b)(integrator, 3.0) # functionally the same as above
310315
The `SymbolicTypeTrait` is used to identify values that can act as symbolic variables. It
311316
has three variants:
312317

313-
- [`NotSymbolic`](@ref) for quantities that are not symbolic. This is the default for all
314-
types.
315-
- [`ScalarSymbolic`](@ref) for quantities that are symbolic, and represent a single
316-
logical value.
317-
- [`ArraySymbolic`](@ref) for quantities that are symbolic, and represent an array of
318-
values. Types implementing this trait must return an array of `ScalarSymbolic` variables
319-
of the appropriate size and dimensions when `collect`ed.
318+
- [`NotSymbolic`](@ref) for quantities that are not symbolic. This is the default for all
319+
types.
320+
- [`ScalarSymbolic`](@ref) for quantities that are symbolic, and represent a single
321+
logical value.
322+
- [`ArraySymbolic`](@ref) for quantities that are symbolic, and represent an array of
323+
values. Types implementing this trait must return an array of `ScalarSymbolic` variables
324+
of the appropriate size and dimensions when `collect`ed.
320325

321326
The trait is implemented through the [`symbolic_type`](@ref) function. Consider the following
322327
example types:
323328

324329
```julia
325330
struct MySym
326-
name::Symbol
331+
name::Symbol
327332
end
328333

329334
struct MySymArr{N}
330-
name::Symbol
331-
size::NTuple{N,Int}
335+
name::Symbol
336+
size::NTuple{N, Int}
332337
end
333338
```
334339

@@ -343,10 +348,8 @@ SymbolicIndexingInterface.symbolic_type(::Type{<:MySymArr}) = ArraySymbolic()
343348
SymbolicIndexingInterface.hasname(::MySymArr) = true
344349
SymbolicIndexingInterface.getname(sym::MySymArr) = sym.name
345350
function Base.collect(sym::MySymArr)
346-
[
347-
MySym(Symbol(sym.name, :_, join(idxs, "_")))
348-
for idxs in Iterators.product(Base.OneTo.(sym.size)...)
349-
]
351+
[MySym(Symbol(sym.name, :_, join(idxs, "_")))
352+
for idxs in Iterators.product(Base.OneTo.(sym.size)...)]
350353
end
351354
```
352355

0 commit comments

Comments
 (0)