Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
metelkin committed Feb 7, 2024
2 parents 2d8a465 + e05e1f0 commit 17a6ce0
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 26 deletions.
12 changes: 6 additions & 6 deletions cases/0-hello-world/master/mm_julia/model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,24 @@ function mm_init_func_(__constants__)
P * default_comp,
],
Float64[
__constants__...,
default_comp,
__constants__...
]
)
end

### calculate RHS of ODE
function mm_ode_func_(__du__, __u__, __p__, t)
__constants__ = __p__[1:2]
(default_comp,) = __p__[3:3]
(default_comp,) = __p__[1:1]
__constants__ = __p__[2:3]
(S_,P_,) = __u__

# Heta rules
P = P_ / default_comp
S = S_ / default_comp
r1 = __constants__[1] * S / (__constants__[2] + S) * default_comp

#__p__[3:3] .= [default_comp,]
#__p__[1:1] .= [default_comp,]
__du__ .= [
-r1, # dS_/dt
r1, # dP_/dt
Expand All @@ -85,8 +85,8 @@ function mm_saving_generator_(__outputIds__::Vector{Symbol})
end

function saving_(__u__, t, __integrator__)
__constants__ = __integrator__.p[1:2]
(default_comp,) = __integrator__.p[3:3]
(default_comp,) = __integrator__.p[1:1]
__constants__ = __integrator__.p[2:3]
(S_,P_,) = __u__

# Heta rules
Expand Down
2 changes: 1 addition & 1 deletion cases/24-define-function/src/index.heta
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@

c1 @Compartment .= 2;
s1 @Species {compartment: c1} .= 100;
r1 @Reaction {actors: s1=} := k1 * pow7() * c1;
r1 @Reaction {actors: s1=} := k1 * pow7(1.1) * c1;

k1 @Const = 0.1;

Expand Down
101 changes: 101 additions & 0 deletions export-formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,3 +413,104 @@ Each namespace in separate file.
|Const: `Infinity`, `NaN` |- |- |+ |+ |+ |+ |+ |+ |+ |na
|`@Scenario` support |- |- |- |- |- |- |- |+ |+ |na
|`@Record {ss: true, ...}` |- |- |+ |- |- |- |- |+ |+ |na
|`#defineFunction` support |- |- |- |- |+ |- |+ |+ |+ |na

## Math expressions conversions

_Skipped cell means no conversion_

| | SLV/DBSolve | Julia | Mrgsolve/R | Simbio/Matlab |
|--|--|--|--|--|
|`abs(x)`| | |`fabs(x)`| |
|`add(x, y)`|`x + y`|`+(x, y)`| | |
|`ceil(x)`| | | | |
|`cube(x)`|`pow(x, 3) or x ^ 3`|`NaNMath.pow(x, 3)`| | |
|`divide(x, y)`|`x / y`|`/(x, y)`| | |
|`exp(x)`| | | | |
|`floor(x)`| | | | |
|`ln(x)`| |`NaNMath.log(x)`| | |
|`log(x)`| |`NaNMath.log(x)`| |`log(x)`|
|`log(x, base)`|`log(x) / log(base)`|`NaNMath.log(base, x)`| |`(log(x)/log(base))`|
|`log10(x)`| |`NaNMath.log10(x)`| | |
|`log2(x)`|`log(x) / log(2)`|`NaNMath.log2(x)`| |`(log(x)/log(2))`|
|`multiply(x, y)`|`x * y`|`*(x, y)`| | |
|`pow(x, y)`| `pow(x, y)` or `x ^ y`|`NaNMath.pow(x, y)`| |`power(x, y)`|
|`sign(x)`| | | | |
|`sqrt(x)`| |`NaNMath.sqrt(x)`| | |
|`nthRoot(x)`|`pow(x, 1/2)` or `x ^ (1/2)`|`NaNMath.sqrt(x)`| | |
|`nthRoot(x, n)`|`pow(x, 1/n)` or `x ^ (1/n)`|`NaNMath.pow(x, (1/n))`| | |
|`square(x)`|`pow(x, 2)` or `x ^ 2`|`NaNMath.pow(x, 2)`| | |
|`subtract(x, y)`|`x - y`|`-(x, y)`| | |
|`max(x, y)`|`max2(x, y)`| |`std::max(x, y)`|`max(x, y)`|
|`max(x, y, z)`|`max3(x, y, z)`| |`std::max(x, y, z)`|`max([x, y, z])`|
|`min(x, y)`|`min2(x, y)`| |`std::min(x, y)`|`min(x, y)`|
|`min(x, y, z)`|`min3(x, y, z)`| |`std::min(x, y, z)`|`min([x, y, z])`|
|`factorial(n)`| |`fact(n)`| | |
|`ifgt(x, y, z1, z2)`| |`x > y ? z1 : z2`| |`tern__(x>y, z1, z2)`|
|`ifge(x, y, z1, z2)`| |`x >= y ? z1 : z2`| |`tern__(x>=y, z1, z2)`|
|`iflt(x, y, z1, z2)`| |`x < y ? z1 : z2`| |`tern__(x<y, z1, z2)`|
|`ifle(x, y, z1, z2)`| |`x <= y ? z1 : z2`| |`tern__(x<=y, z1, z2)`|
|`ifeq(x, y, z1, z2)`| |`x == y ? z1 : z2`| |`tern__(x==y, z1, z2)`|
|`x ^ y`|`x ^ y` or `pow(x, y)`|`NaNMath.pow(x, y)`|`pow(x, y)`| |
|`e`|`exp(1)`|`exp(1.0)`| | |
|`pi`|`acos(-1)` | | | |
|`Infinity`| |`Inf`| | |
|`NaN`| |`NaN`| | |
|`t`| | |`SOLVERTIME`|`time`|
|`a and b`| |`a && b`| |`&`|
|`a or b`| |`a \|\| b`| |`\|`|
|`a xor b`| |`xor(a, b)`| |`xor(a, b)`|
|`not a`| |`!a`| |`~a`|
|`b1 < b2 ? x : y`| `ifgt(b1, b2, x, y)`| | |`tern__(b1 < b2, x, y)`|
|`piecewise(value1, cond1, value2, cond2, ..., otherwise)`|not supported| |not supported| |
|`acos(x)`, `acot(x)`, `acsc(x)`,`asec(x)`, `asin(x)`, `atan(x)`, `cos(x)`, `cot(x)`, `csc(x)`, `sec(x)`, `sin(x)`, `tan(x)`| | | | |
|`acosh(x)`, `acoth(x)`, `acsch(x)`, `asech(x)`, `asinh(x)`, `atanh(x)`, `cosh(x)`, `coth(x)`, `csch(x)`, `sech(x)`, `sinh(x)`, `tanh(x)`| | | | |

_Conversion to SBML's MathML_

| | SBML |
|--|--|
|`abs(x)`|`<apply><abs/>(x)</apply>`|
|`add(x, y)`|`<apply><plus/>(x) (y)</apply>`|
|`ceil(x)`|`<apply><ceiling/>(x)</apply>`|
|`cube(x)`|`<apply><power/>(x)<cn>3</cn></apply>`|
|`divide(x, y)`|`<apply><divide/>(x) (y)</apply>`|
|`exp(x)`|`<apply><exp/>(x)</apply>`|
|`floor(x)`|`<apply><floor/>(x)</apply>`|
|`ln(x)`|`<apply><ln/>(x)</apply>`|
|`log(x)`|`<apply><log/>(x)</apply>`|
|`log(x, base)`|`<apply><log/><logbase>(base)</logbase>(x)</apply>`|
|`log10(x)`|`<apply><log/>(x)</apply>`|
|`log2(x)`|`<apply><log/><logbase><cn>2</cn></logbase>(x)</apply>`|
|`multiply(x, y)`|`<apply><times/>(x) (y)</apply>`|
|`pow(x, y)`|`<apply><power/>(x) (y)</apply>`|
|`sign(x)`|`<apply><sign/>(x)</apply>`|
|`sqrt(x)`|`<apply><root/>(x)</apply>`|
|`nthRoot(x)`|not supported|
|`nthRoot(x, n)`|not supported|
|`square(x)`|`<apply><power/>(x)<cn>2</cn></apply>`|
|`subtract(x, y)`|`<apply><minus/>(x) (y)</apply>`|
|`max(x, y)`|`<apply><max/>(x) (y)</apply>`|
|`max(x, y, z)`|`<apply><max/>(x) (y) (z)</apply>`|
|`min(x, y)`|`<apply><min/>(x) (y)</apply>`|
|`min(x, y, z)`|`<apply><min/>(x) (y) (z)</apply>`|
|`factorial(n)`|`<apply><factorial/>(x)</apply>`|
|`ifgt(x, y, z1, z2)`|not supported|
|`ifge(x, y, z1, z2)`|not supported|
|`iflt(x, y, z1, z2)`|not supported|
|`ifle(x, y, z1, z2)`|not supported|
|`ifeq(x, y, z1, z2)`|not supported|
|`x ^ y`|`<apply><pow/>(x) (y)</apply>`|
|`e`|not supported|
|`pi`|not supported|
|`Infinity`|not supported|
|`NaN`|not supported|
|`t`|`<csymbol definitionURL="http://www.sbml.org/sbml/symbols/time">t</csymbol>`|
|`a and b`|`<apply><and/>(x) (y)</apply>`|
|`a or b`|`<apply><or/>(x) (y)</apply>`|
|`a xor b`|`<apply><xor>(x) (y)</apply>`|
|`not a`|`<apply><not>(x)</apply>`|
|`b1 < b2 ? x : y`|`<piecewise><piece>(x)<apply><smaller/>(b1) (b2)</apply></piece><otherwise>(y)</otherwise></piecewise>`|
|`piecewise(value1, cond1, value2, cond2, ..., otherwise)`|`<piecewise><piece>(value1) (cond1)</piece><piece>(value2) (cond2)</piece><otherwise>(otherwise)</otherwise></piecewise>`|
|`acos(x)`, `acot(x)`, `acsc(x)`,`asec(x)`, `asin(x)`, `atan(x)`, `cos(x)`, `cot(x)`, `csc(x)`, `sec(x)`, `sin(x)`, `tan(x)`|`<apply><arccos/>(x)</apply>`...|
|`acosh(x)`, `acoth(x)`, `acsch(x)`, `asech(x)`, `asinh(x)`, `atanh(x)`, `cosh(x)`, `coth(x)`, `csch(x)`, `sech(x)`, `sinh(x)`, `tanh(x)`|not supported|
2 changes: 1 addition & 1 deletion src/julia-export/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Expression.prototype.toJuliaString = function(){
if(node.type==='ConstantNode' && Number.isInteger(node.value)){
return node.value.toExponential(); // to display 6 => 6e0; 6e23 => 6e+23
}
if(node.type==='FunctionNode' && node.fn.name==='plus'){
if(node.type==='FunctionNode' && node.fn.name==='add'){
let args = node.args
.map((arg) => arg.toString(options))
.join(', ');
Expand Down
6 changes: 5 additions & 1 deletion src/matlab-export/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ Expression.prototype.toMatlabString = function(){
let args = node.args
.map((arg) => arg.toString(options))
.join(', ');
return `min([${args}])`;
if (node.args.length <= 2) {
return `min(${args})`;
} else {
return `min([${args}])`;
}
}
if (node.type==='FunctionNode' && node.fn.name==='log') {
if(node.args.length===1){
Expand Down
30 changes: 15 additions & 15 deletions src/templates/julia-model.jl.njk
Original file line number Diff line number Diff line change
Expand Up @@ -101,21 +101,21 @@ function {{ id }}_init_func_(__constants__)
[ 0.0 ], # init for fake variable
{%- endif %}
Float64[
__constants__...,
{%- for record in img.staticRecords %}
{{ record.id }}{{ '*' + record.compartment if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}
__constants__...
]
)
end
{% set constantMaxIndex = img.constants | length %}
{%- set staticMaxIndex = img.staticRecords | length %}
### calculate RHS of ODE
function {{ id }}_ode_func_(__du__, __u__, __p__, t)
__constants__ = __p__[1:{{ constantMaxIndex }}]
({% for record in img.staticRecords -%}
{{ record.id }}{{ '_' if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}) = __p__[{{ constantMaxIndex + 1 }}:{{ constantMaxIndex + staticMaxIndex }}]
{%- endfor %}) = __p__[1:{{ staticMaxIndex }}]
__constants__ = __p__[{{ staticMaxIndex + 1 }}:{{ staticMaxIndex + constantMaxIndex }}]
({% for record in img.dynamicRecords -%}
{{ record.id }}{{ '_' if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}) = __u__ {# TODO: replace by __u__[index] #}
Expand All @@ -131,7 +131,7 @@ function {{ id }}_ode_func_(__du__, __u__, __p__, t)
{{ record.id }} = {{ record.id }}_ / {{ record.compartment }}
{% endif -%}
{% endfor %}
#__p__[{{ constantMaxIndex + 1 }}:{{ constantMaxIndex + staticMaxIndex }}] .= [{% for record in img.staticRecords -%}
#__p__[1:{{ staticMaxIndex }}] .= [{% for record in img.staticRecords -%}
{{ record.id }}{{ '_' if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}]
{%- if img.dynamicRecords | length > 0 %}
Expand Down Expand Up @@ -163,10 +163,10 @@ function {{ id }}_saving_generator_(__outputIds__::Vector{Symbol})
end

function saving_(__u__, t, __integrator__)
__constants__ = __integrator__.p[1:{{ img.constants | length }}]
({% for record in img.staticRecords -%}
{{ record.id }}{{ '_' if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}) = __integrator__.p[{{ constantMaxIndex + 1 }}:{{ constantMaxIndex + staticMaxIndex }}]
{%- endfor %}) = __integrator__.p[1:{{ staticMaxIndex }}]
__constants__ = __integrator__.p[{{ staticMaxIndex + 1 }}:{{ staticMaxIndex + constantMaxIndex }}]
({% for record in img.dynamicRecords -%}
{{ record.id }}{{ '_' if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}) = __u__{# TODO: replace by __u__[index] #}
Expand Down Expand Up @@ -219,10 +219,10 @@ end

{%- for event in img.events | filter2('switcher.className', 'DSwitcher') %}
function {{ id }}_{{ event.switcher.id }}_condition_func_(__u__, t, __integrator__)
__constants__ = __integrator__.p[1:{{ img.constants | length }}]
({% for record in img.staticRecords -%}
{{ record.id }}{{ '_' if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}) = __integrator__.p[{{ constantMaxIndex + 1 }}:{{ constantMaxIndex + staticMaxIndex }}]
{%- endfor %}) = __integrator__.p[1:{{ staticMaxIndex }}]
__constants__ = __integrator__.p[{{ staticMaxIndex + 1 }}:{{ staticMaxIndex + constantMaxIndex }}]
({% for record in img.dynamicRecords -%}
{{ record.id }}{{ '_' if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}) = __u__
Expand All @@ -245,10 +245,10 @@ end

{%- for event in img.events | filter2('switcher.className', 'CSwitcher') %}
function {{ id }}_{{ event.switcher.id }}_condition_func_(__u__, t, __integrator__)
__constants__ = __integrator__.p[1:{{ img.constants | length }}]
({% for record in img.staticRecords -%}
{{ record.id }}{{ '_' if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}) = __integrator__.p[{{ constantMaxIndex + 1 }}:{{ constantMaxIndex + staticMaxIndex }}]
{%- endfor %}) = __integrator__.p[1:{{ staticMaxIndex }}]
__constants__ = __integrator__.p[{{ staticMaxIndex + 1}}:{{ staticMaxIndex + constantMaxIndex }}]
({% for record in img.dynamicRecords -%}
{{ record.id }}{{ '_' if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}) = __u__
Expand All @@ -273,10 +273,10 @@ end

{%- for event in img.events | filter2('switcher.className', 'StopSwitcher') %}
function {{ id }}_{{ event.switcher.id }}_condition_func_(__u__, t, __integrator__)
__constants__ = __integrator__.p[1:{{ img.constants | length }}]
({% for record in img.staticRecords -%}
{{ record.id }}{{ '_' if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}) = __integrator__.p[{{ constantMaxIndex + 1 }}:{{ constantMaxIndex + staticMaxIndex }}]
{%- endfor %}) = __integrator__.p[1:{{ staticMaxIndex }}]
__constants__ = __integrator__.p[{{ staticMaxIndex + 1 }}:{{ staticMaxIndex + constantMaxIndex }}]
({% for record in img.dynamicRecords -%}
{{ record.id }}{{ '_' if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}) = __u__
Expand All @@ -301,10 +301,10 @@ end
{% for event in img.events | exclude2('switcher.className', 'StopSwitcher') -%}
function {{ id }}_{{ event.switcher.id }}_affect_func_(__integrator__)
t = __integrator__.t
__constants__ = __integrator__.p[1:{{ img.constants | length }}]
({% for record in img.staticRecords -%}
{{ record.id }}{{ '_' if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}) = __integrator__.p[{{ constantMaxIndex + 1 }}:{{ constantMaxIndex + staticMaxIndex }}]
{%- endfor %}) = __integrator__.p[1:{{ staticMaxIndex }}]
__constants__ = __integrator__.p[{{ staticMaxIndex + 1 }}:{{ staticMaxIndex + constantMaxIndex }}]
({% for record in img.dynamicRecords -%}
{{ record.id }}{{ '_' if record.instanceOf('Species') and not record.isAmount }},
{%- endfor %}) = __integrator__.u
Expand Down Expand Up @@ -349,7 +349,7 @@ function {{ id }}_{{ event.switcher.id }}_affect_func_(__integrator__)
{%- endif %}
__integrator__.p[[
{%- for record in img.staticRecords -%}
{{ loop.index + constantMaxIndex + ',' if record.getAssignment(event.switcher.id) is defined }}
{{ loop.index + ',' if record.getAssignment(event.switcher.id) is defined }}
{%- endfor -%}
]] = [
{%- for record in img.staticRecords | exclude2('assignments.' + event.switcher.id, undefined) %}
Expand Down
4 changes: 2 additions & 2 deletions test/julia-export/to-julia-string.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ describe('Expression exports to Julia', () => {
let expr = Expression.fromString('divide(x,y)');
expect(expr.toJuliaString()).to.be.equal('/(x, y)');
});
it('toJuliaString() for "plus(x,y)"', () => {
let expr = Expression.fromString('plus(x,y)');
it('toJuliaString() for "add(x,y)"', () => {
let expr = Expression.fromString('add(x,y)');
expect(expr.toJuliaString()).to.be.equal('+(x, y)');
});
it('toJuliaString() for "square(x)"', () => {
Expand Down

0 comments on commit 17a6ce0

Please sign in to comment.