def test_conditionals(self): # Tests if and piecewise writing a = myokit.Name('a') b = myokit.Number(1) cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') c1 = '<apply><gt/><cn>5.0</cn><cn>3.0</cn></apply>' c2 = '<apply><lt/><cn>2.0</cn><cn>1.0</cn></apply>' # If e = myokit.If(cond1, a, b) x = ( '<piecewise>' '<piece><ci>a</ci>' + c1 + '</piece>' '<otherwise><cn>1.0</cn></otherwise>' '</piecewise>' ) self.assertWrite(e, x) # Piecewise e = myokit.Piecewise(cond1, a, cond2, b, myokit.Number(100)) x = ( '<piecewise>' '<piece><ci>a</ci>' + c1 + '</piece>' '<piece><cn>1.0</cn>' + c2 + '</piece>' '<otherwise><cn>100.0</cn></otherwise>' '</piecewise>' ) self.assertWrite(e, x)
def test_conditionals(self): # Tests if and piecewise writing a = myokit.Name('a') b = myokit.Number(1) c = myokit.Number(1) cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') ca = '<mi>a</mi>' cb = '<mn>1.0</mn>' cc = '<mn>1.0</mn>' c1 = '<mrow><mn>5.0</mn><mo>></mo><mn>3.0</mn></mrow>' c2 = '<mrow><mn>2.0</mn><mo><</mo><mn>1.0</mn></mrow>' # If x = myokit.If(cond1, a, b) self.assertWrite( x, '<piecewise>' '<piece>' + ca + c1 + '</piece>' '<otherwise>' + cb + '</otherwise>' '</piecewise>') # Piecewise x = myokit.Piecewise(cond1, a, cond2, b, c) self.assertWrite( x, '<piecewise>' '<piece>' + ca + c1 + '</piece>' '<piece>' + cb + c2 + '</piece>' '<otherwise>' + cc + '</otherwise>' '</piecewise>')
def _parse_expression(self, s, var=None): """ Attempts to read an expression from the given string ``s`` and parse it using the context of variable ``var`` to resolve any references. """ s = str(s) # Pre-process some basic html entities entities = { '&eq;': '==', '≠': '!=', '&neq;': '!=', # Not a html entity! '<': '<', '>': '>', '≤': '<=', '≥': '>=', } s = s.replace('&', '&') for k, v in entities.items(): s = s.replace(k, v) # Attempt to handle single a?b:c construct if '?' in s: c, v = s.split('?', 1) if ':' in v: v = v.split(':', 1) else: v = (v, '0') return myokit.If(myokit.parse_expression(c, var), myokit.parse_expression(v[0], var), myokit.parse_expression(v[1], var)) return myokit.parse_expression(s, var)
def test_logic_operators(self): # Tests parsing logic operators # Not cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') c1 = '<apply><gt/><cn>5.0</cn><cn>3.0</cn></apply>' c2 = '<apply><lt/><cn>2.0</cn><cn>1.0</cn></apply>' e = myokit.Not(cond1) x = '<apply><not/>' + c1 + '</apply>' self.assertEqual(self.p(x), e) # And e = myokit.And(cond1, cond2) x = '<apply><and/>' + c1 + c2 + '</apply>' self.assertEqual(self.p(x), e) # Or e = myokit.Or(cond1, cond2) x = '<apply><or/>' + c1 + c2 + '</apply>' self.assertEqual(self.p(x), e) # Xor e = myokit.And( myokit.Or(cond1, cond2), myokit.Not(myokit.And(cond1, cond2)) ) x = '<apply><xor/>' + c1 + c2 + '</apply>' self.assertEqual(self.p(x), e)
def test_user_function(self): # Test :class:`UserFunction` creation and methods. # Create without arguments f = myokit.UserFunction('bert', [], myokit.Number(12)) args = list(f.arguments()) self.assertEqual(len(args), 0) self.assertEqual(f.convert([]), myokit.Number(12)) # Create with one argument f = myokit.UserFunction('x', [myokit.Name('a')], myokit.parse_expression('1 + a')) self.assertEqual(len(list(f.arguments())), 1) args = {myokit.Name('a'): myokit.Number(3)} self.assertEqual(f.convert(args).eval(), 4) # Create with two argument f = myokit.UserFunction( 'x', [myokit.Name('a'), myokit.Name('b')], myokit.parse_expression('a + b')) self.assertEqual(len(list(f.arguments())), 2) args = { myokit.Name('a'): myokit.Number(3), myokit.Name('b'): myokit.Number(4) } self.assertEqual(f.convert(args), myokit.parse_expression('3 + 4')) # Call with wrong arguments del (args[myokit.Name('a')]) self.assertRaisesRegex(ValueError, 'Wrong number', f.convert, args) args[myokit.Name('c')] = myokit.Number(100) self.assertRaisesRegex(ValueError, 'Missing input argument', f.convert, args)
def test_logical(self): # Tests printing logical operators and functions a = myokit.Name(self.avar) b = myokit.Number('12', 'pF') c = myokit.Number(1) ca = '<ci>a</ci>' cb = ('<cn cellml:units="picofarad">12.0</cn>') cc = ('<cn cellml:units="dimensionless">1.0</cn>') # Not cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') c1 = ('<apply><gt/>' '<cn cellml:units="dimensionless">5.0</cn>' '<cn cellml:units="dimensionless">3.0</cn>' '</apply>') c2 = ('<apply><lt/>' '<cn cellml:units="dimensionless">2.0</cn>' '<cn cellml:units="dimensionless">1.0</cn>' '</apply>') x = myokit.Not(cond1) self.assertWrite(x, '<apply><not/>' + c1 + '</apply>') # And x = myokit.And(cond1, cond2) self.assertWrite(x, '<apply><and/>' + c1 + c2 + '</apply>') # Or x = myokit.Or(cond1, cond2) self.assertWrite(x, '<apply><or/>' + c1 + c2 + '</apply>') # If x = myokit.If(cond1, a, b) self.assertWrite( x, '<piecewise>' '<piece>' + ca + c1 + '</piece>' '<otherwise>' + cb + '</otherwise>' '</piecewise>') # Piecewise x = myokit.Piecewise(cond1, a, cond2, b, c) self.assertWrite( x, '<piecewise>' '<piece>' + ca + c1 + '</piece>' '<piece>' + cb + c2 + '</piece>' '<otherwise>' + cc + '</otherwise>' '</piecewise>')
def evaluate(expression): """ Evaluates an expression in mmt syntax. """ import myokit try: e = myokit.parse_expression(expression) e = e.eval() if e.is_literal() else e print(expression + ' = ' + str(e)) except myokit.ParseError as ex: print(myokit.format_parse_error(ex, iter([expression])))
def test_logic_operators(self): # Tests writing logic operators cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') c1 = '<mrow><mn>5.0</mn><mo>></mo><mn>3.0</mn></mrow>' c2 = '<mrow><mn>2.0</mn><mo><</mo><mn>1.0</mn></mrow>' # Not x = myokit.Not(cond1) self.assertWrite( x, '<mrow><mo>(</mo><mo>not</mo>' + c1 + '<mo>)</mo></mrow>') # And x = myokit.And(cond1, cond2) self.assertWrite(x, '<mrow>' + c1 + '<mo>and</mo>' + c2 + '</mrow>') # Or x = myokit.Or(cond1, cond2) self.assertWrite(x, '<mrow>' + c1 + '<mo>or</mo>' + c2 + '</mrow>')
def test_logic_operators(self): # Tests writing logic operators # Not cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') c1 = '<apply><gt/><cn>5.0</cn><cn>3.0</cn></apply>' c2 = '<apply><lt/><cn>2.0</cn><cn>1.0</cn></apply>' e = myokit.Not(cond1) x = '<apply><not/>' + c1 + '</apply>' self.assertWrite(e, x) # And e = myokit.And(cond1, cond2) x = '<apply><and/>' + c1 + c2 + '</apply>' self.assertWrite(e, x) # Or e = myokit.Or(cond1, cond2) x = '<apply><or/>' + c1 + c2 + '</apply>' self.assertWrite(e, x)
def test_python_writer(self): # Test Python expression writer obtaining method. import myokit w = myokit.python_writer() import myokit.formats import myokit.formats.python self.assertIsInstance(w, myokit.formats.python.PythonExpressionWriter) # Test custom name method for this writer e = myokit.parse_expression('5 + 3 * x') self.assertEqual(w.ex(e), '5.0 + 3.0 * x') # Test with unvalidated model (no unames set) m = myokit.Model() c = m.add_component('c') x = c.add_variable('x') x.set_rhs('5 + x') self.assertEqual(w.ex(x.rhs()), '5.0 + c_x')
def opiecewise(self): """ Test of OrderedPiecewise class """ x = myokit.Name('x') p = myokit.OrderedPiecewise( x, myokit.parse_expression('1 * 10'), myokit.Number(1), myokit.parse_expression('2 * 10'), myokit.Number(2), myokit.parse_expression('3 * 10'), myokit.Number(3), myokit.parse_expression('4 * 10') ) def test(p, x): self.assertEqual(p.eval(subst={x: 0}), 10) self.assertEqual(p.eval(subst={x: 0.99}), 10) self.assertEqual(p.eval(subst={x: 1}), 20) self.assertEqual(p.eval(subst={x: 1.99}), 20) self.assertEqual(p.eval(subst={x: 2}), 30) self.assertEqual(p.eval(subst={x: 2.99}), 30) self.assertEqual(p.eval(subst={x: 3}), 40) self.assertEqual(p.eval(subst={x: 4}), 40) test(p, x) # Conversion to piecewise w = myokit.Piecewise( myokit.Less(x, myokit.Number(1)), myokit.parse_expression('1* 10'), myokit.Less(x, myokit.Number(2)), myokit.parse_expression('2 *10'), myokit.Less( x, myokit.Number(3)), myokit.parse_expression('3 * 10'), myokit.parse_expression('4 * 10')) test(w, x) q = p.piecewise() self.assertEqual(q, w) test(p, x) # Test conversion to binary tree r = p.if_tree() test(r, x)
def test_logical(self): # Single and double precision and native maths ws = myokit.formats.opencl.OpenCLExpressionWriter() wd = myokit.formats.opencl.OpenCLExpressionWriter( myokit.DOUBLE_PRECISION) wn = myokit.formats.opencl.OpenCLExpressionWriter(native_math=False) a = myokit.Name(myokit.Model().add_component('c').add_variable('a')) b = myokit.Number('12', 'pF') cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') condx = myokit.Number(1.2) # Not x = myokit.Not(cond1) self.assertEqual(ws.ex(x), '!((5.0f > 3.0f))') self.assertEqual(wd.ex(x), '!((5.0 > 3.0))') self.assertEqual(wn.ex(x), '!((5.0f > 3.0f))') x = myokit.Not(condx) self.assertEqual(ws.ex(x), '!((1.2f != 0.0f))') self.assertEqual(wd.ex(x), '!((1.2 != 0.0))') self.assertEqual(wn.ex(x), '!((1.2f != 0.0f))') # And x = myokit.And(cond1, cond2) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) && (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) && (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) && (2.0f < 1.0f))') x = myokit.And(condx, cond2) self.assertEqual(ws.ex(x), '((1.2f != 0.0f) && (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((1.2 != 0.0) && (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((1.2f != 0.0f) && (2.0f < 1.0f))') x = myokit.And(cond1, condx) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) && (1.2f != 0.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) && (1.2 != 0.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) && (1.2f != 0.0f))') # Or x = myokit.Or(cond1, cond2) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) || (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) || (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) || (2.0f < 1.0f))') x = myokit.Or(condx, cond2) self.assertEqual(ws.ex(x), '((1.2f != 0.0f) || (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((1.2 != 0.0) || (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((1.2f != 0.0f) || (2.0f < 1.0f))') x = myokit.Or(cond1, condx) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) || (1.2f != 0.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) || (1.2 != 0.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) || (1.2f != 0.0f))') # If x = myokit.If(cond1, a, b) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) ? c.a : 12.0f)') self.assertEqual(wd.ex(x), '((5.0 > 3.0) ? c.a : 12.0)') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) ? c.a : 12.0f)') x = myokit.If(condx, a, b) self.assertEqual(ws.ex(x), '((1.2f != 0.0f) ? c.a : 12.0f)') self.assertEqual(wd.ex(x), '((1.2 != 0.0) ? c.a : 12.0)') self.assertEqual(wn.ex(x), '((1.2f != 0.0f) ? c.a : 12.0f)') # Piecewise c = myokit.Number(1) x = myokit.Piecewise(cond1, a, cond2, b, c) self.assertEqual( ws.ex(x), '((5.0f > 3.0f) ? c.a : ((2.0f < 1.0f) ? 12.0f : 1.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) ? c.a : ((2.0 < 1.0) ? 12.0 : 1.0))') self.assertEqual( wn.ex(x), '((5.0f > 3.0f) ? c.a : ((2.0f < 1.0f) ? 12.0f : 1.0f))') x = myokit.Piecewise(condx, a, condx, b, c) self.assertEqual( ws.ex(x), '((1.2f != 0.0f) ? c.a : ((1.2f != 0.0f) ? 12.0f : 1.0f))') self.assertEqual(wd.ex(x), '((1.2 != 0.0) ? c.a : ((1.2 != 0.0) ? 12.0 : 1.0))') self.assertEqual( wn.ex(x), '((1.2f != 0.0f) ? c.a : ((1.2f != 0.0f) ? 12.0f : 1.0f))')
def test_conditionals(self): # Tests if and piecewise parsing # If a = myokit.Name('c.a') b = myokit.Number(1.0) cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') c1 = '<apply><gt/><cn>5.0</cn><cn>3.0</cn></apply>' c2 = '<apply><lt/><cn>2.0</cn><cn>1.0</cn></apply>' e = myokit.If(cond1, a, b) x = ( '<piecewise>' '<piece><ci>c.a</ci>' + c1 + '</piece>' '<otherwise><cn>1.0</cn></otherwise>' '</piecewise>' ) self.assertEqual(self.p(x), e.piecewise()) # Piecewise e = myokit.Piecewise(cond1, a, cond2, b, myokit.Number(100)) x = ( '<piecewise>' '<piece><ci>c.a</ci>' + c1 + '</piece>' '<piece><cn>1.0</cn>' + c2 + '</piece>' '<otherwise><cn>100.0</cn></otherwise>' '</piecewise>' ) self.assertEqual(self.p(x), e) # Piecewise with extra otherwise x = ( '<piecewise>' ' <piece>' ' <cn>1.0</cn><apply><eq/><cn>1.0</cn><cn>1.0</cn></apply>' ' </piece>' ' <otherwise>' ' <cn>2</cn>' ' </otherwise>' ' <otherwise>' ' <cn>3</cn>' ' </otherwise>' '</piecewise>' ) self.assertRaisesRegex( mathml.MathMLError, 'Found more than one <otherwise>', self.p, x) # Check otherwise is automatically added if not given x = ( '<piecewise>' ' <piece>' ' <cn>2</cn><apply><eq/><cn>1.0</cn><cn>1.0</cn></apply>' ' </piece>' ' <piece>' ' <cn>1.0</cn><apply><eq/><cn>1.0</cn><cn>1.0</cn></apply>' ' </piece>' '</piecewise>' ) e = self.p(x) pieces = list(e.pieces()) self.assertEqual(len(pieces), 3) self.assertEqual(pieces[0], myokit.Number(2)) self.assertEqual(pieces[1], myokit.Number(1)) self.assertEqual(pieces[2], myokit.Number(0)) # Too much stuff in a piece x = ( '<piecewise>' ' <piece>' ' <cn>1</cn><apply><eq/><cn>1</cn><cn>1</cn></apply>' ' <cn>2</cn>' ' </piece>' ' <otherwise>' ' <cn>3</cn>' ' </otherwise>' '</piecewise>' ) self.assertRaisesRegex( mathml.MathMLError, '<piece> element must have exactly 2 children', self.p, x) # Too much stuff in an otherwise x = ( '<piecewise>' ' <piece>' ' <cn>1</cn><apply><eq/><cn>1</cn><cn>1</cn></apply>' ' </piece>' ' <otherwise>' ' <cn>3</cn><ci>x</ci>' ' </otherwise>' '</piecewise>' ) self.assertRaisesRegex( mathml.MathMLError, '<otherwise> element must have exactly 1', self.p, x) # Unexpected tag in piecwise x = ( '<piecewise>' ' <piece>' ' <cn>1.0</cn><apply><eq/><cn>1.0</cn><cn>1.0</cn></apply>' ' </piece>' ' <otherwise>' ' <cn>3</cn>' ' </otherwise>' ' <apply><eq/><cn>1.0</cn><cn>1.0</cn></apply>' '</piecewise>' ) self.assertRaisesRegex( mathml.MathMLError, 'Unexpected content in <piecewise>', self.p, x)
def test_trig_extra(self): # Tests parsing of the annoying trig functions. # Cosecant x = self.p('<apply><csc/><cn>3</cn></apply>') y = myokit.parse_expression('1/ sin(3)') self.assertEqual(x, y) # Secant x = self.p('<apply><sec/><cn>3</cn></apply>') y = myokit.parse_expression('1/ cos(3)') self.assertEqual(x, y) # Cotangent x = self.p('<apply><cot/><cn>3</cn></apply>') y = myokit.parse_expression('1/ tan(3)') self.assertEqual(x, y) # arc-cosecant x = self.p('<apply><arccsc/><cn>3</cn></apply>') y = myokit.parse_expression('asin(1/ 3)') self.assertEqual(x, y) # arc-secant x = self.p('<apply><arcsec/><cn>3</cn></apply>') y = myokit.parse_expression('acos(1/ 3)') self.assertEqual(x, y) # arc-cotangent x = self.p('<apply><arccot/><cn>3</cn></apply>') y = myokit.parse_expression('atan(1/ 3)') self.assertEqual(x, y) # Hyperbolic sine x = self.p('<apply><sinh/><cn>3</cn></apply>') y = myokit.parse_expression('0.5 * (exp(3) - exp(-3))') self.assertEqual(x, y) # Hyperbolic cosine x = self.p('<apply><cosh/><cn>3</cn></apply>') y = myokit.parse_expression('0.5 * (exp(3) + exp(-3))') self.assertEqual(x, y) # Hyperbolic tangent x = self.p('<apply><tanh/><cn>3</cn></apply>') y = myokit.parse_expression('(exp(2*3) - 1)/ (exp(2*3) + 1)') self.assertEqual(x, y) # Hyperbolic arc sine x = self.p('<apply><arcsinh/><cn>3</cn></apply>') y = myokit.parse_expression('log(3 + sqrt(1 + 3*3))') self.assertEqual(x, y) # Hyperbolic arc cosine x = self.p('<apply><arccosh/><cn>3</cn></apply>') y = myokit.parse_expression('log(3 + sqrt(3 + 1) * sqrt(3 - 1))') self.assertEqual(x, y) # Hyperbolic arc tangent x = self.p('<apply><arctanh/><cn>3</cn></apply>') y = myokit.parse_expression('0.5 * (log(1 + 3) - log(1 - 3))') self.assertEqual(x, y) # Hyperbolic cosecant x = self.p('<apply><csch/><cn>3</cn></apply>') y = myokit.parse_expression('2/ (exp(3) - exp(-3))') self.assertEqual(x, y) # Hyperbolic secant x = self.p('<apply><sech/><cn>3</cn></apply>') y = myokit.parse_expression('2/ (exp(3) + exp(-3))') self.assertEqual(x, y) # Hyperbolic cotangent x = self.p('<apply><coth/><cn>3</cn></apply>') y = myokit.parse_expression('(exp(2*3) + 1)/ (exp(2*3) - 1)') self.assertEqual(x, y) # Hyperbolic arc cosecant x = self.p('<apply><arccsch/><cn>3</cn></apply>') y = myokit.parse_expression('log(sqrt(1/(3*3) + 1) + 1/3)') self.assertEqual(x, y) # Hyperbolic arc secant x = self.p('<apply><arcsech/><cn>3</cn></apply>') y = myokit.parse_expression('log(sqrt(1/(3*3) - 1) + 1/3)') self.assertEqual(x, y) # Hyperbolic arc cotangent x = self.p('<apply><arccoth/><cn>3</cn></apply>') y = myokit.parse_expression('0.5 * log((3 + 1)/ (3 - 1))') self.assertEqual(x, y)
def test_format_parse_error(self): """ Test format_parse_error. """ # Test basic formatting, with and without source bad = ' 5 + / 2' try: myokit.parse_expression(bad) except myokit.ParseError as e: # No source self.assertEqual( myokit.format_parse_error(e), '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 8', ])) # List-of-strings source self.assertEqual( myokit.format_parse_error(e, source=[bad]), '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 8', ' 5 + / 2', ' ^' ])) # File source with TemporaryDirectory() as d: path = d.path('mmt') with open(path, 'w') as f: f.write(bad + '\n') myokit.format_parse_error(e, source=path), '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 8', ' 5 + / 2', ' ^' ]) # Line doesn't exist in source self.assertEqual( myokit.format_parse_error(e, source=[]), '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 8', ])) # Char doesn't exist in source self.assertEqual( myokit.format_parse_error(e, source=['x']), '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 8', ])) # Very long lines bad = ' 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 100 + 1000 + 11' bad += ' + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22' bad += ' + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31' # Error near start error = '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 12', ' 1 + 2 + / 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 100 + 1000 + ..', ' ^', ]) b = bad[:12] + '/ ' + bad[12:] try: myokit.parse_expression(b) except myokit.ParseError as e: self.assertEqual(myokit.format_parse_error(e, source=[b]), error) error = '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 83', ' ..+ 12 + 13 + 14 + 15 + / 16 + 17 + 18 + 19 + 20 + 21 + 22..', ' ^', ]) b = bad[:83] + '/ ' + bad[83:] try: myokit.parse_expression(b) except myokit.ParseError as e: self.assertEqual(myokit.format_parse_error(e, source=[b]), error) error = '\n'.join([ 'Syntax error', ' Unexpected token SLASH "/" expecting expression', 'On line 1 character 133', ' ..+ 21 + 22 + 23 + 24 + 25 + / 26 + 27 + 28 + 29 + 30 + 31', ' ^', ]) b = bad[:133] + '/ ' + bad[133:] try: myokit.parse_expression(b) except myokit.ParseError as e: self.assertEqual(myokit.format_parse_error(e, source=[b]), error)
def test_all(self): w = myokit.formats.ewriter('easyml') model = myokit.Model() component = model.add_component('c') avar = component.add_variable('a') # Name a = myokit.Name(avar) self.assertEqual(w.ex(a), 'c.a') # Number with unit b = myokit.Number('12', 'pF') self.assertEqual(w.ex(b), '12.0') # Integer c = myokit.Number(1) self.assertEqual(w.ex(c), '1.0') # Integer # Prefix plus x = myokit.PrefixPlus(b) self.assertEqual(w.ex(x), '12.0') # Prefix minus x = myokit.PrefixMinus(b) self.assertEqual(w.ex(x), '(-12.0)') # Plus x = myokit.Plus(a, b) self.assertEqual(w.ex(x), 'c.a + 12.0') # Minus x = myokit.Minus(a, b) self.assertEqual(w.ex(x), 'c.a - 12.0') # Multiply x = myokit.Multiply(a, b) self.assertEqual(w.ex(x), 'c.a * 12.0') # Divide x = myokit.Divide(a, b) self.assertEqual(w.ex(x), 'c.a / 12.0') # Quotient x = myokit.Quotient(a, b) with WarningCollector() as c: self.assertEqual(w.ex(x), 'floor(c.a / 12.0)') # Remainder x = myokit.Remainder(a, b) with WarningCollector() as c: self.assertEqual(w.ex(x), 'c.a - 12.0 * (floor(c.a / 12.0))') # Power x = myokit.Power(a, b) self.assertEqual(w.ex(x), 'pow(c.a, 12.0)') # Sqrt x = myokit.Sqrt(b) self.assertEqual(w.ex(x), 'sqrt(12.0)') # Exp x = myokit.Exp(a) self.assertEqual(w.ex(x), 'exp(c.a)') # Log(a) x = myokit.Log(b) self.assertEqual(w.ex(x), 'log(12.0)') # Log(a, b) x = myokit.Log(a, b) self.assertEqual(w.ex(x), '(log(c.a) / log(12.0))') # Log10 x = myokit.Log10(b) self.assertEqual(w.ex(x), 'log10(12.0)') # Sin with WarningCollector() as c: x = myokit.Sin(b) self.assertEqual(w.ex(x), 'sin(12.0)') # Cos x = myokit.Cos(b) self.assertEqual(w.ex(x), 'cos(12.0)') # Tan x = myokit.Tan(b) self.assertEqual(w.ex(x), 'tan(12.0)') # ASin x = myokit.ASin(b) self.assertEqual(w.ex(x), 'asin(12.0)') # ACos x = myokit.ACos(b) self.assertEqual(w.ex(x), 'acos(12.0)') # ATan x = myokit.ATan(b) self.assertEqual(w.ex(x), 'atan(12.0)') with WarningCollector() as c: # Floor x = myokit.Floor(b) self.assertEqual(w.ex(x), 'floor(12.0)') # Ceil x = myokit.Ceil(b) self.assertEqual(w.ex(x), 'ceil(12.0)') # Abs x = myokit.Abs(b) self.assertEqual(w.ex(x), 'fabs(12.0)') # Equal x = myokit.Equal(a, b) self.assertEqual(w.ex(x), '(c.a == 12.0)') # NotEqual x = myokit.NotEqual(a, b) self.assertEqual(w.ex(x), '(c.a != 12.0)') # More x = myokit.More(a, b) self.assertEqual(w.ex(x), '(c.a > 12.0)') # Less x = myokit.Less(a, b) self.assertEqual(w.ex(x), '(c.a < 12.0)') # MoreEqual x = myokit.MoreEqual(a, b) self.assertEqual(w.ex(x), '(c.a >= 12.0)') # LessEqual x = myokit.LessEqual(a, b) self.assertEqual(w.ex(x), '(c.a <= 12.0)') # Not cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') x = myokit.Not(cond1) self.assertEqual(w.ex(x), '!((5.0 > 3.0))') # And x = myokit.And(cond1, cond2) self.assertEqual(w.ex(x), '((5.0 > 3.0) and (2.0 < 1.0))') # Or x = myokit.Or(cond1, cond2) self.assertEqual(w.ex(x), '((5.0 > 3.0) or (2.0 < 1.0))') # If x = myokit.If(cond1, a, b) self.assertEqual(w.ex(x), '((5.0 > 3.0) ? c.a : 12.0)') # Piecewise c = myokit.Number(1) x = myokit.Piecewise(cond1, a, cond2, b, c) self.assertEqual(w.ex(x), '((5.0 > 3.0) ? c.a : ((2.0 < 1.0) ? 12.0 : 1.0))') # Test without a Myokit expression self.assertRaisesRegex(ValueError, 'Unknown expression type', w.ex, 7)
def test_conditional(self): # Single and double precision and native maths ws = myokit.formats.opencl.OpenCLExpressionWriter() wd = myokit.formats.opencl.OpenCLExpressionWriter( myokit.DOUBLE_PRECISION) wn = myokit.formats.opencl.OpenCLExpressionWriter(native_math=False) a = myokit.Name(myokit.Model().add_component('c').add_variable('a')) b = myokit.Number('12', 'pF') cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') # Equal x = myokit.Equal(a, b) self.assertEqual(ws.ex(x), '(c.a == 12.0f)') self.assertEqual(wd.ex(x), '(c.a == 12.0)') self.assertEqual(wn.ex(x), '(c.a == 12.0f)') x = myokit.Equal(cond1, cond2) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) == (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) == (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) == (2.0f < 1.0f))') x = myokit.Equal(cond1, b) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) == (12.0f != 0.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) == (12.0 != 0.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) == (12.0f != 0.0f))') x = myokit.Equal(a, cond2) self.assertEqual(ws.ex(x), '((c.a != 0.0f) == (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((c.a != 0.0) == (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((c.a != 0.0f) == (2.0f < 1.0f))') # NotEqual x = myokit.NotEqual(a, b) self.assertEqual(ws.ex(x), '(c.a != 12.0f)') self.assertEqual(wd.ex(x), '(c.a != 12.0)') self.assertEqual(wn.ex(x), '(c.a != 12.0f)') x = myokit.NotEqual(cond1, cond2) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) != (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) != (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) != (2.0f < 1.0f))') x = myokit.NotEqual(cond1, b) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) != (12.0f != 0.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) != (12.0 != 0.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) != (12.0f != 0.0f))') x = myokit.NotEqual(a, cond2) self.assertEqual(ws.ex(x), '((c.a != 0.0f) != (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((c.a != 0.0) != (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((c.a != 0.0f) != (2.0f < 1.0f))') # More x = myokit.More(a, b) self.assertEqual(ws.ex(x), '(c.a > 12.0f)') self.assertEqual(wd.ex(x), '(c.a > 12.0)') self.assertEqual(wn.ex(x), '(c.a > 12.0f)') x = myokit.More(cond1, cond2) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) > (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) > (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) > (2.0f < 1.0f))') x = myokit.More(cond1, b) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) > (12.0f != 0.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) > (12.0 != 0.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) > (12.0f != 0.0f))') x = myokit.More(a, cond2) self.assertEqual(ws.ex(x), '((c.a != 0.0f) > (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((c.a != 0.0) > (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((c.a != 0.0f) > (2.0f < 1.0f))') # Less x = myokit.Less(a, b) self.assertEqual(ws.ex(x), '(c.a < 12.0f)') self.assertEqual(wd.ex(x), '(c.a < 12.0)') self.assertEqual(wn.ex(x), '(c.a < 12.0f)') x = myokit.Less(cond1, cond2) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) < (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) < (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) < (2.0f < 1.0f))') x = myokit.Less(cond1, b) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) < (12.0f != 0.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) < (12.0 != 0.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) < (12.0f != 0.0f))') x = myokit.Less(a, cond2) self.assertEqual(ws.ex(x), '((c.a != 0.0f) < (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((c.a != 0.0) < (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((c.a != 0.0f) < (2.0f < 1.0f))') # MoreEqual x = myokit.MoreEqual(a, b) self.assertEqual(ws.ex(x), '(c.a >= 12.0f)') self.assertEqual(wd.ex(x), '(c.a >= 12.0)') self.assertEqual(wn.ex(x), '(c.a >= 12.0f)') x = myokit.MoreEqual(cond1, cond2) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) >= (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) >= (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) >= (2.0f < 1.0f))') x = myokit.MoreEqual(cond1, b) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) >= (12.0f != 0.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) >= (12.0 != 0.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) >= (12.0f != 0.0f))') x = myokit.MoreEqual(a, cond2) self.assertEqual(ws.ex(x), '((c.a != 0.0f) >= (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((c.a != 0.0) >= (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((c.a != 0.0f) >= (2.0f < 1.0f))') # LessEqual x = myokit.LessEqual(a, b) self.assertEqual(ws.ex(x), '(c.a <= 12.0f)') self.assertEqual(wd.ex(x), '(c.a <= 12.0)') self.assertEqual(wn.ex(x), '(c.a <= 12.0f)') x = myokit.LessEqual(cond1, cond2) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) <= (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) <= (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) <= (2.0f < 1.0f))') x = myokit.LessEqual(cond1, b) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) <= (12.0f != 0.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) <= (12.0 != 0.0))') self.assertEqual(wn.ex(x), '((5.0f > 3.0f) <= (12.0f != 0.0f))') x = myokit.LessEqual(a, cond2) self.assertEqual(ws.ex(x), '((c.a != 0.0f) <= (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((c.a != 0.0) <= (2.0 < 1.0))') self.assertEqual(wn.ex(x), '((c.a != 0.0f) <= (2.0f < 1.0f))')
def test_all(self): w = myokit.formats.python.PythonExpressionWriter() model = myokit.Model() component = model.add_component('c') avar = component.add_variable('a') # Name a = myokit.Name(avar) self.assertEqual(w.ex(a), 'c.a') # Number with unit b = myokit.Number('12', 'pF') self.assertEqual(w.ex(b), '12.0') # Prefix plus x = myokit.PrefixPlus(b) self.assertEqual(w.ex(x), '12.0') # Prefix minus x = myokit.PrefixMinus(b) self.assertEqual(w.ex(x), '(-12.0)') # Plus x = myokit.Plus(a, b) self.assertEqual(w.ex(x), 'c.a + 12.0') # Minus x = myokit.Minus(a, b) self.assertEqual(w.ex(x), 'c.a - 12.0') # Multiply x = myokit.Multiply(a, b) self.assertEqual(w.ex(x), 'c.a * 12.0') # Divide x = myokit.Divide(a, b) self.assertEqual(w.ex(x), 'c.a / 12.0') # Quotient x = myokit.Quotient(a, b) self.assertEqual(w.ex(x), 'c.a // 12.0') # Remainder x = myokit.Remainder(a, b) self.assertEqual(w.ex(x), 'c.a % 12.0') # Power x = myokit.Power(a, b) self.assertEqual(w.ex(x), 'c.a ** 12.0') # Sqrt x = myokit.Sqrt(b) self.assertEqual(w.ex(x), 'math.sqrt(12.0)') # Exp x = myokit.Exp(a) self.assertEqual(w.ex(x), 'math.exp(c.a)') # Log(a) x = myokit.Log(b) self.assertEqual(w.ex(x), 'math.log(12.0)') # Log(a, b) x = myokit.Log(a, b) self.assertEqual(w.ex(x), 'math.log(c.a, 12.0)') # Log10 x = myokit.Log10(b) self.assertEqual(w.ex(x), 'math.log10(12.0)') # Sin x = myokit.Sin(b) self.assertEqual(w.ex(x), 'math.sin(12.0)') # Cos x = myokit.Cos(b) self.assertEqual(w.ex(x), 'math.cos(12.0)') # Tan x = myokit.Tan(b) self.assertEqual(w.ex(x), 'math.tan(12.0)') # ASin x = myokit.ASin(b) self.assertEqual(w.ex(x), 'math.asin(12.0)') # ACos x = myokit.ACos(b) self.assertEqual(w.ex(x), 'math.acos(12.0)') # ATan x = myokit.ATan(b) self.assertEqual(w.ex(x), 'math.atan(12.0)') # Floor x = myokit.Floor(b) self.assertEqual(w.ex(x), 'math.floor(12.0)') # Ceil x = myokit.Ceil(b) self.assertEqual(w.ex(x), 'math.ceil(12.0)') # Abs x = myokit.Abs(b) self.assertEqual(w.ex(x), 'abs(12.0)') # Equal x = myokit.Equal(a, b) self.assertEqual(w.ex(x), '(c.a == 12.0)') # NotEqual x = myokit.NotEqual(a, b) self.assertEqual(w.ex(x), '(c.a != 12.0)') # More x = myokit.More(a, b) self.assertEqual(w.ex(x), '(c.a > 12.0)') # Less x = myokit.Less(a, b) self.assertEqual(w.ex(x), '(c.a < 12.0)') # MoreEqual x = myokit.MoreEqual(a, b) self.assertEqual(w.ex(x), '(c.a >= 12.0)') # LessEqual x = myokit.LessEqual(a, b) self.assertEqual(w.ex(x), '(c.a <= 12.0)') # Not cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') x = myokit.Not(cond1) self.assertEqual(w.ex(x), 'not ((5.0 > 3.0))') # And x = myokit.And(cond1, cond2) self.assertEqual(w.ex(x), '((5.0 > 3.0) and (2.0 < 1.0))') # Or x = myokit.Or(cond1, cond2) self.assertEqual(w.ex(x), '((5.0 > 3.0) or (2.0 < 1.0))') # If x = myokit.If(cond1, a, b) self.assertEqual(w.ex(x), '(c.a if (5.0 > 3.0) else 12.0)') # Piecewise c = myokit.Number(1) x = myokit.Piecewise(cond1, a, cond2, b, c) self.assertEqual( w.ex(x), '(c.a if (5.0 > 3.0) else (12.0 if (2.0 < 1.0) else 1.0))') # Test fetching using ewriter method w = myokit.formats.ewriter('python') self.assertIsInstance(w, myokit.formats.python.PythonExpressionWriter) # Test lhs method w.set_lhs_function(lambda x: 'sheep') self.assertEqual(w.ex(a), 'sheep') # Test without a Myokit expression self.assertRaisesRegex(ValueError, 'Unknown expression type', w.ex, 7)
def test_all(self): w = myokit.formats.matlab.MatlabExpressionWriter() model = myokit.Model() component = model.add_component('c') avar = component.add_variable('a') # Name a = myokit.Name(avar) self.assertEqual(w.ex(a), 'c.a') # Number with unit b = myokit.Number('12', 'pF') self.assertEqual(w.ex(b), '12.0') # Prefix plus x = myokit.PrefixPlus(b) self.assertEqual(w.ex(x), '12.0') # Prefix minus x = myokit.PrefixMinus(b) self.assertEqual(w.ex(x), '(-12.0)') # Plus x = myokit.Plus(a, b) self.assertEqual(w.ex(x), 'c.a + 12.0') # Minus x = myokit.Minus(a, b) self.assertEqual(w.ex(x), 'c.a - 12.0') # Multiply x = myokit.Multiply(a, b) self.assertEqual(w.ex(x), 'c.a * 12.0') # Divide x = myokit.Divide(a, b) self.assertEqual(w.ex(x), 'c.a / 12.0') # Quotient x = myokit.Quotient(a, b) self.assertEqual(w.ex(x), 'floor(c.a / 12.0)') # Remainder x = myokit.Remainder(a, b) self.assertEqual(w.ex(x), 'mod(c.a, 12.0)') # Power x = myokit.Power(a, b) self.assertEqual(w.ex(x), 'c.a ^ 12.0') # Sqrt x = myokit.Sqrt(b) self.assertEqual(w.ex(x), 'sqrt(12.0)') # Exp x = myokit.Exp(a) self.assertEqual(w.ex(x), 'exp(c.a)') # Log(a) x = myokit.Log(b) self.assertEqual(w.ex(x), 'log(12.0)') # Log(a, b) x = myokit.Log(a, b) self.assertEqual(w.ex(x), '(log(c.a) / log(12.0))') # Log10 x = myokit.Log10(b) self.assertEqual(w.ex(x), 'log10(12.0)') # Sin x = myokit.Sin(b) self.assertEqual(w.ex(x), 'sin(12.0)') # Cos x = myokit.Cos(b) self.assertEqual(w.ex(x), 'cos(12.0)') # Tan x = myokit.Tan(b) self.assertEqual(w.ex(x), 'tan(12.0)') # ASin x = myokit.ASin(b) self.assertEqual(w.ex(x), 'asin(12.0)') # ACos x = myokit.ACos(b) self.assertEqual(w.ex(x), 'acos(12.0)') # ATan x = myokit.ATan(b) self.assertEqual(w.ex(x), 'atan(12.0)') # Floor x = myokit.Floor(b) self.assertEqual(w.ex(x), 'floor(12.0)') # Ceil x = myokit.Ceil(b) self.assertEqual(w.ex(x), 'ceil(12.0)') # Abs x = myokit.Abs(b) self.assertEqual(w.ex(x), 'abs(12.0)') # Equal x = myokit.Equal(a, b) self.assertEqual(w.ex(x), '(c.a == 12.0)') # NotEqual x = myokit.NotEqual(a, b) self.assertEqual(w.ex(x), '(c.a != 12.0)') # More x = myokit.More(a, b) self.assertEqual(w.ex(x), '(c.a > 12.0)') # Less x = myokit.Less(a, b) self.assertEqual(w.ex(x), '(c.a < 12.0)') # MoreEqual x = myokit.MoreEqual(a, b) self.assertEqual(w.ex(x), '(c.a >= 12.0)') # LessEqual x = myokit.LessEqual(a, b) self.assertEqual(w.ex(x), '(c.a <= 12.0)') # Not cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') x = myokit.Not(cond1) self.assertEqual(w.ex(x), '!((5.0 > 3.0))') # And x = myokit.And(cond1, cond2) self.assertEqual(w.ex(x), '((5.0 > 3.0) && (2.0 < 1.0))') # Or x = myokit.Or(cond1, cond2) self.assertEqual(w.ex(x), '((5.0 > 3.0) || (2.0 < 1.0))') # If (custom function) x = myokit.If(cond1, a, b) self.assertEqual(w.ex(x), 'ifthenelse((5.0 > 3.0), c.a, 12.0)') # Piecewise c = myokit.Number(1) x = myokit.Piecewise(cond1, a, cond2, b, c) self.assertEqual( w.ex(x), 'ifthenelse((5.0 > 3.0), c.a, ifthenelse((2.0 < 1.0), 12.0, 1.0))') # Test fetching using ewriter method w = myokit.formats.ewriter('matlab') self.assertIsInstance(w, myokit.formats.matlab.MatlabExpressionWriter) # Test without a Myokit expression self.assertRaisesRegex(ValueError, 'Unknown expression type', w.ex, 7)
def test_all(self): w = myokit.formats.latex.LatexExpressionWriter() model = myokit.Model() component = model.add_component('c') avar = component.add_variable('a') # Model needs to be validated --> sets unames avar.set_rhs(12) avar.set_binding('time') model.validate() # Name a = myokit.Name(avar) self.assertEqual(w.ex(a), '\\text{a}') # Number with unit b = myokit.Number('12', 'pF') self.assertEqual(w.ex(b), '12.0') # Prefix plus x = myokit.PrefixPlus(b) self.assertEqual(w.ex(x), '12.0') # Prefix minus x = myokit.PrefixMinus(b) self.assertEqual(w.ex(x), '\\left(-12.0\\right)') # Prefix minus with bracket x = myokit.PrefixMinus(myokit.Plus(a, b)) self.assertEqual(w.ex(x), '\\left(-\\left(\\text{a}+12.0\\right)\\right)') # Plus x = myokit.Plus(a, b) self.assertEqual(w.ex(x), '\\text{a}+12.0') # Minus x = myokit.Minus(a, b) self.assertEqual(w.ex(x), '\\text{a}-12.0') # Multiply x = myokit.Multiply(a, b) self.assertEqual(w.ex(x), '\\text{a}*12.0') # Divide x = myokit.Divide(a, b) self.assertEqual(w.ex(x), '\\frac{\\text{a}}{12.0}') # Quotient # Not supported in latex! x = myokit.Quotient(a, b) self.assertEqual( w.ex(x), '\\left\\lfloor\\frac{\\text{a}}{12.0}\\right\\rfloor') # Remainder x = myokit.Remainder(a, b) self.assertEqual(w.ex(x), '\\bmod\\left(\\text{a},12.0\\right)') # Power x = myokit.Power(a, b) self.assertEqual(w.ex(x), '\\text{a}^{12.0}') # Power with brackets x = myokit.Power(myokit.Plus(a, b), b) self.assertEqual(w.ex(x), '\\left(\\text{a}+12.0\\right)^{12.0}') # Sqrt x = myokit.Sqrt(b) self.assertEqual(w.ex(x), '\\sqrt{12.0}') # Exp x = myokit.Exp(a) self.assertEqual(w.ex(x), '\\exp\\left(\\text{a}\\right)') # Log(a) x = myokit.Log(b) self.assertEqual(w.ex(x), '\\log\\left(12.0\\right)') # Log(a, b) x = myokit.Log(a, b) self.assertEqual(w.ex(x), '\\log_{12.0}\\left(\\text{a}\\right)') # Log10 x = myokit.Log10(b) self.assertEqual(w.ex(x), '\\log_{10.0}\\left(12.0\\right)') # Sin x = myokit.Sin(b) self.assertEqual(w.ex(x), '\\sin\\left(12.0\\right)') # Cos x = myokit.Cos(b) self.assertEqual(w.ex(x), '\\cos\\left(12.0\\right)') # Tan x = myokit.Tan(b) self.assertEqual(w.ex(x), '\\tan\\left(12.0\\right)') # ASin x = myokit.ASin(b) self.assertEqual(w.ex(x), '\\arcsin\\left(12.0\\right)') # ACos x = myokit.ACos(b) self.assertEqual(w.ex(x), '\\arccos\\left(12.0\\right)') # ATan x = myokit.ATan(b) self.assertEqual(w.ex(x), '\\arctan\\left(12.0\\right)') # Floor x = myokit.Floor(b) self.assertEqual(w.ex(x), '\\left\\lfloor{12.0}\\right\\rfloor') # Ceil x = myokit.Ceil(b) self.assertEqual(w.ex(x), '\\left\\lceil{12.0}\\right\\rceil') # Abs x = myokit.Abs(b) self.assertEqual(w.ex(x), '\\lvert{12.0}\\rvert') # Equal x = myokit.Equal(a, b) self.assertEqual(w.ex(x), '\\left(\\text{a}=12.0\\right)') # NotEqual x = myokit.NotEqual(a, b) self.assertEqual(w.ex(x), '\\left(\\text{a}\\neq12.0\\right)') # More x = myokit.More(a, b) self.assertEqual(w.ex(x), '\\left(\\text{a}>12.0\\right)') # Less x = myokit.Less(a, b) self.assertEqual(w.ex(x), '\\left(\\text{a}<12.0\\right)') # MoreEqual x = myokit.MoreEqual(a, b) self.assertEqual(w.ex(x), '\\left(\\text{a}\\geq12.0\\right)') # LessEqual x = myokit.LessEqual(a, b) self.assertEqual(w.ex(x), '\\left(\\text{a}\\leq12.0\\right)') # Not cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') x = myokit.Not(cond1) self.assertEqual(w.ex(x), '\\not\\left(\\left(5.0>3.0\\right)\\right)') # And x = myokit.And(cond1, cond2) self.assertEqual( w.ex(x), '\\left(\\left(5.0>3.0\\right)\\and' '\\left(2.0<1.0\\right)\\right)') # Or x = myokit.Or(cond1, cond2) self.assertEqual( w.ex(x), '\\left(\\left(5.0>3.0\\right)\\or' '\\left(2.0<1.0\\right)\\right)') # If x = myokit.If(cond1, a, b) self.assertEqual( w.ex(x), 'if\\left(\\left(5.0>3.0\\right),\\text{a},12.0\\right)') # Piecewise c = myokit.Number(1) x = myokit.Piecewise(cond1, a, cond2, b, c) self.assertEqual( w.ex(x), 'piecewise\\left(\\left(5.0>3.0\\right),\\text{a},' '\\left(2.0<1.0\\right),12.0,1.0\\right)') # Test fetching using ewriter method w = myokit.formats.ewriter('latex') self.assertIsInstance(w, myokit.formats.latex.LatexExpressionWriter) # Test without a Myokit expression self.assertRaisesRegex(ValueError, 'Unknown expression type', w.ex, 7)
def test_all(self): # Single and double precision ws = myokit.formats.cuda.CudaExpressionWriter() wd = myokit.formats.cuda.CudaExpressionWriter(myokit.DOUBLE_PRECISION) model = myokit.Model() component = model.add_component('c') avar = component.add_variable('a') # Name a = myokit.Name(avar) self.assertEqual(ws.ex(a), 'c.a') self.assertEqual(wd.ex(a), 'c.a') # Number with unit b = myokit.Number('12', 'pF') self.assertEqual(ws.ex(b), '12.0f') self.assertEqual(wd.ex(b), '12.0') # Prefix plus x = myokit.PrefixPlus(b) self.assertEqual(ws.ex(x), '12.0f') self.assertEqual(wd.ex(x), '12.0') # Prefix minus x = myokit.PrefixMinus(b) self.assertEqual(ws.ex(x), '(-12.0f)') self.assertEqual(wd.ex(x), '(-12.0)') # Plus x = myokit.Plus(a, b) self.assertEqual(ws.ex(x), 'c.a + 12.0f') self.assertEqual(wd.ex(x), 'c.a + 12.0') # Minus x = myokit.Minus(a, b) self.assertEqual(ws.ex(x), 'c.a - 12.0f') self.assertEqual(wd.ex(x), 'c.a - 12.0') # Multiply x = myokit.Multiply(a, b) self.assertEqual(ws.ex(x), 'c.a * 12.0f') self.assertEqual(wd.ex(x), 'c.a * 12.0') # Divide x = myokit.Divide(a, b) self.assertEqual(ws.ex(x), 'c.a / 12.0f') self.assertEqual(wd.ex(x), 'c.a / 12.0') # Quotient x = myokit.Quotient(a, b) self.assertEqual(ws.ex(x), 'floorf(c.a / 12.0f)') self.assertEqual(wd.ex(x), 'floor(c.a / 12.0)') # Remainder x = myokit.Remainder(a, b) self.assertEqual(ws.ex(x), 'c.a - 12.0f * (floorf(c.a / 12.0f))') self.assertEqual(wd.ex(x), 'c.a - 12.0 * (floor(c.a / 12.0))') # Power x = myokit.Power(a, b) self.assertEqual(ws.ex(x), 'powf(c.a, 12.0f)') self.assertEqual(wd.ex(x), 'pow(c.a, 12.0)') # Square x = myokit.Power(a, myokit.Number(2)) self.assertEqual(ws.ex(x), '(c.a * c.a)') self.assertEqual(wd.ex(x), '(c.a * c.a)') # Square with brackets x = myokit.Power(myokit.Plus(a, b), myokit.Number(2)) self.assertEqual(ws.ex(x), '((c.a + 12.0f) * (c.a + 12.0f))') self.assertEqual(wd.ex(x), '((c.a + 12.0) * (c.a + 12.0))') # Sqrt x = myokit.Sqrt(b) self.assertEqual(ws.ex(x), 'sqrtf(12.0f)') self.assertEqual(wd.ex(x), 'sqrt(12.0)') # Exp x = myokit.Exp(a) self.assertEqual(ws.ex(x), 'expf(c.a)') self.assertEqual(wd.ex(x), 'exp(c.a)') # Log(a) x = myokit.Log(b) self.assertEqual(ws.ex(x), 'logf(12.0f)') self.assertEqual(wd.ex(x), 'log(12.0)') # Log(a, b) x = myokit.Log(a, b) self.assertEqual(ws.ex(x), '(logf(c.a) / logf(12.0f))') self.assertEqual(wd.ex(x), '(log(c.a) / log(12.0))') # Log10 x = myokit.Log10(b) self.assertEqual(ws.ex(x), 'log10f(12.0f)') self.assertEqual(wd.ex(x), 'log10(12.0)') # Sin x = myokit.Sin(b) self.assertEqual(ws.ex(x), 'sinf(12.0f)') self.assertEqual(wd.ex(x), 'sin(12.0)') # Cos x = myokit.Cos(b) self.assertEqual(ws.ex(x), 'cosf(12.0f)') self.assertEqual(wd.ex(x), 'cos(12.0)') # Tan x = myokit.Tan(b) self.assertEqual(ws.ex(x), 'tanf(12.0f)') self.assertEqual(wd.ex(x), 'tan(12.0)') # ASin x = myokit.ASin(b) self.assertEqual(ws.ex(x), 'asinf(12.0f)') self.assertEqual(wd.ex(x), 'asin(12.0)') # ACos x = myokit.ACos(b) self.assertEqual(ws.ex(x), 'acosf(12.0f)') self.assertEqual(wd.ex(x), 'acos(12.0)') # ATan x = myokit.ATan(b) self.assertEqual(ws.ex(x), 'atanf(12.0f)') self.assertEqual(wd.ex(x), 'atan(12.0)') # Floor x = myokit.Floor(b) self.assertEqual(ws.ex(x), 'floorf(12.0f)') self.assertEqual(wd.ex(x), 'floor(12.0)') # Ceil x = myokit.Ceil(b) self.assertEqual(ws.ex(x), 'ceilf(12.0f)') self.assertEqual(wd.ex(x), 'ceil(12.0)') # Abs x = myokit.Abs(b) self.assertEqual(ws.ex(x), 'fabsf(12.0f)') self.assertEqual(wd.ex(x), 'fabs(12.0)') # Equal x = myokit.Equal(a, b) self.assertEqual(ws.ex(x), '(c.a == 12.0f)') self.assertEqual(wd.ex(x), '(c.a == 12.0)') # NotEqual x = myokit.NotEqual(a, b) self.assertEqual(ws.ex(x), '(c.a != 12.0f)') self.assertEqual(wd.ex(x), '(c.a != 12.0)') # More x = myokit.More(a, b) self.assertEqual(ws.ex(x), '(c.a > 12.0f)') self.assertEqual(wd.ex(x), '(c.a > 12.0)') # Less x = myokit.Less(a, b) self.assertEqual(ws.ex(x), '(c.a < 12.0f)') self.assertEqual(wd.ex(x), '(c.a < 12.0)') # MoreEqual x = myokit.MoreEqual(a, b) self.assertEqual(ws.ex(x), '(c.a >= 12.0f)') self.assertEqual(wd.ex(x), '(c.a >= 12.0)') # LessEqual x = myokit.LessEqual(a, b) self.assertEqual(ws.ex(x), '(c.a <= 12.0f)') self.assertEqual(wd.ex(x), '(c.a <= 12.0)') # Not cond1 = myokit.parse_expression('5 > 3') cond2 = myokit.parse_expression('2 < 1') x = myokit.Not(cond1) self.assertEqual(ws.ex(x), '!((5.0f > 3.0f))') self.assertEqual(wd.ex(x), '!((5.0 > 3.0))') # And x = myokit.And(cond1, cond2) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) && (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) && (2.0 < 1.0))') # Or x = myokit.Or(cond1, cond2) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) || (2.0f < 1.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) || (2.0 < 1.0))') # If x = myokit.If(cond1, a, b) self.assertEqual(ws.ex(x), '((5.0f > 3.0f) ? c.a : 12.0f)') self.assertEqual(wd.ex(x), '((5.0 > 3.0) ? c.a : 12.0)') # Piecewise c = myokit.Number(1) x = myokit.Piecewise(cond1, a, cond2, b, c) self.assertEqual( ws.ex(x), '((5.0f > 3.0f) ? c.a : ((2.0f < 1.0f) ? 12.0f : 1.0f))') self.assertEqual(wd.ex(x), '((5.0 > 3.0) ? c.a : ((2.0 < 1.0) ? 12.0 : 1.0))') # Test fetching using ewriter method w = myokit.formats.ewriter('cuda') self.assertIsInstance(w, myokit.formats.cuda.CudaExpressionWriter) # Test without a Myokit expression self.assertRaisesRegex(ValueError, 'Unknown expression type', w.ex, 7)