Unverified Commit 3f0d7bd2 authored by Miroslav Kratochvil's avatar Miroslav Kratochvil Committed by GitHub
Browse files

Merge pull request #69 from LCSB-BioCore/mk-symbolics-completeness

Support MathTime conversion to Symbolics, document the whole thing
parents f61be314 7f1506c8
......@@ -89,7 +89,14 @@ Modules = [SBML]
Pages = ["utils.jl"]
```
## Internal math manipulation
## Math and `Symbolics.jl` compatibility
```@autodocs
Modules = [SBML]
Pages = ["symbolics.jl"]
```
### Internal math helpers
```@autodocs
Modules = [SBML]
......
......@@ -16,6 +16,6 @@ include("symbolics.jl")
sbml = (sym::Symbol) -> dlsym(SBML_jll.libsbml_handle, sym)
export SBMLVersion, readSBML, getS, getLBs, getUBs, getOCs
export convert_level_and_version, libsbml_convert, convert_simplify_math
export set_level_and_version, libsbml_convert, convert_simplify_math
end # module
......@@ -2,7 +2,7 @@
const VPtr = Ptr{Cvoid}
"""
function get_string(x::VPtr, fn_sym)::Maybe{String}
get_string(x::VPtr, fn_sym)::Maybe{String}
C-call the SBML function `fn_sym` with a single parameter `x`, interpret the
result as a string and return it, or throw exception in case the pointer is
......@@ -18,9 +18,9 @@ function get_string(x::VPtr, fn_sym)::String
end
"""
function get_optional_string(x::VPtr, fn_sym)::Maybe{String}
get_optional_string(x::VPtr, fn_sym)::Maybe{String}
Like [`get_string`](@Ref), but returns `nothing` instead of throwing an
Like [`get_string`](@ref), but returns `nothing` instead of throwing an
exception.
This is used to get notes and annotations and several other things (see
......@@ -82,7 +82,7 @@ Read the SBML from a XML file in `fn` and return the contained `SBML.Model`.
The `sbml_conversion` is a function that does an in-place modification of the
single parameter, which is the C pointer to the loaded SBML document (C type
`SBMLDocument*`). Several functions for doing that are prepared, including
[`convert_level_and_version`](@ref), [`libsbml_convert`](@ref), and
[`set_level_and_version`](@ref), [`libsbml_convert`](@ref), and
[`convert_simplify_math`](@ref).
# Example
......
default_symbolics_mapping = Dict(
"""
default_symbolics_mapping :: Dict{String,Any}
Default mapping of SBML function names to Julia functions, represented as a
dictionary from Strings (SBML names) to anything `eval`uable as Julia&Symbolics
functions, such as symbols and expressions.
The default mapping only contains the basic SBML functions that are
unambiguously represented in Julia; it is supposed to be extended by the user
if more functions need to be supported.
"""
default_symbolics_mapping = Dict{String,Any}(
"+" => :+,
"-" => :-,
"*" => :*,
......@@ -12,15 +23,40 @@ default_symbolics_mapping = Dict(
"ceiling" => :ceil,
"floor" => :floor,
"piecewise" => :(Core.ifelse),
#TODO extend this in the future
)
allowed_sym(x, allowed_funs) =
haskey(allowed_funs, x) ? allowed_funs[x] :
throw(DomainError(x, "Unknown SBML function"))
function Base.convert(::Type{Num}, x::SBML.Math; mapping = default_symbolics_mapping)
"""
Base.convert(
::Type{Num},
x::SBML.Math;
mapping = default_symbolics_mapping,
convert_time = (x::SBML.MathTime) -> Num(Variable(Symbol(x.id))).val,
)
Convert SBML.[`Math`](@ref) to `Num` type Symbolics package. The conversion of
functions can be customized by supplying a custom mapping to symbols; if
nothing is supplied, [`default_symbolics_mapping`](@ref) that translates basic
functions to their Julia equivalents is assumed.
Translation of [`MathLambda`](@ref) is not supported by Symbolics.
[`MathTime`](@ref) is handled specially, the function from the argument
`convert_time` is called to possibly specify any desired behavior. By default,
it just creates a variable with the same name as the time variable name stored
in SBML.
"""
function Base.convert(
::Type{Num},
x::SBML.Math;
mapping = default_symbolics_mapping,
convert_time = (x::SBML.MathTime) -> Num(Variable(Symbol(x.id))).val,
)
conv(x::SBML.MathApply) = eval(allowed_sym(x.fn, mapping))(conv.(x.args)...)
conv(x::SBML.MathTime) = convert_time(x)
conv(x::SBML.MathIdent) = Num(Variable(Symbol(x.id))).val
conv(x::SBML.MathVal) = x.val
conv(x::SBML.MathLambda) = throw(DomainError(x, "can't translate lambdas to symbolics"))
......
@testset "Math to Symbolics conversions" begin
@variables A B C D E
@variables A B C D Time
test = SBML.MathApply(
"*",
......@@ -21,11 +21,11 @@
),
],
),
SBML.MathIdent("E"),
SBML.MathTime("Time"),
],
)
@test isequal(convert(Num, test), (A * B - C * D) * E)
@test isequal(convert(Num, test), (A * B - C * D) * Time)
test = SBML.MathApply(
"piecewise",
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment