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)
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)
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)
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)
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)])
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))
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)
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)
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
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)
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')
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)
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))
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)
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)
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
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)
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)
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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
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)
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
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
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))
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
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)
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)
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)])
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)
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
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])
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
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)
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)
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)
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)
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)
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)
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)
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)
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
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')
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)
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)
def apply(self, m, evaluation): 'PseudoInverse[m_]' matrix = to_sympy_matrix(m) pinv = matrix.pinv() return from_sympy(pinv)
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())
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)
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))
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))
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 ])
def apply(self, x, evaluation): 'Ceiling[x_]' x = x.to_sympy() return from_sympy(sympy.ceiling(x))