symbolics.jl 2.13 KB
Newer Older
paulflang's avatar
paulflang committed
1

2
3
4
5
6
7
8
9
10
11
12
"""
    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.
"""
13
const default_symbolics_mapping = Dict{String,Any}(
paulflang's avatar
paulflang committed
14
15
16
17
18
19
20
21
22
23
24
    "+" => :+,
    "-" => :-,
    "*" => :*,
    "/" => :/,
    "power" => :^,
    "lt" => :<,
    "leq" => :<=,
    "geq" => :>=,
    "gt" => :>,
    "ceiling" => :ceil,
    "floor" => :floor,
25
    "piecewise" => :(Core.ifelse),
anand jain's avatar
anand jain committed
26
    "ln" => :log,
anand jain's avatar
add exp    
anand jain committed
27
    "exp" => :exp,
paulflang's avatar
paulflang committed
28
29
)

30
31
32
allowed_sym(x, allowed_funs) =
    haskey(allowed_funs, x) ? allowed_funs[x] :
    throw(DomainError(x, "Unknown SBML function"))
paulflang's avatar
paulflang committed
33

34
35
36
37
38
39
40
41
"""
    Base.convert(
        ::Type{Num},
        x::SBML.Math;
        mapping = default_symbolics_mapping,
        convert_time = (x::SBML.MathTime) -> Num(Variable(Symbol(x.id))).val,
    )

Miroslav Kratochvil's avatar
a typo.    
Miroslav Kratochvil committed
42
43
Convert SBML.[`Math`](@ref) to `Num` type from Symbolics package. The
conversion of functions can be customized by supplying a custom mapping; if
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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,
)
60
    conv(x::SBML.MathApply) = eval(allowed_sym(x.fn, mapping))(conv.(x.args)...)
61
    conv(x::SBML.MathTime) = convert_time(x)
62
    conv(x::SBML.MathIdent) = Num(Variable(Symbol(x.id))).val
paulflang's avatar
paulflang committed
63
    conv(x::SBML.MathVal) = x.val
64
    conv(x::SBML.MathLambda) = throw(DomainError(x, "can't translate lambdas to symbolics"))
paulflang's avatar
paulflang committed
65
66
    conv(x)
end