Skip to content

Commit

Permalink
simplify and correct structures
Browse files Browse the repository at this point in the history
  • Loading branch information
mantepse committed Nov 16, 2024
1 parent b918066 commit 7af0ee8
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 62 deletions.
106 changes: 49 additions & 57 deletions src/sage/rings/lazy_species.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from sage.combinat.set_partition import SetPartitions
from sage.graphs.graph_generators import graphs
from sage.groups.perm_gps.permgroup_named import SymmetricGroup, CyclicPermutationGroup
from sage.libs.gap.libgap import libgap
from sage.structure.element import parent
import itertools
from collections import defaultdict
Expand Down Expand Up @@ -307,9 +306,9 @@ def _add_(self, other):
sage: E = L(lambda n: SymmetricGroup(n))
sage: F = L(lambda n: SymmetricGroup(n))
sage: list(E.structures([1,2,3]))
[((1, 2, 3), E_3)]
[(E_3, ((1, 2, 3),))]
sage: list((E+F).structures([1,2,3]))
[((1, 2, 3), E_3), ((1, 2, 3), E_3)]
[(E_3, ((1, 2, 3),)), (E_3, ((1, 2, 3),))]
"""
return SumSpeciesElement(self, other)
Expand All @@ -327,14 +326,14 @@ def _mul_(self, other):
sage: L = LazySpecies(ZZ, "X")
sage: E = L(lambda n: SymmetricGroup(n))
sage: sorted((E^2).structures([1,2,3]))
[(((), 1), ((1, 2, 3), E_3)),
(((1,), X), ((2, 3), E_2)),
(((1, 2), E_2), ((3,), X)),
(((1, 2, 3), E_3), ((), 1)),
(((1, 3), E_2), ((2,), X)),
(((2,), X), ((1, 3), E_2)),
(((2, 3), E_2), ((1,), X)),
(((3,), X), ((1, 2), E_2))]
[((1, ()), (E_3, ((1, 2, 3),))),
((X, ((1,),)), (E_2, ((2, 3),))),
((X, ((2,),)), (E_2, ((1, 3),))),
((X, ((3,),)), (E_2, ((1, 2),))),
((E_2, ((1, 2),)), (X, ((3,),))),
((E_2, ((1, 3),)), (X, ((2,),))),
((E_2, ((2, 3),)), (X, ((1,),))),
((E_3, ((1, 2, 3),)), (1, ()))]
"""
return ProductSpeciesElement(self, other)

Expand All @@ -354,61 +353,55 @@ def structures(self, *labels):
sage: L = LazySpecies(QQ, "X")
sage: E = L(lambda n: SymmetricGroup(n))
sage: list(E.structures([1,2,3]))
[((1, 2, 3), E_3)]
[(E_3, ((1, 2, 3),))]
sage: P = L(lambda n: CyclicPermutationGroup(n))
sage: list(P.structures([1,2,3]))
[((1, 2, 3), C_3), ((2, 1, 3), C_3)]
[(C_3, ((1, 2, 3),)), (C_3, ((1, 3, 2),))]
sage: F = 1/(2-E)
sage: sorted(F.structures([1,2,3]))
[((1, 2, 3), E_3),
((1, 2, 3), X*E_2, 0),
((1, 2, 3), X*E_2, 1),
((1, 2, 3), X^3),
((1, 3, 2), X^3),
((2, 1, 3), X^3),
((2, 3, 1), X*E_2, 0),
((2, 3, 1), X*E_2, 1),
((2, 3, 1), X^3),
((3, 1, 2), X*E_2, 0),
((3, 1, 2), X*E_2, 1),
((3, 1, 2), X^3),
((3, 2, 1), X^3)]
[(E_3, ((1, 2, 3),)),
(X*E_2, ((1,), (2, 3)), 0),
(X*E_2, ((1,), (2, 3)), 1),
(X*E_2, ((2,), (1, 3)), 0),
(X*E_2, ((2,), (1, 3)), 1),
(X*E_2, ((3,), (1, 2)), 0),
(X*E_2, ((3,), (1, 2)), 1),
(X^3, ((1,), (2,), (3,))),
(X^3, ((1,), (3,), (2,))),
(X^3, ((2,), (1,), (3,))),
(X^3, ((2,), (3,), (1,))),
(X^3, ((3,), (1,), (2,))),
(X^3, ((3,), (2,), (1,)))]
sage: from sage.rings.species import PolynomialSpecies
sage: L = LazySpecies(QQ, "X, Y")
sage: P = PolynomialSpecies(QQ, "X, Y")
sage: XY = L(P(PermutationGroup([], domain=[1, 2]), {0: [1], 1: [2]}))
sage: list((XY).structures([1], [2]))
[((1, 2), X*Y)]
sage: list((XY).structures([1], ["a"]))
[(X*Y, ((1,), ('a',)))]
sage: list(E(XY).structures([1,2],[3,4]))
[((1, 2, 3, 4), {((1,2)(3,4),): ({1, 2}, {3, 4})}),
((2, 1, 3, 4), {((1,2)(3,4),): ({1, 2}, {3, 4})})]
sage: sorted(E(XY).structures([1,2], [3, 4])) # random
[((E_2, ((((2, 'X'), (3, 'Y')), ((1, 'X'), (4, 'Y'))),)),
((X*Y, ((1,), (4,))), (X*Y, ((2,), (3,))))),
((E_2, ((((3, 'Y'), (1, 'X')), ((2, 'X'), (4, 'Y'))),)),
((X*Y, ((1,), (3,))), (X*Y, ((2,), (4,)))))]
sage: list(XY.structures([], [1, 2]))
[]
"""
labels = label_sets(self.parent()._arity, labels)
n = tuple([len(U) for U in labels])
S = SymmetricGroup(sum(n)).young_subgroup(n)
F = self[sum(n)]
l = [e for l in labels for e in l][::-1]
F = self[sum(map(len, labels))]
for M, c in F.monomial_coefficients().items():
if c not in ZZ or c < 0:
raise NotImplementedError("only implemented for proper non-virtual species")
G, dompart = M.permutation_group()
if not tuple(len(b) for b in dompart) == n:
continue
types = [tuple(S(rep)._act_on_list_on_position(l))[::-1]
for rep in libgap.RightTransversal(S, G)]
if c == 1:
for s in types:
yield s, M
for s in M.structures(*labels):
yield M, s
else:
for e, s in cartesian_product([range(c), types]):
yield s, M, e
for e, s in cartesian_product([range(c), M.structures(*labels)]):
yield M, s, e

def isotypes(self, labels):
pass
Expand Down Expand Up @@ -484,7 +477,7 @@ def __call__(self, *args):
sage: F = E(C(A))
sage: [sum(F[n].monomial_coefficients().values()) for n in range(1, 7)]
[1, 3, 7, 19, 47, 130]
sage: oeis(_)
sage: oeis(_) # optional -- internet
0: A001372: Number of unlabeled mappings (or mapping patterns)
from n points to themselves; number of unlabeled endofunctions.
Expand Down Expand Up @@ -558,7 +551,7 @@ def structures(self, *labels):
sage: L.<X, Y> = LazySpecies(QQ)
sage: list((X*Y).structures([1], [2]))
[(((1,), X), ((2,), Y))]
[((X, ((1,),)), (Y, ((2,),)))]
"""
def dissections(s):
for subset in subsets(s):
Expand Down Expand Up @@ -656,16 +649,17 @@ def structures(self, *labels):
sage: L = LazySpecies(QQ, "X")
sage: E = L.Sets()
sage: E1 = L.Sets(min=1)
sage: list(E(E1).structures([1,2,3]))
[({((1, 0), (2, 0), (3, 0))}, ({1, 2, 3},)),
({((1, 0), (2, 0)), ((3, 0),)}, ({1, 2}, {3})),
({((1, 0), (3, 0)), ((2, 0),)}, ({1, 3}, {2})),
({((1, 0),), ((2, 0), (3, 0))}, ({1}, {2, 3})),
({((1, 0),), ((2, 0),), ((3, 0),)}, ({1}, {2}, {3}))]
sage: sorted(E(E1).structures([1,2,3])) # random
[({((2, 'X'), (3, 'X'), (1, 'X'))}, ({1, 2, 3},)),
({((2, 'X'), (1, 'X')), ((3, 'X'),)}, ({1, 2}, {3})),
({((2, 'X'),), ((3, 'X'), (1, 'X'))}, ({1, 3}, {2})),
({((1, 'X'),), ((2, 'X'), (3, 'X'))}, ({1}, {2, 3})),
({((1, 'X'),), ((2, 'X'),), ((3, 'X'),)}, ({1}, {2}, {3}))]
sage: C = L.Cycles()
sage: L.<X, Y> = LazySpecies(QQ)
sage: sum(1 for s in C(X*Y).structures([1,2,3], [1,2,3]))
12
sage: C(X*Y).generating_series()[6]
1/3*X^3*Y^3
Expand All @@ -677,15 +671,16 @@ def structures(self, *labels):
G = self._args
m = len(G) # == F.parent()._arity
k = self.parent()._arity # == G[i].parent()._arity
names = self.parent()._laurent_poly_ring._indices._indices._names
labels = label_sets(k, labels)
# make label sets disjoint
U = [(e, i) for i, l in enumerate(labels) for e in l]
U = [(e, i) for l, i in zip(labels, names) for e in l]

def split_set(C):
C_split = defaultdict(list)
for e, i in C:
C_split[i].append(e)
return [C_split[i] for i in range(k)]
return [C_split[i] for i in names]

Par_U = SetPartitions(U)
for pi in Par_U:
Expand Down Expand Up @@ -777,7 +772,6 @@ def __init__(self, base_ring, names, sparse):

class SetSpecies(LazySpeciesElement):
def __init__(self, parent, min):
P = parent._laurent_poly_ring
S = parent(lambda n: SymmetricGroup(n) if n >= min else 0)
super().__init__(parent, S._coeff_stream)

Expand All @@ -798,7 +792,6 @@ def structures(self, *labels):

class CycleSpecies(LazySpeciesElement):
def __init__(self, parent):
P = parent._laurent_poly_ring
S = parent(lambda n: CyclicPermutationGroup(n) if n else 0)
super().__init__(parent, S._coeff_stream)

Expand Down Expand Up @@ -836,7 +829,6 @@ def isotypes(self, labels):

class SetPartitionSpecies(LazySpeciesElement):
def __init__(self, parent):
P = parent._laurent_poly_ring
E = parent.Sets()
E1 = parent.Sets(min=1)
super().__init__(parent, E(E1)._coeff_stream)
Expand Down
16 changes: 11 additions & 5 deletions src/sage/rings/species.py
Original file line number Diff line number Diff line change
Expand Up @@ -1587,7 +1587,7 @@ def structures(self, *labels):
sage: a = M(PermutationGroup([(3,4),(5,)]), {0:[1,3,4], 1:[2,5]})
sage: a
X*Y^2*E_2(X)
sage: list(a.structures([1, 2, 3], ["a", "b"]))
sage: sorted(a.structures([1, 2, 3], ["a", "b"]))
[((1,), ('a',), ('b',), (2, 3)),
((1,), ('b',), ('a',), (2, 3)),
((2,), ('a',), ('b',), (1, 3)),
Expand All @@ -1599,7 +1599,7 @@ def structures(self, *labels):
sage: a = M(G, {0: [1, 2, 3], 1: [4, 5]})
sage: a
X*E_2(XY)
sage: list(a.structures([1, 2, 3], ["a", "b"]))
sage: sorted(a.structures([1, 2, 3], ["a", "b"]))
[((1,), (2, 3, 'a', 'b')),
((1,), (2, 3, 'b', 'a')),
((2,), (1, 3, 'a', 'b')),
Expand All @@ -1611,9 +1611,15 @@ def structures(self, *labels):
labels = label_sets(k, labels)
atoms = [a for a, n in self._monomial.items() for _ in range(n)]
sizes = [a._mc for a in atoms]
dissections = product(*[OrderedSetPartitions(l, [mc[i] for mc in sizes])
for i, l in enumerate(labels)])
for d in dissections:
try:
# TODO: maybe OrderedSetPartitions should not raise
# an error if the second argument is a composition,
# but not of the right size
dissections = [OrderedSetPartitions(l, [mc[i] for mc in sizes])
for i, l in enumerate(labels)]
except ValueError:
return
for d in product(*dissections):
yield from product(*[a.structures(*[l[i] for l in d])
for i, a in enumerate(atoms)])

Expand Down

0 comments on commit 7af0ee8

Please sign in to comment.