Skip to content

Commit

Permalink
move the old __eq__ code from contains to is_in
Browse files Browse the repository at this point in the history
  • Loading branch information
smichr committed Sep 15, 2012
1 parent 556cc4e commit e1ef520
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 85 deletions.
108 changes: 61 additions & 47 deletions sympy/combinatorics/perm_groups.py
Expand Up @@ -1024,7 +1024,7 @@ def centralizer(self, other):
>>> S = SymmetricGroup(6)
>>> C = CyclicGroup(6)
>>> H = S.centralizer(C)
>>> H.contains(C, 1)
>>> H.is_in(C)
True
See Also
Expand Down Expand Up @@ -1123,7 +1123,7 @@ def commutator(self, G, H):
>>> S = SymmetricGroup(5)
>>> A = AlternatingGroup(5)
>>> G = S.commutator(S, A)
>>> G.contains(A, 1)
>>> G.is_in(A)
True
See Also
Expand Down Expand Up @@ -1427,9 +1427,9 @@ def derived_series(self):
>>> S = SymmetricGroup(4)
>>> len(S.derived_series())
4
>>> S.derived_series()[1].contains(AlternatingGroup(4), 1)
>>> S.derived_series()[1].is_in(AlternatingGroup(4))
True
>>> S.derived_series()[2].contains(DihedralGroup(2), 1)
>>> S.derived_series()[2].is_in(DihedralGroup(2))
True
See Also
Expand All @@ -1441,7 +1441,7 @@ def derived_series(self):
res = [self]
current = self
next = self.derived_subgroup()
while not current.contains(next, 1):
while not current.is_in(next):
res.append(next)
current = next
next = next.derived_subgroup()
Expand Down Expand Up @@ -1681,8 +1681,49 @@ def generators(self):
"""
return self._generators

def contains(self, g, foo=None):
"""Test if permutation (or group) ``g`` belong to self, ``G``.
def is_in(self, G):
"""Test if group ``self`` is contained in ``G``.
One group is contained in another if all its generators are contained
in the other's. This is not the same thing as a naive equality check.
Examples
========
>>> from sympy.combinatorics import Permutation
>>> Permutation.print_cyclic = True
>>> from sympy.combinatorics.perm_groups import PermutationGroup
>>> p = Permutation(0, 1, 2, 3, 4, 5)
>>> G1 = PermutationGroup([Permutation(0, 1, 2), Permutation(0, 1)])
>>> G2 = PermutationGroup([Permutation(0, 2), Permutation(0, 1, 2)])
>>> G3 = PermutationGroup([p, p**2])
>>> assert G1.order() == G2.order() == G3.order() == 6
>>> G1.is_in(G2)
True
>>> G1.is_in(G3)
False
>>> PermutationGroup(G3[1]).is_in(G3)
False
>>> PermutationGroup(G3[0]).is_in(G3)
True
See Also
========
contains
"""
if not isinstance(G, PermutationGroup):
return False
if self == G:
return True
if self.degree != G.degree:
return False
if self.order() != G.order():
return False
return all(G.contains(g) for g in self)

def contains(self, g):
"""Test if permutation ``g`` belong to self, ``G``.
If ``g`` is an element of ``G`` it can be written as a product
of factors drawn from the cosets of ``G``'s stabilizers. To see
Expand All @@ -1696,8 +1737,6 @@ def contains(self, g, foo=None):
>>> Permutation.print_cyclic = True
>>> from sympy.combinatorics.perm_groups import PermutationGroup
A group might contain a permutation:
>>> a = Permutation(1, 2)
>>> b = Permutation(2, 3, 1)
>>> G = PermutationGroup(a, b, degree=5)
Expand All @@ -1716,44 +1755,19 @@ def contains(self, g, foo=None):
>>> G.has(elem)
False
A group might also contain another group:
>>> p = Permutation(0, 1, 2, 3, 4, 5)
>>> G1 = PermutationGroup([Permutation(0, 1, 2), Permutation(0, 1)])
>>> G2 = PermutationGroup([Permutation(0, 2), Permutation(0, 1, 2)])
>>> G3 = PermutationGroup([p, p**2])
>>> assert G1.order() == G2.order() == G3.order() == 6
>>> assert G1.contains(G2, 1) and not G1.contains(G3, 1)
See Also
========
coset_factor, has
coset_factor, has, in
"""
if isinstance(g, Permutation):
if g in self.generators:
return True
return bool(self.coset_factor(g.array_form))
elif isinstance(g, PermutationGroup):
if self == g:
return True
if self.degree != g.degree:
return False
if self.order() != g.order():
return False
# if A.contains(B) == B.contains(A) then we
# can process the generators of the shorter one;
# if that is not True, the following swap should be
# removed and all "A.contains(B, 1)" in combinatorics
# should be re-written as B.contains(A) and the foo=None
# parameter can be removed.
if len(self) < len(g):
g, self = self, g
return all(self.contains(gi) for gi in g)
else:
raise ValueError('expecting permutation or '
'permutation group, not %s' % g)
if not isinstance(g, Permutation):
return False
if g.size != self.degree:
return False
if g in self.generators:
return True
return bool(self.coset_factor(g.array_form))

@property
def is_abelian(self):
Expand Down Expand Up @@ -2125,7 +2139,7 @@ def lower_central_series(self):
>>> A = AlternatingGroup(4)
>>> len(A.lower_central_series())
2
>>> A.lower_central_series()[1].contains(DihedralGroup(2), 1)
>>> A.lower_central_series()[1].is_in(DihedralGroup(2))
True
See Also
Expand All @@ -2137,7 +2151,7 @@ def lower_central_series(self):
res = [self]
current = self
next = self.commutator(self, current)
while not current.contains(next, 1):
while not current.is_in(next):
res.append(next)
current = next
next = self.commutator(self, current)
Expand Down Expand Up @@ -2293,7 +2307,7 @@ def normal_closure(self, other, k=10):
>>> G = S.normal_closure(C)
>>> G.order()
60
>>> G.contains(AlternatingGroup(5), 1)
>>> G.is_in(AlternatingGroup(5))
True
See Also
Expand Down Expand Up @@ -2619,7 +2633,7 @@ def pointwise_stabilizer(self, points):
>>> from sympy.combinatorics.named_groups import SymmetricGroup
>>> S = SymmetricGroup(7)
>>> Stab = S.pointwise_stabilizer([2, 3, 5])
>>> Stab.contains(S.stabilizer(2).stabilizer(3).stabilizer(5), 1)
>>> Stab.is_in(S.stabilizer(2).stabilizer(3).stabilizer(5))
True
See Also
Expand Down Expand Up @@ -3410,7 +3424,7 @@ def subgroup_search(self, prop, base=None, strong_gens=None, tests=None,\
>>> prop_even = lambda x: x.is_even
>>> base, strong_gens = S.schreier_sims_incremental()
>>> G = S.subgroup_search(prop_even, base=base, strong_gens=strong_gens)
>>> G.contains(AlternatingGroup(7), 1)
>>> G.is_in(AlternatingGroup(7))
True
>>> _verify_bsgs(G, base, G.generators)
True
Expand Down
72 changes: 36 additions & 36 deletions sympy/combinatorics/tests/test_perm_groups.py
Expand Up @@ -98,7 +98,7 @@ def test_center():
for j in (1, 5, 7):
for k in (1, 1, 11):
G = AbelianGroup(i, j, k)
assert G.center().contains(G, 1)
assert G.center().is_in(G)
# the center of a nonabelian simple group is trivial
for i in(1, 5, 9):
A = AlternatingGroup(i)
Expand All @@ -107,19 +107,19 @@ def test_center():
D = DihedralGroup(5)
A = AlternatingGroup(3)
C = CyclicGroup(4)
G.contains(D*A*C, 1)
G.is_in(D*A*C)
assert _verify_centralizer(G, G)

def test_centralizer():
# the centralizer of the trivial group is the entire group
S = SymmetricGroup(2)
assert S.centralizer(Permutation(range(2))).contains(S, 1)
assert S.centralizer(Permutation(range(2))).is_in(S)
A = AlternatingGroup(5)
assert A.centralizer(Permutation(range(5))).contains(A, 1)
assert A.centralizer(Permutation(range(5))).is_in(A)
# a centralizer in the trivial group is the trivial group itself
triv = PermutationGroup([Permutation([0,1,2,3])])
D = DihedralGroup(4)
assert triv.centralizer(D).contains(triv, 1)
assert triv.centralizer(D).is_in(triv)
# brute-force verifications for centralizers of groups
for i in (4, 5, 6):
S = SymmetricGroup(i)
Expand All @@ -128,7 +128,7 @@ def test_centralizer():
D = DihedralGroup(i)
for gp in (S, A, C, D):
for gp2 in (S, A, C, D):
if not gp2.contains(gp, 1):
if not gp2.is_in(gp):
assert _verify_centralizer(gp, gp2)
# verify the centralizer for all elements of several groups
S = SymmetricGroup(5)
Expand Down Expand Up @@ -237,22 +237,22 @@ def test_is_normal():
assert G5.order() == 24
G6 = G1.normal_closure(G5.generators)
assert G6.order() == 120
assert G1.contains(G6, 1)
assert not G1.contains(G4, 1)
assert G2.contains(G4, 1)
assert G1.is_in(G6)
assert not G1.is_in(G4)
assert G2.is_in(G4)

def test_eq():
a = [[1,2,0,3,4,5], [1,0,2,3,4,5], [2,1,0,3,4,5], [1,2,0,3,4,5]]
a = [Permutation(p) for p in a + [[1,2,3,4,5,0]]]
g = Permutation([1,2,3,4,5,0])
G1, G2, G3 = [PermutationGroup(x) for x in [a[:2],a[2:4],[g, g**2]]]
assert G1.order() == G2.order() == G3.order() == 6
assert G1.contains(G2, 1)
assert not G1.contains(G3, 1)
assert G1.is_in(G2)
assert not G1.is_in(G3)
G4 = PermutationGroup([Permutation([0,1])])
assert not G1.contains(G4, 1)
assert not G1.is_in(G4)
assert G4.is_subgroup(G1)
assert PermutationGroup(g, g).contains(PermutationGroup(g), 1)
assert PermutationGroup(g, g).is_in(PermutationGroup(g))
assert SymmetricGroup(3).is_subgroup(SymmetricGroup(4))
assert SymmetricGroup(3).is_subgroup(SymmetricGroup(3)*CyclicGroup(5))
assert not CyclicGroup(5).is_subgroup(SymmetricGroup(3)*CyclicGroup(5))
Expand Down Expand Up @@ -309,7 +309,7 @@ def test_rubik():
assert G1.order() == 170659735142400
assert not G1.is_normal(G)
G2 = G.normal_closure(G1.generators)
assert G2.contains(G, 1)
assert G2.is_in(G)

def test_direct_product():
C = CyclicGroup(4)
Expand Down Expand Up @@ -489,22 +489,22 @@ def _subgroup_search(i, j, k):
A = AlternatingGroup(i)
C = CyclicGroup(i)
Sym = S.subgroup_search(prop_true)
assert Sym.contains(S, 1)
assert Sym.is_in(S)
Alt = S.subgroup_search(prop_even)
assert Alt.contains(A, 1)
assert Alt.is_in(A)
Sym = S.subgroup_search(prop_true, init_subgroup=C)
assert Sym.contains(S, 1)
assert Sym.is_in(S)
points = [7]
assert S.stabilizer(7).contains(S.subgroup_search(prop_fix_points), 1)
assert S.stabilizer(7).is_in(S.subgroup_search(prop_fix_points))
points = [3, 4]
assert S.stabilizer(3).stabilizer(4).contains(
S.subgroup_search(prop_fix_points), 1)
assert S.stabilizer(3).stabilizer(4).is_in(
S.subgroup_search(prop_fix_points))
points = [3, 5]
fix35 = A.subgroup_search(prop_fix_points)
points = [5]
fix5 = A.subgroup_search(prop_fix_points)
assert A.subgroup_search(prop_fix_points, init_subgroup=fix35
).contains(fix5, 1)
).is_in(fix5)
base, strong_gens = A.schreier_sims_incremental()
g = A.generators[0]
comm_g =\
Expand All @@ -528,7 +528,7 @@ def test_normal_closure():
assert closure.is_trivial
# the normal closure of the entire group is the entire group
A = AlternatingGroup(4)
assert A.normal_closure(A).contains(A, 1)
assert A.normal_closure(A).is_in(A)
# brute-force verifications for subgroups
for i in (3, 4, 5):
S = SymmetricGroup(i)
Expand Down Expand Up @@ -557,58 +557,58 @@ def test_normal_closure():
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()[0].contains(triv, 1)
assert triv.derived_series()[0].is_in(triv)
# the derived series for a simple group consists only of the group itself
for i in (5, 6, 7):
A = AlternatingGroup(i)
assert A.derived_series()[0].contains(A, 1)
assert A.derived_series()[0].is_in(A)
# the derived series for S_4 is S_4 > A_4 > K_4 > triv
S = SymmetricGroup(4)
series = S.derived_series()
assert series[1].contains(AlternatingGroup(4), 1)
assert series[2].contains(DihedralGroup(2), 1)
assert series[1].is_in(AlternatingGroup(4))
assert series[2].is_in(DihedralGroup(2))
assert series[3].is_trivial

def test_lower_central_series():
# the lower central series of the trivial group consists of the trivial
# group
triv = PermutationGroup([Permutation([0, 1, 2])])
assert triv.lower_central_series()[0].contains(triv, 1)
assert triv.lower_central_series()[0].is_in(triv)
# the lower central series of a simple group consists of the group itself
for i in (5, 6, 7):
A = AlternatingGroup(i)
assert A.lower_central_series()[0].contains(A, 1)
assert A.lower_central_series()[0].is_in(A)
# GAP-verified example
S = SymmetricGroup(6)
series = S.lower_central_series()
assert len(series) == 2
assert series[1].contains(AlternatingGroup(6), 1)
assert series[1].is_in(AlternatingGroup(6))

def test_commutator():
# the commutator of the trivial group and the trivial group is trivial
S = SymmetricGroup(3)
triv = PermutationGroup([Permutation([0, 1, 2])])
assert S.commutator(triv, triv).contains(triv, 1)
assert S.commutator(triv, triv).is_in(triv)
# the commutator of the trivial group and any other group is again trivial
A = AlternatingGroup(3)
assert S.commutator(triv, A).contains(triv, 1)
assert S.commutator(triv, A).is_in(triv)
# the commutator is commutative
for i in (3, 4, 5):
S = SymmetricGroup(i)
A = AlternatingGroup(i)
D = DihedralGroup(i)
assert S.commutator(A, D).contains(S.commutator(D, A), 1)
assert S.commutator(A, D).is_in(S.commutator(D, A))
# the commutator of an abelian group is trivial
S = SymmetricGroup(7)
A1 = AbelianGroup(2, 5)
A2 = AbelianGroup(3, 4)
triv = PermutationGroup([Permutation([0, 1, 2, 3, 4, 5, 6])])
assert S.commutator(A1, A1).contains(triv, 1)
assert S.commutator(A2, A2).contains(triv, 1)
assert S.commutator(A1, A1).is_in(triv)
assert S.commutator(A2, A2).is_in(triv)
# examples calculated by hand
S = SymmetricGroup(3)
A = AlternatingGroup(3)
assert S.commutator(A, S).contains(A, 1)
assert S.commutator(A, S).is_in(A)

def test_is_nilpotent():
# every abelian group is nilpotent
Expand All @@ -634,7 +634,7 @@ def test_pointwise_stabilizer():
for point in (2, 0, 3, 4, 1):
stab = stab.stabilizer(point)
points.append(point)
assert S.pointwise_stabilizer(points).contains(stab, 1)
assert S.pointwise_stabilizer(points).is_in(stab)

def test_make_perm():
assert cube.pgroup.make_perm(5, seed=list((range(5)))) == \
Expand Down

0 comments on commit e1ef520

Please sign in to comment.