Repository: sympy/sympy

Issue:
Matrix.jordan_cells() fails
I have SymPy 0.7.7.dev (Python 2.7.6-64-bit) and the following **matrix**:
```python
M = Matrix([
   ...: [1, 0, 0, 1],
   ...: [0, 1, 1, 0],
   ...: [0, 0, 1, 1],
   ...: [0, 0, 0, 1]])
```
A 4x4 matrix, not very spectacular. However, the following computation **fails**:
```python
M.jordan_cells()
```
Here is what my interpreter says:
>/usr/local/lib/python2.7/dist-packages/sympy-0.7.7.dev-py2.7.egg/sympy/matrices/matrices.pyc in jordan_cells(self, calc_transformation)
>   3827         P = MutableMatrix.zeros(n)
>   3828         for j in range(0, n):
>-> 3829             P[:, j] = Pcols_new[j]
>   3830 
>   3831         return type(self)(P), Jcells

>IndexError: list index out of range

I believe that the Jordan normal form **can be** computed for this matrix. So I guess I fell in a corner case.
The online engine [WolframAlpha](http://www.wolframalpha.com/input/?i=jordan+normal+form+calculator&f1={{1%2C+0%2C+0%2C+1}%2C+{0%2C+1%2C+1%2C+0}%2C+{0%2C+0%2C+1%2C+1}%2C+{0%2C+0%2C+0%2C+1}}&f=JordanDecompositionCalculator.theMatrix_{{1%2C+0%2C+0%2C+1}%2C+{0%2C+1%2C+1%2C+0}%2C+{0%2C+0%2C+1%2C+1}%2C+{0%2C+0%2C+0%2C+1}}) finds a solution.
Can anyone help or fix?

[jordan_cells_failure.txt](https://github.com/sympy/sympy/files/57273/jordan_cells_failure.txt)

Discussion:

Patch:
diff --git a/sympy/categories/baseclasses.py b/sympy/categories/baseclasses.py
index 79b12d08da..9b3d68937a 100644
--- a/sympy/categories/baseclasses.py
+++ b/sympy/categories/baseclasses.py
@@ -1,6 +1,6 @@
 from __future__ import print_function, division
 
-from sympy.core import S, Basic, Dict, Symbol, Tuple, sympify
+from sympy.core import S, Basic, Dict, Symbol, Tuple
 from sympy.core.compatibility import range, iterable
 from sympy.sets import Set, FiniteSet, EmptySet
 
@@ -722,8 +722,8 @@ def __new__(cls, *args):
 
                 for morphism in conclusions_arg:
                     # Check that no new objects appear in conclusions.
-                    if ((sympify(objects.contains(morphism.domain)) is S.true) and
-                        (sympify(objects.contains(morphism.codomain)) is S.true)):
+                    if ((objects.contains(morphism.domain) == S.true) and
+                        (objects.contains(morphism.codomain) == S.true)):
                         # No need to add identities and recurse
                         # composites this time.
                         Diagram._add_morphism_closure(
@@ -920,14 +920,14 @@ def subdiagram_from_objects(self, objects):
 
         new_premises = {}
         for morphism, props in self.premises.items():
-            if ((sympify(objects.contains(morphism.domain)) is S.true) and
-                (sympify(objects.contains(morphism.codomain)) is S.true)):
+            if ((objects.contains(morphism.domain) == S.true) and
+                (objects.contains(morphism.codomain) == S.true)):
                 new_premises[morphism] = props
 
         new_conclusions = {}
         for morphism, props in self.conclusions.items():
-            if ((sympify(objects.contains(morphism.domain)) is S.true) and
-                (sympify(objects.contains(morphism.codomain)) is S.true)):
+            if ((objects.contains(morphism.domain) == S.true) and
+                (objects.contains(morphism.codomain) == S.true)):
                 new_conclusions[morphism] = props
 
         return Diagram(new_premises, new_conclusions)
diff --git a/sympy/combinatorics/named_groups.py b/sympy/combinatorics/named_groups.py
index 6febe32ee8..1c5ddb768c 100644
--- a/sympy/combinatorics/named_groups.py
+++ b/sympy/combinatorics/named_groups.py
@@ -13,8 +13,9 @@ def AbelianGroup(*cyclic_orders):
     Returns the direct product of cyclic groups with the given orders.
 
     According to the structure theorem for finite abelian groups ([1]),
-    every finite abelian group can be written as the direct product of
-    finitely many cyclic groups.
+    every finite abelian group can be written as the direct product of finitely
+    many cyclic groups.
+    [1] http://groupprops.subwiki.org/wiki/Structure_theorem_for_finitely_generated_abelian_groups
 
     Examples
     ========
@@ -26,19 +27,12 @@ def AbelianGroup(*cyclic_orders):
     PermutationGroup([
             (6)(0 1 2),
             (3 4 5 6)])
-    >>> _.is_group
-    True
+    >>> _.is_group()
+    False
 
     See Also
     ========
-
     DirectProduct
-
-    References
-    ==========
-
-    [1] http://groupprops.subwiki.org/wiki/Structure_theorem_for_finitely_generated_abelian_groups
-
     """
     groups = []
     degree = 0
@@ -70,8 +64,8 @@ def AlternatingGroup(n):
 
     >>> from sympy.combinatorics.named_groups import AlternatingGroup
     >>> G = AlternatingGroup(4)
-    >>> G.is_group
-    True
+    >>> G.is_group()
+    False
     >>> a = list(G.generate_dimino())
     >>> len(a)
     12
@@ -139,8 +133,8 @@ def CyclicGroup(n):
 
     >>> from sympy.combinatorics.named_groups import CyclicGroup
     >>> G = CyclicGroup(6)
-    >>> G.is_group
-    True
+    >>> G.is_group()
+    False
     >>> G.order()
     6
     >>> list(G.generate_schreier_sims(af=True))
@@ -184,8 +178,8 @@ def DihedralGroup(n):
 
     >>> from sympy.combinatorics.named_groups import DihedralGroup
     >>> G = DihedralGroup(5)
-    >>> G.is_group
-    True
+    >>> G.is_group()
+    False
     >>> a = list(G.generate_dimino())
     >>> [perm.cyclic_form for perm in a]
     [[], [[0, 1, 2, 3, 4]], [[0, 2, 4, 1, 3]],
@@ -245,8 +239,8 @@ def SymmetricGroup(n):
 
     >>> from sympy.combinatorics.named_groups import SymmetricGroup
     >>> G = SymmetricGroup(4)
-    >>> G.is_group
-    True
+    >>> G.is_group()
+    False
     >>> G.order()
     24
     >>> list(G.generate_schreier_sims(af=True))
@@ -299,8 +293,8 @@ def RubikGroup(n):
     """Return a group of Rubik's cube generators
 
     >>> from sympy.combinatorics.named_groups import RubikGroup
-    >>> RubikGroup(2).is_group
-    True
+    >>> RubikGroup(2).is_group()
+    False
     """
     from sympy.combinatorics.generators import rubik
     if n <= 1:
diff --git a/sympy/combinatorics/perm_groups.py b/sympy/combinatorics/perm_groups.py
index 720abd62d3..f999efcbd7 100644
--- a/sympy/combinatorics/perm_groups.py
+++ b/sympy/combinatorics/perm_groups.py
@@ -16,7 +16,6 @@
 from sympy.ntheory import sieve
 from sympy.utilities.iterables import has_variety, is_sequence, uniq
 from sympy.utilities.randtest import _randrange
-from itertools import islice
 
 rmul = Permutation.rmul_with_af
 _af_new = Permutation._af_new
@@ -117,7 +116,6 @@ class PermutationGroup(Basic):
     [13] http://www.math.colostate.edu/~hulpke/CGT/cgtnotes.pdf
 
     """
-    is_group = True
 
     def __new__(cls, *args, **kwargs):
         """The default constructor. Accepts Cycle and Permutation forms.
@@ -168,29 +166,11 @@ def __new__(cls, *args, **kwargs):
     def __getitem__(self, i):
         return self._generators[i]
 
-    def __contains__(self, i):
-        """Return True if `i` is contained in PermutationGroup.
-
-        Examples
-        ========
-
-        >>> from sympy.combinatorics import Permutation, PermutationGroup
-        >>> p = Permutation(1, 2, 3)
-        >>> Permutation(3) in PermutationGroup(p)
-        True
-
-        """
-        if not isinstance(i, Permutation):
-            raise TypeError("A PermutationGroup contains only Permutations as "
-                            "elements, not elements of type %s" % type(i))
-        return self.contains(i)
-
     def __len__(self):
         return len(self._generators)
 
     def __eq__(self, other):
-        """Return True if PermutationGroup generated by elements in the
-        group are same i.e they represent the same PermutationGroup.
+        """Return True if self and other have the same generators.
 
         Examples
         ========
@@ -208,25 +188,7 @@ def __eq__(self, other):
         """
         if not isinstance(other, PermutationGroup):
             return False
-
-        set_self_gens = set(self.generators)
-        set_other_gens = set(other.generators)
-
-        # before reaching the general case there are also certain
-        # optimisation and obvious cases requiring less or no actual
-        # computation.
-        if set_self_gens == set_other_gens:
-            return True
-
-        # in the most general case it will check that each generator of
-        # one group belongs to the other PermutationGroup and vice-versa
-        for gen1 in set_self_gens:
-            if not other.contains(gen1):
-                return False
-        for gen2 in set_other_gens:
-            if not self.contains(gen2):
-                return False
-        return True
+        return set(self.generators) == set(other.generators)
 
     def __hash__(self):
         return super(PermutationGroup, self).__hash__()
@@ -1059,18 +1021,6 @@ def degree(self):
         """
         return self._degree
 
-    @property
-    def elements(self):
-        """Returns all the elements of the permutatio group in
-        a list
-
-        Examples
-        ========
-
-        >>> from sympy.combinatorics import Permutation
-        """
-        return set(list(islice(self.generate(), None)))
-
     def derived_series(self):
         r"""Return the derived series for the group.
 
@@ -1182,14 +1132,14 @@ def generate(self, method="coset", af=False):
         >>> from sympy.combinatorics import PermutationGroup
         >>> from sympy.combinatorics.polyhedron import tetrahedron
 
-        The permutation group given in the tetrahedron object is also
+        The permutation group given in the tetrahedron object is not
         true groups:
 
         >>> G = tetrahedron.pgroup
-        >>> G.is_group
-        True
+        >>> G.is_group()
+        False
 
-        Also the group generated by the permutations in the tetrahedron
+        But the group generated by the permutations in the tetrahedron
         pgroup -- even the first two -- is a proper group:
 
         >>> H = PermutationGroup(G[0], G[1])
@@ -1207,7 +1157,7 @@ def generate(self, method="coset", af=False):
             (0 3 2),
             (3)(0 1 2),
             (0 2)(1 3)])
-        >>> _.is_group
+        >>> _.is_group()
         True
         """
         if method == "coset":
@@ -3153,6 +3103,101 @@ def transitivity_degree(self):
         else:
             return self._transitivity_degree
 
+    def is_group(self):
+        """Return True if the group meets three criteria: identity is present,
+        the inverse of every element is also an element, and the product of
+        any two elements is also an element. If any of the tests fail, False
+        is returned.
+
+        Examples
+        ========
+
+        >>> from sympy.combinatorics import Permutation
+        >>> Permutation.print_cyclic = True
+        >>> from sympy.combinatorics import PermutationGroup
+        >>> from sympy.combinatorics.polyhedron import tetrahedron
+
+        The permutation group given in the tetrahedron object is not
+        a true group:
+
+        >>> G = tetrahedron.pgroup
+        >>> G.is_group()
+        False
+
+        But the group generated by the permutations in the tetrahedron
+        pgroup is a proper group:
+
+        >>> H = PermutationGroup(list(G.generate()))
+        >>> H.is_group()
+        True
+
+        The identity permutation is present:
+
+        >>> H.has(Permutation(G.degree - 1))
+        True
+
+        The product of any two elements from the group is also in the group:
+
+        >>> from sympy import TableForm
+        >>> g = list(H)
+        >>> n = len(g)
+        >>> m = []
+        >>> for i in g:
+        ...     m.append([g.index(i*H) for H in g])
+        ...
+        >>> TableForm(m, headings=[range(n), range(n)], wipe_zeros=False)
+           | 0  1  2  3  4  5  6  7  8  9  10 11
+        ----------------------------------------
+         0 | 11 0  8  10 6  2  7  4  5  3  9  1
+         1 | 0  1  2  3  4  5  6  7  8  9  10 11
+         2 | 6  2  7  4  5  3  9  1  11 0  8  10
+         3 | 5  3  9  1  11 0  8  10 6  2  7  4
+         4 | 3  4  0  2  10 6  11 8  9  7  1  5
+         5 | 4  5  6  7  8  9  10 11 0  1  2  3
+         6 | 10 6  11 8  9  7  1  5  3  4  0  2
+         7 | 9  7  1  5  3  4  0  2  10 6  11 8
+         8 | 7  8  4  6  2  10 3  0  1  11 5  9
+         9 | 8  9  10 11 0  1  2  3  4  5  6  7
+        10 | 2  10 3  0  1  11 5  9  7  8  4  6
+        11 | 1  11 5  9  7  8  4  6  2  10 3  0
+        >>>
+        The entries in the table give the element in the group corresponding
+        to the product of a given column element and row element:
+
+        >>> g[3]*g[2] == g[9]
+        True
+
+        The inverse of every element is also in the group:
+
+        >>> TableForm([[g.index(~gi) for gi in g]], headings=[[], range(n)],
+        ...    wipe_zeros=False)
+        0  1 2 3 4  5 6 7 8 9 10 11
+        ---------------------------
+        11 1 7 3 10 9 6 2 8 5 4  0
+
+        So we see that g[1] and g[3] are equivalent to their inverse while
+        g[7] == ~g[2].
+        """
+        # identity present
+        I = Permutation(size=self.degree)
+        for g in self:
+            if g == I:
+                break
+        else:
+            return False
+
+        # associativity already holds: a*(b*c) == (a*b)*c for permutations
+
+        # inverse of each is present
+        if not all(self.has(~a) for a in self):
+            return False
+
+        # closure
+        for a in self:
+            for b in self:
+                if not self.has(a*b):
+                    return False
+        return True
 
 def _orbit(degree, generators, alpha, action='tuples'):
     r"""Compute the orbit of alpha ``\{g(\alpha) | g \in G\}`` as a set.
diff --git a/sympy/combinatorics/polyhedron.py b/sympy/combinatorics/polyhedron.py
index d4ba35609f..3cb730aefc 100644
--- a/sympy/combinatorics/polyhedron.py
+++ b/sympy/combinatorics/polyhedron.py
@@ -637,9 +637,9 @@ def _pgroup_calcs():
     ... tetrahedron, cube, octahedron, dodecahedron, icosahedron)
     ...
     >>> polyhedra = (tetrahedron, cube, octahedron, dodecahedron, icosahedron)
-    >>> [h.pgroup.is_group for h in polyhedra]
+    >>> [h.pgroup.is_group() for h in polyhedra]
     ...
-    [True, True, True, True, True]
+    [False, False, False, False, False]
 
     Although tests in polyhedron's test suite check that powers of the
     permutations in the groups generate all permutations of the vertices
@@ -656,7 +656,7 @@ def _pgroup_calcs():
     ...             perms.add(p)
     ...
     ...     perms = [Permutation(p) for p in perms]
-    ...     assert PermutationGroup(perms).is_group
+    ...     assert PermutationGroup(perms).is_group()
 
     In addition to doing the above, the tests in the suite confirm that the
     faces are all present after the application of each permutation.
diff --git a/sympy/core/function.py b/sympy/core/function.py
index bca7628304..2c2f8e9f4a 100644
--- a/sympy/core/function.py
+++ b/sympy/core/function.py
@@ -646,23 +646,14 @@ def fdiff(self, argindex=1):
         """
         if not (1 <= argindex <= len(self.args)):
             raise ArgumentIndexError(self, argindex)
-
-        if self.args[argindex - 1].is_Symbol:
-            for i in range(len(self.args)):
-                if i == argindex - 1:
-                    continue
-                # See issue 8510
-                if self.args[argindex - 1] in self.args[i].free_symbols:
-                    break
-            else:
-                return Derivative(self, self.args[argindex - 1], evaluate=False)
-        # See issue 4624 and issue 4719 and issue 5600
-        arg_dummy = Dummy('xi_%i' % argindex)
-        arg_dummy.dummy_index = hash(self.args[argindex - 1])
-        new_args = [arg for arg in self.args]
-        new_args[argindex-1] = arg_dummy
-        return Subs(Derivative(self.func(*new_args), arg_dummy),
-            arg_dummy, self.args[argindex - 1])
+        if not self.args[argindex - 1].is_Symbol:
+            # See issue 4624 and issue 4719 and issue 5600
+            arg_dummy = Dummy('xi_%i' % argindex)
+            arg_dummy.dummy_index = hash(self.args[argindex - 1])
+            return Subs(Derivative(
+                self.subs(self.args[argindex - 1], arg_dummy),
+                arg_dummy), arg_dummy, self.args[argindex - 1])
+        return Derivative(self, self.args[argindex - 1], evaluate=False)
 
     def _eval_as_leading_term(self, x):
         """Stub that should be overridden by new Functions to return
diff --git a/sympy/matrices/matrices.py b/sympy/matrices/matrices.py
index 3a248551eb..7cf41cc890 100644
--- a/sympy/matrices/matrices.py
+++ b/sympy/matrices/matrices.py
@@ -3617,7 +3617,6 @@ def _jordan_block_structure(self):
                 # `a_0` is `dim(Kernel(Ms[0]) = dim (Kernel(I)) = 0` since `I` is regular
 
                 l_jordan_chains={}
-                chain_vectors=[]
                 Ms = [I]
                 Ns = [[]]
                 a = [0]
@@ -3673,41 +3672,34 @@ def _jordan_block_structure(self):
 
                 for s in reversed(range(1, smax+1)):
                     S = Ms[s]
-                    # We want the vectors in `Kernel((self-lI)^s)` (**),
-                    # but without those in `Kernel(self-lI)^s-1` so we will add these as additional equations
-                    # to the system formed by `S` (`S` will no longer be quadratic but this does no harm
-                    # since `S` is rank deficient).
+                    # We want the vectors in `Kernel((self-lI)^s)`,
+                    # but without those in `Kernel(self-lI)^s-1`
+                    # so we will add their adjoints as additional equations
+                    # to the system formed by `S` to get the orthogonal
+                    # complement.
+                    # (`S` will no longer be quadratic.)
+
                     exclude_vectors = Ns[s-1]
                     for k in range(0, a[s-1]):
                         S = S.col_join((exclude_vectors[k]).adjoint())
-                    # We also want to exclude the vectors in the chains for the bigger blocks
+
+                    # We also want to exclude the vectors
+                    # in the chains for the bigger blocks
                     # that we have already computed (if there are any).
                     # (That is why we start with the biggest s).
 
-                    ########   Implementation remark:   ########
-
-                    # Doing so for *ALL* already computed chain vectors
-                    # we actually exclude some vectors twice because they are already excluded
-                    # by the condition (**).
-                    # This happens if there are more than one blocks attached to the same eigenvalue *AND*
-                    # the current blocksize is smaller than the block whose chain vectors we exclude.
-                    # If the current block has size `s_i` and the next bigger block has size `s_i-1` then
-                    # the first `s_i-s_i-1` chainvectors of the bigger block are already excluded by (**).
-                    # The unnecassary adding of these equations could be avoided if the algorithm would
-                    # take into account the lengths of the already computed chains which are already stored
-                    # and add only the last `s` items.
-                    # However the following loop would be a good deal more nested to do so.
-                    # Since adding a linear dependent equation does not change the result,
-                    # it can harm only in terms of efficiency.
-                    # So to be sure I left it there for the moment.
-
-                    l = len(chain_vectors)
-                    if l > 0:
-                        for k in range(0, l):
-                            old = chain_vectors[k].adjoint()
-                            S = S.col_join(old)
+                    # Since Jordan blocks are not orthogonal in general
+                    # (in the original space), only those chain vectors
+                    # that are on level s (index `s-1` in a chain)
+                    # are added.
+
+                    for chain_list in l_jordan_chains.values():
+                        for chain in chain_list:
+                            S = S.col_join(chain[s-1].adjoint())
+
                     e0s = S.nullspace()
-                    # Determine the number of chain leaders which equals the number of blocks with that size.
+                    # Determine the number of chain leaders
+                    # for blocks of size `s`.
                     n_e0 = len(e0s)
                     s_chains = []
                     # s_cells=[]
@@ -3719,7 +3711,6 @@ def _jordan_block_structure(self):
 
                         # We want the chain leader appear as the last of the block.
                         chain.reverse()
-                        chain_vectors += chain
                         s_chains.append(chain)
                     l_jordan_chains[s] = s_chains
             jordan_block_structures[eigenval] = l_jordan_chains
diff --git a/sympy/sets/sets.py b/sympy/sets/sets.py
index ac7a486dba..3b0ba18a62 100644
--- a/sympy/sets/sets.py
+++ b/sympy/sets/sets.py
@@ -511,8 +511,8 @@ def __sub__(self, other):
         return Complement(self, other)
 
     def __contains__(self, other):
-        symb = sympify(self.contains(other))
-        if not (symb is S.true or symb is S.false):
+        symb = self.contains(other)
+        if symb not in (True, False):
             raise TypeError('contains did not evaluate to a bool: %r' % symb)
         return bool(symb)
 
@@ -949,8 +949,8 @@ def _union(self, other):
                 return Interval(start, end, left_open, right_open)
 
         # If I have open end points and these endpoints are contained in other
-        if ((self.left_open and sympify(other.contains(self.start)) is S.true) or
-                (self.right_open and sympify(other.contains(self.end)) is S.true)):
+        if ((self.left_open and other.contains(self.start) == True) or
+                (self.right_open and other.contains(self.end) == True)):
             # Fill in my end points and return
             open_left = self.left_open and self.start not in other
             open_right = self.right_open and self.end not in other
@@ -1427,23 +1427,13 @@ def _contains(self, other):
         return And(*[set.contains(other) for set in self.args])
 
     def __iter__(self):
-        no_iter = True
         for s in self.args:
             if s.is_iterable:
-                no_iter = False
                 other_sets = set(self.args) - set((s,))
                 other = Intersection(other_sets, evaluate=False)
-                for x in s:
-                    c = sympify(other.contains(x))
-                    if c is S.true:
-                        yield x
-                    elif c is S.false:
-                        pass
-                    else:
-                        yield c
+                return (x for x in s if x in other)
 
-        if no_iter:
-            raise ValueError("None of the constituent sets are iterable")
+        raise ValueError("None of the constituent sets are iterable")
 
     @staticmethod
     def _handle_finite_sets(args):
@@ -1495,7 +1485,7 @@ def _handle_finite_sets(args):
                     # contained in `v` then remove them from `v`
                     # and add this as a new arg
                     contained = [x for x in symbolic_s_list
-                        if sympify(v.contains(x)) is S.true]
+                        if v.contains(x) == True]
                     if contained != symbolic_s_list:
                         new_args.append(
                             v - FiniteSet(
@@ -1847,20 +1837,12 @@ def _complement(self, other):
                 return None
 
         elif isinstance(other, FiniteSet):
-            unk = []
-            for i in self:
-                c = sympify(other.contains(i))
-                if c is not S.true and c is not S.false:
-                    unk.append(i)
-            unk = FiniteSet(*unk)
+            unk = FiniteSet(*[el for el in self if other.contains(el)
+                not in (True, False)])
             if unk == self:
                 return
-            not_true = []
-            for i in other:
-                c = sympify(self.contains(i))
-                if c is not S.true:
-                    not_true.append(i)
-            return Complement(FiniteSet(*not_true), unk)
+            return Complement(FiniteSet(*[el for el in other if
+                self.contains(el) != True]), unk)
 
         return Set._complement(self, other)
 
@@ -1875,7 +1857,7 @@ def _union(self, other):
             return FiniteSet(*(self._elements | other._elements))
 
         # If other set contains one of my elements, remove it from myself
-        if any(sympify(other.contains(x)) is S.true for x in self):
+        if any(other.contains(x) == True for x in self):
             return set((
                 FiniteSet(*[x for x in self
                     if other.contains(x) != True]), other))
diff --git a/sympy/stats/rv.py b/sympy/stats/rv.py
index 1b04700aec..b3686a1fab 100644
--- a/sympy/stats/rv.py
+++ b/sympy/stats/rv.py
@@ -387,8 +387,7 @@ def __contains__(self, other):
         for domain in self.domains:
             # Collect the parts of this event which associate to this domain
             elem = frozenset([item for item in other
-                              if sympify(domain.symbols.contains(item[0]))
-                              is S.true])
+                              if domain.symbols.contains(item[0]) == S.true])
             # Test this sub-event
             if elem not in domain:
                 return False


Test patch:
diff --git a/sympy/combinatorics/tests/test_perm_groups.py b/sympy/combinatorics/tests/test_perm_groups.py
index d8f7118cda..13dbcf2359 100644
--- a/sympy/combinatorics/tests/test_perm_groups.py
+++ b/sympy/combinatorics/tests/test_perm_groups.py
@@ -8,7 +8,6 @@
 from sympy.combinatorics.polyhedron import tetrahedron as Tetra, cube
 from sympy.combinatorics.testutil import _verify_bsgs, _verify_centralizer,\
     _verify_normal_closure
-from sympy.utilities.pytest import raises
 
 rmul = Permutation.rmul
 
@@ -62,20 +61,6 @@ def test_order():
     assert g.order() == 1814400
 
 
-def test_equality():
-    p_1 = Permutation(0, 1, 3)
-    p_2 = Permutation(0, 2, 3)
-    p_3 = Permutation(0, 1, 2)
-    p_4 = Permutation(0, 1, 3)
-    g_1 = PermutationGroup(p_1, p_2)
-    g_2 = PermutationGroup(p_3, p_4)
-    g_3 = PermutationGroup(p_2, p_1)
-
-    assert g_1 == g_2
-    assert g_1.generators != g_2.generators
-    assert g_1 == g_3
-
-
 def test_stabilizer():
     S = SymmetricGroup(2)
     H = S.stabilizer(0)
@@ -210,7 +195,6 @@ def test_coset_factor():
     d = Permutation([1, 0, 2, 3, 4, 5])
     assert not g.coset_factor(d.array_form)
     assert not g.contains(d)
-    assert Permutation(2) in G
     c = Permutation([1, 0, 2, 3, 5, 4])
     v = g.coset_factor(c, True)
     tr = g.basic_transversals
@@ -707,13 +691,3 @@ def test_make_perm():
         Permutation([4, 7, 6, 5, 0, 3, 2, 1])
     assert cube.pgroup.make_perm(7, seed=list(range(7))) == \
         Permutation([6, 7, 3, 2, 5, 4, 0, 1])
-
-
-def test_elements():
-    p = Permutation(2, 3)
-    assert PermutationGroup(p).elements == set([Permutation(3), Permutation(2, 3)])
-
-
-def test_is_group():
-    assert PermutationGroup(Permutation(1,2), Permutation(2,4)).is_group == True
-    assert SymmetricGroup(4).is_group == True
diff --git a/sympy/combinatorics/tests/test_polyhedron.py b/sympy/combinatorics/tests/test_polyhedron.py
index 1b842b043e..6e55499c46 100644
--- a/sympy/combinatorics/tests/test_polyhedron.py
+++ b/sympy/combinatorics/tests/test_polyhedron.py
@@ -75,7 +75,7 @@ def check(h, size, rpt, target):
                 f = [[c[i] for i in f] for f in P.faces]
                 assert h.faces == Polyhedron(c, f).faces
         assert len(got) == target
-        assert PermutationGroup([Permutation(g) for g in got]).is_group
+        assert PermutationGroup([Permutation(g) for g in got]).is_group()
 
     for h, size, rpt, target in zip(
         (tetrahedron, square, octahedron, dodecahedron, icosahedron),
diff --git a/sympy/core/tests/test_function.py b/sympy/core/tests/test_function.py
index 96a9514932..86c0b6a723 100644
--- a/sympy/core/tests/test_function.py
+++ b/sympy/core/tests/test_function.py
@@ -289,12 +289,6 @@ def test_deriv1():
     assert f(3*sin(x)).diff(x) == 3*cos(x)*Subs(Derivative(f(x), x),
             Tuple(x), Tuple(3*sin(x)))
 
-    # See issue 8510
-    assert f(x, x + z).diff(x) == Subs(Derivative(f(y, x + z), y), Tuple(y), Tuple(x)) \
-            + Subs(Derivative(f(x, y), y), Tuple(y), Tuple(x + z))
-    assert f(x, x**2).diff(x) == Subs(Derivative(f(y, x**2), y), Tuple(y), Tuple(x)) \
-            + 2*x*Subs(Derivative(f(x, y), y), Tuple(y), Tuple(x**2))
-
 
 def test_deriv2():
     assert (x**3).diff(x) == 3*x**2
diff --git a/sympy/matrices/tests/test_matrices.py b/sympy/matrices/tests/test_matrices.py
index dd1bf13efc..61bc128932 100644
--- a/sympy/matrices/tests/test_matrices.py
+++ b/sympy/matrices/tests/test_matrices.py
@@ -1621,6 +1621,19 @@ def test_jordan_form_complex_issue_9274():
     assert J == Jmust1 or J == Jmust2
     assert simplify(P*J*P.inv()) == A
 
+def test_issue_10220():
+    # two non-orthogonal Jordan blocks with eigenvalue 1
+    M = Matrix([[1, 0, 0, 1],
+                [0, 1, 1, 0],
+                [0, 0, 1, 1],
+                [0, 0, 0, 1]])
+    P, C = M.jordan_cells()
+    assert P == Matrix([[0, 1, 0, 1],
+                        [1, 0, 0, 0],
+                        [0, 1, 0, 0],
+                        [0, 0, 1, 0]])
+    assert len(C) == 2
+
 
 def test_Matrix_berkowitz_charpoly():
     UA, K_i, K_w = symbols('UA K_i K_w')
diff --git a/sympy/sets/tests/test_sets.py b/sympy/sets/tests/test_sets.py
index 1afe34c7bb..cc9065d56c 100644
--- a/sympy/sets/tests/test_sets.py
+++ b/sympy/sets/tests/test_sets.py
@@ -936,8 +936,3 @@ def test_issue_10113():
     assert imageset(x, f, S.Reals) == Union(Interval(-oo, 0), Interval(1, oo, True, True))
     assert imageset(x, f, Interval(-2, 2)) == Interval(-oo, 0)
     assert imageset(x, f, Interval(-2, 3)) == Union(Interval(-oo, 0), Interval(S(9)/5, oo))
-
-
-def test_issue_10248():
-    assert list(Intersection(S.Reals, FiniteSet(x))) == [
-        And(x < oo, x > -oo)]