Permalink
Browse files

More tests, new file structure.

Added some more tests for the new functions and created a new file,
sympy/combinatorics/testutil.py that will accomodate utility functions
used specifically in testing functions from the combinatorics module
  • Loading branch information...
Aleksandar Makelov
Aleksandar Makelov committed Aug 16, 2012
1 parent 16ca149 commit 63821895c092e71bd0edfaa8ef508b133bbdd3d4
@@ -8,7 +8,7 @@
from sympy.ntheory import isprime, sieve
from sympy.combinatorics.util import _check_cycles_alt_sym,\
_distribute_gens_by_base, _orbits_transversals_from_bsgs,\
-_handle_precomputed_bsgs, _base_ordering, _strong_gens_from_distr, _strip, _verify_bsgs
+_handle_precomputed_bsgs, _base_ordering, _strong_gens_from_distr, _strip
def _smallest_change(h, alpha):
"""
@@ -663,7 +663,7 @@ def baseswap(self, base, strong_gens, pos, randomized=False,\
========
>>> from sympy.combinatorics.named_groups import SymmetricGroup
- >>> from sympy.combinatorics.util import _verify_bsgs
+ >>> from sympy.combinatorics.testutil import _verify_bsgs
>>> S = SymmetricGroup(4)
>>> S.schreier_sims()
>>> S.baseswap(S.base, S.strong_gens, 1, randomized=False)
@@ -2559,7 +2559,7 @@ def schreier_sims_incremental(self, base=None, gens=None):
>>> from sympy.combinatorics.named_groups import AlternatingGroup
>>> from sympy.combinatorics.perm_groups import PermutationGroup
- >>> from sympy.combinatorics.util import _verify_bsgs
+ >>> from sympy.combinatorics.testutil import _verify_bsgs
>>> A = AlternatingGroup(7)
>>> base = [2, 3]
>>> seq = [2, 3]
@@ -2705,7 +2705,7 @@ def schreier_sims_random(self, base=None, gens=None, consec_succ=10,\
========
>>> from sympy.combinatorics.perm_groups import PermutationGroup
- >>> from sympy.combinatorics.util import _verify_bsgs
+ >>> from sympy.combinatorics.testutil import _verify_bsgs
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> S = SymmetricGroup(5)
>>> base, strong_gens = S.schreier_sims_random(consec_succ=5)
@@ -2993,7 +2993,7 @@ def subgroup_search(self, prop, base=None, strong_gens=None, tests=None,\
>>> from sympy.combinatorics.named_groups import (SymmetricGroup,
... AlternatingGroup)
>>> from sympy.combinatorics.perm_groups import PermutationGroup
- >>> from sympy.combinatorics.util import _verify_bsgs
+ >>> from sympy.combinatorics.testutil import _verify_bsgs
>>> S = SymmetricGroup(7)
>>> prop_even = lambda x: x.is_even
>>> base, strong_gens = S.schreier_sims_incremental()
@@ -0,0 +1,14 @@
+from sympy.combinatorics.group_constructs import DirectProduct
+from sympy.combinatorics.named_groups import CyclicGroup, DihedralGroup
+
+def test_direct_product_n():
+ C = CyclicGroup(4)
+ D = DihedralGroup(4)
+ G = DirectProduct(C, C, C)
+ assert G.order() == 64
+ assert G.degree == 12
+ assert len(G.orbits()) == 3
+ assert G.is_abelian == True
+ H = DirectProduct(D, C)
+ assert H.order() == 32
+ assert H.is_abelian == False
@@ -6,9 +6,9 @@
from sympy.utilities.pytest import raises, skip, XFAIL
from sympy.combinatorics.generators import rubik_cube_generators
import random
-from sympy.combinatorics.util import _verify_bsgs, _naive_list_centralizer,\
-_cmp_perm_lists
-
+from sympy.combinatorics.testutil import _verify_bsgs, _verify_centralizer,\
+_cmp_perm_lists, _verify_normal_closure
+from sympy.combinatorics.util import _distribute_gens_by_base
def test_new():
a = Permutation([1, 0])
@@ -99,9 +99,7 @@ def test_center():
A = AlternatingGroup(3)
C = CyclicGroup(4)
G = D*A*C
- center_list_naive = _naive_list_centralizer(G, G)
- center_list = list((G.center()).generate())
- assert _cmp_perm_lists(center_list_naive, center_list)
+ assert _verify_centralizer(G, G)
def test_centralizer():
# the centralizer of the trivial group is the entire group
@@ -113,13 +111,40 @@ def test_centralizer():
triv = PermutationGroup([Permutation([0,1,2,3])])
D = DihedralGroup(4)
assert triv.centralizer(D) == triv
- # brute-force verifications
- S = SymmetricGroup(6)
- g = Permutation([2, 3, 4, 5, 0, 1])
- centralizer = S.centralizer(g)
- centralizer_list = list(centralizer.generate())
- centralizer_list_naive = _naive_list_centralizer(S, g)
- assert _cmp_perm_lists(centralizer_list, centralizer_list_naive)
+ # brute-force verifications for centralizers of groups
+ for i in (4, 5, 6):
+ S = SymmetricGroup(i)
+ A = AlternatingGroup(i)
+ C = CyclicGroup(i)
+ D = DihedralGroup(i)
+ for gp in (S, A, C, D):
+ for gp2 in (S, A, C, D):
+ if gp2 != gp:
+ assert _verify_centralizer(gp, gp2)
+ # verify the centralizer for all elements of several groups
+ S = SymmetricGroup(5)
+ elements = list(S.generate_dimino())
+ for element in elements:
+ assert _verify_centralizer(S, element)
+ A = AlternatingGroup(5)
+ elements = list(A.generate_dimino())
+ for element in elements:
+ assert _verify_centralizer(A, element)
+ D = DihedralGroup(7)
+ elements = list(D.generate_dimino())
+ for element in elements:
+ assert _verify_centralizer(D, element)
+ # verify centralizers of small groups within small groups
+ small = []
+ for i in (1, 2, 3):
+ small.append(SymmetricGroup(i))
+ small.append(AlternatingGroup(i))
+ small.append(DihedralGroup(i))
+ small.append(CyclicGroup(i))
+ for gp in small:
+ for gp2 in small:
+ if gp.degree == gp2.degree:
+ assert _verify_centralizer(gp, gp2)
def test_coset_repr():
a = Permutation([0, 2, 1])
@@ -410,18 +435,6 @@ def test_baseswap():
assert randomized[0] == [0, 2, 1]
assert _verify_bsgs(S, randomized[0], randomized[1]) == True
-def test_direct_product_n():
- C = CyclicGroup(4)
- D = DihedralGroup(4)
- G = DirectProduct(C, C, C)
- assert G.order() == 64
- assert G.degree == 12
- assert len(G.orbits()) == 3
- assert G.is_abelian == True
- H = DirectProduct(D, C)
- assert H.order() == 32
- assert H.is_abelian == False
-
def test_schreier_sims_incremental():
identity = Permutation([0, 1, 2, 3, 4])
TrivialGroup = PermutationGroup([identity])
@@ -476,3 +489,47 @@ def test_subgroup_search():
comm_g = A.subgroup_search(prop_comm_g, base=base, strong_gens=strong_gens)
assert _verify_bsgs(comm_g, base, comm_g.generators) == True
assert [prop_comm_g(gen) == True for gen in comm_g.generators]
+
+def test_normal_closure():
+ # the normal closure of the trivial group is trivial
+ S = SymmetricGroup(3)
+ identity = Permutation([0, 1, 2])
+ closure = S.normal_closure(identity)
+ assert closure.is_trivial
+ # the normal closure of the entire group is the entire group
+ A = AlternatingGroup(4)
+ assert A.normal_closure(A) == A
+ # brute-force verifications for subgroups
+ for i in (3, 4, 5):
+ S = SymmetricGroup(i)
+ A = AlternatingGroup(i)
+ D = DihedralGroup(i)
+ C = CyclicGroup(i)
+ for gp in (A, D, C):
+ assert _verify_normal_closure(S, gp)
+ # brute-force verifications for all elements of a group
+ S = SymmetricGroup(5)
+ elements = list(S.generate_dimino())
+ for element in elements:
+ assert _verify_normal_closure(S, element)
+ # small groups
+ small = []
+ for i in (1, 2, 3):
+ small.append(SymmetricGroup(i))
+ small.append(AlternatingGroup(i))
+ small.append(DihedralGroup(i))
+ small.append(CyclicGroup(i))
+ for gp in small:
+ for gp2 in small:
+ if gp2.is_subgroup(gp):
+ assert _verify_normal_closure(gp, gp2)
+
+def test_derived_series():
+ # the derived series of the trivial group consists only of the trivial group
+ triv = PermutationGroup([Permutation([0, 1, 2])])
+ assert triv.derived_series() == [triv]
+ # the derived series for a simple group consists only of the group itself
+ for i in (5, 6, 7):
+ A = AlternatingGroup(7)
+ assert A.derived_series() == A
+
@@ -0,0 +1,13 @@
+from sympy.combinatorics.named_groups import SymmetricGroup
+from sympy.combinatorics.testutil import _verify_bsgs
+
+def test_verify_bsgs():
+ S = SymmetricGroup(5)
+ S.schreier_sims()
+ base = S.base
+ strong_gens = S.strong_gens
+ gens = S.generators
+ assert _verify_bsgs(S, base, strong_gens) == True
+ assert _verify_bsgs(S, base[:-1], strong_gens) == False
+ assert _verify_bsgs(S, base, S.generators) == False
+
@@ -5,7 +5,8 @@
from sympy.combinatorics.util import _check_cycles_alt_sym, _strip,\
_distribute_gens_by_base, _strong_gens_from_distr,\
_orbits_transversals_from_bsgs, _handle_precomputed_bsgs, _base_ordering,\
-_verify_bsgs, _remove_gens
+_remove_gens
+from sympy.combinatorics.testutil import _verify_bsgs
def test_check_cycles_alt_sym():
perm1 = Permutation([[0, 1, 2, 3, 4, 5, 6], [7], [8], [9]])
@@ -97,16 +98,6 @@ def test_base_ordering():
degree = 7
assert _base_ordering(base, degree) == [3, 4, 0, 5, 1, 2, 6]
-def test_verify_bsgs():
- S = SymmetricGroup(5)
- S.schreier_sims()
- base = S.base
- strong_gens = S.strong_gens
- gens = S.generators
- assert _verify_bsgs(S, base, strong_gens) == True
- assert _verify_bsgs(S, base[:-1], strong_gens) == False
- assert _verify_bsgs(S, base, S.generators) == False
-
def test_remove_gens():
S = SymmetricGroup(10)
base, strong_gens = S.schreier_sims_incremental()
@@ -0,0 +1,156 @@
+from sympy.combinatorics.named_groups import SymmetricGroup, DihedralGroup, AlternatingGroup, CyclicGroup
+from sympy.combinatorics.util import _distribute_gens_by_base
+
+def _cmp_perm_lists(first, second):
+ """
+ Compare two lists of permutations as sets.
+
+ This is used for testing purposes. Since the array form of a
+ permutation is currently a list, Permutation is not hashable
+ and cannot be put into a set.
+
+ Examples
+ ========
+
+ >>> from sympy.combinatorics.permutations import Permutation
+ >>> from sympy.combinatorics.testutil import _cmp_perm_lists
+ >>> a = Permutation([0, 2, 3, 4, 1])
+ >>> b = Permutation([1, 2, 0, 4, 3])
+ >>> c = Permutation([3, 4, 0, 1, 2])
+ >>> ls1 = [a, b, c]
+ >>> ls2 = [b, c, a]
+ >>> _cmp_perm_lists(ls1, ls2)
+ True
+
+ """
+ first.sort(key = lambda x: x.array_form)
+ second.sort(key = lambda x: x.array_form)
+ return first == second
+
+def _naive_list_centralizer(self, other):
+ from sympy.combinatorics.perm_groups import PermutationGroup
+ """
+ Return a list of elements for the centralizer of a subgroup/set/element.
+
+ This is a brute-force implementation that goes over all elements of the group
+ and checks for membership in the centralizer. It is used to
+ test ``.centralizer()`` from ``sympy.combinatorics.perm_groups``.
+
+ Examples
+ ========
+ >>> from sympy.combinatorics.testutil import _naive_list_centralizer
+ >>> from sympy.combinatorics.named_groups import DihedralGroup
+ >>> D = DihedralGroup(4)
+ >>> _naive_list_centralizer(D, D)
+ [Permutation([0, 1, 2, 3]), Permutation([2, 3, 0, 1])]
+
+ See Also
+ ========
+
+ sympy.combinatorics.perm_groups.centralizer
+
+ """
+ if hasattr(other, 'generators'):
+ elements = list(self.generate_dimino())
+ gens = other.generators
+ commutes_with_gens = lambda x: [x*gen for gen in gens] == [gen*x for gen in gens]
+ centralizer_list = []
+ for element in elements:
+ if commutes_with_gens(element):
+ centralizer_list.append(element)
+ return centralizer_list
+ elif hasattr(other, 'getitem'):
+ return _naive_list_centralizer(self, PermutationGroup(other))
+ elif hasattr(other, 'array_form'):
+ return _naive_list_centralizer(self, PermutationGroup([other]))
+
+def _verify_bsgs(group, base, gens):
+ """
+ Verify the correctness of a base and strong generating set.
+
+ This is a naive implementation using the definition of a base and a strong
+ generating set relative to it. There are other procedures for
+ verifying a base and strong generating set, but this one will
+ serve for more robust testing.
+
+ Examples
+ ========
+
+ >>> from sympy.combinatorics.named_groups import AlternatingGroup
+ >>> from sympy.combinatorics.testutil import _verify_bsgs
+ >>> A = AlternatingGroup(4)
+ >>> A.schreier_sims()
+ >>> _verify_bsgs(A, A.base, A.strong_gens)
+ True
+
+ See Also
+ ========
+
+ sympy.combinatorics.perm_groups.PermutationGroup.schreier_sims
+
+ """
+ from sympy.combinatorics.perm_groups import PermutationGroup
+ strong_gens_distr = _distribute_gens_by_base(base, gens)
+ base_len = len(base)
+ degree = group.degree
+ current_stabilizer = group
+ for i in range(base_len):
+ candidate = PermutationGroup(strong_gens_distr[i])
+ if current_stabilizer.order() != candidate.order():
+ return False
+ current_stabilizer = current_stabilizer.stabilizer(base[i])
+ if current_stabilizer.order() != 1:
+ return False
+ return True
+
+def _verify_centralizer(group, arg, centr=None):
+ """
+ Verify the centralizer of a group/set/element inside another group.
+
+ This is used for testing ``.centralizer()`` from ``sympy.combinatorics.perm_groups``
+
+ Examples
+ ========
+
+ >>> from sympy.combinatorics.named_groups import SymmetricGroup, AlternatingGroup
+ >>> from sympy.combinatorics.perm_groups import PermutationGroup
+ >>> from sympy.combinatorics.permutations import Permutation
+ >>> from sympy.combinatorics.testutil import _verify_centralizer
+ >>> S = SymmetricGroup(5)
+ >>> A = AlternatingGroup(5)
+ >>> centr = PermutationGroup([Permutation([0, 1, 2, 3, 4])])
+ >>> _verify_centralizer(S, A, centr)
+ True
+
+ See Also
+ ========
+
+ _naive_list_centralizer, sympy.combinatorics.perm_groups.PermutationGroup.centralizer,\
+ _cmp_perm_lists
+
+ """
+ if centr is None:
+ centr = group.centralizer(arg)
+ centr_list = list(centr.generate_dimino())
+ centr_list_naive = _naive_list_centralizer(group, arg)
+ return _cmp_perm_lists(centr_list, centr_list_naive)
+
+def _verify_normal_closure(group, arg, closure=None):
+ from sympy.combinatorics.perm_groups import PermutationGroup
+ if closure is None:
+ closure = group.normal_closure(arg)
+ conjugates = []
+ group_els = list(group.generate_dimino())
+ if hasattr(arg, 'generators'):
+ subgr_gens = arg.generators
+ elif hasattr(arg, '__getitem__'):
+ subgr_gens = arg
+ elif hasattr(arg, 'array_form'):
+ subgr_gens = [arg]
+ for el in group_els:
+ for gen in subgr_gens:
+ conjugate = (~el)*gen*el
+ if conjugate not in conjugates:
+ conjugates.append(conjugate)
+ naive_closure = PermutationGroup(conjugates)
+ return closure == naive_closure
Oops, something went wrong.

0 comments on commit 6382189

Please sign in to comment.