def test_functions(self):
        # Test printing functions

        a = myokit.Name(self.avar)
        b = myokit.Number('12', 'pF')
        ca = '<ci>a</ci>'
        cb = ('<cn cellml:units="picofarad">12.0</cn>')

        # Power
        x = myokit.Power(a, b)
        self.assertWrite(x, '<apply><power/>' + ca + cb + '</apply>')
        # Sqrt
        x = myokit.Sqrt(b)
        self.assertWrite(x, '<apply><root/>' + cb + '</apply>')
        # Exp
        x = myokit.Exp(a)
        self.assertWrite(x, '<apply><exp/>' + ca + '</apply>')

        # Floor
        x = myokit.Floor(b)
        self.assertWrite(x, '<apply><floor/>' + cb + '</apply>')
        # Ceil
        x = myokit.Ceil(b)
        self.assertWrite(x, '<apply><ceiling/>' + cb + '</apply>')
        # Abs
        x = myokit.Abs(b)
        self.assertWrite(x, '<apply><abs/>' + cb + '</apply>')
    def test_functions(self):
        # Tests writing basic functions

        a = myokit.Name(self.avar)
        b = myokit.Number('12', 'pF')
        ca = '<mi>c.a</mi>'
        cb = '<mn>12.0</mn>'

        # Power
        x = myokit.Power(a, b)
        self.assertWrite(x, '<msup>' + ca + cb + '</msup>')

        # Sqrt
        x = myokit.Sqrt(b)
        self.assertWrite(
            x, '<mrow><mi>root</mi><mfenced>' + cb + '</mfenced></mrow>')

        # Exp
        x = myokit.Exp(a)
        self.assertWrite(x, '<msup><mi>e</mi>' + ca + '</msup>')

        # Log(a)
        x = myokit.Log(b)
        self.assertWrite(
            x, '<mrow><mi>ln</mi><mfenced>' + cb + '</mfenced></mrow>')

        # Log(a, b)
        x = myokit.Log(a, b)
        self.assertWrite(
            x, '<mrow><msub><mi>log</mi>' + cb + '</msub>'
            '<mfenced>' + ca + '</mfenced></mrow>')

        # Log10
        x = myokit.Log10(b)
        self.assertWrite(
            x, '<mrow><mi>log</mi><mfenced>' + cb + '</mfenced></mrow>')

        # Floor
        x = myokit.Floor(b)
        self.assertWrite(
            x, '<mrow><mi>floor</mi><mfenced>' + cb + '</mfenced></mrow>')

        # Ceil
        x = myokit.Ceil(b)
        self.assertWrite(
            x, '<mrow><mi>ceiling</mi><mfenced>' + cb + '</mfenced></mrow>')

        # Abs
        x = myokit.Abs(b)
        self.assertWrite(
            x, '<mrow><mi>abs</mi><mfenced>' + cb + '</mfenced></mrow>')

        # Quotient
        x = myokit.Quotient(a, b)
        self.assertWrite(x, '<mrow>' + ca + '<mo>//</mo>' + cb + '</mrow>')

        # Remainder
        x = myokit.Remainder(a, b)
        self.assertWrite(x, '<mrow>' + ca + '<mo>%</mo>' + cb + '</mrow>')
    def test_functions(self):
        # Tests writing basic functions

        # Power
        a = myokit.Name('a')
        b = myokit.Number(1)
        e = myokit.Power(a, b)
        x = '<apply><power/><ci>a</ci><cn>1.0</cn></apply>'
        self.assertWrite(e, x)

        # Sqrt
        e = myokit.Sqrt(b)
        x = '<apply><root/><cn>1.0</cn></apply>'
        self.assertWrite(e, x)

        # Exp
        e = myokit.Exp(a)
        x = '<apply><exp/><ci>a</ci></apply>'
        self.assertWrite(e, x)

        # Log(a)
        e = myokit.Log(b)
        x = '<apply><ln/><cn>1.0</cn></apply>'
        self.assertWrite(e, x)

        # Log(a, b)
        e = myokit.Log(a, b)
        x = '<apply><log/><logbase><cn>1.0</cn></logbase><ci>a</ci></apply>'
        self.assertWrite(e, x)

        # Log10
        e = myokit.Log10(b)
        x = '<apply><log/><cn>1.0</cn></apply>'
        self.assertWrite(e, x)

        # Floor
        e = myokit.Floor(b)
        x = '<apply><floor/><cn>1.0</cn></apply>'
        self.assertWrite(e, x)

        # Ceil
        e = myokit.Ceil(b)
        x = '<apply><ceiling/><cn>1.0</cn></apply>'
        self.assertWrite(e, x)

        # Abs
        e = myokit.Abs(b)
        x = '<apply><abs/><cn>1.0</cn></apply>'
        self.assertWrite(e, x)

        # Quotient
        e = myokit.Quotient(a, b)
        x = '<apply><quotient/><ci>a</ci><cn>1.0</cn></apply>'
        self.assertWrite(e, x)

        # Remainder
        e = myokit.Remainder(a, b)
        x = '<apply><rem/><ci>a</ci><cn>1.0</cn></apply>'
        self.assertWrite(e, x)
    def test_functions(self):
        # Tests parsing basic functions

        # Power
        a = myokit.Name('a')
        b = myokit.Number(1)
        e = myokit.Power(a, b)
        x = '<apply><power/><ci>a</ci><cn>1.0</cn></apply>'
        self.assertEqual(self.p(x), e)

        #TODO: Degree etc.

        # Exp
        e = myokit.Exp(a)
        x = '<apply><exp/><ci>a</ci></apply>'
        self.assertEqual(self.p(x), e)

        # No operands
        x = '<apply><exp/></apply>'
        self.assertRaisesRegex(
            mathml.MathMLError, 'Expecting 1 operand\(s\)', self.p, x)

        # Too many operands
        x = '<apply><exp/><cn>1</cn><cn>2</cn></apply>'
        self.assertRaisesRegex(
            mathml.MathMLError, 'Expecting 1 operand\(s\)', self.p, x)

        # Floor
        e = myokit.Floor(b)
        x = '<apply><floor/><cn>1.0</cn></apply>'
        self.assertEqual(self.p(x), e)

        # Ceil
        e = myokit.Ceil(b)
        x = '<apply><ceiling/><cn>1.0</cn></apply>'
        self.assertEqual(self.p(x), e)

        # Abs
        e = myokit.Abs(b)
        x = '<apply><abs/><cn>1.0</cn></apply>'
        self.assertEqual(self.p(x), e)

        # Quotient
        e = myokit.Quotient(a, b)
        x = '<apply><quotient/><ci>a</ci><cn>1.0</cn></apply>'
        self.assertEqual(self.p(x), e)

        # Remainder
        e = myokit.Remainder(a, b)
        x = '<apply><rem/><ci>a</ci><cn>1.0</cn></apply>'
        self.assertEqual(self.p(x), e)
Beispiel #5
0
 def _ex_quotient(self, e):
     return self.ex(myokit.Floor(myokit.Divide(e[0], e[1])))
Beispiel #6
0
 def _ex_quotient(self, e):
     # Note that this _must_ round towards minus infinity.
     # See myokit.Quotient.
     # Assuming it follows C and so we need a custom implementation.
     return self.ex(myokit.Floor(myokit.Divide(e[0], e[1])))
Beispiel #7
0
 def _ex_quotient(self, e, t):
     # CellML 1.0 subset doesn't contain quotient
     # Note that this _must_ round towards minus infinity!
     # See myokit.Quotient !
     return self.ex(myokit.Floor(myokit.Divide(e[0], e[1])), t)
Beispiel #8
0
 def _ex_quotient(self, e, t):
     # Note that this _must_ round towards minus infinity!
     # See myokit.Quotient !
     return self.ex(myokit.Floor(myokit.Divide(e[0], e[1])), t)
Beispiel #9
0
    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)
Beispiel #10
0
    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)
Beispiel #11
0
    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)
Beispiel #12
0
    def test_functions(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')

        # Power
        x = myokit.Power(a, b)
        self.assertEqual(ws.ex(x), 'pow(c.a, 12.0f)')
        self.assertEqual(wd.ex(x), 'pow(c.a, 12.0)')
        self.assertEqual(wn.ex(x), 'pow(c.a, 12.0f)')
        # 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)')
        self.assertEqual(wn.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))')
        self.assertEqual(wn.ex(x), '((c.a + 12.0f) * (c.a + 12.0f))')
        # Sqrt
        x = myokit.Sqrt(b)
        self.assertEqual(ws.ex(x), 'native_sqrt(12.0f)')
        self.assertEqual(wd.ex(x), 'native_sqrt(12.0)')
        self.assertEqual(wn.ex(x), 'sqrt(12.0f)')
        # Exp
        x = myokit.Exp(a)
        self.assertEqual(ws.ex(x), 'native_exp(c.a)')
        self.assertEqual(wd.ex(x), 'native_exp(c.a)')
        self.assertEqual(wn.ex(x), 'exp(c.a)')
        # Log(a)
        x = myokit.Log(b)
        self.assertEqual(ws.ex(x), 'native_log(12.0f)')
        self.assertEqual(wd.ex(x), 'native_log(12.0)')
        self.assertEqual(wn.ex(x), 'log(12.0f)')
        # Log(a, b)
        x = myokit.Log(a, b)
        self.assertEqual(ws.ex(x), '(native_log(c.a) / native_log(12.0f))')
        self.assertEqual(wd.ex(x), '(native_log(c.a) / native_log(12.0))')
        self.assertEqual(wn.ex(x), '(log(c.a) / log(12.0f))')
        # Log10
        x = myokit.Log10(b)
        self.assertEqual(ws.ex(x), 'native_log10(12.0f)')
        self.assertEqual(wd.ex(x), 'native_log10(12.0)')
        self.assertEqual(wn.ex(x), 'log10(12.0f)')

        # Sin
        x = myokit.Sin(b)
        self.assertEqual(ws.ex(x), 'native_sin(12.0f)')
        self.assertEqual(wd.ex(x), 'native_sin(12.0)')
        self.assertEqual(wn.ex(x), 'sin(12.0f)')
        # Cos
        x = myokit.Cos(b)
        self.assertEqual(ws.ex(x), 'native_cos(12.0f)')
        self.assertEqual(wd.ex(x), 'native_cos(12.0)')
        self.assertEqual(wn.ex(x), 'cos(12.0f)')
        # Tan
        x = myokit.Tan(b)
        self.assertEqual(ws.ex(x), 'native_tan(12.0f)')
        self.assertEqual(wd.ex(x), 'native_tan(12.0)')
        self.assertEqual(wn.ex(x), 'tan(12.0f)')
        # ASin
        x = myokit.ASin(b)
        self.assertEqual(ws.ex(x), 'asin(12.0f)')
        self.assertEqual(wd.ex(x), 'asin(12.0)')
        self.assertEqual(wn.ex(x), 'asin(12.0f)')
        # ACos
        x = myokit.ACos(b)
        self.assertEqual(ws.ex(x), 'acos(12.0f)')
        self.assertEqual(wd.ex(x), 'acos(12.0)')
        self.assertEqual(wn.ex(x), 'acos(12.0f)')
        # ATan
        x = myokit.ATan(b)
        self.assertEqual(ws.ex(x), 'atan(12.0f)')
        self.assertEqual(wd.ex(x), 'atan(12.0)')
        self.assertEqual(wn.ex(x), 'atan(12.0f)')

        # Floor
        x = myokit.Floor(b)
        self.assertEqual(ws.ex(x), 'floor(12.0f)')
        self.assertEqual(wd.ex(x), 'floor(12.0)')
        self.assertEqual(wn.ex(x), 'floor(12.0f)')
        # Ceil
        x = myokit.Ceil(b)
        self.assertEqual(ws.ex(x), 'ceil(12.0f)')
        self.assertEqual(wd.ex(x), 'ceil(12.0)')
        self.assertEqual(wn.ex(x), 'ceil(12.0f)')
        # Abs
        x = myokit.Abs(b)
        self.assertEqual(ws.ex(x), 'fabs(12.0f)')
        self.assertEqual(wd.ex(x), 'fabs(12.0)')
        self.assertEqual(wn.ex(x), 'fabs(12.0f)')
 def _ex_quotient(self, e):
     # Use floor to round towards minus infinity
     return self.ex(myokit.Floor(myokit.Divide(e[0], e[1])))
Beispiel #14
0
    def test_reader_writer(self):
        # Test using the proper reader/writer
        try:
            import sympy as sp
        except ImportError:
            print('Sympy not found, skipping test.')
            return

        # Create writer and reader
        w = mypy.SymPyExpressionWriter()
        r = mypy.SymPyExpressionReader(self._model)

        # Name
        a = self._a
        ca = sp.Symbol('c.a')
        self.assertEqual(w.ex(a), ca)
        self.assertEqual(r.ex(ca), a)

        # Number with unit
        b = myokit.Number('12', 'pF')
        cb = sp.Float(12)
        self.assertEqual(w.ex(b), cb)
        # Note: Units are lost in sympy im/ex-port!
        #self.assertEqual(r.ex(cb), b)

        # Number without unit
        b = myokit.Number('12')
        cb = sp.Float(12)
        self.assertEqual(w.ex(b), cb)
        self.assertEqual(r.ex(cb), b)

        # Prefix plus
        x = myokit.PrefixPlus(b)
        self.assertEqual(w.ex(x), cb)
        # Note: Sympy doesn't seem to have a prefix plus
        self.assertEqual(r.ex(cb), b)

        # Prefix minus
        # Note: SymPy treats -x as Mul(NegativeOne, x)
        # But for numbers just returns a number with a negative value
        x = myokit.PrefixMinus(b)
        self.assertEqual(w.ex(x), -cb)
        self.assertEqual(float(r.ex(-cb)), float(x))

        # Plus
        x = myokit.Plus(a, b)
        self.assertEqual(w.ex(x), ca + cb)
        # Note: SymPy likes to re-order the operands...
        self.assertEqual(float(r.ex(ca + cb)), float(x))

        # Minus
        x = myokit.Minus(a, b)
        self.assertEqual(w.ex(x), ca - cb)
        self.assertEqual(float(r.ex(ca - cb)), float(x))

        # Multiply
        x = myokit.Multiply(a, b)
        self.assertEqual(w.ex(x), ca * cb)
        self.assertEqual(float(r.ex(ca * cb)), float(x))

        # Divide
        x = myokit.Divide(a, b)
        self.assertEqual(w.ex(x), ca / cb)
        self.assertEqual(float(r.ex(ca / cb)), float(x))

        # Quotient
        x = myokit.Quotient(a, b)
        self.assertEqual(w.ex(x), ca // cb)
        self.assertEqual(float(r.ex(ca // cb)), float(x))

        # Remainder
        x = myokit.Remainder(a, b)
        self.assertEqual(w.ex(x), ca % cb)
        self.assertEqual(float(r.ex(ca % cb)), float(x))

        # Power
        x = myokit.Power(a, b)
        self.assertEqual(w.ex(x), ca**cb)
        self.assertEqual(float(r.ex(ca**cb)), float(x))

        # Sqrt
        x = myokit.Sqrt(a)
        cx = sp.sqrt(ca)
        self.assertEqual(w.ex(x), cx)
        # Note: SymPy converts sqrt to power
        self.assertEqual(float(r.ex(cx)), float(x))

        # Exp
        x = myokit.Exp(a)
        cx = sp.exp(ca)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # Log(a)
        x = myokit.Log(a)
        cx = sp.log(ca)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # Log(a, b)
        x = myokit.Log(a, b)
        cx = sp.log(ca, cb)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(float(r.ex(cx)), float(x))

        # Log10
        x = myokit.Log10(b)
        cx = sp.log(cb, 10)
        self.assertEqual(w.ex(x), cx)
        self.assertAlmostEqual(float(r.ex(cx)), float(x))

        # Sin
        x = myokit.Sin(a)
        cx = sp.sin(ca)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # Cos
        x = myokit.Cos(a)
        cx = sp.cos(ca)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # Tan
        x = myokit.Tan(a)
        cx = sp.tan(ca)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # ASin
        x = myokit.ASin(a)
        cx = sp.asin(ca)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # ACos
        x = myokit.ACos(a)
        cx = sp.acos(ca)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # ATan
        x = myokit.ATan(a)
        cx = sp.atan(ca)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # Floor
        x = myokit.Floor(a)
        cx = sp.floor(ca)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # Ceil
        x = myokit.Ceil(a)
        cx = sp.ceiling(ca)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # Abs
        x = myokit.Abs(a)
        cx = sp.Abs(ca)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # Equal
        x = myokit.Equal(a, b)
        cx = sp.Eq(ca, cb)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # NotEqual
        x = myokit.NotEqual(a, b)
        cx = sp.Ne(ca, cb)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # More
        x = myokit.More(a, b)
        cx = sp.Gt(ca, cb)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # Less
        x = myokit.Less(a, b)
        cx = sp.Lt(ca, cb)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # MoreEqual
        x = myokit.MoreEqual(a, b)
        cx = sp.Ge(ca, cb)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # LessEqual
        x = myokit.LessEqual(a, b)
        cx = sp.Le(ca, cb)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # Not
        x = myokit.Not(a)
        cx = sp.Not(ca)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # And
        cond1 = myokit.More(a, b)
        cond2 = myokit.Less(a, b)
        c1 = sp.Gt(ca, cb)
        c2 = sp.Lt(ca, cb)

        x = myokit.And(cond1, cond2)
        cx = sp.And(c1, c2)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # Or
        x = myokit.Or(cond1, cond2)
        cx = sp.Or(c1, c2)
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # If
        # Note: sympy only does piecewise, not if
        x = myokit.If(cond1, a, b)
        cx = sp.Piecewise((ca, c1), (cb, True))
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x.piecewise())

        # Piecewise
        c = myokit.Number(1)
        cc = sp.Float(1)
        x = myokit.Piecewise(cond1, a, cond2, b, c)
        cx = sp.Piecewise((ca, c1), (cb, c2), (cc, True))
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # Myokit piecewise's (like CellML's) always have a final True
        # condition (i.e. an 'else'). SymPy doesn't require this, so test if
        # we can import this --> It will add an "else 0"
        x = myokit.Piecewise(cond1, a, myokit.Number(0))
        cx = sp.Piecewise((ca, c1))
        self.assertEqual(r.ex(cx), x)

        # SymPy function without Myokit equivalent --> Should raise exception
        cu = sp.principal_branch(cx, cc)
        self.assertRaisesRegex(ValueError, 'Unsupported type', r.ex, cu)

        # Derivative
        m = self._model.clone()
        avar = m.get('c.a')
        r = mypy.SymPyExpressionReader(self._model)
        avar.promote(4)
        x = myokit.Derivative(self._a)
        cx = sp.symbols('dot(c.a)')
        self.assertEqual(w.ex(x), cx)
        self.assertEqual(r.ex(cx), x)

        # Equation
        e = myokit.Equation(a, b)
        ce = sp.Eq(ca, cb)
        self.assertEqual(w.eq(e), ce)
        # There's no backwards equivalent for this!
        # The ereader can handle it, but it becomes and Equals expression.

        # Test sympy division
        del (m, avar, x, cx, e, ce)
        a = self._model.get('c.a')
        b = self._model.get('c').add_variable('bbb')
        b.set_rhs('1 / a')
        e = b.rhs()
        ce = w.ex(b.rhs())
        e = r.ex(ce)
        self.assertEqual(
            e,
            myokit.Multiply(myokit.Number(1),
                            myokit.Power(myokit.Name(a), myokit.Number(-1))))

        # Test sympy negative numbers
        a = self._model.get('c.a')
        e1 = myokit.PrefixMinus(myokit.Name(a))
        ce = w.ex(e1)
        e2 = r.ex(ce)
        self.assertEqual(e1, e2)
Beispiel #15
0
    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)
Beispiel #16
0
 def _ex_floor(self, e):
     return myokit.Floor(self.ex(e.args[0]))
Beispiel #17
0
    def _parse_apply(self, apply_element):
        """
        Parses an ``<apply>`` element.
        """
        # Apply must have kids
        if len(apply_element) == 0:
            raise MathMLError('Apply must contain at least one child element.',
                              apply_element)

        # Get first child
        iterator = iter(apply_element)
        element = self._next(iterator)

        # Decide what to do based on first child
        _, name = split(element.tag)

        # Handle derivative
        if name == 'diff':
            return self._parse_derivative(element, iterator)

        # Algebra (unary/binary/n-ary operators)
        elif name == 'plus':
            return self._parse_nary(element, iterator, myokit.Plus,
                                    myokit.PrefixPlus)
        elif name == 'minus':
            return self._parse_nary(element, iterator, myokit.Minus,
                                    myokit.PrefixMinus)
        elif name == 'times':
            return self._parse_nary(element, iterator, myokit.Multiply)
        elif name == 'divide':
            return self._parse_nary(element, iterator, myokit.Divide)

        # Basic functions
        elif name == 'exp':
            return myokit.Exp(*self._eat(element, iterator))
        elif name == 'ln':
            return myokit.Log(*self._eat(element, iterator))
        elif name == 'log':
            return self._parse_log(element, iterator)
        elif name == 'root':
            return self._parse_root(element, iterator)
        elif name == 'power':
            return myokit.Power(*self._eat(element, iterator, 2))
        elif name == 'floor':
            return myokit.Floor(*self._eat(element, iterator))
        elif name == 'ceiling':
            return myokit.Ceil(*self._eat(element, iterator))
        elif name == 'abs':
            return myokit.Abs(*self._eat(element, iterator))
        elif name == 'quotient':
            return myokit.Quotient(*self._eat(element, iterator, 2))
        elif name == 'rem':
            return myokit.Remainder(*self._eat(element, iterator, 2))

        # Logic
        elif name == 'and':
            return self._parse_nary(element, iterator, myokit.And)
        elif name == 'or':
            return self._parse_nary(element, iterator, myokit.Or)
        elif name == 'xor':
            # Becomes ``(x or y) and not(x and y)``
            x, y = self._eat(element, iterator, 2)
            return myokit.And(myokit.Or(x, y), myokit.Not(myokit.And(x, y)))

        elif name == 'not':
            return myokit.Not(*self._eat(element, iterator))
        elif name == 'eq' or name == 'equivalent':
            return myokit.Equal(*self._eat(element, iterator, 2))
        elif name == 'neq':
            return myokit.NotEqual(*self._eat(element, iterator, 2))
        elif name == 'gt':
            return myokit.More(*self._eat(element, iterator, 2))
        elif name == 'lt':
            return myokit.Less(*self._eat(element, iterator, 2))
        elif name == 'geq':
            return myokit.MoreEqual(*self._eat(element, iterator, 2))
        elif name == 'leq':
            return myokit.LessEqual(*self._eat(element, iterator, 2))

        # Trigonometry
        elif name == 'sin':
            return myokit.Sin(*self._eat(element, iterator))
        elif name == 'cos':
            return myokit.Cos(*self._eat(element, iterator))
        elif name == 'tan':
            return myokit.Tan(*self._eat(element, iterator))
        elif name == 'arcsin':
            return myokit.ASin(*self._eat(element, iterator))
        elif name == 'arccos':
            return myokit.ACos(*self._eat(element, iterator))
        elif name == 'arctan':
            return myokit.ATan(*self._eat(element, iterator))

        # Redundant trigonometry (CellML includes this)
        elif name == 'csc':
            # Cosecant: csc(x) = 1 / sin(x)
            return myokit.Divide(self._const(1),
                                 myokit.Sin(*self._eat(element, iterator)))
        elif name == 'sec':
            # Secant: sec(x) = 1 / cos(x)
            return myokit.Divide(self._const(1),
                                 myokit.Cos(*self._eat(element, iterator)))
        elif name == 'cot':
            # Contangent: cot(x) = 1 / tan(x)
            return myokit.Divide(self._const(1),
                                 myokit.Tan(*self._eat(element, iterator)))
        elif name == 'arccsc':
            # ArcCosecant: acsc(x) = asin(1/x)
            return myokit.ASin(
                myokit.Divide(self._const(1), *self._eat(element, iterator)))
        elif name == 'arcsec':
            # ArcSecant: asec(x) = acos(1/x)
            return myokit.ACos(
                myokit.Divide(self._const(1), *self._eat(element, iterator)))
        elif name == 'arccot':
            # ArcCotangent: acot(x) = atan(1/x)
            return myokit.ATan(
                myokit.Divide(self._const(1), *self._eat(element, iterator)))

        # Hyperbolic trig
        elif name == 'sinh':
            # Hyperbolic sine: sinh(x) = 0.5 * (e^x - e^-x)
            x = self._eat(element, iterator)[0]
            return myokit.Multiply(
                self._const(0.5),
                myokit.Minus(myokit.Exp(x), myokit.Exp(myokit.PrefixMinus(x))))
        elif name == 'cosh':
            # Hyperbolic cosine: cosh(x) = 0.5 * (e^x + e^-x)
            x = self._eat(element, iterator)[0]
            return myokit.Multiply(
                self._const(0.5),
                myokit.Plus(myokit.Exp(x), myokit.Exp(myokit.PrefixMinus(x))))
        elif name == 'tanh':
            # Hyperbolic tangent: tanh(x) = (e^2x - 1) / (e^2x + 1)
            x = self._eat(element, iterator)[0]
            e2x = myokit.Exp(myokit.Multiply(self._const(2), x))
            return myokit.Divide(myokit.Minus(e2x, self._const(1)),
                                 myokit.Plus(e2x, self._const(1)))
        elif name == 'arcsinh':
            # Inverse hyperbolic sine: asinh(x) = log(x + sqrt(x*x + 1))
            x = self._eat(element, iterator)[0]
            return myokit.Log(
                myokit.Plus(
                    x,
                    myokit.Sqrt(
                        myokit.Plus(myokit.Multiply(x, x), self._const(1)))))
        elif name == 'arccosh':
            # Inverse hyperbolic cosine:
            #   acosh(x) = log(x + sqrt(x*x - 1))
            x = self._eat(element, iterator)[0]
            return myokit.Log(
                myokit.Plus(
                    x,
                    myokit.Sqrt(
                        myokit.Minus(myokit.Multiply(x, x), self._const(1)))))
        elif name == 'arctanh':
            # Inverse hyperbolic tangent:
            #   atanh(x) = 0.5 * log((1 + x) / (1 - x))
            x = self._eat(element, iterator)[0]
            return myokit.Multiply(
                self._const(0.5),
                myokit.Log(
                    myokit.Divide(myokit.Plus(self._const(1), x),
                                  myokit.Minus(self._const(1), x))))

        # Hyperbolic redundant trig
        elif name == 'csch':
            # Hyperbolic cosecant: csch(x) = 2 / (exp(x) - exp(-x))
            x = self._eat(element, iterator)[0]
            return myokit.Divide(
                self._const(2),
                myokit.Minus(myokit.Exp(x), myokit.Exp(myokit.PrefixMinus(x))))
        elif name == 'sech':
            # Hyperbolic secant: sech(x) = 2 / (exp(x) + exp(-x))
            x = self._eat(element, iterator)[0]
            return myokit.Divide(
                self._const(2),
                myokit.Plus(myokit.Exp(x), myokit.Exp(myokit.PrefixMinus(x))))
        elif name == 'coth':
            # Hyperbolic cotangent:
            #   coth(x) = (exp(2*x) + 1) / (exp(2*x) - 1)
            x = self._eat(element, iterator)[0]
            e2x = myokit.Exp(myokit.Multiply(self._const(2), x))
            return myokit.Divide(myokit.Plus(e2x, self._const(1)),
                                 myokit.Minus(e2x, self._const(1)))
        elif name == 'arccsch':
            # Inverse hyperbolic cosecant:
            #   arccsch(x) = log(1 / x + sqrt(1 / x^2 + 1))
            x = self._eat(element, iterator)[0]
            return myokit.Log(
                myokit.Plus(
                    myokit.Divide(self._const(1), x),
                    myokit.Sqrt(
                        myokit.Plus(
                            myokit.Divide(self._const(1),
                                          myokit.Multiply(x, x)),
                            self._const(1)))))
        elif name == 'arcsech':
            # Inverse hyperbolic secant:
            #   arcsech(x) = log(1 / x + sqrt(1 / x^2 - 1))
            x = self._eat(element, iterator)[0]
            return myokit.Log(
                myokit.Plus(
                    myokit.Divide(self._const(1), x),
                    myokit.Sqrt(
                        myokit.Minus(
                            myokit.Divide(self._const(1),
                                          myokit.Multiply(x, x)),
                            self._const(1)))))
        elif name == 'arccoth':
            # Inverse hyperbolic cotangent:
            #   arccoth(x) = 0.5 * log((x + 1) / (x - 1))
            x = self._eat(element, iterator)[0]
            return myokit.Multiply(
                self._const(0.5),
                myokit.Log(
                    myokit.Divide(myokit.Plus(x, self._const(1)),
                                  myokit.Minus(x, self._const(1)))))

        # Last option: A single atomic inside an apply
        # Do this one last to stop e.g. <apply><times /></apply> returning the
        # error 'Unsupported element' (which is what parse_atomic would call).
        elif len(apply_element) == 1:
            return self._parse_atomic(element)

        # Unexpected element
        else:
            raise MathMLError(
                'Unsupported element in apply: ' + str(element.tag) + '.',
                element)
Beispiel #18
0
    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 parsex(node):
        """
        Parses a mathml expression.
        """
        def chain(kind, node, unary=None):
            """
            Parses operands for chained operators (for example plus, minus,
            times and division).

            The argument ``kind`` must be the myokit expression type being
            parsed, ``node`` is a DOM node and ``unary``, if given, should be
            the unary expression type (unary Plus or unary Minus).
            """
            ops = []
            node = dom_next(node)
            while node:
                ops.append(parsex(node))
                node = dom_next(node)
            n = len(ops)
            if n < 1:
                raise MathMLError('Operator needs at least one operand.')
            if n < 2:
                if unary:
                    return unary(ops[0])
                else:
                    raise MathMLError('Operator needs at least two operands')
            ex = kind(ops[0], ops[1])
            for i in range(2, n):
                ex = kind(ex, ops[i])
            return ex

        # Start parsing
        name = node.tagName
        if name == 'apply':
            # Brackets, can be ignored in an expression tree.
            return parsex(dom_child(node))

        elif name == 'ci':
            # Reference
            var = str(node.firstChild.data).strip()
            if var_table is not None:
                try:
                    var = var_table[var]
                except KeyError:
                    if logger:
                        logger.warn('Unable to resolve reference to <' +
                                    str(var) + '>.')
            return myokit.Name(var)

        elif name == 'diff':
            # Derivative
            # Check time variable
            bvar = dom_next(node, 'bvar')
            if derivative_post_processor:
                derivative_post_processor(parsex(dom_child(bvar, 'ci')))

            # Check degree, if given
            d = dom_child(bvar, 'degree')
            if d is not None:
                d = parsex(dom_child(d, 'cn')).eval()
                if not d == 1:
                    raise MathMLError(
                        'Only derivatives of degree one are supported.')

            # Create derivative and return
            x = dom_next(node, 'ci')
            if x is None:
                raise MathMLError(
                    'Derivative of an expression found: only derivatives of'
                    ' variables are supported.')
            return myokit.Derivative(parsex(x))

        elif name == 'cn':
            # Number
            number = parse_mathml_number(node, logger)
            if number_post_processor:
                return number_post_processor(node, number)
            return number

        #
        # Algebra
        #

        elif name == 'plus':
            return chain(myokit.Plus, node, myokit.PrefixPlus)

        elif name == 'minus':
            return chain(myokit.Minus, node, myokit.PrefixMinus)

        elif name == 'times':
            return chain(myokit.Multiply, node)

        elif name == 'divide':
            return chain(myokit.Divide, node)

        #
        # Functions
        #

        elif name == 'exp':
            return myokit.Exp(parsex(dom_next(node)))

        elif name == 'ln':
            return myokit.Log(parsex(dom_next(node)))

        elif name == 'log':
            if dom_next(node).tagName != 'logbase':
                return myokit.Log10(parsex(dom_next(node)))
            else:
                return myokit.Log(parsex(dom_next(dom_next(node))),
                                  parsex(dom_child(dom_next(node))))

        elif name == 'root':
            # Check degree, if given
            nxt = dom_next(node)
            if nxt.tagName == 'degree':
                # Degree given, return x^(1/d) unless d is 2
                d = parsex(dom_child(nxt))
                x = parsex(dom_next(nxt))
                if d.is_literal() and d.eval() == 2:
                    return myokit.Sqrt(x)
                return myokit.Power(x, myokit.Divide(myokit.Number(1), d))
            else:
                return myokit.Sqrt(parsex(nxt))

        elif name == 'power':
            n2 = dom_next(node)
            return myokit.Power(parsex(n2), parsex(dom_next(n2)))

        elif name == 'floor':
            return myokit.Floor(parsex(dom_next(node)))

        elif name == 'ceiling':
            return myokit.Ceil(parsex(dom_next(node)))

        elif name == 'abs':
            return myokit.Abs(parsex(dom_next(node)))

        elif name == 'quotient':
            n2 = dom_next(node)
            return myokit.Quotient(parsex(n2), parsex(dom_next(n2)))

        elif name == 'rem':
            n2 = dom_next(node)
            return myokit.Remainder(parsex(n2), parsex(dom_next(n2)))

        #
        # Trigonometry
        #

        elif name == 'sin':
            return myokit.Sin(parsex(dom_next(node)))

        elif name == 'cos':
            return myokit.Cos(parsex(dom_next(node)))

        elif name == 'tan':
            return myokit.Tan(parsex(dom_next(node)))

        elif name == 'arcsin':
            return myokit.ASin(parsex(dom_next(node)))

        elif name == 'arccos':
            return myokit.ACos(parsex(dom_next(node)))

        elif name == 'arctan':
            return myokit.ATan(parsex(dom_next(node)))

        #
        # Redundant trigonometry (CellML includes this)
        #

        elif name == 'csc':
            # Cosecant: csc(x) = 1 / sin(x)
            return myokit.Divide(myokit.Number(1),
                                 myokit.Sin(parsex(dom_next(node))))

        elif name == 'sec':
            # Secant: sec(x) = 1 / cos(x)
            return myokit.Divide(myokit.Number(1),
                                 myokit.Cos(parsex(dom_next(node))))

        elif name == 'cot':
            # Contangent: cot(x) = 1 / tan(x)
            return myokit.Divide(myokit.Number(1),
                                 myokit.Tan(parsex(dom_next(node))))

        elif name == 'arccsc':
            # ArcCosecant: acsc(x) = asin(1/x)
            return myokit.ASin(
                myokit.Divide(myokit.Number(1), parsex(dom_next(node))))

        elif name == 'arcsec':
            # ArcSecant: asec(x) = acos(1/x)
            return myokit.ACos(
                myokit.Divide(myokit.Number(1), parsex(dom_next(node))))

        elif name == 'arccot':
            # ArcCotangent: acot(x) = atan(1/x)
            return myokit.ATan(
                myokit.Divide(myokit.Number(1), parsex(dom_next(node))))

        #
        # Hyperbolic trigonometry (CellML again)
        #

        elif name == 'sinh':
            # Hyperbolic sine: sinh(x) = 0.5 * (e^x - e^-x)
            x = parsex(dom_next(node))
            return myokit.Multiply(
                myokit.Number(0.5),
                myokit.Minus(myokit.Exp(x), myokit.Exp(myokit.PrefixMinus(x))))

        elif name == 'cosh':
            # Hyperbolic cosine: cosh(x) = 0.5 * (e^x + e^-x)
            x = parsex(dom_next(node))
            return myokit.Multiply(
                myokit.Number(0.5),
                myokit.Plus(myokit.Exp(x), myokit.Exp(myokit.PrefixMinus(x))))

        elif name == 'tanh':
            # Hyperbolic tangent: tanh(x) = (e^2x - 1) / (e^2x + 1)
            x = parsex(dom_next(node))
            e2x = myokit.Exp(myokit.Multiply(myokit.Number(2), x))
            return myokit.Divide(myokit.Minus(e2x, myokit.Number(1)),
                                 myokit.Plus(e2x, myokit.Number(1)))

        #
        # Inverse hyperbolic trigonometry (CellML...)
        #

        elif name == 'arcsinh':
            # Inverse hyperbolic sine: asinh(x) = log(x + sqrt(1 + x*x))
            x = parsex(dom_next(node))
            return myokit.Log(
                myokit.Plus(
                    x,
                    myokit.Sqrt(
                        myokit.Plus(myokit.Number(1), myokit.Multiply(x, x)))))

        elif name == 'arccosh':
            # Inverse hyperbolic cosine:
            #   acosh(x) = log(x + sqrt(x + 1) * sqrt(x - 1))
            x = parsex(dom_next(node))
            return myokit.Log(
                myokit.Plus(
                    x,
                    myokit.Multiply(
                        myokit.Sqrt(myokit.Plus(x, myokit.Number(1))),
                        myokit.Sqrt(myokit.Minus(x, myokit.Number(1))))))

        elif name == 'arctanh':
            # Inverse hyperbolic tangent:
            #   atanh(x) = 0.5 * (log(1 + x) - log(1 - x))
            x = parsex(dom_next(node))
            return myokit.Multiply(
                myokit.Number(0.5),
                myokit.Minus(myokit.Log(myokit.Plus(myokit.Number(1), x)),
                             myokit.Log(myokit.Minus(myokit.Number(1), x))))

        #
        # Hyperbolic redundant trigonometry (CellML...)
        #

        elif name == 'csch':
            # Hyperbolic cosecant: csch(x) = 2 / (exp(x) - exp(-x))
            x = parsex(dom_next(node))
            return myokit.Divide(
                myokit.Number(2),
                myokit.Minus(myokit.Exp(x), myokit.Exp(myokit.PrefixMinus(x))))

        elif name == 'sech':
            # Hyperbolic secant: sech(x) = 2 / (exp(x) + exp(-x))
            x = parsex(dom_next(node))
            return myokit.Divide(
                myokit.Number(2),
                myokit.Plus(myokit.Exp(x), myokit.Exp(myokit.PrefixMinus(x))))

        elif name == 'coth':
            # Hyperbolic cotangent:
            #   coth(x) = (exp(2*x) + 1) / (exp(2*x) - 1)
            x = parsex(dom_next(node))
            e2x = myokit.Exp(myokit.Multiply(myokit.Number(2), x))
            return myokit.Divide(myokit.Plus(e2x, myokit.Number(1)),
                                 myokit.Minus(e2x, myokit.Number(1)))

        #
        # Inverse hyperbolic redundant trigonometry (CellML has a lot to answer
        # for...)
        #

        elif name == 'arccsch':
            # Inverse hyperbolic cosecant:
            #   arccsch(x) = log(sqrt(1/(x*x) + 1) + 1/x)
            x = parsex(dom_next(node))
            return myokit.Log(
                myokit.Plus(
                    myokit.Sqrt(
                        myokit.Plus(
                            myokit.Divide(myokit.Number(1),
                                          myokit.Multiply(x, x)),
                            myokit.Number(1))),
                    myokit.Divide(myokit.Number(1), x)))
        elif name == 'arcsech':
            # Inverse hyperbolic secant:
            #   arcsech(x) = log(sqrt(1/(x*x) - 1) + 1/x)
            x = parsex(dom_next(node))
            return myokit.Log(
                myokit.Plus(
                    myokit.Sqrt(
                        myokit.Minus(
                            myokit.Divide(myokit.Number(1),
                                          myokit.Multiply(x, x)),
                            myokit.Number(1))),
                    myokit.Divide(myokit.Number(1), x)))
        elif name == 'arccoth':
            # Inverse hyperbolic cotangent:
            #   arccoth(x) = 0.5 * (log(3 + 1) - log(3 - 1))
            x = parsex(dom_next(node))
            return myokit.Multiply(
                myokit.Number(0.5),
                myokit.Log(
                    myokit.Divide(myokit.Plus(x, myokit.Number(1)),
                                  myokit.Minus(x, myokit.Number(1)))))

        #
        # Logic
        #

        elif name == 'and':
            return chain(myokit.And, node)

        elif name == 'or':
            return chain(myokit.Or, node)

        elif name == 'not':
            return chain(None, node, myokit.Not)

        elif name == 'eq' or name == 'equivalent':
            n2 = dom_next(node)
            return myokit.Equal(parsex(n2), parsex(dom_next(n2)))

        elif name == 'neq':
            n2 = dom_next(node)
            return myokit.NotEqual(parsex(n2), parsex(dom_next(n2)))

        elif name == 'gt':
            n2 = dom_next(node)
            return myokit.More(parsex(n2), parsex(dom_next(n2)))

        elif name == 'lt':
            n2 = dom_next(node)
            return myokit.Less(parsex(n2), parsex(dom_next(n2)))

        elif name == 'geq':
            n2 = dom_next(node)
            return myokit.MoreEqual(parsex(n2), parsex(dom_next(n2)))

        elif name == 'leq':
            n2 = dom_next(node)
            return myokit.LessEqual(parsex(n2), parsex(dom_next(n2)))

        elif name == 'piecewise':
            # Piecewise contains at least one piece, optionally contains an
            #  "otherwise". Syntax doesn't ensure this statement makes sense.
            conds = []
            funcs = []
            other = None
            piece = dom_child(node)
            while piece:
                if piece.tagName == 'otherwise':
                    if other is None:
                        other = parsex(dom_child(piece))
                    elif logger:
                        logger.warn(
                            'Multiple <otherwise> tags found in <piecewise>'
                            ' statement.')
                elif piece.tagName == 'piece':
                    n2 = dom_child(piece)
                    funcs.append(parsex(n2))
                    conds.append(parsex(dom_next(n2)))
                elif logger:
                    logger.warn('Unexpected tag type in <piecewise>: <' +
                                piece.tagName + '>.')
                piece = dom_next(piece)

            if other is None:
                if logger:
                    logger.warn('No <otherwise> tag found in <piecewise>')
                other = myokit.Number(0)

            # Create string of if statements
            args = []
            f = iter(funcs)
            for c in conds:
                args.append(c)
                args.append(next(f))
            args.append(other)
            return myokit.Piecewise(*args)

        #
        # Constants
        #

        elif name == 'pi':
            return myokit.Number('3.14159265358979323846')
        elif name == 'exponentiale':
            return myokit.Exp(myokit.Number(1))
        elif name == 'true':
            # This is corrent, even in Python True == 1 but not True == 2
            return myokit.Number(1)
        elif name == 'false':
            return myokit.Number(0)

        #
        # Unknown/unhandled elements
        #
        else:
            if logger:
                logger.warn('Unknown element: ' + name)
            ops = []
            node = dom_child(node) if dom_child(node) else dom_next(node)
            while node:
                ops.append(parsex(node))
                node = dom_next(node)
            return myokit.UnsupportedFunction(name, ops)
Beispiel #20
0
 def _ex_quotient(self, e):
     # Note that this _must_ round towards minus infinity.
     # See myokit.Quotient
     # CUDA docs are unclear on convention, so assuming it follows C and
     # so we need a custom implementation.
     return self.ex(myokit.Floor(myokit.Divide(e[0], e[1])))