Question: Dummy fails when is re-evaluated in S and srepr Hi all! Well, i found this little problem, Dummy is a nice function but in the way is implemented exist this: Basically, if you works with Dummy, and you get the expression with srepr or similar, when you eval it every Dummy will be interpreted as a new Dummy, so it fails, in the example you can see we can't eval the second expression because the 2 Dummy expression are interpreted as differents, other ex: So thinking a solution can be use a hash or similar function, like: Always will exist the hash collision, but at least to cover all possible can be sympy check the existents Dummy expressions and check the hash never by equal to other, the probability of the hash collision, to be equal, in the same context, with the same name, and in the same expression, i think is very low. Maybe instead use a hash can be a random expression, with chars like , that can help to avoid hash collision. Thx. Cya.

"""     # In the rare event that a Dummy object needs to be recreated, both the    # `name` and `dummy_index` should be passed.  This is used by `srepr` for    # example:    # >>> d1 = Dummy()    # >>> d2 = eval(srepr(d1))    # >>> d2 == d1    # True    #    # If a new session is started between `srepr` and `eval`, there is a very    # small chance that `d2` will be equal to a previously-created Dummy.     _count = 0    _prng = random.Random()    _base_dummy_index = _prng.randint(10**6, 9*10**6)      __slots__ = ['dummy_index']      is_Dummy = True     def __new__(cls, name=None, **assumptions):    def __new__(cls, name=None, dummy_index=None, **assumptions):        if dummy_index is not None:            assert name is not None, "If you specify a dummy_index, you must also provide a name"         if name is None:             name = "Dummy_" + str(Dummy._count)         if dummy_index is None:            dummy_index = Dummy._base_dummy_index + Dummy._count            Dummy._count += 1         cls._sanitize(assumptions, cls)         obj = Symbol.__xnew__(cls, name, **assumptions)         Dummy._count += 1        obj.dummy_index = Dummy._count        obj.dummy_index = dummy_index         return obj      def __getstate__(self):diff --git a/sympy/printing/repr.py b/sympy/printing/repr.py-- a/sympy/printing/repr.py++ b/sympy/printing/repr.py


Question: Dummy fails when is re-evaluated in S and srepr Hi all! Well, i found this little problem, Dummy is a nice function but in the way is implemented exist this: Basically, if you works with Dummy, and you get the expression with srepr or similar, when you eval it every Dummy will be interpreted as a new Dummy, so it fails, in the example you can see we can't eval the second expression because the 2 Dummy expression are interpreted as differents, other ex: So thinking a solution can be use a hash or similar function, like: Always will exist the hash collision, but at least to cover all possible can be sympy check the existents Dummy expressions and check the hash never by equal to other, the probability of the hash collision, to be equal, in the same context, with the same name, and in the same expression, i think is very low. Maybe instead use a hash can be a random expression, with chars like , that can help to avoid hash collision. Thx. Cya.

def _print_Symbol(self, expr):         d = expr._assumptions.generator<ins>        # print the dummy_index like it was an assumption        if expr.is_Dummy:            d['dummy_index'] = expr.dummy_index</ins>         if d == {}:             return "%s(%s)" % (expr.__class__.__name__, self._print(expr.name))         else:


Question: Test failure in Travis I was able to reproduce this locally on a 64-bit system running Ubuntu 16.04. How to reproduce:

# remove it             if Func is Add:                 take = min(func_dicts[k][i] for i in com_dict)                com_func_take = Mul(take, from_dict(com_dict), evaluate=False)                _sum = from_dict(com_dict)                if take == 1:                    com_func_take = _sum                else:                    com_func_take = Mul(take, _sum, evaluate=False)             else:                 take = igcd(*[func_dicts[k][i] for i in com_dict])                com_func_take = Pow(from_dict(com_dict), take, evaluate=False)                base = from_dict(com_dict)                if take == 1:                    com_func_take = base                else:                    com_func_take = Pow(base, take, evaluate=False)             for di in com_dict:                 func_dicts[k][di] -= take*com_dict[di]             # compute the remaining expression


Question: Test failure in Travis I was able to reproduce this locally on a 64-bit system running Ubuntu 16.04. How to reproduce:

#     R = [(x0, d + f), (x1, b + d)]     #     C = [e + x0 + x1, g + x0 + x1, a + c + d + f + g]     # but the args of C[-1] should not be `(a + c, d + f + g)`    nested = [[i for i in f.args if isinstance(i, f.func)] for f in exprs]     for i in range(len(exprs)):         F = reduced_exprs[i].func         if not (F is Mul or F is Add):             continue        nested = [a for a in exprs[i].args if isinstance(a, F)]        args = []        for a in reduced_exprs[i].args:            if isinstance(a, F):                for ai in a.args:                    if isinstance(ai, F) and ai not in nested:                        args.extend(ai.args)                    else:                        args.append(ai)            else:                args.append(a)        reduced_exprs[i] = F(*args)        if any(isinstance(a, F) for a in reduced_exprs[i].args):            reduced_exprs[i] = F(*reduced_exprs[i].args)      return replacements, reduced_exprs


Question: Codegen: sign function in Fortran The Fortran code generated by Sympy for the sign function is not a valid Fortran syntax. With Sympy 1.0 and Python 3.6: (The same behavior is obtained with .) The syntax of the sign function in Fortran is given . I guess it would be preferable to generate something like or depending of the context. I'm not sure how to get the same behavior than Sympy for , but at least it would be compilable.

def _get_comment(self, text):         return "! {0}".format(text)<ins>#issue 12267    def _print_sign(self,func):        if func.args[0].is_integer:            return "merge(0, isign(1, {0}), {0} == 0)".format(self._print(func.args[0]))        elif func.args[0].is_complex:            return "merge(cmplx(0d0, 0d0), {0}/abs({0}), abs({0}) == 0d0)".format(self._print(func.args[0]))        else:            return "merge(0d0, dsign(1d0, {0}), {0} == 0d0)".format(self._print(func.args[0]))</ins>      def _declare_number_const(self, name, value):         return "parameter ({0} = {1})".format(name, value)


Question: Sum of the elements of an identity matrix is zero I think this is a bug. I created a matrix by M.T * M under an assumption that M is orthogonal. SymPy successfully recognized that the result is an identity matrix. I tested its identity-ness by element-wise, queries, and sum of the diagonal elements and received expected results. However, when I attempt to evaluate the total sum of the elements the result was 0 while 'n' is expected.

from functools import wraps from sympy.core import S, Symbol, Tuple, Integer, Basic, Exprfrom sympy.core import S, Symbol, Tuple, Integer, Basic, Expr, Eq from sympy.core.decorators import call_highest_priority from sympy.core.compatibility import range from sympy.core.sympify import SympifyError, sympify from sympy.functions import conjugate, adjointfrom sympy.functions.special.tensor_functions import KroneckerDelta from sympy.matrices import ShapeError from sympy.simplify import simplify


Question: Sum of the elements of an identity matrix is zero I think this is a bug. I created a matrix by M.T * M under an assumption that M is orthogonal. SymPy successfully recognized that the result is an identity matrix. I tested its identity-ness by element-wise, queries, and sum of the diagonal elements and received expected results. However, when I attempt to evaluate the total sum of the elements the result was 0 while 'n' is expected.

if self.args[0] != v.args[0]:             return S.Zero <del>        from sympy import KroneckerDelta</del>         return KroneckerDelta(self.args[1], v.args[1])*KroneckerDelta(self.args[2], v.args[2])


Question: Sum of the elements of an identity matrix is zero I think this is a bug. I created a matrix by M.T * M under an assumption that M is orthogonal. SymPy successfully recognized that the result is an identity matrix. I tested its identity-ness by element-wise, queries, and sum of the diagonal elements and received expected results. However, when I attempt to evaluate the total sum of the elements the result was 0 while 'n' is expected.

return self      def _entry(self, i, j):        if i == j:        eq = Eq(i, j)        if eq is S.true:             return S.One        else:        elif eq is S.false:             return S.Zero        return KroneckerDelta(i, j)      def _eval_determinant(self):         return S.One


Question: DiagonalMatrix[i, j] -0 Similar to , DiagonalMatrix references to position (i,j) give 0:

from __future__ import print_function, division  from sympy.matrices.expressions import MatrixExprfrom sympy.core import Sfrom sympy.core import S, Eqfrom sympy.functions.special.tensor_functions import KroneckerDelta class DiagonalMatrix(MatrixExpr):     arg = property(lambda self: self.args[0])     shape = property(lambda self: (self.arg.shape[0], self.arg.shape[0]))      def _entry(self, i, j):        return S.Zero if i != j else self.arg[i, 0]        eq = Eq(i, j)        if eq is S.false:            return S.Zero        elif eq is S.true:            return self.arg[i, i]        return self.arg[i, j]*KroneckerDelta(i, j)  class DiagonalOf(MatrixExpr):     arg = property(lambda self: self.args[0])


Question: isupper() raises IndexError for tall matrices The function Matrix.isupper raises an IndexError for a 4x2 matrix of zeros. The code for isupper() is For a 4x2 matrix, isupper iterates over the indices: The attempt to index the (3,2) entry appears to be the source of the error.

def _eval_is_upper_hessenberg(self):         return all(self[i, j].is_zero                    for i in range(2, self.rows)                   for j in range(i - 1))                   for j in range(min(self.cols, (i - 1))))      def _eval_values(self):         return [i for i in self if not i.is_zero]


Question: isupper() raises IndexError for tall matrices The function Matrix.isupper raises an IndexError for a 4x2 matrix of zeros. The code for isupper() is For a 4x2 matrix, isupper iterates over the indices: The attempt to index the (3,2) entry appears to be the source of the error.

"""         return all(self[i, j].is_zero                    for i in range(1, self.rows)                   for j in range(i))                   for j in range(min(i, self.cols)))      @property     def is_zero(self):


Question: constructor fails with non-disjoint cycles Calling raises a instead of constructing the identity permutation. If the cycles passed in are non-disjoint, they should be applied in left-to-right order and the resulting permutation should be returned. This should be easy to compute. I don't see a reason why non-disjoint cycles should be forbidden.

# counting starts from 1.          temp = flatten(args)        if has_dups(temp):            if is_cycle:                raise ValueError('there were repeated elements; to resolve '                'cycles use Cycle%s.' % ''.join([str(tuple(c)) for c in args]))            else:                raise ValueError('there were repeated elements.')        if has_dups(temp) and not is_cycle:            raise ValueError('there were repeated elements.')         temp = set(temp)          if not is_cycle and \


Question: Totient of any non-integer number According to the Totient function definition on , the totient of non-integer numbers is not there. But in sympy: the value is returned, instead of an error.

from sympy.core.compatibility import as_int, SYMPY_INTS, range from sympy.core.singleton import S from sympy.core.function import Function<ins>from sympy.core.expr import Expr</ins>  small_trailing = [i and max(int(not i % 2**j) and j for j in range(1, 8))     for i in range(256)]


Question: Totient of any non-integer number According to the Totient function definition on , the totient of non-integer numbers is not there. But in sympy: the value is returned, instead of an error.

for p, k in factors.items():                 t *= (p - 1) * p**(k - 1)             return t<ins>        elif not isinstance(n, Expr) or (n.is_integer is False) or (n.is_positive is False):            raise ValueError("n must be a positive integer")</ins>      def _eval_is_integer(self):         return fuzzy_and([self.args[0].is_integer, self.args[0].is_positive])


Question: diffgeom does not support multivector fields (0,m) well enough A limitation of the diffgeom package is that it does not provide support for fields higher than (0,m). TensorProduct, WedgeProduct, and others all assume inputs of differential form-fields, while mixed multivector fields make sense in some contexts (such as Poisson geometry). I'll work on implementing (n,m)-fields in the current code, where it makes sense.

from sympy.core.compatibility import reduce from sympy.combinatorics import Permutation <ins></ins> # TODO you are a bit excessive in the use of Dummies # TODO dummy point, literal field # TODO too often one needs to call doit or simplify on the output, check the


Question: diffgeom does not support multivector fields (0,m) well enough A limitation of the diffgeom package is that it does not provide support for fields higher than (0,m). TensorProduct, WedgeProduct, and others all assume inputs of differential form-fields, while mixed multivector fields make sense in some contexts (such as Poisson geometry). I'll work on implementing (n,m)-fields in the current code, where it makes sense.

if covariant_order(scalar_field) or contravariant_order(scalar_field):             raise ValueError('Only scalar fields can be supplied as arguments to vector fields.') <ins>        if scalar_field is None:            return self</ins>         base_scalars = list(scalar_field.atoms(BaseScalarField))          # First step: e_x(x+r**2) -> e_x(x) + 2*r*e_x(r)


Question: diffgeom does not support multivector fields (0,m) well enough A limitation of the diffgeom package is that it does not provide support for fields higher than (0,m). TensorProduct, WedgeProduct, and others all assume inputs of differential form-fields, while mixed multivector fields make sense in some contexts (such as Poisson geometry). I'll work on implementing (n,m)-fields in the current code, where it makes sense.

"""Tensor product of forms.      The tensor product permits the creation of multilinear functionals (i.e.    higher order tensors) out of lower order forms (e.g. 1-forms). However, the    higher tensors thus created lack the interesting features provided by the    other type of product, the wedge product, namely they are not antisymmetric    and hence are not form fields.    higher order tensors) out of lower order fields (e.g. 1-forms and vector    fields). However, the higher tensors thus created lack the interesting    features provided by the other type of product, the wedge product, namely    they are not antisymmetric and hence are not form fields.      Examples     ========


Question: diffgeom does not support multivector fields (0,m) well enough A limitation of the diffgeom package is that it does not provide support for fields higher than (0,m). TensorProduct, WedgeProduct, and others all assume inputs of differential form-fields, while mixed multivector fields make sense in some contexts (such as Poisson geometry). I'll work on implementing (n,m)-fields in the current code, where it makes sense.

0     >>> TensorProduct(R2.dx, R2.x*R2.dy)(R2.x*R2.e_x, R2.e_y)     x**2<ins>    >>> TensorProduct(R2.e_x, R2.e_y)(R2.x**2, R2.y**2)    4*x*y    >>> TensorProduct(R2.e_y, R2.dx)(R2.y)    dx</ins>      You can nest tensor products.


Question: diffgeom does not support multivector fields (0,m) well enough A limitation of the diffgeom package is that it does not provide support for fields higher than (0,m). TensorProduct, WedgeProduct, and others all assume inputs of differential form-fields, while mixed multivector fields make sense in some contexts (such as Poisson geometry). I'll work on implementing (n,m)-fields in the current code, where it makes sense.

"""     def __new__(cls, *args):        if any(contravariant_order(a) for a in args):            raise ValueError('A vector field was supplied as an argument to TensorProduct.')        scalar = Mul(*[m for m in args if covariant_order(m) == 0])        forms = [m for m in args if covariant_order(m)]        if forms:            if len(forms) == 1:                return scalar*forms[0]            return scalar*super(TensorProduct, cls).__new__(cls, *forms)        scalar = Mul(*[m for m in args if covariant_order(m) + contravariant_order(m) == 0])        multifields = [m for m in args if covariant_order(m) + contravariant_order(m)]        if multifields:            if len(multifields) == 1:                return scalar*multifields[0]            return scalar*super(TensorProduct, cls).__new__(cls, *multifields)         else:             return scalar


Question: diffgeom does not support multivector fields (0,m) well enough A limitation of the diffgeom package is that it does not provide support for fields higher than (0,m). TensorProduct, WedgeProduct, and others all assume inputs of differential form-fields, while mixed multivector fields make sense in some contexts (such as Poisson geometry). I'll work on implementing (n,m)-fields in the current code, where it makes sense.

super(TensorProduct, self).__init__()         self._args = args     def __call__(self, *v_fields):        """Apply on a list of vector_fields.    def __call__(self, *fields):        """Apply on a list of fields.         If the number of vector fields supplied is not equal to the order of        the form field the list of arguments is padded with ``None``'s.        If the number of input fields supplied is not equal to the order of        the tensor product field, the list of arguments is padded with ``None``'s.          The list of arguments is divided in sublists depending on the order of         the forms inside the tensor product. The sublists are provided as         arguments to these forms and the resulting expressions are given to the         constructor of ``TensorProduct``.         """        tot_order = covariant_order(self)        tot_args = len(v_fields)        tot_order = covariant_order(self) + contravariant_order(self)        tot_args = len(fields)         if tot_args != tot_order:            v_fields = list(v_fields) + [None]*(tot_order - tot_args)        orders = [covariant_order(f) for f in self._args]            fields = list(fields) + [None]*(tot_order - tot_args)        orders = [covariant_order(f) + contravariant_order(f) for f in self._args]         indices = [sum(orders[:i + 1]) for i in range(len(orders) - 1)]        v_fields = [v_fields[i:j] for i, j in zip([0] + indices, indices + [None])]        multipliers = [t[0].rcall(*t[1]) for t in zip(self._args, v_fields)]        fields = [fields[i:j] for i, j in zip([0] + indices, indices + [None])]        multipliers = [t[0].rcall(*t[1]) for t in zip(self._args, fields)]         return TensorProduct(*multipliers)      def _latex(self, printer, *args):


Question: diffgeom does not support multivector fields (0,m) well enough A limitation of the diffgeom package is that it does not provide support for fields higher than (0,m). TensorProduct, WedgeProduct, and others all assume inputs of differential form-fields, while mixed multivector fields make sense in some contexts (such as Poisson geometry). I'll work on implementing (n,m)-fields in the current code, where it makes sense.

-1     >>> WedgeProduct(R2.dx, R2.x*R2.dy)(R2.x*R2.e_x, R2.e_y)     x**2<ins>    >>> WedgeProduct(R2.e_x,R2.e_y)(R2.y,None)    -e_x</ins>      You can nest wedge products.


Question: diffgeom does not support multivector fields (0,m) well enough A limitation of the diffgeom package is that it does not provide support for fields higher than (0,m). TensorProduct, WedgeProduct, and others all assume inputs of differential form-fields, while mixed multivector fields make sense in some contexts (such as Poisson geometry). I'll work on implementing (n,m)-fields in the current code, where it makes sense.

"""     # TODO the calculation of signatures is slow     # TODO you do not need all these permutations (neither the prefactor)    def __call__(self, *vector_fields):    def __call__(self, *fields):         """Apply on a list of vector_fields.          The expression is rewritten internally in terms of tensor products and evaluated."""        orders = (covariant_order(e) for e in self.args)        orders = (covariant_order(e) + contravariant_order(e) for e in self.args)         mul = 1/Mul(*(factorial(o) for o in orders))        perms = permutations(vector_fields)        perms = permutations(fields)         perms_par = (Permutation(            p).signature() for p in permutations(list(range(len(vector_fields)))))            p).signature() for p in permutations(list(range(len(fields)))))         tensor_prod = TensorProduct(*self.args)         return mul*Add(*[tensor_prod(*p[0])*p[1] for p in zip(perms, perms_par)])


Question: diffgeom does not support multivector fields (0,m) well enough A limitation of the diffgeom package is that it does not provide support for fields higher than (0,m). TensorProduct, WedgeProduct, and others all assume inputs of differential form-fields, while mixed multivector fields make sense in some contexts (such as Poisson geometry). I'll work on implementing (n,m)-fields in the current code, where it makes sense.

return 0     elif isinstance(expr, BaseVectorField):         return 1<ins>    elif isinstance(expr, TensorProduct):        return sum(contravariant_order(a) for a in expr.args)</ins>     elif not _strict or expr.atoms(BaseScalarField):         return 0     else:  # If it does not contain anything related to the diffgeom module and it is _strict


Question: Poly(x,x,y).free_symbols -{x, y} instead of just {x} No free symbols of generators that don't appear in the expression of the polynomial should appear in the set of free symbols.

========          >>> from sympy import Poly        >>> from sympy.abc import x, y        >>> from sympy.abc import x, y, z          >>> Poly(x**2 + 1).free_symbols         {x}


Question: Poly(x,x,y).free_symbols -{x, y} instead of just {x} No free symbols of generators that don't appear in the expression of the polynomial should appear in the set of free symbols.

{x, y}         >>> Poly(x**2 + y, x).free_symbols         {x, y}        >>> Poly(x**2 + y, x, z).free_symbols        {x, y}          """        symbols = set([])        for gen in self.gens:            symbols |= gen.free_symbols        symbols = set()        gens = self.gens        for i in range(len(gens)):            for monom in self.monoms():                if monom[i]:                    symbols |= gens[i].free_symbols                    break          return symbols | self.free_symbols_in_domain


Question: Poly(x,x,y).free_symbols -{x, y} instead of just {x} No free symbols of generators that don't appear in the expression of the polynomial should appear in the set of free symbols.

def ltrim(f, gen):         """        Remove dummy generators from the "left" of ``f``.        Remove dummy generators from ``f`` that are to the left of        specified ``gen`` in the generators as ordered. When ``gen``        is an integer, it refers to the generator located at that        position within the tuple of generators of ``f``.          Examples         ========


Question: Poly(x,x,y).free_symbols -{x, y} instead of just {x} No free symbols of generators that don't appear in the expression of the polynomial should appear in the set of free symbols.

>>> Poly(y**2 + y*z**2, x, y, z).ltrim(y)         Poly(y**2 + y*z**2, y, z, domain='ZZ')        >>> Poly(z, x, y, z).ltrim(-1)        Poly(z, z, domain='ZZ')          """         rep = f.as_dict(native=True)         j = f._gen_to_level(gen)         terms = {}          for monom, coeff in rep.items():            monom = monom[j:]             if monom not in terms:                terms[monom] = coeff            else:            if any(i for i in monom[:j]):                # some generator is used in the portion to be trimmed                 raise PolynomialError("can't left trim %s" % f)             terms[monom[j:]] = coeff         gens = f.gens[j:]          return f.new(DMP.from_dict(terms, len(gens) - 1, f.rep.dom), *gens)


Question: Poly(x,x,y).free_symbols -{x, y} instead of just {x} No free symbols of generators that don't appear in the expression of the polynomial should appear in the set of free symbols.

False          """        indices = set([])        indices = set()          for gen in gens:             try:diff --git a/sympy/solvers/polysys.py b/sympy/solvers/polysys.py-- a/sympy/solvers/polysys.py++ b/sympy/solvers/polysys.py


Question: Poly(x,x,y).free_symbols -{x, y} instead of just {x} No free symbols of generators that don't appear in the expression of the polynomial should appear in the set of free symbols.

from sympy.polys import Poly, groebner, roots from sympy.polys.polytools import parallel_poly_from_expr from sympy.polys.polyerrors import (ComputationFailed,    PolificationFailed, CoercionFailed)    PolificationFailed, CoercionFailed, PolynomialError) from sympy.simplify import rcollect from sympy.utilities import default_sort_key, postfixes


Question: Poly(x,x,y).free_symbols -{x, y} instead of just {x} No free symbols of generators that don't appear in the expression of the polynomial should appear in the set of free symbols.

if len(polys) == len(opt.gens) == 2:         f, g = polys         a, b = f.degree_list()        c, d = g.degree_list()        if a <= 2 and b <= 2 and c <= 2 and d <= 2:        if all(i <= 2 for i in f.degree_list() + g.degree_list()):             try:                 return solve_biquadratic(f, g, opt)             except SolveFailed:


Question: Poly(x,x,y).free_symbols -{x, y} instead of just {x} No free symbols of generators that don't appear in the expression of the polynomial should appear in the set of free symbols.

if len(G) != 2:         raise SolveFailed     p, q = G     x, y = opt.gens    p, q = G    if not p.gcd(q).is_ground:        # not 0-dimensional        raise SolveFailed      p = Poly(p, x, expand=False)    q = q.ltrim(-1)     p_roots = [ rcollect(expr, y) for expr in roots(p).keys() ]    q = q.ltrim(-1)     q_roots = list(roots(q).keys())      solutions = []


Question: Poly(x,x,y).free_symbols -{x, y} instead of just {x} No free symbols of generators that don't appear in the expression of the polynomial should appear in the set of free symbols.

def _is_univariate(f):         """Returns True if 'f' is univariate in its last variable. """         for monom in f.monoms():            if any(m > 0 for m in monom[:-1]):            if any(m for m in monom[:-1]):                 return False          return True


Question: Wrong/surprising result from noncommutative The following behavior in Sympy seems surprising: I would have expected this produces . The issue appears to be that uses fractional powers in the substitution. This then raises questions on what noncommutative symbols in Sympy actually mean mathematically. At least in my use cases for them, certainly does not imply . I would suggest something like the following:

def _eval_subs(self, old, new):         from sympy import exp, log, Symbol         def _check(ct1, ct2, old):            """Return bool, pow where, if bool is True, then the exponent of            Pow `old` will combine with `pow` so the substitution is valid,            otherwise bool will be False,            """Return (bool, pow, remainder_pow) where, if bool is True, then the            exponent of Pow `old` will combine with `pow` so the substitution            is valid, otherwise bool will be False.            For noncommutative objects, `pow` will be an integer, and a factor            `Pow(old.base, remainder_pow)` needs to be included. If there is            no such factor, None is returned. For commutative objects,            remainder_pow is always None.              cti are the coefficient and terms of an exponent of self or old             In this _eval_subs routine a change like (b**(2*x)).subs(b**x, y)             will give y**2 since (b**x)**2 == b**(2*x); if that equality does             not hold then the substitution should not occur so `bool` will be             False.             """             coeff1, terms1 = ct1             coeff2, terms2 = ct2             if terms1 == terms2:                pow = coeff1/coeff2                try:                    pow = as_int(pow)                    combines = True                except ValueError:                    combines = Pow._eval_power(                        Pow(*old.as_base_exp(), evaluate=False),                        pow) is not None                return combines, pow            return False, None                if old.is_commutative:                    # Allow fractional powers for commutative objects                    pow = coeff1/coeff2                    try:                        pow = as_int(pow)                        combines = True                    except ValueError:                        combines = Pow._eval_power(                            Pow(*old.as_base_exp(), evaluate=False),                            pow) is not None                    return combines, pow, None                else:                    # With noncommutative symbols, substitute only integer powers                    if not isinstance(terms1, tuple):                        terms1 = (terms1,)                    if not all(term.is_integer for term in terms1):                        return False, None, None                    try:                        # Round pow toward zero                        pow, remainder = divmod(as_int(coeff1), as_int(coeff2))                        if pow < 0 and remainder != 0:                            pow += 1                            remainder -= as_int(coeff2)                        if remainder == 0:                            remainder_pow = None                        else:                            remainder_pow = Mul(remainder, *terms1)                        return True, pow, remainder_pow                    except ValueError:                        # Can't substitute                        pass            return False, None, None          if old == self.base:             return new**self.exp._subs(old, new)


Question: Wrong/surprising result from noncommutative The following behavior in Sympy seems surprising: I would have expected this produces . The issue appears to be that uses fractional powers in the substitution. This then raises questions on what noncommutative symbols in Sympy actually mean mathematically. At least in my use cases for them, certainly does not imply . I would suggest something like the following:

if self.exp.is_Add is False:                 ct1 = self.exp.as_independent(Symbol, as_Add=False)                 ct2 = old.exp.as_independent(Symbol, as_Add=False)                ok, pow = _check(ct1, ct2, old)                ok, pow, remainder_pow = _check(ct1, ct2, old)                 if ok:                     # issue 5180: (x**(6*y)).subs(x**(3*y),z)->z**2                    return self.func(new, pow)                    result = self.func(new, pow)                    if remainder_pow is not None:                        result = Mul(result, Pow(old.base, remainder_pow))                    return result             else:  # b**(6*x+a).subs(b**(3*x), y) -> y**2 * b**a                 # exp(exp(x) + exp(x**2)).subs(exp(exp(x)), w) -> w * exp(exp(x**2))                 oarg = old.exp


Question: Wrong/surprising result from noncommutative The following behavior in Sympy seems surprising: I would have expected this produces . The issue appears to be that uses fractional powers in the substitution. This then raises questions on what noncommutative symbols in Sympy actually mean mathematically. At least in my use cases for them, certainly does not imply . I would suggest something like the following:

for a in self.exp.args:                     newa = a._subs(old, new)                     ct1 = newa.as_coeff_mul()                    ok, pow = _check(ct1, ct2, old)                    ok, pow, remainder_pow = _check(ct1, ct2, old)                     if ok:                         new_l.append(new**pow)                        if remainder_pow is not None:                            o_al.append(remainder_pow)                         continue                    elif not old.is_commutative and not newa.is_integer:                        # If any term in the exponent is non-integer,                        # we do not do any substitutions in the noncommutative case                        return                     o_al.append(newa)                 if new_l:                     new_l.append(Pow(self.base, Add(*o_al), evaluate=False))


Question: Wrong/surprising result from noncommutative The following behavior in Sympy seems surprising: I would have expected this produces . The issue appears to be that uses fractional powers in the substitution. This then raises questions on what noncommutative symbols in Sympy actually mean mathematically. At least in my use cases for them, certainly does not imply . I would suggest something like the following:

ct1 = old.args[0].as_independent(Symbol, as_Add=False)             ct2 = (self.exp*log(self.base)).as_independent(                 Symbol, as_Add=False)            ok, pow = _check(ct1, ct2, old)            ok, pow, remainder_pow = _check(ct1, ct2, old)             if ok:                return self.func(new, pow)  # (2**x).subs(exp(x*log(2)), z) -> z                result = self.func(new, pow)  # (2**x).subs(exp(x*log(2)), z) -> z                if remainder_pow is not None:                    result = Mul(result, Pow(old.base, remainder_pow))                return result      def as_base_exp(self):         """Return base and exp of self.


Question: Behavior of Matrix hstack and vstack changed in sympy 1.1 In sympy 1.0: returns Now, same in sympy 1.1: returns (0, 3) whereas: returns (1, 6)

>>> C == A.row_insert(A.rows, Matrix(B))         True         """        if not self:            return type(self)(other)        # A null matrix can always be stacked (see  #10770)        if self.rows == 0 and self.cols != other.cols:            return self._new(0, other.cols, []).col_join(other)         A, B = self, other         if not A.cols == B.cols:             raise ShapeError()


Question: Behavior of Matrix hstack and vstack changed in sympy 1.1 In sympy 1.0: returns Now, same in sympy 1.1: returns (0, 3) whereas: returns (1, 6)

>>> C == A.col_insert(A.cols, B)         True         """        if not self:            return type(self)(other)        # A null matrix can always be stacked (see  #10770)        if self.cols == 0 and self.rows != other.rows:            return self._new(other.rows, 0, []).row_join(other)         A, B = self, other         if not A.rows == B.rows:             raise ShapeError()


Question: decompose() function in intpoly returns a list of arbitrary order The decompose() function, with separate=True, returns , which is ordered arbitrarily. What is this used for? It should be sorted somehow, or returning a set (in which case, why not just use the returned dictionary and have the caller take the values). This is causing test failures for me after some changes to the core. CC

>>> decompose(x**2 + x*y + x + y + x**3*y**2 + y**5)     {1: x + y, 2: x**2 + x*y, 5: x**3*y**2 + y**5}     >>> decompose(x**2 + x*y + x + y + x**3*y**2 + y**5, True)    [x, y, x**2, y**5, x*y, x**3*y**2]    {x, x**2, y, y**5, x*y, x**3*y**2}     """     expr = S(expr)     poly_dict = {}


Question: decompose() function in intpoly returns a list of arbitrary order The decompose() function, with separate=True, returns , which is ordered arbitrarily. What is this used for? It should be sorted somehow, or returning a set (in which case, why not just use the returned dictionary and have the caller take the values). This is causing test failures for me after some changes to the core. CC

degrees = [(sum(degree_list(monom, *symbols)), monom)                        for monom in expr.args]             if separate:                return [monom[1] for monom in degrees]                return {monom[1] for monom in degrees}             else:                 for monom in degrees:                     degree, term = monom


Question: decompose() function in intpoly returns a list of arbitrary order The decompose() function, with separate=True, returns , which is ordered arbitrarily. What is this used for? It should be sorted somehow, or returning a set (in which case, why not just use the returned dictionary and have the caller take the values). This is causing test failures for me after some changes to the core. CC

poly_dict[0] = expr      if separate:        return list(poly_dict.values())        return set(poly_dict.values())     return poly_dict


Question: Exponent doesn't fully simplify Say I have code like this: The output is How do I simplify it to 0?

args.append(a)                     else:                         args.append(newa)                if not _aresame(tuple(args), tail_args):                    tail = self.func(*args)                return self.func(x, tail)                return self.func(x, *args)          # this is the same as above, but there were no pure-number args to         # deal with


Question: Exponent doesn't fully simplify Say I have code like this: The output is How do I simplify it to 0?

args.append(a)             else:                 args.append(newa)        if not _aresame(tuple(args), self.args):            return self.func(*args)        return self        return self.func(*args)      @classmethod     def make_args(cls, expr):


Question: degree(multivariate) -degree of first generator When giving the degree function a multivariate expression, the default degree returned is for the first generator which is chosen canonically but arbitrarily. When the degree method of Poly is called, this is not so bad because one would/should know what the generators are. For the case of using the function, however, I believe it allows ambiguity to pass silently by not requiring the generator to be specified. Here, the return value depends on the symbols chosen

GeneratorsError, ) from sympy.utilities import group, sift, publicfrom sympy.utilities import group, sift, public, filldedent  import sympy.polys import mpmath


Question: degree(multivariate) -degree of first generator When giving the degree function a multivariate expression, the default degree returned is for the first generator which is chosen canonically but arbitrarily. When the degree method of Poly is called, this is not so bad because one would/should know what the generators are. For the case of using the function, however, I believe it allows ambiguity to pass silently by not requiring the generator to be specified. Here, the return value depends on the symbols chosen

from sympy.polys import polyoptions as options from sympy.core.compatibility import iterable, rangefrom sympy.core.compatibility import iterable, range, ordered  @public class Poly(Expr):


Question: degree(multivariate) -degree of first generator When giving the degree function a multivariate expression, the default degree returned is for the first generator which is chosen canonically but arbitrarily. When the degree method of Poly is called, this is not so bad because one would/should know what the generators are. For the case of using the function, however, I believe it allows ambiguity to pass silently by not requiring the generator to be specified. Here, the return value depends on the symbols chosen

p, _ = poly_from_expr(f.as_expr())         if gen not in p.gens:             return S.Zero<ins>    elif not f.is_Poly and len(f.free_symbols) > 1:        raise TypeError(filldedent('''         A symbolic generator of interest is required for a multivariate         expression like func = %s, e.g. degree(func, gen = %s) instead of         degree(func, gen = %s).        ''' % (f, next(ordered(f.free_symbols)), gen)))</ins>      return Integer(p.degree(gen))


Question: Mod(x2, x) is not (always) 0 When the base is not an integer, is not 0. The base is not tested to be an integer in Mod's eval logic: so but

if p.is_infinite or q.is_infinite or p is nan or q is nan:                 return nan             if (p == q or p == -q or                    p.is_Pow and p.exp.is_Integer and p.base == q or                    p.is_Pow and p.exp.is_integer and p.base == q and q.is_integer                    and p.exp.is_positive or                     p.is_integer and q == 1):                 return S.Zero


Question: cse() has strange behaviour for MatrixSymbol indexing Example: This gives the following output: and are just copies of the matrices and , respectively.

Substitutions containing any Symbol from ``ignore`` will be ignored.     """     from sympy.matrices.expressions import MatrixExpr, MatrixSymbol, MatMul, MatAdd<ins>    from sympy.matrices.expressions.matexpr import MatrixElement</ins>      if opt_subs is None:         opt_subs = dict()


Question: cse() has strange behaviour for MatrixSymbol indexing Example: This gives the following output: and are just copies of the matrices and , respectively.

if not isinstance(expr, (Basic, Unevaluated)):             return         if isinstance(expr, Basic) and (expr.is_Atom or expr.is_Order):        if isinstance(expr, Basic) and (expr.is_Atom or expr.is_Order or isinstance(expr, MatrixSymbol) or isinstance(expr, MatrixElement)):             if expr.is_Symbol:                 excluded_symbols.add(expr)             return


Question: Problem factoring trivial polynomial The factoring of w is incorrect - look at the order of x it is 10^-8 not 10^-4. Bug in simplify ? Hi, I'm running into issues where simplify comes up with incorrect results. sympy verion 1.0, python version 3.52, ubuntu 16.04. I've also verified the same with the Sympy online console (). The problem comes when trying to simplify a mass matrix for a simple 3-DOF robot: If I use the matrix above directly, I get correct results: which should be: If on the other hand, I simplify first I get an incorrect result: I was wondering if this is a bug with simplify, or am I doing something wrong? Thanks.

factors[i] = (dup_convert(f, K, K0), k)              coeff = K0.convert(coeff, K)            coeff = K0.quo(coeff, denom)             if K0_inexact is None:                coeff = coeff/denom            else:            if K0_inexact:                 for i, (f, k) in enumerate(factors):                    f = dup_quo_ground(f, denom, K0)                    max_norm = dup_max_norm(f, K0)                    f = dup_quo_ground(f, max_norm, K0)                     f = dup_convert(f, K0, K0_inexact)                     factors[i] = (f, k)                    coeff = K0.mul(coeff, K0.pow(max_norm, k))                  coeff = K0_inexact.convert(coeff, K0)                 K0 = K0_inexact


Question: Problem factoring trivial polynomial The factoring of w is incorrect - look at the order of x it is 10^-8 not 10^-4. Bug in simplify ? Hi, I'm running into issues where simplify comes up with incorrect results. sympy verion 1.0, python version 3.52, ubuntu 16.04. I've also verified the same with the Sympy online console (). The problem comes when trying to simplify a mass matrix for a simple 3-DOF robot: If I use the matrix above directly, I get correct results: which should be: If on the other hand, I simplify first I get an incorrect result: I was wondering if this is a bug with simplify, or am I doing something wrong? Thanks.

factors[i] = (dmp_convert(f, u, K, K0), k)              coeff = K0.convert(coeff, K)            coeff = K0.quo(coeff, denom)             if K0_inexact is None:                coeff = coeff/denom            else:            if K0_inexact:                 for i, (f, k) in enumerate(factors):                    f = dmp_quo_ground(f, denom, u, K0)                    max_norm = dmp_max_norm(f, u, K0)                    f = dmp_quo_ground(f, max_norm, u, K0)                     f = dmp_convert(f, u, K0, K0_inexact)                     factors[i] = (f, k)                    coeff = K0.mul(coeff, K0.pow(max_norm, k))                  coeff = K0_inexact.convert(coeff, K0)                 K0 = K0_inexact


Question: simplify doesn't do the last simplification step Note: I'm using Python 3.5.1 and sympy 0.7.6.1. Full script is attached in the .zip file: I've been using Sympy to compute Laplacian in different geometrical coordinates system. This usually creates extremelly long expressions and simplify usually does a great job. However, I've come against one particular case where simplify does most of the job but doesn't perform the ultimate simplification step. I've reduced the problem set getting rid of all of the Derivative terms. The initial expression is still huge (675 ops!): ! A first call to sucessfully reduces it to : ! Which is great (23 ops), but somehow frustrating as we can factorize it a little more. If I apply again, then I get the expression I wanted (7 ops): ! If simplify worked perfectly, shouldn't yield a different result from From my understanding of how simplify works, it successively tries different simplification strategies and compares them. In that case, the order of the different strategies matters. In my particular case, the strategy than eventually did the final factorisation step may have been called to early. I fixed that calling simplify again. We could fix it applying an optional recursive mode at the end of the simplify function: I can make the pull request if that helps.

from sympy.core.compatibility import (iterable,     ordered, range, as_int) from sympy.core.numbers import Float, I, pi, Rational, Integerfrom sympy.core.function import expand_log, count_ops, _mexpand, _coeff_isnegfrom sympy.core.function import expand_log, count_ops, _mexpand, _coeff_isneg, nfloat from sympy.core.rules import Transform from sympy.core.evaluate import global_evaluate from sympy.functions import (


Question: simplify doesn't do the last simplification step Note: I'm using Python 3.5.1 and sympy 0.7.6.1. Full script is attached in the .zip file: I've been using Sympy to compute Laplacian in different geometrical coordinates system. This usually creates extremelly long expressions and simplify usually does a great job. However, I've come against one particular case where simplify does most of the job but doesn't perform the ultimate simplification step. I've reduced the problem set getting rid of all of the Derivative terms. The initial expression is still huge (675 ops!): ! A first call to sucessfully reduces it to : ! Which is great (23 ops), but somehow frustrating as we can factorize it a little more. If I apply again, then I get the expression I wanted (7 ops): ! If simplify worked perfectly, shouldn't yield a different result from From my understanding of how simplify works, it successively tries different simplification strategies and compares them. In that case, the order of the different strategies matters. In my particular case, the strategy than eventually did the final factorisation step may have been called to early. I fixed that calling simplify again. We could fix it applying an optional recursive mode at the end of the simplify function: I can make the pull request if that helps.

return e  def simplify(expr, ratio=1.7, measure=count_ops, fu=False):def simplify(expr, ratio=1.7, measure=count_ops, rational=False):     """     Simplifies the given expression.


Question: simplify doesn't do the last simplification step Note: I'm using Python 3.5.1 and sympy 0.7.6.1. Full script is attached in the .zip file: I've been using Sympy to compute Laplacian in different geometrical coordinates system. This usually creates extremelly long expressions and simplify usually does a great job. However, I've come against one particular case where simplify does most of the job but doesn't perform the ultimate simplification step. I've reduced the problem set getting rid of all of the Derivative terms. The initial expression is still huge (675 ops!): ! A first call to sucessfully reduces it to : ! Which is great (23 ops), but somehow frustrating as we can factorize it a little more. If I apply again, then I get the expression I wanted (7 ops): ! If simplify worked perfectly, shouldn't yield a different result from From my understanding of how simplify works, it successively tries different simplification strategies and compares them. In that case, the order of the different strategies matters. In my particular case, the strategy than eventually did the final factorisation step may have been called to early. I fixed that calling simplify again. We could fix it applying an optional recursive mode at the end of the simplify function: I can make the pull request if that helps.

simplification strategies and then compares them using the measure     function, we get a completely different result that is still different     from the input expression by doing this.<ins>    If rational=True, Floats will be recast as Rationals before simplification.    If rational=None, Floats will be recast as Rationals but the result will    be recast as Floats. If rational=False(default) then nothing will be done    to the Floats.</ins>     """     expr = sympify(expr)


Question: simplify doesn't do the last simplification step Note: I'm using Python 3.5.1 and sympy 0.7.6.1. Full script is attached in the .zip file: I've been using Sympy to compute Laplacian in different geometrical coordinates system. This usually creates extremelly long expressions and simplify usually does a great job. However, I've come against one particular case where simplify does most of the job but doesn't perform the ultimate simplification step. I've reduced the problem set getting rid of all of the Derivative terms. The initial expression is still huge (675 ops!): ! A first call to sucessfully reduces it to : ! Which is great (23 ops), but somehow frustrating as we can factorize it a little more. If I apply again, then I get the expression I wanted (7 ops): ! If simplify worked perfectly, shouldn't yield a different result from From my understanding of how simplify works, it successively tries different simplification strategies and compares them. In that case, the order of the different strategies matters. In my particular case, the strategy than eventually did the final factorisation step may have been called to early. I fixed that calling simplify again. We could fix it applying an optional recursive mode at the end of the simplify function: I can make the pull request if that helps.

if len(expr.args) == 1 and len(expr.args[0].args) == 1 and \                isinstance(expr.args[0], expr.inverse(argindex=1)):                 return simplify(expr.args[0].args[0], ratio=ratio,                                measure=measure, fu=fu)        return expr.func(*[simplify(x, ratio=ratio, measure=measure, fu=fu)                                measure=measure, rational=rational)        return expr.func(*[simplify(x, ratio=ratio, measure=measure, rational=rational)                          for x in expr.args])      # TODO: Apply different strategies, considering expression pattern:


Question: simplify doesn't do the last simplification step Note: I'm using Python 3.5.1 and sympy 0.7.6.1. Full script is attached in the .zip file: I've been using Sympy to compute Laplacian in different geometrical coordinates system. This usually creates extremelly long expressions and simplify usually does a great job. However, I've come against one particular case where simplify does most of the job but doesn't perform the ultimate simplification step. I've reduced the problem set getting rid of all of the Derivative terms. The initial expression is still huge (675 ops!): ! A first call to sucessfully reduces it to : ! Which is great (23 ops), but somehow frustrating as we can factorize it a little more. If I apply again, then I get the expression I wanted (7 ops): ! If simplify worked perfectly, shouldn't yield a different result from From my understanding of how simplify works, it successively tries different simplification strategies and compares them. In that case, the order of the different strategies matters. In my particular case, the strategy than eventually did the final factorisation step may have been called to early. I fixed that calling simplify again. We could fix it applying an optional recursive mode at the end of the simplify function: I can make the pull request if that helps.

return choices[0]         return min(choices, key=measure) <ins>    # rationalize Floats    floats = False    if rational is not False and expr.has(Float):        floats = True        expr = nsimplify(expr, rational=True)</ins>     expr = bottom_up(expr, lambda w: w.normal())     expr = Mul(*powsimp(expr).as_content_primitive())     _e = cancel(expr)


Question: simplify doesn't do the last simplification step Note: I'm using Python 3.5.1 and sympy 0.7.6.1. Full script is attached in the .zip file: I've been using Sympy to compute Laplacian in different geometrical coordinates system. This usually creates extremelly long expressions and simplify usually does a great job. However, I've come against one particular case where simplify does most of the job but doesn't perform the ultimate simplification step. I've reduced the problem set getting rid of all of the Derivative terms. The initial expression is still huge (675 ops!): ! A first call to sucessfully reduces it to : ! Which is great (23 ops), but somehow frustrating as we can factorize it a little more. If I apply again, then I get the expression I wanted (7 ops): ! If simplify worked perfectly, shouldn't yield a different result from From my understanding of how simplify works, it successively tries different simplification strategies and compares them. In that case, the order of the different strategies matters. In my particular case, the strategy than eventually did the final factorisation step may have been called to early. I fixed that calling simplify again. We could fix it applying an optional recursive mode at the end of the simplify function: I can make the pull request if that helps.

if expr.has(BesselBase):         expr = besselsimp(expr)     if expr.has(TrigonometricFunction) and not fu or expr.has(            HyperbolicFunction):    if expr.has(TrigonometricFunction, HyperbolicFunction):         expr = trigsimp(expr, deep=True)      if expr.has(log):


Question: simplify doesn't do the last simplification step Note: I'm using Python 3.5.1 and sympy 0.7.6.1. Full script is attached in the .zip file: I've been using Sympy to compute Laplacian in different geometrical coordinates system. This usually creates extremelly long expressions and simplify usually does a great job. However, I've come against one particular case where simplify does most of the job but doesn't perform the ultimate simplification step. I've reduced the problem set getting rid of all of the Derivative terms. The initial expression is still huge (675 ops!): ! A first call to sucessfully reduces it to : ! Which is great (23 ops), but somehow frustrating as we can factorize it a little more. If I apply again, then I get the expression I wanted (7 ops): ! If simplify worked perfectly, shouldn't yield a different result from From my understanding of how simplify works, it successively tries different simplification strategies and compares them. In that case, the order of the different strategies matters. In my particular case, the strategy than eventually did the final factorisation step may have been called to early. I fixed that calling simplify again. We could fix it applying an optional recursive mode at the end of the simplify function: I can make the pull request if that helps.

expr = product_simplify(expr)      short = shorter(powsimp(expr, combine='exp', deep=True), powsimp(expr), expr)<ins>    short = shorter(short, cancel(short))</ins>     short = shorter(short, factor_terms(short), expand_power_exp(expand_mul(short)))     if short.has(TrigonometricFunction, HyperbolicFunction, ExpBase):         short = exptrigsimp(short, simplify=False)


Question: simplify doesn't do the last simplification step Note: I'm using Python 3.5.1 and sympy 0.7.6.1. Full script is attached in the .zip file: I've been using Sympy to compute Laplacian in different geometrical coordinates system. This usually creates extremelly long expressions and simplify usually does a great job. However, I've come against one particular case where simplify does most of the job but doesn't perform the ultimate simplification step. I've reduced the problem set getting rid of all of the Derivative terms. The initial expression is still huge (675 ops!): ! A first call to sucessfully reduces it to : ! Which is great (23 ops), but somehow frustrating as we can factorize it a little more. If I apply again, then I get the expression I wanted (7 ops): ! If simplify worked perfectly, shouldn't yield a different result from From my understanding of how simplify works, it successively tries different simplification strategies and compares them. In that case, the order of the different strategies matters. In my particular case, the strategy than eventually did the final factorisation step may have been called to early. I fixed that calling simplify again. We could fix it applying an optional recursive mode at the end of the simplify function: I can make the pull request if that helps.

if measure(expr) > ratio*measure(original_expr):         expr = original_expr <ins>    # restore floats    if floats and rational is None:        expr = nfloat(expr, exponent=False)</ins>     return expr


Question: Simplification fails to recognize sin expressed as exponentials The expression for has not been recognized, while expressions for and have.

short = shorter(short, cancel(short))     short = shorter(short, factor_terms(short), expand_power_exp(expand_mul(short)))     if short.has(TrigonometricFunction, HyperbolicFunction, ExpBase):        short = exptrigsimp(short, simplify=False)        short = exptrigsimp(short)      # get rid of hollow 2-arg Mul factorization     hollow_mul = Transform(


Question: Simplification fails to recognize sin expressed as exponentials The expression for has not been recognized, while expressions for and have.

def expander(fro):         def repl(nu, z):             if (nu % 1) == S(1)/2:                return exptrigsimp(trigsimp(unpolarify(                return simplify(trigsimp(unpolarify(                         fro(nu, z0).rewrite(besselj).rewrite(jn).expand(                             func=True)).subs(z0, z)))             elif nu.is_Integer and nu > 1:diff --git a/sympy/simplify/trigsimp.py b/sympy/simplify/trigsimp.py-- a/sympy/simplify/trigsimp.py++ b/sympy/simplify/trigsimp.py


Question: Simplification fails to recognize sin expressed as exponentials The expression for has not been recognized, while expressions for and have.

return trigsimpfunc(expr)  def exptrigsimp(expr, simplify=True):def exptrigsimp(expr):     """     Simplifies exponential / trigonometric / hyperbolic functions.    When ``simplify`` is True (default) the expression obtained after the    simplification step will be then be passed through simplify to    precondition it so the final transformations will be applied.      Examples     ========


Question: Simplification fails to recognize sin expressed as exponentials The expression for has not been recognized, while expressions for and have.

return min(*choices, key=count_ops)     newexpr = bottom_up(expr, exp_trig)     if simplify:        newexpr = newexpr.simplify()    # conversion from exp to hyperbolic    ex = newexpr.atoms(exp, S.Exp1)    ex = [ei for ei in ex if 1/ei not in ex]    ## sinh and cosh    for ei in ex:        e2 = ei**-2        if e2 in ex:            a = e2.args[0]/2 if not e2 is S.Exp1 else S.Half            newexpr = newexpr.subs((e2 + 1)*ei, 2*cosh(a))            newexpr = newexpr.subs((e2 - 1)*ei, 2*sinh(a))    ## exp ratios to tan and tanh    for ei in ex:        n, d = ei - 1, ei + 1        et = n/d        etinv = d/n  # not 1/et or else recursion errors arise        a = ei.args[0] if ei.func is exp else S.One        if a.is_Mul or a is S.ImaginaryUnit:            c = a.as_coefficient(I)            if c:                t = S.ImaginaryUnit*tan(c/2)                newexpr = newexpr.subs(etinv, 1/t)                newexpr = newexpr.subs(et, t)                continue        t = tanh(a/2)        newexpr = newexpr.subs(etinv, 1/t)        newexpr = newexpr.subs(et, t)    def f(rv):        if not rv.is_Mul:            return rv        rvd = rv.as_powers_dict()        newd = rvd.copy()        def signlog(expr, sign=1):            if expr is S.Exp1:                return sign, 1            elif isinstance(expr, exp):                return sign, expr.args[0]            elif sign == 1:                return signlog(-expr, sign=-1)            else:                return None, None        ee = rvd[S.Exp1]        for k in rvd:            if k.is_Add and len(k.args) == 2:                # k == c*(1 + sign*E**x)                c = k.args[0]                sign, x = signlog(k.args[1]/c)                if not x:                    continue                m = rvd[k]                newd[k] -= m                if ee == -x*m/2:                    # sinh and cosh                    newd[S.Exp1] -= ee                    ee = 0                    if sign == 1:                        newd[2*c*cosh(x/2)] += m                    else:                        newd[-2*c*sinh(x/2)] += m                elif newd[1 - sign*S.Exp1**x] == -m:                    # tanh                    del newd[1 - sign*S.Exp1**x]                    if sign == 1:                        newd[-c/tanh(x/2)] += m                    else:                        newd[-c*tanh(x/2)] += m                else:                    newd[1 + sign*S.Exp1**x] += m                    newd[c] += m        return Mul(*[k**newd[k] for k in newd])    newexpr = bottom_up(newexpr, f)      # sin/cos and sinh/cosh ratios to tan and tanh, respectively     if newexpr.has(HyperbolicFunction):


Question: periodicity(Abs(sin(x)),x) return 2pi periodicity(Abs(sin(x)),x) returns 2pi instead of pi periodicity(x 2, x) give recursion error and It fixes issue it will stop any relational Expression from entering into infinite recursion and return None It improves the periodicity of absolute trigonometric function issue

"""     from sympy import simplify, lcm_list    from sympy.functions.elementary.trigonometric import TrigonometricFunction    from sympy.functions.elementary.complexes import Abs    from sympy.functions.elementary.trigonometric import (        TrigonometricFunction, sin, cos, csc, sec)     from sympy.solvers.decompogen import decompogen    from sympy.core.relational import Relational    def _check(orig_f, period):        '''Return the checked period or raise an error.'''        new_f = orig_f.subs(symbol, symbol + period)        if new_f.equals(orig_f):            return period        else:            raise NotImplementedError(filldedent('''                The period of the given function cannot be verified.                When `%s` was replaced with `%s + %s` in `%s`, the result                was `%s` which was not recognized as being the same as                the original function.                So either the period was wrong or the two forms were                not recognized as being equal.                Set check=False to obtain the value.''' %                (symbol, symbol, period, orig_f, new_f)))      orig_f = f     f = simplify(orig_f)     period = None     if not f.has(symbol):    if symbol not in f.free_symbols:         return S.Zero     if isinstance(f, Relational):        f = f.lhs - f.rhs     if isinstance(f, TrigonometricFunction):         try:             period = f.period(symbol)         except NotImplementedError:             pass     if isinstance(f, Abs):        arg = f.args[0]        if isinstance(arg, (sec, csc, cos)):            # all but tan and cot might have a            # a period that is half as large            # so recast as sin            arg = sin(arg.args[0])        period = periodicity(arg, symbol)        if period is not None and isinstance(arg, sin):            # the argument of Abs was a trigonometric other than            # cot or tan; test to see if the half-period            # is valid. Abs(arg) has behaviour equivalent to            # orig_f, so use that for test:            orig_f = Abs(arg)            try:                return _check(orig_f, period/2)            except NotImplementedError as err:                if check:                    raise NotImplementedError(err)            # else let new orig_f and period be            # checked below     if f.is_Pow:         base, expo = f.args         base_has_sym = base.has(symbol)


Question: periodicity(Abs(sin(x)),x) return 2pi periodicity(Abs(sin(x)),x) returns 2pi instead of pi periodicity(x 2, x) give recursion error and It fixes issue it will stop any relational Expression from entering into infinite recursion and return None It improves the periodicity of absolute trigonometric function issue

if period is not None:         if check:            if orig_f.subs(symbol, symbol + period) == orig_f:                return period            else:                raise NotImplementedError(filldedent('''                    The period of the given function cannot be verified.                    Set check=False to obtain the value.'''))            return _check(orig_f, period)         return period      return Nonediff --git a/sympy/solvers/decompogen.py b/sympy/solvers/decompogen.py-- a/sympy/solvers/decompogen.py++ b/sympy/solvers/decompogen.py


Question: periodicity(Abs(sin(x)),x) return 2pi periodicity(Abs(sin(x)),x) returns 2pi instead of pi periodicity(x 2, x) give recursion error and It fixes issue it will stop any relational Expression from entering into infinite recursion and return None It improves the periodicity of absolute trigonometric function issue

from sympy.core import Function, Pow, sympifyfrom sympy.core import (Function, Pow, sympify, Expr)from sympy.core.relational import Relational from sympy.polys import Poly, decomposefrom sympy.utilities.misc import func_name   def decompogen(f, symbol):


Question: periodicity(Abs(sin(x)),x) return 2pi periodicity(Abs(sin(x)),x) returns 2pi instead of pi periodicity(x 2, x) give recursion error and It fixes issue it will stop any relational Expression from entering into infinite recursion and return None It improves the periodicity of absolute trigonometric function issue

"""     f = sympify(f)<ins>    if not isinstance(f, Expr) or isinstance(f, Relational):        raise TypeError('expecting Expr but got: `%s`' % func_name(f))    if symbol not in f.free_symbols:        return [f]</ins>     result = []      # ===== Simple Functions ===== #


Question: AccumBounds needs recreatable str/srepr The str and srepr should be recreatable. The pretty printer should be the only thing that prints the pretty form.

>>> from sympy.abc import x      >>> AccumBounds(0, 1) + AccumBounds(1, 2)    <1, 3>    AccumBounds(1, 3)      >>> AccumBounds(0, 1) - AccumBounds(0, 2)    <-2, 1>    AccumBounds(-2, 1)      >>> AccumBounds(-2, 3)*AccumBounds(-1, 1)    <-3, 3>    AccumBounds(-3, 3)      >>> AccumBounds(1, 2)*AccumBounds(3, 5)    <3, 10>    AccumBounds(3, 10)      The exponentiation of AccumulationBounds is defined     as follows:


Question: AccumBounds needs recreatable str/srepr The str and srepr should be recreatable. The pretty printer should be the only thing that prints the pretty form.

AccumulationBounds object is neglected.      >>> AccumBounds(-1, 4)**(S(1)/2)    <0, 2>    AccumBounds(0, 2)      >>> AccumBounds(1, 2)**2    <1, 4>    AccumBounds(1, 4)      >>> AccumBounds(-1, oo)**(-1)    <-oo, oo>    AccumBounds(-oo, oo)      Note: `<a, b>^2` is not same as `<a, b>*<a, b>`      >>> AccumBounds(-1, 1)**2    <0, 1>    AccumBounds(0, 1)      >>> AccumBounds(1, 3) < 4     True


Question: AccumBounds needs recreatable str/srepr The str and srepr should be recreatable. The pretty printer should be the only thing that prints the pretty form.

is defined as `f(\langle a, b\rangle) = \{ f(x) \mid a \le x \le b \}`      >>> sin(AccumBounds(pi/6, pi/3))    <1/2, sqrt(3)/2>    AccumBounds(1/2, sqrt(3)/2)      >>> exp(AccumBounds(0, 1))    <1, E>    AccumBounds(1, E)      >>> log(AccumBounds(1, E))    <0, 1>    AccumBounds(0, 1)      Some symbol in an expression can be substituted for a AccumulationBounds     object. But it doesn't necessarily evaluate the AccumulationBounds for


Question: AccumBounds needs recreatable str/srepr The str and srepr should be recreatable. The pretty printer should be the only thing that prints the pretty form.

the form it is used for substituion. For example:      >>> (x**2 + 2*x + 1).subs(x, AccumBounds(-1, 1))    <-1, 4>    AccumBounds(-1, 4)      >>> ((x + 1)**2).subs(x, AccumBounds(-1, 1))    <0, 4>    AccumBounds(0, 4)      References     ==========


Question: AccumBounds needs recreatable str/srepr The str and srepr should be recreatable. The pretty printer should be the only thing that prints the pretty form.

>>> from sympy import AccumBounds, FiniteSet         >>> AccumBounds(1, 3).intersection(AccumBounds(2, 4))        <2, 3>        AccumBounds(2, 3)          >>> AccumBounds(1, 3).intersection(AccumBounds(4, 6))         EmptySet()diff --git a/sympy/printing/pretty/pretty.py b/sympy/printing/pretty/pretty.py-- a/sympy/printing/pretty/pretty.py++ b/sympy/printing/pretty/pretty.py


Question: AccumBounds needs recreatable str/srepr The str and srepr should be recreatable. The pretty printer should be the only thing that prints the pretty form.

return self._print_seq(i.args[:2], left, right)     def _print_AccumuBounds(self, i):    def _print_AccumulationBounds(self, i):         left = '<'         right = '>' diff --git a/sympy/printing/str.py b/sympy/printing/str.py-- a/sympy/printing/str.py++ b/sympy/printing/str.py


Question: AccumBounds needs recreatable str/srepr The str and srepr should be recreatable. The pretty printer should be the only thing that prints the pretty form.

return fin.format(**{'a': a, 'b': b, 'm': m})      def _print_AccumulationBounds(self, i):        left = '<'        right = '>'        return "%s%s, %s%s" % \                (left, self._print(i.min), self._print(i.max), right)        return "AccumBounds(%s, %s)" % (self._print(i.min), self._print(i.max))      def _print_Inverse(self, I):         return "%s^-1" % self.parenthesize(I.arg, PRECEDENCE["Pow"])


Question: implement Piecewise rewriting for Min and Max This was mention in . I am just puttng this here as a separate issue.

from sympy.core.mul import Mul from sympy.core.numbers import Rational from sympy.core.power import Powfrom sympy.core.relational import Equalityfrom sympy.core.relational import Equality, Relational from sympy.core.singleton import Singleton from sympy.core.symbol import Dummy from sympy.core.rules import Transform


Question: implement Piecewise rewriting for Min and Max This was mention in . I am just puttng this here as a separate issue.

from sympy.functions.elementary.integers import floor from sympy.logic.boolalg import And <ins>def _minmax_as_Piecewise(op, *args):    # helper for Min/Max rewrite as Piecewise    from sympy.functions.elementary.piecewise import Piecewise    ec = []    for i, a in enumerate(args):        c = []        for j in range(i + 1, len(args)):            c.append(Relational(a, args[j], op))        ec.append((a, And(*c)))    return Piecewise(*ec)</ins> class IdentityFunction(with_metaclass(Singleton, Lambda)):     """     The identity function


Question: implement Piecewise rewriting for Min and Max This was mention in . I am just puttng this here as a separate issue.

return Add(*[j*Mul(*[Heaviside(j - i) for i in args if i!=j]) \                 for j in args]) <ins>    def _eval_rewrite_as_Piecewise(self, *args):        return _minmax_as_Piecewise('>=', *args)</ins>     def _eval_is_positive(self):         return fuzzy_or(a.is_positive for a in self.args)


Question: implement Piecewise rewriting for Min and Max This was mention in . I am just puttng this here as a separate issue.

return Add(*[j*Mul(*[Heaviside(i-j) for i in args if i!=j]) \                 for j in args]) <ins>    def _eval_rewrite_as_Piecewise(self, *args):        return _minmax_as_Piecewise('<=', *args)</ins>     def _eval_is_positive(self):         return fuzzy_and(a.is_positive for a in self.args)


Question: Test failures on non-NumPy environment Following tests fail on where NumPy is not installed: Temporarily fixed by : Following doctest fails:

[(k, 'mpmath.' + v) for k, v in _known_functions_mpmath.items()]     )) <del>    def _print_Integer(self, e):        return '%s(%d)' % (self._module_format('mpmath.mpf'), e)</del>     def _print_Float(self, e):         # XXX: This does not handle setting mpmath.mp.dps. It is assumed that         # the caller of the lambdified function will have set it to sufficient


Question: evalf with subs argument incorrectly evaluates expressions with floor returns instead of 20. (Python 3.6.1, SymPy 1.1.1). It seems that incorrect attribute is somehow attached to the result of , which is why 20 is then rounded to the nearest power of 2. Considering that works correctly, perhaps a fix would be to make pass its subs argument to first, i.e., act the same as Based on a

x = fzero             nint += int(no*(mpf_cmp(x or fzero, fzero) == no))         nint = from_int(nint)        return nint, fastlog(nint) + 10        return nint, INF      re_, im_, re_acc, im_acc = None, None, None, None


Question: Eigenvalues of a 3 by 3 symbolic matrix are not found by .eigenvals throws Since the characteristic polynomial is cubic, it can be solved explicitly: returns three roots of the characteristic polynomial. I do not understand why these are not found by which returns (hence the failure of method). Declaring x as a real symbol does not help. Based on Stack Overflow post

if not result:                                 for root in _try_decompose(f):                                     _update_dict(result, root, 1)<ins>                        else:                            for r in _try_heuristics(f):                                _update_dict(result, r, 1)</ins>                     else:                         for root in _try_decompose(f):                             _update_dict(result, root, 1)


Question: UnboundLocalError in evalf I found this after changing the order of Mul args in Based on the code, I think the elif clauses that define reprec and imprec should have an . That appears to fix it, although I didn't try to debug to see why the arg order is mattering here.

elif re.is_number:                 re = re._to_mpmath(prec, allow_ints=False)._mpf_                 reprec = prec            else:                raise NotImplementedError             if im == 0:                 im = None                 imprec = None             elif im.is_number:                 im = im._to_mpmath(prec, allow_ints=False)._mpf_                 imprec = prec            else:                raise NotImplementedError             r = re, im, reprec, imprec         except AttributeError:             raise NotImplementedError


Question: bell(n).limit(n, oo) should be oo rather than bell(oo) should take the value infinity, but the current output is . As the Bell numbers represent the number of partitions of a set, it seems natural that should be able to be evaluated rather than be returned unevaluated. This issue is also in line with the recent fixes to the corresponding limit for the Fibonacci numbers and Lucas numbers. I'm new to Sympy, so I'd appreciate the opportunity to fix this bug myself if that's alright.

@classmethod     def eval(cls, n, k_sym=None, symbols=None):<ins>        if n is S.Infinity:            if k_sym is None:                return S.Infinity            else:                raise ValueError("Bell polynomial is not defined")        if n.is_negative or n.is_integer is False:            raise ValueError("a non-negative integer expected")</ins>         if n.is_Integer and n.is_nonnegative:             if k_sym is None:                 return Integer(cls._bell(int(n)))


Question: Python 2-3 pickle fails with float-containing expressions Dumping a pickled sympy expression containing a float in Python 2, then loading it in Python 3 generates an error. Here is a minimum working example, verified with sympy git commit (master at time of writing), Python 2.7 and Python 3.6: and the result:

# it's a hexadecimal (coming from a pickled object)                 # assume that it is in standard form                 num = list(num)<ins>                # If we're loading an object pickled in Python 2 into                # Python 3, we may need to strip a tailing 'L' because                # of a shim for int on Python 3, see issue #13470.                if num[1].endswith('L'):                    num[1] = num[1][:-1]</ins>                 num[1] = long(num[1], 16)                 _mpf_ = tuple(num)             else:


Question: .subs on coth(log(tan(x))) errors for certain integral values from sympy import * x = Symbol('x') e = coth(log(tan(x))) print(e.subs(x, 2)) ... File "C:\Users\E\Desktop\sympy-master\sympy\functions\elementary\", line 590, in eval if cotm is S.ComplexInfinity: NameError: name 'cotm' is not defined Fails for 2, 3, 5, 6, 8, 9, 11, 12, 13, 15, 18, ... etc.

x, m = _peeloff_ipi(arg)                 if m:                     cothm = coth(m)                    if cotm is S.ComplexInfinity:                    if cothm is S.ComplexInfinity:                         return coth(x)                     else: # cothm == 0                         return tanh(x)


Question: Product(n + 1 / 2k, [k, 0, n-1]) is incorrect from sympy import from import n,k p = Product(n + 1 / 2k, [k, 0, n-1]).doit() print(simplify(p)) 2(n(-n + 1)/2) + nn print(p.subs(n,2)) 9/2 This is incorrect- for example, the product for is . The correct expression involves the .

# There is expression, which couldn't change by                 # as_numer_denom(). E.g. n**(2/3) + 1 --> (n**(2/3) + 1, 1).                 # We have to catch this case.                p = sum([self._eval_product(i, (k, a, n)) for i in p.as_coeff_Add()])                from sympy.concrete.summations import Sum                p = exp(Sum(log(p), (k, a, n)))             else:                 p = self._eval_product(p, (k, a, n))             return p / q


Question: randMatrix won't generatte symmetric sparse matrices When setting the percent parameter to anything else than 100, randMatrix fails to generate symmetric matrices. Consider the following examples: ' ' ' In [1]: import sympy In [2]: from sympy.matrices import randMatrix In [3]: randMatrix(3, symmetric=True, percent=1) Out[3]: Matrix([ [13, 61, 13], [59, 29, 59], [88, 13, 61]]) In [4]: randMatrix(3, symmetric=True, percent=50) Out[4]: Matrix([ [90, 60, 0], [ 0, 0, 0], [60, 59, 25]]) In [7]: randMatrix(3, symmetric=True, percent=99) Out[7]: Matrix([ [0, 0, 19], [0, 0, 0], [0, 0, 0]]) In [9]: randMatrix(3, symmetric=True, percent=0) Out[9]: Matrix([ [78, 78, 61], [68, 8, 61], [22, 68, 8]]) ' ' ' Also, the documentation says , but the behaviour is the opposite. Setting it to 100 (default) produces the expected behaviour. The problem happens with both the released version from pypi and git master.

out[j, i] = out[i, j]     return out <ins></ins> def jordan_cell(eigenval, n):     """     Create a Jordan block:


Question: randMatrix won't generatte symmetric sparse matrices When setting the percent parameter to anything else than 100, randMatrix fails to generate symmetric matrices. Consider the following examples: ' ' ' In [1]: import sympy In [2]: from sympy.matrices import randMatrix In [3]: randMatrix(3, symmetric=True, percent=1) Out[3]: Matrix([ [13, 61, 13], [59, 29, 59], [88, 13, 61]]) In [4]: randMatrix(3, symmetric=True, percent=50) Out[4]: Matrix([ [90, 60, 0], [ 0, 0, 0], [60, 59, 25]]) In [7]: randMatrix(3, symmetric=True, percent=99) Out[7]: Matrix([ [0, 0, 19], [0, 0, 0], [0, 0, 0]]) In [9]: randMatrix(3, symmetric=True, percent=0) Out[9]: Matrix([ [78, 78, 61], [68, 8, 61], [22, 68, 8]]) ' ' ' Also, the documentation says , but the behaviour is the opposite. Setting it to 100 (default) produces the expected behaviour. The problem happens with both the released version from pypi and git master.

>>> A == randMatrix(3, seed=1)     True     >>> randMatrix(3, symmetric=True, percent=50) # doctest:+SKIP    [0, 68, 43]    [0, 68,  0]    [0, 91, 34]    [77, 70,  0],    [70,  0,  0],    [ 0,  0, 88]     """     if c is None:         c = r     # Note that ``Random()`` is equivalent to ``Random(None)``     prng = prng or random.Random(seed)    if symmetric and r != c:        raise ValueError(            'For symmetric matrices, r must equal c, but %i != %i' % (r, c))     if not symmetric:         m = Matrix._new(r, c, lambda i, j: prng.randint(min, max))    else:        m = zeros(r)        for i in range(r):            for j in range(i, r):                m[i, j] = prng.randint(min, max)        for i in range(r):            for j in range(i):                m[i, j] = m[j, i]    if percent == 100:        return m    else:        z = int(r*c*percent // 100)        if percent == 100:            return m        z = int(r*c*(100 - percent) // 100)         m._mat[:z] = [S.Zero]*z         prng.shuffle(m._mat)        return m    # Symmetric case    if r != c:        raise ValueError('For symmetric matrices, r must equal c, but %i != %i' % (r, c))    m = zeros(r)    ij = [(i, j) for i in range(r) for j in range(i, r)]    if percent != 100:        ij = prng.sample(ij, int(len(ij)*percent // 100))    for i, j in ij:        value = prng.randint(min, max)        m[i, j] = m[j, i] = value     return m


Question: Mod(Mod(x + 1, 2) + 1, 2) should simplify to Mod(x, 2) From Also, something like could be simplified. Recursively.

elif (qinner*(q + qinner)).is_nonpositive:                 # |qinner| < |q| and have different sign                 return p<ins>        elif isinstance(p, Add):            # separating into modulus and non modulus            both_l = non_mod_l, mod_l = [], []            for arg in p.args:                both_l[isinstance(arg, cls)].append(arg)            # if q same for all            if mod_l and all(inner.args[1] == q for inner in mod_l):                net = Add(*non_mod_l) + Add(*[i.args[0] for i in mod_l])                return cls(net, q)        elif isinstance(p, Mul):            # separating into modulus and non modulus            both_l = non_mod_l, mod_l = [], []            for arg in p.args:                both_l[isinstance(arg, cls)].append(arg)            if mod_l and all(inner.args[1] == q for inner in mod_l):                # finding distributive term                non_mod_l = [cls(x, q) for x in non_mod_l]                mod = []                non_mod = []                for j in non_mod_l:                    if isinstance(j, cls):                        mod.append(j.args[0])                    else:                        non_mod.append(j)                prod_mod = Mul(*mod)                prod_non_mod = Mul(*non_mod)                prod_mod1 = Mul(*[i.args[0] for i in mod_l])                net = prod_mod1*prod_mod                return prod_non_mod*cls(net, q)</ins>         # XXX other possibilities?          # extract gcd; any further simplification should be done by the user


Question: Undefined functions with number arguments should have is_number be False Original issue for : Original author:

"""         other = _sympify(other)        if not (other.is_Symbol or other.is_number):            raise TypeError("Input of type real symbol or Number expected")          if other is S.Infinity or other is S.NegativeInfinity:             if self.min is S.NegativeInfinity or self.max is S.Infinity:                 return True             return False         return And(self.min <= other and self.max >= other)        rv = And(self.min <= other, self.max >= other)        if rv not in (True, False):            raise TypeError("input failed to evaluate")        return rv      def intersection(self, other):         """diff --git a/sympy/core/basic.py b/sympy/core/basic.py-- a/sympy/core/basic.py++ b/sympy/core/basic.py


Question: Undefined functions with number arguments should have is_number be False Original issue for : Original author:

is_real = self.is_real         if is_real is False:             return False        is_number = self.is_number        if is_number is False:        if not self.is_number:             return False        # don't re-eval numbers that are already evaluated since        # this will create spurious precision         n, i = [p.evalf(2) if not p.is_Number else p             for p in self.as_real_imag()]        if not i.is_Number or not n.is_Number:        if not (i.is_Number and n.is_Number):             return False         if i:             # if _prec = 1 we can't decide and if not,diff --git a/sympy/core/expr.py b/sympy/core/expr.py-- a/sympy/core/expr.py++ b/sympy/core/expr.py


Question: Undefined functions with number arguments should have is_number be False Original issue for : Original author:

@property     def is_number(self):        """Returns True if ``self`` has no free symbols.        It will be faster than ``if not self.free_symbols``, however, since        ``is_number`` will fail as soon as it hits a free symbol.        """Returns True if ``self`` has no free symbols and no        undefined functions (AppliedUndef, to be precise). It will be        faster than ``if not self.free_symbols``, however, since        ``is_number`` will fail as soon as it hits a free symbol        or undefined function.          Examples         ========         >>> from sympy import log, Integral        >>> from sympy import log, Integral, cos, sin, pi        >>> from sympy.core.function import Function         >>> from sympy.abc import x        >>> f = Function('f')          >>> x.is_number         False        >>> f(1).is_number        False         >>> (2*x).is_number         False        >>> (2 + log(2)).is_number        True         >>> (2 + Integral(2, x)).is_number         False         >>> (2 + Integral(2, (x, 1, 2))).is_number         True         Not all numbers are Numbers in the SymPy sense:        >>> pi.is_number, pi.is_Number        (True, False)        If something is a number it should evaluate to a number with        real and imaginary parts that are Numbers; the result may not        be comparable, however, since the real and/or imaginary part        of the result may not have precision.        >>> cos(1).is_number and cos(1).is_comparable        True        >>> z = cos(1)**2 + sin(1)**2 - 1        >>> z.is_number        True        >>> z.is_comparable        False        See Also        ========        sympy.core.basic.is_comparable         """         return all(obj.is_number for obj in self.args)


Question: Undefined functions with number arguments should have is_number be False Original issue for : Original author:

simplify = flags.get('simplify', True)         # Except for expressions that contain units, only one of these should        # be necessary since if something is        # known to be a number it should also know that there are no        # free symbols. But is_number quits as soon as it hits a non-number        # whereas free_symbols goes until all free symbols have been collected,        # thus is_number should be faster. But a double check on free symbols        # is made just in case there is a discrepancy between the two.        free = self.free_symbols        if self.is_number or not free:            # if the following assertion fails then that object's free_symbols            # method needs attention: if an expression is a number it cannot            # have free symbols            assert not free        if self.is_number:             return True        free = self.free_symbols        if not free:            return True  # assume f(1) is some constant          # if we are only interested in some symbols and they are not in the         # free symbols then this expression is constant wrt those symbols


Question: Undefined functions with number arguments should have is_number be False Original issue for : Original author:

def _n2(a, b):    """Return (a - b).evalf(2) if it, a and b are comparable, else None.    """Return (a - b).evalf(2) if a and b are comparable, else None.     This should only be used when a and b are already sympified.     """    if not all(i.is_number for i in (a, b)):        return    # /!\ if is very important (see issue 8245) not to    # /!\ it is very important (see issue 8245) not to     # use a re-evaluated number in the calculation of dif     if a.is_comparable and b.is_comparable:         dif = (a - b).evalf(2)diff --git a/sympy/core/function.py b/sympy/core/function.py-- a/sympy/core/function.py++ b/sympy/core/function.py


Question: Undefined functions with number arguments should have is_number be False Original issue for : Original author:

function.     """     is_number = False     def __new__(cls, *args, **options):         args = list(map(sympify, args))         obj = super(AppliedUndef, cls).__new__(cls, *args, **options)diff --git a/sympy/functions/elementary/miscellaneous.py b/sympy/functions/elementary/miscellaneous.py-- a/sympy/functions/elementary/miscellaneous.py++ b/sympy/functions/elementary/miscellaneous.py


Question: Undefined functions with number arguments should have is_number be False Original issue for : Original author:

from sympy.core.containers import Tuple from sympy.core.operations import LatticeOp, ShortCircuit from sympy.core.function import (Application, Lambda,    ArgumentIndexError, AppliedUndef)    ArgumentIndexError) from sympy.core.expr import Expr from sympy.core.mul import Mul from sympy.core.numbers import Rational


Question: Undefined functions with number arguments should have is_number be False Original issue for : Original author:

# pre-filter, checking comparability of arguments             if not isinstance(arg, Expr) or arg.is_real is False or (                     arg.is_number and<del>                    not arg.has(AppliedUndef) and</del>                     not arg.is_comparable):                 raise ValueError("The argument '%s' is not comparable." % arg)


Question: Python code printer (pycode) should support Assignment There is a lookup on 'contract', either we should give it a default in the or we should make the code accessing use with a default.

code0 = self._print(temp)                 lines.append(code0)             return "\n".join(lines)        elif self._settings["contract"] and (lhs.has(IndexedBase) or        elif self._settings.get("contract", False) and (lhs.has(IndexedBase) or                 rhs.has(IndexedBase)):             # Here we check if there is looping to be done, and if so             # print the required loops.diff --git a/sympy/printing/pycode.py b/sympy/printing/pycode.py-- a/sympy/printing/pycode.py++ b/sympy/printing/pycode.py


Question: Python code printer (pycode) should support Assignment There is a lookup on 'contract', either we should give it a default in the or we should make the code accessing use with a default.

def _format_code(self, lines):         return lines <ins>    def _get_statement(self, codestring):        return "%s" % codestring</ins>     def _get_comment(self, text):         return "  # {0}".format(text)


Question: Matrix.col_insert() no longer seems to work correctly. Example: The 3 x 3 identify matrix to the right of the columns of twos is shifted from the bottom three rows to the top three rows. Do you think this has to do with your matrix refactor?

return self[i, j]             elif pos <= j < pos + other.cols:                 return other[i, j - pos]            return self[i, j - pos - other.cols]            return self[i, j - other.cols]          return self._new(self.rows, self.cols + other.cols,                          lambda i, j: entry(i, j))


Question: Ordinal arithmetic It would be nice if SymPy would have provided ordinal arithmetic. That would require either definining a new object called , that will either inherit from or from (option 1), or new assumption(s) that will allow the current symbols to be ordinals. How can it work with assumptions? Roughly as follows: and arithmetic should be defined: addition, multiplication and exponentiation (all are not commutative in general), and some other useful methods, such as: relationals supporting ordinals cantor normal form prime ordinals (perhaps also with the assumption) limits of sequences of ordinals cardinals (related to ) some "known" ordinals such as omega, omega_1, ..., epsilon numbers, etc. you can find a python implementation of non-symbolic ordinal arithmetic. I can be up to the task of defining a symbolic variation, but I don't think I can implement it in SymPy.

else:             return 'O(%s)' % self.stringify(expr.args, ', ', 0)     def _print_Ordinal(self, expr):        return expr.__str__()     def _print_Cycle(self, expr):         return expr.__str__() diff --git a/sympy/sets/__init__.py b/sympy/sets/__init__.py-- a/sympy/sets/__init__.py++ b/sympy/sets/__init__.py


Question: Ordinal arithmetic It would be nice if SymPy would have provided ordinal arithmetic. That would require either definining a new object called , that will either inherit from or from (option 1), or new assumption(s) that will allow the current symbols to be ordinals. How can it work with assumptions? Roughly as follows: and arithmetic should be defined: addition, multiplication and exponentiation (all are not commutative in general), and some other useful methods, such as: relationals supporting ordinals cantor normal form prime ordinals (perhaps also with the assumption) limits of sequences of ordinals cardinals (related to ) some "known" ordinals such as omega, omega_1, ..., epsilon numbers, etc. you can find a python implementation of non-symbolic ordinal arithmetic. I can be up to the task of defining a symbolic variation, but I don't think I can implement it in SymPy.

from .fancysets import ImageSet, Range, ComplexRegion from .contains import Contains from .conditionset import ConditionSetfrom .ordinals import Ordinal, OmegaPower, ord0 from ..core.singleton import S Reals = S.Reals del Sdiff --git a/sympy/sets/ordinals.py b/sympy/sets/ordinals.pynew file mode 100644-- /dev/null++ b/sympy/sets/ordinals.py