Example #1
0
    def apply(self, z, evaluation):
        '%(name)s[z__]'

        args = z.get_sequence()

        if len(args) != self.nargs:
            return

        # if no arguments are inexact attempt to use sympy
        if all(not x.is_inexact() for x in args):
            result = Expression(self.get_name(), *args).to_sympy()
            result = self.prepare_mathics(result)
            result = from_sympy(result)
            # evaluate leaves to convert e.g. Plus[2, I] -> Complex[2, 1]
            result = result.evaluate_leaves(evaluation)
        else:
            prec = min_prec(*args)
            with mpmath.workprec(prec):
                mpmath_args = [sympy2mpmath(x.to_sympy()) for x in args]
                if None in mpmath_args:
                    return
                try:
                    result = self.eval(*mpmath_args)
                    result = from_sympy(mpmath2sympy(result, prec))
                except ValueError, exc:
                    text = str(exc)
                    if text == 'gamma function pole':
                        return Symbol('ComplexInfinity')
                    else:
                        raise
                except ZeroDivisionError:
                    return
                except SpecialValueError, exc:
                    return Symbol(exc.name)
Example #2
0
    def apply(self, z, evaluation):
        "%(name)s[z__]"

        args = z.get_sequence()

        if len(args) != self.nargs:
            return

        # if no arguments are inexact attempt to use sympy
        if len([True for x in args if Expression("InexactNumberQ", x).evaluate(evaluation).is_true()]) == 0:
            expr = Expression(self.get_name(), *args).to_sympy()
            result = from_sympy(expr)
            # evaluate leaves to convert e.g. Plus[2, I] -> Complex[2, 1]
            result = result.evaluate_leaves(evaluation)
        else:
            prec = min_prec(*args)
            with mpmath.workprec(prec):
                mpmath_args = [sympy2mpmath(x.to_sympy()) for x in args]
                if None in mpmath_args:
                    return
                try:
                    result = self.eval(*mpmath_args)
                    result = from_sympy(mpmath2sympy(result, prec))
                except ValueError, exc:
                    text = str(exc)
                    if text == "gamma function pole":
                        return Symbol("ComplexInfinity")
                    else:
                        raise
                except ZeroDivisionError:
                    return
                except SpecialValueError, exc:
                    return Symbol(exc.name)
Example #3
0
    def apply(self, r, i, evaluation):
        'Complex[r_?NumberQ, i_?NumberQ]'

        if isinstance(r, Complex) or isinstance(i, Complex):
            sym_form = r.to_sympy() + sympy.I * i.to_sympy()
            r, i = sym_form.simplify().as_real_imag()
            r, i = from_sympy(r), from_sympy(i)
        return Complex(r, i)
Example #4
0
    def apply(self, items, evaluation):
        'Times[items___]'

        #TODO: Clean this up and optimise it        

        items = items.numerify(evaluation).get_sequence()
        number = (sympy.Integer(1), sympy.Integer(0))
        leaves = []

        prec = min_prec(*items)
        is_real = all([not isinstance(i, Complex) for i in items])

        for item in items:
            if isinstance(item, Number):
                if isinstance(item, Complex):
                    sym_real, sym_imag = item.real.to_sympy(), item.imag.to_sympy()
                else:
                    sym_real, sym_imag = item.to_sympy(), sympy.Integer(0)

                if prec is not None:
                    sym_real = sym_real.n(dps(prec))
                    sym_imag = sym_imag.n(dps(prec))

                if sym_real.is_zero and sym_imag.is_zero and prec is None:
                    return Integer('0')
                number = (number[0]*sym_real - number[1]*sym_imag, number[0]*sym_imag + number[1]*sym_real)
            elif leaves and item == leaves[-1]:
                leaves[-1] = Expression('Power', leaves[-1], Integer(2))
            elif leaves and item.has_form('Power', 2) and leaves[-1].has_form('Power', 2) and item.leaves[0].same(leaves[-1].leaves[0]):
                leaves[-1].leaves[1] = Expression('Plus', item.leaves[1], leaves[-1].leaves[1])
            elif leaves and item.has_form('Power', 2) and item.leaves[0].same(leaves[-1]):
                leaves[-1] = Expression('Power', leaves[-1], Expression('Plus', item.leaves[1], Integer(1)))
            elif leaves and leaves[-1].has_form('Power', 2) and leaves[-1].leaves[0].same(item):
                leaves[-1] = Expression('Power', item, Expression('Plus', Integer(1), leaves[-1].leaves[1]))
            else:
                leaves.append(item)
        if number == (1, 0):
            number = None
        elif number == (-1, 0) and leaves and leaves[0].has_form('Plus', None):
            leaves[0].leaves = [Expression('Times', Integer(-1), leaf) for leaf in leaves[0].leaves]
            number = None

        if number is not None:
            if number[1].is_zero and is_real:
                leaves.insert(0, Number.from_mp(number[0], prec))
            elif number[1].is_zero and number[1].is_Integer and prec is None:
                leaves.insert(0, Number.from_mp(number[0], prec))
            else:
                leaves.insert(0, Complex(from_sympy(number[0]), from_sympy(number[1]), prec))

        if not leaves:
            return Integer(1)
        elif len(leaves) == 1:
            return leaves[0]
        else:
            return Expression('Times', *leaves)
Example #5
0
    def apply(self, m, evaluation):
        'QRDecomposition[m_?MatrixQ]'

        matrix = to_sympy_matrix(m)
        try:
            Q, R = matrix.QRdecomposition()
        except sympy.matrices.MatrixError:
            return evaluation.message('QRDecomposition', 'sympy')
        Q = Q.transpose()
        return Expression('List', *[from_sympy(Q), from_sympy(R)])
Example #6
0
 def append_last():
     if last_item is not None:
         if last_count == 1:
             leaves.append(last_item)
         else:
             if last_item.has_form('Times', None):
                 last_item.leaves.insert(0, from_sympy(last_count))
                 leaves.append(last_item)
             else:
                 leaves.append(Expression(
                     'Times', from_sympy(last_count), last_item))
Example #7
0
    def apply(self, m, l, evaluation):
        'Norm[m_, l_]'

        if isinstance(l, Symbol):
            pass
        elif isinstance(l, (Real, Integer)) and l.to_python() >= 1:
            pass
        else:
            return evaluation.message('Norm', 'ptype', l)

        l = l.to_sympy()
        if l is None:
            return
        matrix = to_sympy_matrix(m)

        if matrix is None:
            return evaluation.message('Norm', 'nvm')
        if len(matrix) == 0:
            return

        try:
            res = matrix.norm(l)
        except NotImplementedError:
            return evaluation.message('Norm', 'normnotimplemented')

        return from_sympy(res)
Example #8
0
 def apply(self, items, evaluation):
     'Piecewise[items__]'
     result = self.to_sympy(Expression('Piecewise', *items.get_sequence()))
     if result is None:
         return
     if not isinstance(result, sympy.Piecewise):
         return from_sympy(result)
Example #9
0
    def apply(self, expr, evaluation):
        'Variables[expr_]'

        variables = set()

        def find_vars(e):
            if e.to_sympy().is_constant():
                return
            elif e.is_symbol():
                variables.add(e)
            elif (e.has_form('Plus', None) or
                  e.has_form('Times', None)):
                for l in e.leaves:
                    find_vars(l)
            elif e.has_form('Power', 2):
                (a, b) = e.leaves  # a^b
                if not(a.to_sympy().is_constant()) and b.to_sympy().is_rational:
                    find_vars(a)
            elif not(e.is_atom()):
                variables.add(e)

        exprs = expr.leaves if expr.has_form('List', None) else [expr]
        for e in exprs:
            find_vars(from_sympy(e.to_sympy().expand()))

        variables = Expression('List', *variables)
        variables.sort()        # MMA doesn't do this
        return variables
Example #10
0
    def apply(self, expr, x, x0, evaluation, options={}):
        'Limit[expr_, x_->x0_, OptionsPattern[Limit]]'

        expr = expr.to_sympy()
        x = x.to_sympy()
        x0 = x0.to_sympy()

        if expr is None or x is None or x0 is None:
            return

        direction = self.get_option(options, 'Direction', evaluation)
        value = direction.get_int_value()
        if value not in (-1, 1):
            evaluation.message('Limit', 'ldir', direction)
        if value > 0:
            dir_sympy = '-'
        else:
            dir_sympy = '+'

        try:
            result = sympy.limit(expr, x, x0, dir_sympy)
        except sympy.PoleError:
            pass
        except RuntimeError:
            # Bug in Sympy: RuntimeError: maximum recursion depth exceeded
            # while calling a Python object
            pass
        except NotImplementedError:
            pass
        except TypeError:
            # Unknown SymPy0.7.6 bug
            pass
        else:
            return from_sympy(result)
Example #11
0
    def apply(self, m, b, evaluation):
        'LinearSolve[m_, b_]'

        matrix = matrix_data(m)
        if matrix is None:
            return
        if not b.has_form('List', None):
            return
        if len(b.leaves) != len(matrix):
            return evaluation.message('LinearSolve', 'lslc')
        system = [mm + [v] for mm, v in zip(matrix, b.leaves)]
        system = to_sympy_matrix(system)
        if system is None:
            return
        syms = [sympy.Dummy('LinearSolve_var%d' % k)
                for k in range(system.cols - 1)]
        sol = sympy.solve_linear_system(system, *syms)
        if sol:
            # substitute 0 for variables that are not in result dictionary
            free_vars = dict((sym, sympy.Integer(
                0)) for sym in syms if sym not in sol)
            sol.update(free_vars)
            sol = [(sol[sym] if sym in free_vars else sol[sym].subs(free_vars))
                   for sym in syms]
            return from_sympy(sol)
        else:
            return evaluation.message('LinearSolve', 'nosol')
Example #12
0
    def apply(self, m, evaluation):
        'Eigenvectors[m_]'

        matrix = to_sympy_matrix(m)
        if matrix is None or matrix.cols != matrix.rows or matrix.cols == 0:
            return evaluation.message('Eigenvectors', 'matsq', m)
        # sympy raises an error for some matrices that Mathematica can compute.
        try:
            eigenvects = matrix.eigenvects()
        except NotImplementedError:
            return evaluation.message(
                'Eigenvectors', 'eigenvecnotimplemented', m)

        # The eigenvectors are given in the same order as the eigenvalues.
        eigenvects = sorted(eigenvects, key=lambda (
            val, c, vect): (abs(val), -val), reverse=True)
        result = []
        for val, count, basis in eigenvects:
            # Select the i'th basis vector, convert matrix to vector,
            # and convert from sympy
            vects = [from_sympy(list(b)) for b in basis]

            # This follows Mathematica convention better; higher indexed pivots
            # are outputted first. e.g. {{0,1},{1,0}} instead of {{1,0},{0,1}}
            vects.reverse()

            # Add the vectors to results
            result.extend(vects)
        result.extend([Expression('List', *(
            [0] * matrix.rows))] * (matrix.rows - len(result)))
        return Expression('List', *result)
Example #13
0
    def apply(self, x, evaluation):
        'Rationalize[x_]'

        py_x = x.to_sympy()
        if py_x is None or (not py_x.is_number) or (not py_x.is_real):
            return x
        return from_sympy(self.find_approximant(py_x))
Example #14
0
    def apply(self, expr, evaluation):
        'Denominator[expr_]'

        sympy_expr = expr.to_sympy()
        if sympy_expr is None:
            return None
        numer, denom = sympy_expr.as_numer_denom()
        return from_sympy(denom)
Example #15
0
    def apply(self, expr, evaluation):
        'Simplify[expr_]'

        sympy_expr = expr.to_sympy()
        if sympy_expr is None:
            return
        sympy_result = sympy.simplify(sympy_expr)
        return from_sympy(sympy_result)
Example #16
0
 def apply_exact(self, z, evaluation):
     '%(name)s[z_?ExactNumberQ]'
     
     expr = Expression(self.get_name(), z).to_sympy()
     result = from_sympy(expr)
     # evaluate leaves to convert e.g. Plus[2, I] -> Complex[2, 1]
     result = result.evaluate_leaves(evaluation)
     return result
Example #17
0
    def apply(self, m, evaluation):
        'Det[m_]'

        matrix = to_sympy_matrix(m)
        if matrix is None or matrix.cols != matrix.rows or matrix.cols == 0:
            return evaluation.message('Det', 'matsq', m)
        det = matrix.det()
        return from_sympy(det)
Example #18
0
 def apply(self, m, evaluation):
     'MatrixExp[m_]'
     sympy_m = to_sympy_matrix(m)
     try:
         res = sympy_m.exp()
     except NotImplementedError:
         return evaluation.message('MatrixExp', 'matrixexpnotimplemented', m)
     return from_sympy(res)
Example #19
0
    def apply(self, expr, evaluation):
        'Together[expr_]'

        expr_sympy = expr.to_sympy()
        result = sympy.together(expr_sympy)
        result = from_sympy(result)
        result = cancel(result)
        return result
Example #20
0
 def apply(self, m, power, evaluation):
     'MatrixPower[m_, power_]'
     sympy_m = to_sympy_matrix(m)
     try:
         res = sympy_m ** power.to_sympy()
     except NotImplementedError:
         return evaluation.message('MatrixPower', 'matrixpowernotimplemented', m)
     return from_sympy(res)
Example #21
0
 def apply(self, m, evaluation):
     'Inverse[m_]'
     
     matrix = to_sympy_matrix(m)
     if matrix is None or matrix.cols != matrix.rows or matrix.cols == 0:
         return evaluation.message('Inverse', 'matsq', m)
     inv = matrix.inv()
     return from_sympy(inv)
Example #22
0
    def apply(self, m, evaluation):
        'RowReduce[m_]'

        matrix = to_sympy_matrix(m)
        if matrix is None:
            return
        reduced = matrix.rref()[0]
        return from_sympy(reduced)
Example #23
0
 def apply(self, m, evaluation):
     'Tr[m_]'
     
     matrix = to_sympy_matrix(m)
     if matrix is None or matrix.cols != matrix.rows or matrix.cols == 0:
         return evaluation.message('Tr', 'matsq', m)
     tr = matrix.trace()
     return from_sympy(tr)
Example #24
0
    def apply(self, m, evaluation):
        'PseudoInverse[m_]'

        matrix = to_sympy_matrix(m)
        if matrix is None:
            return evaluation.message('PseudoInverse', 'matrix', m, 1)
        pinv = matrix.pinv()
        return from_sympy(pinv)
Example #25
0
 def apply(self, a, b, evaluation):
     'Cross[a_, b_]'
     a = to_sympy_matrix(a)
     b = to_sympy_matrix(b)
     try:
         res = a.cross(b)
     except sympy.ShapeError:
         return evaluation.message('Cross', 'nonn1')
     return from_sympy(res)
Example #26
0
    def apply_N(self, k, precision, evaluation):
        'N[AiryBiZero[k_Integer], precision_]'

        prec = get_precision(precision, evaluation)
        k_int = k.get_int_value()

        with mpmath.workprec(prec):
            result = mpmath2sympy(mpmath.airybizero(k_int), prec)
        return from_sympy(result)
Example #27
0
    def apply(self, m, evaluation):
        'NullSpace[m_]'

        matrix = to_sympy_matrix(m)
        if matrix is None:
            return
        nullspace = matrix.nullspace()
        # convert n x 1 matrices to vectors
        nullspace = [list(vec) for vec in nullspace]
        return from_sympy(nullspace)
Example #28
0
    def apply(self, m, b, evaluation):
        'LeastSquares[m_, b_]'

        matrix = to_sympy_matrix(m)
        b_vector = to_sympy_matrix([el.to_sympy() for el in b.leaves])

        try:
            solution = matrix.solve_least_squares(b_vector)  # default method = Cholesky
        except NotImplementedError as e:
            return evaluation.message('LeastSquares', 'underdetermined')

        return from_sympy(solution)
Example #29
0
    def apply(self, expr, var, evaluation):
        'Apart[expr_, var_Symbol]'

        expr_sympy = expr.to_sympy()
        var_sympy = var.to_sympy()
        try:
            result = sympy.apart(expr_sympy, var_sympy)
            result = from_sympy(result)
            return result
        except sympy.PolynomialError:
            # raised e.g. for apart(sin(1/(x**2-y**2)))
            return expr
Example #30
0
 def apply(self, m, evaluation):
     'Eigenvalues[m_]'
     
     matrix = to_sympy_matrix(m)
     if matrix is None or matrix.cols != matrix.rows or matrix.cols == 0:
         return evaluation.message('Eigenvalues', 'matsq', m)
     eigenvalues = matrix.eigenvals()
     eigenvalues = sorted(eigenvalues.iteritems(), key=lambda (v, c): abs(v), reverse=True)
     result = []
     for val, count in eigenvalues:
         result.extend([val] * count)
     return from_sympy(result)
Example #31
0
    def apply(self, expr, var, evaluation):
        "Apart[expr_, var_Symbol]"

        expr_sympy = expr.to_sympy()
        var_sympy = var.to_sympy()
        if expr_sympy is None or var_sympy is None:
            return None

        try:
            result = sympy.apart(expr_sympy, var_sympy)
            result = from_sympy(result)
            return result
        except sympy.PolynomialError:
            # raised e.g. for apart(sin(1/(x**2-y**2)))
            return expr
Example #32
0
    def apply(self, expr, evaluation):
        'Simplify[expr_]'

        expr_sympy = expr.to_sympy()
        result = expr_sympy
        try:
            result = sympy.simplify(result)
        except TypeError:
            # XXX What's going on here?
            pass
        result = sympy.trigsimp(result)
        result = sympy.together(result)
        result = sympy.cancel(result)
        result = from_sympy(result)
        return result
Example #33
0
    def apply(self, polys, xlist, alist, evaluation):
        'ClassicalDixonResultant[polys_, xlist_,alist_]'
        ####this is not written in a wrapper function as it is not used anywhere else

        res = DixonMatrix_apply(polys, xlist, alist)
        if isinstance(res, String):
            return res
        if res.to_sympy() == sympy.sympify(0):
            return res
        rsym = res.leaves
        dixon_list = [j.leaves for j in rsym]

        dixon_sym = [[j.to_sympy() for j in i] for i in dixon_list]
        dix_mat = sympy.Matrix(dixon_sym)
        return from_sympy(sympy.det(dix_mat))
Example #34
0
    def apply(self, z, evaluation):
        '%(name)s[z__]'

        args = z.get_sequence()

        if not self.check_nargs(len(args)):
            return

        # if no arguments are inexact attempt to use sympy
        if all(not x.is_inexact() for x in args):
            result = Expression(self.get_name(), *args).to_sympy()
            result = self.prepare_mathics(result)
            result = from_sympy(result)
            # evaluate leaves to convert e.g. Plus[2, I] -> Complex[2, 1]
            result = result.evaluate_leaves(evaluation)
        else:
            prec = min_prec(*args)
            with mpmath.workprec(prec):
                mpmath_args = [sympy2mpmath(x.to_sympy()) for x in args]
                if None in mpmath_args:
                    return
                try:
                    result = self.eval(*mpmath_args)
                    result = from_sympy(mpmath2sympy(result, prec))
                except ValueError as exc:
                    text = str(exc)
                    if text == 'gamma function pole':
                        return Symbol('ComplexInfinity')
                    else:
                        raise
                except ZeroDivisionError:
                    return
                except SpecialValueError as exc:
                    return Symbol(exc.name)

        return result
Example #35
0
    def apply(self, m, power, evaluation):
        'MatrixPower[m_, power_]'
        sympy_m = to_sympy_matrix(m)
        if sympy_m is None:
            return evaluation.message('MatrixPower', 'matrix', m, 1)

        sympy_power = power.to_sympy()
        if sympy_power is None:
            return

        try:
            res = sympy_m ** sympy_power
        except NotImplementedError:
            return evaluation.message('MatrixPower', 'matrixpowernotimplemented', m)
        return from_sympy(res)
Example #36
0
    def apply_constraints(self, f, vars, evaluation):
        'Maximize[f_?ListQ, vars_]'

        constraints = [function for function in f.leaves]
        constraints[0] = from_sympy(constraints[0].to_sympy() * -1)

        dual_solutions = Expression('Minimize', constraints,
                                    vars).evaluate(evaluation).leaves

        solutions = []
        for dual_solution in dual_solutions:
            solution_leaves = dual_solution.leaves
            solutions.append([solution_leaves[0] * -1, solution_leaves[1]])

        return from_python(solutions)
Example #37
0
    def apply(self, m, evaluation):
        'Eigenvalues[m_]'

        matrix = to_sympy_matrix(m)
        if matrix is None or matrix.cols != matrix.rows or matrix.cols == 0:
            return evaluation.message('Eigenvalues', 'matsq', m)
        eigenvalues = matrix.eigenvals()
        try:
            eigenvalues = sorted(eigenvalues.iteritems(),
                                 key=lambda (v, c): (abs(v), -v), reverse=True)
        except TypeError as e:
            if not str(e).startswith('cannot determine truth value of'):
                raise e
            eigenvalues = eigenvalues.items()
        return from_sympy([v for (v, c) in eigenvalues for _ in xrange(c)])
Example #38
0
    def apply(self, z, evaluation):
        '%(name)s[z__]'

        args = z.get_sequence()

        if len(args) != self.nargs:
            return

        # if no arguments are inexact attempt to use sympy
        if len([
                True for x in args if Expression('InexactNumberQ', x).evaluate(
                    evaluation).is_true()
        ]) == 0:
            expr = Expression(self.get_name(), *args).to_sympy()
            result = from_sympy(expr)
            # evaluate leaves to convert e.g. Plus[2, I] -> Complex[2, 1]
            result = result.evaluate_leaves(evaluation)
        else:
            prec = min_prec(*args)
            with mpmath.workprec(prec):
                mpmath_args = [sympy2mpmath(x.to_sympy()) for x in args]
                if None in mpmath_args:
                    return
                try:
                    result = self.eval(*mpmath_args)
                    result = from_sympy(mpmath2sympy(result, prec))
                except ValueError, exc:
                    text = str(exc)
                    if text == 'gamma function pole':
                        return Symbol('ComplexInfinity')
                    else:
                        raise
                except ZeroDivisionError:
                    return
                except SpecialValueError, exc:
                    return Symbol(exc.name)
Example #39
0
def cancel(expr):
    if expr.has_form('Plus', None):
        return Expression('Plus', *[cancel(leaf) for leaf in expr.leaves])
    else:
        try:
            result = expr.to_sympy()
            # result = sympy.powsimp(result, deep=True)
            result = sympy.cancel(result)

            # cancel factors out rationals, so we factor them again
            result = sympy_factor(result)

            return from_sympy(result)
        except sympy.PolynomialError:
            # e.g. for non-commutative expressions
            return expr
Example #40
0
 def apply_list(self, expr, vars, evaluation):
     'FactorTermsList[expr_, vars_List]'
     if expr == Integer(0):
         return Expression('List', Integer(1), Integer(0))
     elif isinstance(expr, Number):
         return Expression('List', expr, Integer(1))
     
     for x in vars.leaves:
         if not(isinstance(x, Atom)):
             return evaluation.message('CoefficientList', 'ivar', x)
     
     sympy_expr = expr.to_sympy()
     if sympy_expr is None:
         return Expression('List', Integer(1), expr)
     sympy_expr = sympy.together(sympy_expr)
     
     sympy_vars = [x.to_sympy() for x in vars.leaves if isinstance(x, Symbol) and sympy_expr.is_polynomial(x.to_sympy())]
     
     result = []
     numer, denom = sympy_expr.as_numer_denom()
     try:
         from sympy import factor, factor_list, Poly
         if denom == 1:
             # Get numerical part
             num_coeff, num_polys = factor_list(Poly(numer))
             result.append(num_coeff)
             
             # Get factors are independent of sub list of variables
             if (sympy_vars and isinstance(expr, Expression) 
                 and any(x.free_symbols.issubset(sympy_expr.free_symbols) for x in sympy_vars)):
                 for i in reversed(range(len(sympy_vars))):
                     numer = factor(numer) / factor(num_coeff)
                     num_coeff, num_polys = factor_list(Poly(numer), *[x for x in sympy_vars[:(i+1)]])
                     result.append(sympy.expand(num_coeff))
             
             # Last factor
             numer = factor(numer) / factor(num_coeff)
             result.append(sympy.expand(numer))
         else:
             num_coeff, num_polys = factor_list(Poly(numer))
             den_coeff, den_polys = factor_list(Poly(denom))
             result = [num_coeff / den_coeff, sympy.expand(factor(numer)/num_coeff / (factor(denom)/den_coeff))]
     except sympy.PolynomialError: # MMA does not raise error for non poly
         result.append(sympy.expand(numer))
         # evaluation.message(self.get_name(), 'poly', expr)
     
     return Expression('List', *[from_sympy(i) for i in result])
Example #41
0
    def apply(self, f, xs, evaluation):
        'Integrate[f_, xs__]'

        f_sympy = f.to_sympy()
        if isinstance(f_sympy, SympyExpression):
            return
        xs = xs.get_sequence()
        vars = []
        prec = None
        for x in xs:
            if x.has_form('List', 3):
                x, a, b = x.leaves
                prec_a = a.get_precision()
                prec_b = b.get_precision()
                if prec_a is not None and prec_b is not None:
                    prec_new = min(prec_a, prec_b)
                    if prec is None or prec_new < prec:
                        prec = prec_new
                a = a.to_sympy()
                b = b.to_sympy()
            else:
                a = b = None
                a_mathics, b_mathics = a, b
            if not x.get_name():
                evaluation.message('Integrate', 'ilim')
                return
            x = x.to_sympy()
            if a is None or b is None:
                vars.append(x)
            else:
                vars.append((x, a, b))
        try:
            result = sympy.integrate(f_sympy, *vars)
        except sympy.PolynomialError:
            return
        except ValueError:
            # e.g. ValueError: can't raise polynomial to a negative power
            return
        except NotImplementedError:
            # e.g. NotImplementedError: Result depends on the sign of
            # -sign(_Mathics_User_j)*sign(_Mathics_User_w)
            return

        if prec is not None:
            result = sympy.N(result)
        result = from_sympy(result)
        return result
Example #42
0
    def apply_iter(self, expr, i, imin, imax, di, evaluation):
        '%(name)s[expr_, {i_Symbol, imin_, imax_, di_}]'

        if isinstance(self, SympyFunction) and di.get_int_value() == 1:
            whole_expr = Expression(self.get_name(), expr,
                                    Expression('List', i, imin, imax))
            sympy_expr = whole_expr.to_sympy()

            # apply Together to produce results similar to Mathematica
            result = sympy.together(sympy_expr)
            result = from_sympy(result)
            result = cancel(result)

            if not result.same(whole_expr):
                return result

        index = imin.evaluate(evaluation)
        imax = imax.evaluate(evaluation)
        di = di.evaluate(evaluation)

        result = []
        while True:
            cont = Expression('LessEqual', index, imax).evaluate(evaluation)
            if cont == Symbol('False'):
                break
            if cont != Symbol('True'):
                if self.throw_iterb:
                    evaluation.message(self.get_name(), 'iterb')
                return

            evaluation.check_stopped()
            try:
                item = dynamic_scoping(expr.evaluate, {i.name: index},
                                       evaluation)
                result.append(item)
            except ContinueInterrupt:
                if self.allow_loopcontrol:
                    pass
                else:
                    raise
            except BreakInterrupt:
                if self.allow_loopcontrol:
                    break
                else:
                    raise
            index = Expression('Plus', index, di).evaluate(evaluation)
        return self.get_result(result)
Example #43
0
    def apply(self, expr, evaluation):
        'Factor[expr_]'

        expr_sympy = expr.to_sympy()
        if expr_sympy is None:
            return None

        try:
            result = sympy.together(expr_sympy)
            numer, denom = result.as_numer_denom()
            if denom == 1:
                result = sympy.factor(expr_sympy)
            else:
                result = sympy.factor(numer) / sympy.factor(denom)
        except sympy.PolynomialError:
            return expr
        return from_sympy(result)
Example #44
0
 def apply(self, m, evaluation):
     'Eigenvectors[m_]'
     
     matrix = to_sympy_matrix(m)
     if matrix is None or matrix.cols != matrix.rows or matrix.cols == 0:
         return evaluation.message('Eigenvectors', 'matsq', m)
     eigenvects = matrix.eigenvects()
     eigenvects = sorted(eigenvects, key=lambda (val, c, vect): abs(val), reverse=True)
     result = []
     for val, count, basis in eigenvects:
         vect = basis[0] # select first basis vector
         vect = list(vect)   # convert matrix to vector (list)
         vect = from_sympy(vect)
         result.append(vect)
     result.extend([Expression('List', *([0] * matrix.rows))] * (matrix.rows - len(result)))
     return Expression('List', *result)
     
Example #45
0
    def apply(self, m, b, evaluation):
        'LeastSquares[m_, b_]'

        matrix = to_sympy_matrix(m)
        if matrix is None:
            return evaluation.message('LeastSquares', 'matrix', m, 1)

        b_vector = to_sympy_matrix(b)
        if b_vector is None:
            return evaluation.message('LeastSquares', 'matrix', b, 2)

        try:
            solution = matrix.solve_least_squares(b_vector)  # default method = Cholesky
        except NotImplementedError as e:
            return evaluation.message('LeastSquares', 'underdetermined')

        return from_sympy(solution)
Example #46
0
    def apply_iter(self, expr, i, imin, imax, di, evaluation):
        '%(name)s[expr_, {i_Symbol, imin_, imax_, di_}]'

        if di.get_int_value() == 1 and isinstance(self, SympyFunction):
            whole_expr = Expression(self.get_name(), expr,
                                    Expression('List', i, imin, imax))
            sympy_expr = whole_expr.to_sympy()

            # apply Together to produce results similar to Mathematica
            result = sympy.together(sympy_expr)
            result = from_sympy(result)
            result = cancel(result)

            if not result.same(whole_expr):
                return result

        index = imin.evaluate(evaluation).get_real_value()
        imax = imax.evaluate(evaluation).get_real_value()
        di = di.evaluate(evaluation).get_real_value()

        if index is None or imax is None or di is None:
            if self.throw_iterb:
                evaluation.message(self.get_name(), 'iterb')
            return

        result = []
        while index <= imax:
            evaluation.check_stopped()
            try:
                item = dynamic_scoping(expr.evaluate,
                                       {i.name: Number.from_mp(index)},
                                       evaluation)
                result.append(item)
            except ContinueInterrupt:
                if self.allow_loopcontrol:
                    pass
                else:
                    raise
            except BreakInterrupt:
                if self.allow_loopcontrol:
                    break
                else:
                    raise
            index = index + di
        return self.get_result(result)
Example #47
0
 def apply_dx(self, x, dx, evaluation):
     "Rationalize[x_, dx_]"
     py_x = x.to_sympy()
     if py_x is None:
         return x
     py_dx = dx.to_sympy()
     if (
         py_dx is None
         or (not py_dx.is_number)
         or (not py_dx.is_real)
         or py_dx.is_negative
     ):
         return evaluation.message("Rationalize", "tolnn", dx)
     elif py_dx == 0:
         return from_sympy(self.find_exact(py_x))
     a = self.approx_interval_continued_fraction(py_x - py_dx, py_x + py_dx)
     sym_x = sympy.ntheory.continued_fraction_reduce(a)
     return Rational(sym_x)
Example #48
0
    def apply(self, m, power, evaluation):
        "MatrixPower[m_, power_]"
        sympy_m = to_sympy_matrix(m)
        if sympy_m is None:
            return evaluation.message("MatrixPower", "matrix", m, 1)

        sympy_power = power.to_sympy()
        if sympy_power is None:
            return

        try:
            res = sympy_m**sympy_power
        except NotImplementedError:
            return evaluation.message("MatrixPower",
                                      "matrixpowernotimplemented", m)
        except ValueError as e:
            return evaluation.message("MatrixPower",
                                      "matrixpowernotinvertible", m)
        return from_sympy(res)
Example #49
0
def _coefficient(name, expr, form, n, evaluation):
    if expr == Symbol('Null') or form == Symbol('Null') or n == Symbol('Null'):
        return Integer(0)
    
    if not(isinstance(form, Symbol)) and not(isinstance(form, Expression)):
        return evaluation.message(name, 'ivar', form)
    
    sympy_exprs = expr.to_sympy().as_ordered_terms()
    sympy_var = form.to_sympy()
    sympy_n = n.to_sympy()
    
    def combine_exprs(exprs):
        result = 0
        for e in exprs:
            result += e
        return result
    
    # expand sub expressions if they contain variables
    sympy_exprs = [sympy.expand(e) if sympy_var.free_symbols.issubset(e.free_symbols) else e for e in sympy_exprs]
    sympy_expr = combine_exprs(sympy_exprs)
    sympy_result = sympy_expr.coeff(sympy_var, sympy_n)
    return from_sympy(sympy_result)
Example #50
0
    def apply(self, f, n, n0, evaluation, options={}):
        'DiscreteLimit[f_, n_->n0_, OptionsPattern[DiscreteLimit]]'

        f = f.to_sympy(convert_all_global_functions=True)
        n = n.to_sympy()
        n0 = n0.to_sympy()

        if n0 != sympy.oo:
            return

        if f is None or n is None:
            return

        trials = options['System`Trials'].get_int_value()

        if trials is None or trials <= 0:
            evaluation.message('DiscreteLimit', 'dltrials')
            trials = 5

        try:
            return from_sympy(sympy.limit_seq(f, n, trials))
        except:
            pass
Example #51
0
 def apply(self, m, b, evaluation):
     'LinearSolve[m_, b_]'
     
     matrix = matrix_data(m)
     if matrix is None:
         return
     if not b.has_form('List', None):
         return
     if len(b.leaves) != len(matrix):
         return evaluation.message('LinearSolve', 'lslc')
     system = [m + [v] for m, v in zip(matrix, b.leaves)]
     system = to_sympy_matrix(system)
     if system is None:
         return
     syms = [sympy.Symbol('LinearSolve_var%d' % k, dummy=True) for k in range(system.cols - 1)]
     sol = sympy.solve_linear_system(system, *syms)
     if sol:
         # substitute 0 for variables that are not in result dictionary 
         free_vars = dict((sym, sympy.Integer(0)) for sym in syms if sym not in sol)
         sol.update(free_vars)
         sol = [(sol[sym] if sym in free_vars else sol[sym].subs(free_vars)) for sym in syms]
         return from_sympy(sol)
     else:
         return evaluation.message('LinearSolve', 'nosol')
Example #52
0
def DixonPolynomial_apply(polys, xlist, alist):

    xsym = [i.to_sympy() for i in xlist.leaves]
    asym = [i.to_sympy() for i in alist.leaves]
    res = DixonSub_apply(polys, xlist, alist)

    if not isinstance(
            res,
            Expression):  ####checking if the DixonSub_apply returned error
        return res
    rsym = res.leaves
    dixon_list = [j.leaves for j in rsym
                  ]  ###two level Mathics list unpacked in 2 level python-list
    dixon_sym = [[j.to_sympy() for j in i] for i in dixon_list]
    dix_mat = sympy.Matrix(
        dixon_sym)  ###2-level python list to sympy.Matrix object

    for i in range(1, len(xsym) + 1):
        #####together has poor results in sympy so simplify was used
        dix_mat[i, :] = sympy.simplify(
            (dix_mat[i, :] - dix_mat[i - 1, :]) / (xsym[i - 1] - asym[i - 1]))
    # print(rsym[0])
    det_m = sympy.simplify(sympy.det(dix_mat))
    return from_sympy(det_m)
Example #53
0
    def apply(self, m, l, evaluation):
        'Norm[m_, l_]'

        if isinstance(l, Symbol):
            pass
        elif isinstance(l, (Real, Integer)) and l.to_python() >= 1:
            pass
        else:
            return evaluation.message('Norm', 'ptype', l)

        l = l.to_sympy()
        matrix = to_sympy_matrix(m)

        if matrix is None:
            return evaluation.message('Norm', 'nvm')
        if len(matrix) == 0:
            return

        try:
            res = matrix.norm(l)
        except NotImplementedError:
            return evaluation.message('Norm', 'normnotimplemented')

        return from_sympy(res)
Example #54
0
    def apply(self, m, evaluation):
        'PseudoInverse[m_]'

        matrix = to_sympy_matrix(m)
        pinv = matrix.pinv()
        return from_sympy(pinv)
Example #55
0
    def apply(self, items, evaluation):
        'Power[items__]'

        items_sequence = items.get_sequence()

        if len(items_sequence) == 2:
            x, y = items_sequence
        else:
            return Expression('Power', *items_sequence)

        if y.get_int_value() == 1:
            return x
        elif x.get_int_value() == 1:
            return x
        elif y.get_int_value() == 0:
            if x.get_int_value() == 0:
                evaluation.message('Power', 'indet', Expression('Power', x, y))
                return Symbol('Indeterminate')
            else:
                return Integer(1)

        elif x.has_form('Power', 2) and isinstance(y, Integer):
            return Expression('Power', x.leaves[0],
                              Expression('Times', x.leaves[1], y))
        elif x.has_form('Times', None) and isinstance(y, Integer):
            return Expression(
                'Times', *[Expression('Power', leaf, y) for leaf in x.leaves])

        elif (isinstance(x, Number) and isinstance(y, Number)
              and not (x.is_inexact() or y.is_inexact())):

            sym_x, sym_y = x.to_sympy(), y.to_sympy()

            try:
                if sympy.re(sym_y) >= 0:
                    result = sym_x**sym_y
                else:
                    if sym_x == 0:
                        evaluation.message('Power', 'infy')
                        return Symbol('ComplexInfinity')
                    result = sympy.Integer(1) / (sym_x**(-sym_y))
                if isinstance(result, sympy.Pow):
                    result = result.simplify()
                    args = [from_sympy(expr) for expr in result.as_base_exp()]
                    result = Expression('Power', *args)
                    result = result.evaluate_leaves(evaluation)
                    return result

                return from_sympy(result)
            except ValueError:
                return Expression('Power', x, y)
            except ZeroDivisionError:
                evaluation.message('Power', 'infy')
                return Symbol('ComplexInfinity')

        elif (isinstance(x, Number) and isinstance(y, Number)
              and (x.is_inexact() or y.is_inexact())):
            try:
                prec = min_prec(x, y)
                with mpmath.workprec(prec):
                    mp_x = sympy2mpmath(x.to_sympy())
                    mp_y = sympy2mpmath(y.to_sympy())
                    result = mp_x**mp_y
                    if isinstance(result, mpmath.mpf):
                        return Real(str(result), prec)
                    elif isinstance(result, mpmath.mpc):
                        return Complex(str(result.real), str(result.imag),
                                       prec)
            except ZeroDivisionError:
                evaluation.message('Power', 'infy')
                return Symbol('ComplexInfinity')
        else:
            numerified_items = items.numerify(evaluation)
            return Expression('Power', *numerified_items.get_sequence())
Example #56
0
    def apply(self, items, evaluation):
        'Times[items___]'

        # TODO: Clean this up and optimise it

        items = items.numerify(evaluation).get_sequence()
        number = (sympy.Integer(1), sympy.Integer(0))
        leaves = []

        prec = min_prec(*items)
        is_real = all([not isinstance(i, Complex) for i in items])

        for item in items:
            if isinstance(item, Number):
                if isinstance(item, Complex):
                    sym_real, sym_imag = item.real.to_sympy(
                    ), item.imag.to_sympy()
                else:
                    sym_real, sym_imag = item.to_sympy(), sympy.Integer(0)

                if prec is not None:
                    sym_real = sym_real.n(dps(prec))
                    sym_imag = sym_imag.n(dps(prec))

                if sym_real.is_zero and sym_imag.is_zero and prec is None:
                    return Integer('0')
                number = (number[0] * sym_real - number[1] * sym_imag,
                          number[0] * sym_imag + number[1] * sym_real)
            elif leaves and item == leaves[-1]:
                leaves[-1] = Expression('Power', leaves[-1], Integer(2))
            elif (leaves and item.has_form('Power', 2)
                  and leaves[-1].has_form('Power', 2)
                  and item.leaves[0].same(leaves[-1].leaves[0])):
                leaves[-1].leaves[1] = Expression('Plus', item.leaves[1],
                                                  leaves[-1].leaves[1])
            elif (leaves and item.has_form('Power', 2)
                  and item.leaves[0].same(leaves[-1])):
                leaves[-1] = Expression(
                    'Power', leaves[-1],
                    Expression('Plus', item.leaves[1], Integer(1)))
            elif (leaves and leaves[-1].has_form('Power', 2)
                  and leaves[-1].leaves[0].same(item)):
                leaves[-1] = Expression(
                    'Power', item,
                    Expression('Plus', Integer(1), leaves[-1].leaves[1]))
            else:
                leaves.append(item)
        if number == (1, 0):
            number = None
        elif number == (-1, 0) and leaves and leaves[0].has_form('Plus', None):
            leaves[0].leaves = [
                Expression('Times', Integer(-1), leaf)
                for leaf in leaves[0].leaves
            ]
            number = None

        if number is not None:
            if number[1].is_zero and is_real:
                leaves.insert(0, Number.from_mp(number[0], prec))
            elif number[1].is_zero and number[1].is_Integer and prec is None:
                leaves.insert(0, Number.from_mp(number[0], prec))
            else:
                leaves.insert(
                    0,
                    Complex(from_sympy(number[0]), from_sympy(number[1]),
                            prec))

        if not leaves:
            return Integer(1)
        elif len(leaves) == 1:
            return leaves[0]
        else:
            return Expression('Times', *leaves)
Example #57
0
    def apply_multiplevariable(self, f, vars, evaluation):
        'Minimize[f_?NotListQ, vars_?ListQ]'

        head_name = vars.get_head_name()
        vars_or = vars
        vars = vars.leaves
        for var in vars:
            if ((var.is_atom() and not var.is_symbol()) or  # noqa
                    head_name in ('System`Plus', 'System`Times',
                                  'System`Power') or 'System`Constant'
                    in var.get_attributes(evaluation.definitions)):

                evaluation.message('Minimize', 'ivar', vars_or)
                return

        vars_sympy = [var.to_sympy() for var in vars]
        sympy_f = f.to_sympy()

        jacobian = [sympy.diff(sympy_f, x) for x in vars_sympy]
        hessian = sympy.Matrix([[sympy.diff(deriv, x) for x in vars_sympy]
                                for deriv in jacobian])

        candidates_tmp = sympy.solve(jacobian, vars_sympy, dict=True)
        candidates = []

        for candidate in candidates_tmp:
            if len(candidate) != len(vars_sympy):
                for variable in candidate:
                    for i in range(len(candidate), len(vars_sympy)):
                        candidate[variable] = candidate[variable].subs(
                            vars_sympy[i], 1)

                for i in range(len(candidate), len(vars_sympy)):
                    candidate[vars_sympy[i]] = 1

            candidates.append(candidate)

        minimum_list = []

        for candidate in candidates:
            eigenvals = hessian.subs(candidate).eigenvals()

            positives_eigenvalues = 0
            negatives_eigenvalues = 0

            for val in eigenvals:
                if val.is_real:
                    if val < 0:
                        negatives_eigenvalues += 1
                    elif val >= 0:
                        positives_eigenvalues += 1

            if positives_eigenvalues + negatives_eigenvalues != len(eigenvals):
                continue

            if positives_eigenvalues == len(eigenvals):
                minimum_list.append(candidate)

        return Expression(
            'List',
            *(Expression('List', from_sympy(
                sympy_f.subs(minimum).simplify()), [
                    Expression('Rule', from_sympy(list(minimum.keys())[i]),
                               from_sympy(list(minimum.values())[i]))
                    for i in range(len(vars_sympy))
                ]) for minimum in minimum_list))
Example #58
0
    def apply_constraints(self, f, vars, evaluation):
        'Minimize[f_?ListQ, vars_?ListQ]'
        head_name = vars.get_head_name()
        vars_or = vars
        vars = vars.leaves
        for var in vars:
            if ((var.is_atom() and not var.is_symbol()) or  # noqa
                    head_name in ('System`Plus', 'System`Times',
                                  'System`Power') or 'System`Constant'
                    in var.get_attributes(evaluation.definitions)):

                evaluation.message('Minimize', 'ivar', vars_or)
                return

        vars_sympy = [var.to_sympy() for var in vars]
        constraints = [function for function in f.leaves]
        objective_function = constraints[0].to_sympy()

        constraints = constraints[1:]

        g_functions = []
        h_functions = []

        g_variables = []
        h_variables = []

        for constraint in constraints:
            left, right = constraint.leaves
            head_name = constraint.get_head_name()

            left = left.to_sympy()
            right = right.to_sympy()

            if head_name == 'System`LessEqual' or head_name == 'System`Less':
                eq = left - right
                eq = sympy.together(eq)
                eq = sympy.cancel(eq)

                g_functions.append(eq)
                g_variables.append(
                    sympy.Symbol('kkt_g' + str(len(g_variables))))

            elif head_name == 'System`GreaterEqual' or head_name == 'System`Greater':
                eq = -1 * (left - right)
                eq = sympy.together(eq)
                eq = sympy.cancel(eq)

                g_functions.append(eq)
                g_variables.append(
                    sympy.Symbol('kkt_g' + str(len(g_variables))))

            elif head_name == 'System`Equal':
                eq = left - right
                eq = sympy.together(eq)
                eq = sympy.cancel(eq)

                h_functions.append(eq)
                h_variables.append(
                    sympy.Symbol('kkt_h' + str(len(h_variables))))

        equations = []

        for variable in vars_sympy:
            equation = sympy.diff(objective_function, variable)

            for i in range(len(g_variables)):
                g_variable = g_variables[i]
                g_function = g_functions[i]

                equation = equation + g_variable * sympy.diff(
                    g_function, variable)

            for i in range(len(h_variables)):
                h_variable = h_variables[i]
                h_function = h_functions[i]

                equation = equation + h_variable * sympy.diff(
                    h_function, variable)

            equations.append(equation)

        for i in range(len(g_variables)):
            g_variable = g_variables[i]
            g_function = g_functions[i]

            equations.append(g_variable * g_function)

        for i in range(len(h_variables)):
            h_variable = h_variables[i]
            h_function = h_functions[i]

            equations.append(h_variable * h_function)

        all_variables = vars_sympy + g_variables + h_variables

        candidates_tmp = sympy.solve(equations, all_variables, dict=True)
        candidates = []

        for candidate in candidates_tmp:
            if len(candidate) != len(vars_sympy):
                for variable in candidate:
                    for i in range(len(candidate), len(vars_sympy)):
                        candidate[variable] = candidate[variable].subs(
                            vars_sympy[i], 1)
                for i in range(len(candidate), len(vars_sympy)):
                    candidate[vars_sympy[i]] = 1

            candidates.append(candidate)

        kkt_candidates = []

        for candidate in candidates:
            kkt_ok = True

            sum_constraints = 0

            for i in range(len(g_variables)):
                g_variable = g_variables[i]
                g_function = g_functions[i]

                if candidate[g_variable] < 0:
                    kkt_ok = False

                if candidate[g_variable] * g_function.subs(candidate) != 0:
                    kkt_ok = False

                sum_constraints = sum_constraints + candidate[g_variable]

            for i in range(len(h_variables)):
                h_variable = h_variables[i]
                h_function = h_functions[i]

                sum_constraints = sum_constraints + abs(candidate[h_variable])

            if sum_constraints <= 0:
                kkt_ok = False

            if not kkt_ok:
                continue

            kkt_candidates.append(candidate)

        hessian = sympy.Matrix([[sympy.diff(deriv, x) for x in all_variables]
                                for deriv in equations])

        for i in range(0, len(all_variables) - len(vars_sympy)):
            hessian.col_del(len(all_variables) - i - 1)
            hessian.row_del(len(all_variables) - i - 1)

        minimum_list = []

        for candidate in kkt_candidates:
            eigenvals = hessian.subs(candidate).eigenvals()

            positives_eigenvalues = 0
            negatives_eigenvalues = 0

            for val in eigenvals:
                val = complex(sympy.N(val, chop=True))

                if val.imag == 0:
                    val = val.real
                    if val < 0:
                        negatives_eigenvalues += 1
                    elif val > 0:
                        positives_eigenvalues += 1

            if positives_eigenvalues + negatives_eigenvalues != len(eigenvals):
                continue

            if positives_eigenvalues == len(eigenvals):
                for g_variable in g_variables:
                    del candidate[g_variable]
                for h_variable in h_variables:
                    del candidate[h_variable]

                minimum_list.append(candidate)

        return Expression(
            'List',
            *(Expression(
                'List',
                from_sympy(objective_function.subs(minimum).simplify()), [
                    Expression('Rule', from_sympy(list(minimum.keys())[i]),
                               from_sympy(list(minimum.values())[i]))
                    for i in range(len(vars_sympy))
                ]) for minimum in minimum_list))
Example #59
0
    def apply(self, eqns, a, n, evaluation):
        'RSolve[eqns_, a_, n_]'

        # TODO: Do this with rules?
        if not eqns.has_form('List', None):
            eqns = Expression('List', eqns)

        if len(eqns.leaves) == 0:
            return

        for eqn in eqns.leaves:
            if eqn.get_head_name() != 'System`Equal':
                evaluation.message('RSolve', 'deqn', eqn)
                return

        if (n.is_atom() and not n.is_symbol()) or \
            n.get_head_name() in ('System`Plus', 'System`Times',
                                  'System`Power') or \
                'System`Constant' in n.get_attributes(evaluation.definitions):
            # TODO: Factor out this check for dsvar into a separate
            # function. DSolve uses this too.
            evaluation.message('RSolve', 'dsvar')
            return

        try:
            a.leaves
            function_form = None
            func = a
        except AttributeError:
            func = Expression(a, n)
            function_form = Expression('List', n)

        if func.is_atom() or len(func.leaves) != 1:
            evaluation.message('RSolve', 'dsfun', a)

        if n not in func.leaves:
            evaluation.message('DSolve', 'deqx')

        # Seperate relations from conditions
        conditions = {}

        def is_relation(eqn):
            left, right = eqn.leaves
            for l, r in [(left, right), (right, left)]:
                if (left.get_head_name() == func.get_head_name() and  # noqa
                        len(left.leaves) == 1 and isinstance(
                            l.leaves[0].to_python(), int) and r.is_numeric()):

                    r_sympy = r.to_sympy()
                    if r_sympy is None:
                        raise ValueError
                    conditions[l.leaves[0].to_python()] = r_sympy
                    return False
            return True

        # evaluate is_relation on all leaves to store conditions
        try:
            relations = [leaf for leaf in eqns.leaves if is_relation(leaf)]
        except ValueError:
            return
        relation = relations[0]

        left, right = relation.leaves
        relation = Expression('Plus', left,
                              Expression('Times', -1,
                                         right)).evaluate(evaluation)

        sym_eq = relation.to_sympy(
            converted_functions=set([func.get_head_name()]))
        if sym_eq is None:
            return
        sym_n = sympy.core.symbols(str(sympy_symbol_prefix + n.name))
        sym_func = sympy.Function(
            str(sympy_symbol_prefix + func.get_head_name()))(sym_n)

        sym_conds = {}
        for cond in conditions:
            sym_conds[sympy.Function(str(
                sympy_symbol_prefix + func.get_head_name()))(cond)] = \
                conditions[cond]

        try:
            # Sympy raises error when given empty conditions. Fixed in
            # upcomming sympy release.
            if sym_conds != {}:
                sym_result = sympy.rsolve(sym_eq, sym_func, sym_conds)
            else:
                sym_result = sympy.rsolve(sym_eq, sym_func)

            if not isinstance(sym_result, list):
                sym_result = [sym_result]
        except ValueError:
            return

        if function_form is None:
            return Expression(
                'List', *[
                    Expression('List', Expression('Rule', a, from_sympy(soln)))
                    for soln in sym_result
                ])
        else:
            return Expression(
                'List', *[
                    Expression(
                        'List',
                        Expression(
                            'Rule', a,
                            Expression('Function', function_form,
                                       from_sympy(soln))))
                    for soln in sym_result
                ])
Example #60
0
 def apply(self, x, evaluation):
     'Ceiling[x_]'
     x = x.to_sympy()
     return from_sympy(sympy.ceiling(x))