diff --git a/cases/0-hello-world/master/mm_julia/model.jl b/cases/0-hello-world/master/mm_julia/model.jl index b0727ac7..3a5ec0e2 100644 --- a/cases/0-hello-world/master/mm_julia/model.jl +++ b/cases/0-hello-world/master/mm_julia/model.jl @@ -49,16 +49,16 @@ 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 @@ -66,7 +66,7 @@ function mm_ode_func_(__du__, __u__, __p__, t) 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 @@ -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 diff --git a/cases/24-define-function/src/index.heta b/cases/24-define-function/src/index.heta index 6fd64ea5..98148a7a 100644 --- a/cases/24-define-function/src/index.heta +++ b/cases/24-define-function/src/index.heta @@ -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; diff --git a/export-formats.md b/export-formats.md index b2053e0f..f7bb2827 100644 --- a/export-formats.md +++ b/export-formats.md @@ -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(x)`| +|`add(x, y)`|`(x) (y)`| +|`ceil(x)`|`(x)`| +|`cube(x)`|`(x)3`| +|`divide(x, y)`|`(x) (y)`| +|`exp(x)`|`(x)`| +|`floor(x)`|`(x)`| +|`ln(x)`|`(x)`| +|`log(x)`|`(x)`| +|`log(x, base)`|`(base)(x)`| +|`log10(x)`|`(x)`| +|`log2(x)`|`2(x)`| +|`multiply(x, y)`|`(x) (y)`| +|`pow(x, y)`|`(x) (y)`| +|`sign(x)`|`(x)`| +|`sqrt(x)`|`(x)`| +|`nthRoot(x)`|not supported| +|`nthRoot(x, n)`|not supported| +|`square(x)`|`(x)2`| +|`subtract(x, y)`|`(x) (y)`| +|`max(x, y)`|`(x) (y)`| +|`max(x, y, z)`|`(x) (y) (z)`| +|`min(x, y)`|`(x) (y)`| +|`min(x, y, z)`|`(x) (y) (z)`| +|`factorial(n)`|`(x)`| +|`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`|`(x) (y)`| +|`e`|not supported| +|`pi`|not supported| +|`Infinity`|not supported| +|`NaN`|not supported| +|`t`|`t`| +|`a and b`|`(x) (y)`| +|`a or b`|`(x) (y)`| +|`a xor b`|`(x) (y)`| +|`not a`|`(x)`| +|`b1 < b2 ? x : y`|`(x)(b1) (b2)(y)`| +|`piecewise(value1, cond1, value2, cond2, ..., otherwise)`|`(value1) (cond1)(value2) (cond2)(otherwise)`| +|`acos(x)`, `acot(x)`, `acsc(x)`,`asec(x)`, `asin(x)`, `atan(x)`, `cos(x)`, `cot(x)`, `csc(x)`, `sec(x)`, `sin(x)`, `tan(x)`|`(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)`|not supported| diff --git a/src/julia-export/expression.js b/src/julia-export/expression.js index ac41034c..3fb3dd2e 100644 --- a/src/julia-export/expression.js +++ b/src/julia-export/expression.js @@ -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(', '); diff --git a/src/matlab-export/expression.js b/src/matlab-export/expression.js index 6b089068..1761768d 100644 --- a/src/matlab-export/expression.js +++ b/src/matlab-export/expression.js @@ -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){ diff --git a/src/templates/julia-model.jl.njk b/src/templates/julia-model.jl.njk index 108fe5dc..fea5581d 100644 --- a/src/templates/julia-model.jl.njk +++ b/src/templates/julia-model.jl.njk @@ -101,10 +101,10 @@ 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 @@ -112,10 +112,10 @@ end {%- 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] #} @@ -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 %} @@ -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] #} @@ -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__ @@ -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__ @@ -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__ @@ -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 @@ -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) %} diff --git a/test/julia-export/to-julia-string.js b/test/julia-export/to-julia-string.js index 8d2ba8f0..1c330726 100644 --- a/test/julia-export/to-julia-string.js +++ b/test/julia-export/to-julia-string.js @@ -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)"', () => {