Skip to content

Commit 67b71f0

Browse files
committed
reapply formatting
1 parent 8ebdf3f commit 67b71f0

8 files changed

+139
-129
lines changed

.JuliaFormatter.toml

+2
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
style = "sciml"
2+
format_markdown = true
3+
format_docstrings = true

README.md

+8-9
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

+99-95
Original file line numberDiff line numberDiff line change
@@ -5,11 +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-
# mapping from observed variable to Expr to calculate its value
12-
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}
1313
end
1414
```
1515

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

2525
```julia
2626
function SymbolicIndexingInterface.is_variable(sys::ExampleSystem, sym)
27-
haskey(sys.state_index, sym)
27+
haskey(sys.state_index, sym)
2828
end
2929

3030
function SymbolicIndexingInterface.variable_index(sys::ExampleSystem, sym)
31-
get(sys.state_index, sym, nothing)
31+
get(sys.state_index, sym, nothing)
3232
end
3333

3434
function SymbolicIndexingInterface.variable_symbols(sys::ExampleSystem)
35-
collect(keys(sys.state_index))
35+
collect(keys(sys.state_index))
3636
end
3737

3838
function SymbolicIndexingInterface.is_parameter(sys::ExampleSystem, sym)
39-
haskey(sys.parameter_index, sym)
39+
haskey(sys.parameter_index, sym)
4040
end
4141

4242
function SymbolicIndexingInterface.parameter_index(sys::ExampleSystem, sym)
43-
get(sys.parameter_index, sym, nothing)
43+
get(sys.parameter_index, sym, nothing)
4444
end
4545

4646
function SymbolicIndexingInterface.parameter_symbols(sys::ExampleSystem)
47-
collect(keys(sys.parameter_index))
47+
collect(keys(sys.parameter_index))
4848
end
4949

5050
function SymbolicIndexingInterface.is_independent_variable(sys::ExampleSystem, sym)
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
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
5454
end
5555

5656
function SymbolicIndexingInterface.independent_variable_symbols(sys::ExampleSystem)
57-
sys.independent_variable === nothing ? [] : [sys.independent_variable]
57+
sys.independent_variable === nothing ? [] : [sys.independent_variable]
5858
end
5959

6060
function SymbolicIndexingInterface.is_time_dependent(sys::ExampleSystem)
61-
sys.independent_variable !== nothing
61+
sys.independent_variable !== nothing
6262
end
6363

6464
SymbolicIndexingInterface.constant_structure(::ExampleSystem) = true
6565

6666
function SymbolicIndexingInterface.all_solvable_symbols(sys::ExampleSystem)
67-
return vcat(
68-
collect(keys(sys.state_index)),
69-
collect(keys(sys.observed)),
70-
)
67+
return vcat(
68+
collect(keys(sys.state_index)),
69+
collect(keys(sys.observed))
70+
)
7171
end
7272

7373
function SymbolicIndexingInterface.all_symbols(sys::ExampleSystem)
74-
return vcat(
75-
all_solvable_symbols(sys),
76-
collect(keys(sys.parameter_index)),
77-
sys.independent_variable === nothing ? Symbol[] : sys.independent_variable
78-
)
74+
return vcat(
75+
all_solvable_symbols(sys),
76+
collect(keys(sys.parameter_index)),
77+
sys.independent_variable === nothing ? Symbol[] : sys.independent_variable
78+
)
7979
end
8080
```
8181

@@ -90,36 +90,38 @@ RuntimeGeneratedFunctions.init(@__MODULE__)
9090

9191
# this type accepts `Expr` for observed expressions involving state/parameter/observed
9292
# variables
93-
SymbolicIndexingInterface.is_observed(sys::ExampleSystem, sym) = sym isa Expr || sym isa Symbol && haskey(sys.observed, sym)
93+
function SymbolicIndexingInterface.is_observed(sys::ExampleSystem, sym)
94+
sym isa Expr || sym isa Symbol && haskey(sys.observed, sym)
95+
end
9496

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

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

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

145148
## Optional methods
146149

@@ -158,7 +161,7 @@ them is not necessary.
158161

159162
```julia
160163
function SymbolicIndexingInterface.parameter_values(sys::ExampleSystem)
161-
sys.p
164+
sys.p
162165
end
163166
```
164167

@@ -174,10 +177,10 @@ Consider the following `ExampleIntegrator`
174177

175178
```julia
176179
mutable struct ExampleIntegrator
177-
u::Vector{Float64}
178-
p::Vector{Float64}
179-
t::Float64
180-
sys::ExampleSystem
180+
u::Vector{Float64}
181+
p::Vector{Float64}
182+
t::Float64
183+
sys::ExampleSystem
181184
end
182185

183186
# define a fallback for the interface methods
@@ -188,6 +191,7 @@ SymbolicIndexingInterface.current_time(sys::ExampleIntegrator) = sys.t
188191
```
189192

190193
Then the following example would work:
194+
191195
```julia
192196
sys = ExampleSystem(Dict(:x => 1, :y => 2, :z => 3), Dict(:a => 1, :b => 2), :t, Dict())
193197
integrator = ExampleIntegrator([1.0, 2.0, 3.0], [4.0, 5.0], 6.0, sys)
@@ -210,10 +214,10 @@ the [`Timeseries`](@ref) trait. The type would then return a timeseries from
210214

211215
```julia
212216
struct ExampleSolution
213-
u::Vector{Vector{Float64}}
214-
t::Vector{Float64}
215-
p::Vector{Float64}
216-
sys::ExampleSystem
217+
u::Vector{Vector{Float64}}
218+
t::Vector{Float64}
219+
p::Vector{Float64}
220+
sys::ExampleSystem
217221
end
218222

219223
# define a fallback for the interface methods
@@ -228,6 +232,7 @@ SymbolicIndexingInterface.current_time(sol::ExampleSolution) = sol.t
228232
```
229233

230234
Then the following example would work:
235+
231236
```julia
232237
# using the same system that the ExampleIntegrator used
233238
sol = ExampleSolution([[1.0, 2.0, 3.0], [1.5, 2.5, 3.5]], [4.0, 5.0], [6.0, 7.0], sys)
@@ -257,32 +262,33 @@ follows:
257262

258263
```julia
259264
function SymbolicIndexingInterface.set_state!(integrator::ExampleIntegrator, val, idx)
260-
integrator.u[idx] = val
261-
integrator.u_modified = true
265+
integrator.u[idx] = val
266+
integrator.u_modified = true
262267
end
263268
```
264269

265270
# The `ParameterIndexingProxy`
266271

267272
[`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
273+
interface and allows using [`getp`](@ref) and [`setp`](@ref) to get and set parameter
269274
values. This allows for a cleaner interface for parameter indexing. Consider the
270275
following example for `ExampleIntegrator`:
271276

272277
```julia
273278
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+
if sym === :ps
280+
return ParameterIndexingProxy(obj)
281+
else
282+
return getfield(obj, sym)
283+
end
279284
end
280285
```
281286

282287
This enables the following API:
283288

284289
```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)
290+
integrator = ExampleIntegrator([1.0, 2.0, 3.0], [4.0, 5.0], 6.0,
291+
Dict(:x => 1, :y => 2, :z => 3), Dict(:a => 1, :b => 2), :t)
286292

287293
integrator.ps[:a] # 4.0
288294
getp(integrator, :a)(integrator) # functionally the same as above
@@ -296,25 +302,25 @@ setp(integrator, :b)(integrator, 3.0) # functionally the same as above
296302
The `SymbolicTypeTrait` is used to identify values that can act as symbolic variables. It
297303
has three variants:
298304

299-
- [`NotSymbolic`](@ref) for quantities that are not symbolic. This is the default for all
300-
types.
301-
- [`ScalarSymbolic`](@ref) for quantities that are symbolic, and represent a single
302-
logical value.
303-
- [`ArraySymbolic`](@ref) for quantities that are symbolic, and represent an array of
304-
values. Types implementing this trait must return an array of `ScalarSymbolic` variables
305-
of the appropriate size and dimensions when `collect`ed.
305+
- [`NotSymbolic`](@ref) for quantities that are not symbolic. This is the default for all
306+
types.
307+
- [`ScalarSymbolic`](@ref) for quantities that are symbolic, and represent a single
308+
logical value.
309+
- [`ArraySymbolic`](@ref) for quantities that are symbolic, and represent an array of
310+
values. Types implementing this trait must return an array of `ScalarSymbolic` variables
311+
of the appropriate size and dimensions when `collect`ed.
306312

307313
The trait is implemented through the [`symbolic_type`](@ref) function. Consider the following
308314
example types:
309315

310316
```julia
311317
struct MySym
312-
name::Symbol
318+
name::Symbol
313319
end
314320

315321
struct MySymArr{N}
316-
name::Symbol
317-
size::NTuple{N,Int}
322+
name::Symbol
323+
size::NTuple{N, Int}
318324
end
319325
```
320326

@@ -329,10 +335,8 @@ SymbolicIndexingInterface.symbolic_type(::Type{<:MySymArr}) = ArraySymbolic()
329335
SymbolicIndexingInterface.hasname(::MySymArr) = true
330336
SymbolicIndexingInterface.getname(sym::MySymArr) = sym.name
331337
function Base.collect(sym::MySymArr)
332-
[
333-
MySym(Symbol(sym.name, :_, join(idxs, "_")))
334-
for idxs in Iterators.product(Base.OneTo.(sym.size)...)
335-
]
338+
[MySym(Symbol(sym.name, :_, join(idxs, "_")))
339+
for idxs in Iterators.product(Base.OneTo.(sym.size)...)]
336340
end
337341
```
338342

0 commit comments

Comments
 (0)